Dash에서 프로세스 교체를 시뮬레이션하는 방법은 무엇입니까?

Dash에서 프로세스 교체를 시뮬레이션하는 방법은 무엇입니까?

bash프로세스 대체를 사용하고 프로세스의 출력을 디스크에 저장된 파일로 처리할 수 있습니다 .

$ echo <(ls)
/dev/fd/63

$ ls -lAhF <(ls)
lr-x------ 1 root root 64 Sep 17 12:55 /dev/fd/63 -> pipe:[1652825]

안타깝게도, dash.

Process Substitution대시에서 시뮬레이션하는 가장 좋은 방법은 무엇입니까?

/tmp/출력을 임시 파일( )에 저장한 후 삭제하고 싶지 않습니다 . 다른 방법이 있나요?

답변1

파이프라인을 수동으로 실행하여 셸이 내부적으로 수행하는 작업을 재현할 수 있습니다. 시스템에 항목이 있으면 파일 설명자 섞기를 사용할 수 있습니다. 번역할 수 있습니다./dev/fd/NNN

main_command <(produce_arg1) <(produce_arg2) >(consume_arg3) >(consume_arg4)

도착하다

{ produce_arg1 |
  { produce_arg2 |
    { main_command /dev/fd5 /dev/fd6 /dev/fd3 /dev/fd4 </dev/fd/8 >/dev/fd/9; } 5<&0 3>&1 |
    consume_arg3; } 6<&0 4>&1; |
  consume_arg4; } 8<&0 9>&1

여러 입력과 출력을 설명하는 좀 더 복잡한 예를 보여 드리겠습니다. 표준 입력에서 읽을 필요가 없고 프로세스 대체를 사용하는 유일한 이유가 명령에 명시적인 파일 이름이 필요하다는 것이라면 간단히 다음을 사용할 수 있습니다 /dev/stdin.

main_command <(produce_arg1)
produce_arg1 | main_command /dev/stdin

그렇지 않은 경우 사용해야 합니다./dev/fd/NNN명명된 파이프. 명명된 파이프는 디렉터리 항목이므로 어딘가에 임시 파일을 만들어야 하지만 해당 파일은 이름일 뿐이며 데이터가 포함되어 있지 않습니다.

tmp=$(mktemp -d)
mkfifo "$tmp/f1" "$tmp/f2" "$tmp/f3" "$tmp/f4"
produce_arg1 >"$tmp/f1" &
produce_arg2 >"$tmp/f2" &
consume_arg3 <"$tmp/f3" &
consume_arg4 <"$tmp/f4" &
main_command "$tmp/f1" "$tmp/f2" "$tmp/f3" "$tmp/f4"
rm -r "$tmp"

답변2

현재 현상금 알림의 문제:

일반적인 예는 너무 복잡합니다. 다음 예제를 구현하는 방법을 설명해 줄 수 있는 사람이 있나요?diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)

답이 있을 것 같습니다여기.

그림에서 알 수 있듯이자일스의 대답, 일반적인 아이디어는 "생산자" 명령의 출력을 파이프라인의 여러 단계에서 새 장치 파일1 로 전송하여 파일 이름을 인수로 사용할 수 있는 "소비자" 명령에서 사용할 수 있도록 하는 것입니다(시스템이 액세스를 제공한다고 가정). 파일 설명자에 /dev/fd/X).

원하는 것을 달성하는 가장 쉬운 방법은 아마도 다음과 같습니다.

xz -cd file1.xz | { xz -cd file2.xz | diff /dev/fd/3 -; } 3<&0

( file1.xz대신 in을 사용하는 것은 "$1"가독성을 위한 것이지 단일 명령으로 충분하기 때문 xz -cd이 아닙니다 .)cat ... | xz -d

첫 번째 "생산자" 명령의 출력은 xz -cd file1.xz복합 명령( {...})으로 파이프되지만 다음 명령의 표준 입력으로 즉시 사용되지는 않습니다.반복됨3복합 명령 내의 모든 것에 대한 액세스를 허용하는 파일 설명자 /dev/fd/3. 두 번째 "생산자" 명령의 출력은 xz -cd file2.xz표준 입력이나 파일 설명자에 있는 어떤 것도 사용하지 않고 표준 입력 및 에서 읽는 3"소비자" 명령으로 파이프됩니다 .diff/dev/fd/3

파이프와 파일 설명자 복사본을 추가하여 필요한 만큼 "생산자" 명령에 대한 장치 파일을 제공할 수 있습니다. 예를 들면 다음과 같습니다.

xz -cd file1.xz | { xz -cd file2.xz | { diff /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0

귀하의 특정 질문과 관련이 없을 수도 있지만 다음 사항에 주목할 가치가 있습니다.

  1. cmd1 <(cmd2) <(cmd3), 초기 실행 환경에 다양한 잠재적 영향을 미칩니다 cmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0.( cmd2 | ( cmd3 | ( cmd1 /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )

  2. 에서 cmd1 <(cmd2) <(cmd3)일어나는 일의 반대는 사용자로부터 어떤 입력도 읽을 수 없게 됩니다 . 이렇게 하려면 더 많은 파일 설명자가 필요합니다. 예를 들어 일치시키려면cmd3cmd1cmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0

    diff <(echo foo) <(read var; echo "$var")
    

    당신은 다음과 같은 것이 필요합니다

    { echo foo | { read var 0<&9; echo "$var" | diff /dev/fd/3 -; } 3<&0; } 9<&0
    

1이들에 대한 자세한 내용은 U&L에서 확인할 수 있습니다./dev, 하위 디렉터리 및 파일 이해.

답변3

다음 예제를 구현하는 방법을 설명해 줄 수 있는 사람이 있나요?
diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)

명명된 파이프는 리디렉션보다 이해하기 쉽다고 생각합니다. 따라서 간단히 말하면 다음과 같습니다.

mkfifo p1 p2               # create pipes
cat "$2" | xz -d > p1 &    # start the commands in the background
cat "$1" | xz -d > p2 &    #    with output to the pipes
diff p1 p2                 # run 'diff', reading from the pipes
rm p1 p2                   # remove them at the end

p1임시 명명된 파이프 이므로 p2이름을 무엇이든 지정할 수 있습니다.

/tmp예를 들어 Gilles의 디렉터리 에 파이프를 만드는 것이 더 현명할 것입니다.답변여기서는 표시할 필요가 없으므로 cat다음과 같이 하세요.

tmpdir=$(mktemp -d)
mkfifo "$tmpdir/p1" "$tmpdir/p2"
xz -d < "$2" > "$tmpdir/p1" &
xz -d < "$1" > "$tmpdir/p2" &
diff "$tmpdir/p1" "$tmpdir/p2"
rm -r "$tmpdir"

mktemp( "예쁜" 파일 이름을 만들 수 있으므로 따옴표를 생략할 수도 있습니다 .)

diff파이프 솔루션에는 주의 사항이 있습니다. 모든 입력을 읽기 전에 주 명령( )이 종료되면 백그라운드 프로세스가 중단될 수 있습니다.

답변4

무엇에 대해:

cat "$2" | xz -d | diff /dev/sdtin /dev/stderr 2<<EOT
`cat "$1" | xz -d`
EOT

관련 정보