
stdout
긴 프로세스에 대한 상태 출력을 보존할 수 있도록 명명된 파이프를 사용하려고 합니다 . 상태 출력용 으로 사용할 수 있지만 stderr
오류 방지를 위해 보관하고 싶습니다. 예는 다음과 같습니다.
#!/bin/bash
pipe=$(mktemp -u)
mkfifo $pipe
dd if=/dev/zero of=$pipe bs=1M count=1024 status=progress & cat $pipe > test.bin
# ¿¿¿ Status of dd command ???
rm $pipe
이 명령은 정확히 내가 하려는 명령은 아니지만 명명된 파이프를 사용하여 한 프로세스의 출력을 다른 프로세스의 입력에 공급하는 조합을 보여줍니다. 내 애플리케이션에서 dd
일부 장기 실행 명령이 로 대체되었습니다 cat
. 이렇게 하면 원하는 작업이 수행되지만 명령 상태를 가져오고 명령 상태를 반환하는 ssh
방법을 모르겠습니다 . 이것이 파이프라면 사용할 수 있지만 병렬 프로세스에서는 작동하지 않는 것 같습니다. 실제 애플리케이션에서는 명령 중 하나(또는 둘 다)가 실패할 수 있습니다.dd
$?
cat
PIPESTATUS
병렬로 실행 중인 프로세스의 상태를 가져오는 방법이 있습니까? 명명된 파이프보다 이를 수행하는 더 좋은 방법이 있습니까?
답변1
비동기 명령의 종료 상태를 얻으려면 다음을 사용할 수 있습니다 wait
.
#!/bin/bash -
pipe=$(mktemp -u) || exit
mkfifo -m 600 -- "$pipe" || exit
dd if=/dev/zero of="$pipe" bs=1M count=1024 status=progress &
dd_pid=$!
cat -- "$pipe" > test.bin
cat_status=$?
wait "$dd_pid"
dd_status=$?
rm -f -- "$pipe"
mktemp
(또한 이러한 /s 의 성공 여부를 확인하지 않거나 mkfifo
인용되지 않은 확장, s 누락과 같은 몇 가지 명백한 버그를 수정합니다 --
.)
(또는 귀하의 경우에 나타나는 실제 명령이 무엇이든 dd
) 쓰기 위해 열기 전에 종료되면 자체 fifo 읽기 전용 상태가 무기한 정지됩니다.dd
$pipe
cat
open()
이 문제를 해결하려면 $pipe
프로세스가 결국 실행될 다른 fd에서 셸을 열어 파이프를 연 직후에 dd
파이프가 인스턴스화되는지 확인합니다 (그리고 fd가 열기 전에 임의로 닫히지 않았다고 가정 ).cat
dd
$pipe
dd if=/dev/zero 3> "$pipe" of="$pipe" bs=1M count=1024 status=progress &
dd_pid=$!
cat -- "$pipe" > test.bin
cat_status=$?
wait "$dd_pid"
dd_status=$?
마찬가지로, cat
파이프를 열기 전에 죽으면 동일한 대칭 문제가 발생하며 이는 동일한 방법으로 해결할 수 있습니다.
시스템에 파일이 있는 경우 명명된 파이프 대신 일반 파이프를 사용하여 종료 상태를 검색할 수도 있습니다./dev/fd/n
/dev/fd/n
bash
$PIPESTATUS
{
dd if=/dev/zero of=/dev/fd/3 bs=1M count=1024 3>&1 >&5 4<&- 5>&- |
cat /dev/fd/3 3<&0 <&4 4<&- 5>&- > test.bin
} 4<&0 5>&1
dd_status=${PIPESTATUS[0]} cat_status=${PIPESTATUS[1]}
( $PIPESTATUS
bash에만 해당되지만 다른 쉘에 대한 대안도 있습니다).
위의 및 둘 다 fd 3(쓰기 및 읽기 측면 ) 에서 파이프를 dd
열고 위의 해결 방법과 마찬가지로 파이프에서 다른 fd를 열고 제공합니다. 우리는 fds 4와 5를 사용하여 두 가지 모두의 원래 stdin과 stdout을 복원합니다(그렇지 않으면 여기서 stdout이 복원되지만 ).cat
dd
cat
/dev/fd/3
cat
test.bin