Bash에서 백그라운드 작업으로 함께 생성되는 다른 프로세스로 파이프되는 프로세스의 PID를 검색해야 합니다. 이전에는 단순히 에 의존했지만 프로세스를 찾기까지 2초 이상의 지연이 있을 수 있는 것으로 pgrep
나타났습니다 .pgrep
#!/bin/bash
cmd1 | cmd2 &
pid=$(pgrep cmd1) # emtpy in about 1/10
이 문제에 대해 제가 찾은 몇 가지 일반적인 조언은 단순한 파이프( cmd1 >(cmd2) & pid=$!
) 대신 프로세스 대체를 사용하거나 jobs
내장 함수를 사용하라는 것입니다. 프로세스 교체는 (전체 런타임 동안) 전체 서브쉘을 실행하므로 지금은 그것을 사용하는 것이 좋지만 jobs
, 같은 실수를 두 번은 반복하지 않기를 바랍니다...
두 프로세스를 모두 생성한 후 즉시 조회를 수행하면 jobs
두 프로세스를 모두 알고 있다고 100% 신뢰할 수 있습니까?
#!/bin/bash
cmd1 | cmd2 &
pid=$(jobs -p %cmd1) # 10/10?
이는 백그라운드에서 작업을 실행하기 때문일 수도 있고 이상한 것일 수도 있지만 set -x
다음 예에서는 일반적으로 실행된 명령을 임의의 순서로 나열합니다. jobs
산출나타나다jobs
지금까지는 정확하지만 실행될 가능성은 완전히 배제하고 싶습니다.앞으로작업이 시작되었습니다(또는 최소한 jobs
두 개의 프로세스가 나열될 수 없습니다)! ?
#!/bin/bash
set -x
tail -f /dev/null | cat &
jobs -l
kill %tail
예:
+ jobs -l
[1]+ 2802325 Running tail -f /dev/null
2802326 | cat &
+ tail -f /dev/null
+ kill %tail
마찬가지로 프로세스 교체의 경우에도 pid=$!
항상 작동한다고 믿을 수 있습니까? 정확히 "가장 최근에 실행된 백그라운드(비동기) 명령의 프로세스 ID로 확장"하도록 설계되었습니까?
답변1
백그라운드 작업이 양식의 파이프라인인 경우에도 cmd1 | cmd2
여전히 단일 백그라운드 작업입니다. 언제 cmd1
시작될지 알 수 있는 방법이 없습니다 .
각각은 &
백그라운드 작업을 생성합니다. 일단 cmd &
반환되면 쉘은 백그라운드 작업인 cmd & jobs
lists를 인식하게 됩니다 cmd
. 실행 중인 프로세스 ID로 cmd & pid=$!
설정합니다 .pid
cmd
파이프는 cmd1 | cmd2
두 개의 다른 하위 프로세스를 생성합니다. 하나는 실행 cmd1
하고 다른 하나는 실행합니다 cmd2
. 두 프로세스 모두 백그라운드 작업을 실행하는 하위 프로세스의 하위 프로세스입니다. 프로세스 트리는 다음과 같습니다 bash -c '{ sleep 123 | sleep 456; } & jobs -p; sleep 789'
.
PID PPID CMD
268 265 | \_ bash -c { sleep 123 | sleep 456; } & sleep 789
269 268 | \_ bash -c { sleep 123 | sleep 456; } & sleep 789
270 269 | | \_ sleep 123
271 269 | | \_ sleep 456
272 268 | \_ sleep 789
268은 원래 bash 프로세스입니다. 269는 인쇄를 위한 백그라운드 작업입니다 jobs -p
. 270과 271은 파이프의 왼쪽과 오른쪽이며, 두 하위 프로세스 모두 백그라운드 작업(269)의 메인 프로세스입니다.
제가 테스트한 bash 버전(Linux의 경우 5.0.17)은 cmd1 | cmd2 &
중괄호 없이 최적화되었습니다. 이 경우 파이프라인의 왼쪽은 백그라운드 작업과 동일한 프로세스에서 실행됩니다.
PID PPID CMD
392 389 | \_ bash -c sleep 123 | sleep 456 & jobs -p; sleep 789
393 392 | \_ sleep 123
394 392 | \_ sleep 456
395 392 | \_ sleep 789
bash 버전 간, 그리고 심지어 플랫폼, 배포판, libc 버전 등 간에도 이 동작이 안정적이라고 믿을 수는 없습니다.
jobs -p %cmd1
코드가 로 시작하는 채용정보를 찾으세요 cmd1
. 찾은 것은 cmd1 | cmd2
. jobs -p %?cmd2
bash의 내장 기능을 통해 cmd1
실행 중인 프로세스 ID에 액세스할 수 있는 방법은 없습니다.cmd2
cmd1
시작되었는지 확인해야 하는 경우 프로세스 대체를 사용하십시오.
cmd1 >(cmd2)
cmd2
언제 시작하고 끝날지 알 수 없습니다 .
cmd1
언제 시작 하고 끝나는 지 알아야 한다면 cmd2
동시에 작동하도록 하고 명명된 파이프를 통해 통신하도록 해야 합니다.
tmp=$(mktemp -d) # Remove this in cleanup code
mkfifo "$tmp/pipe"
cmd1 >"$tmp/pipe" & pid1=$!
cmd2 <"$tmp/pipe" & pid2=$!
…
이 jobs
명령은 스크립트에서는 그다지 유용하지 않습니다. $!
백그라운드 작업의 PID를 기억하는 데 사용됩니다 .
1 아니면 적어도 그래야 합니다. 내 버전에서는 작업 사양이 불분명하다고 불평하는데, 작업이 하나만 있다고 되어 있기 때문에 버그임이 틀림없습니다.