Bash에 프로세스가 완료 될 때까지 기다리는 내장 기능이 있습니까?
이 wait
명령은 자식 프로세스가 완료 될 때까지 기다릴 수 있습니다. 스크립트를 진행하기 전에 프로세스가 완료 될 때까지 기다리는 방법이 있는지 알고 싶습니다.
이를 수행하는 기계적 방법은 다음과 같지만 Bash에 내장 기능이 있는지 알고 싶습니다.
while ps -p `cat $PID_FILE` > /dev/null; do sleep 1; done
Bash에 프로세스가 완료 될 때까지 기다리는 내장 기능이 있습니까?
이 wait
명령은 자식 프로세스가 완료 될 때까지 기다릴 수 있습니다. 스크립트를 진행하기 전에 프로세스가 완료 될 때까지 기다리는 방법이 있는지 알고 싶습니다.
이를 수행하는 기계적 방법은 다음과 같지만 Bash에 내장 기능이 있는지 알고 싶습니다.
while ps -p `cat $PID_FILE` > /dev/null; do sleep 1; done
답변:
리눅스 :
tail --pid=$pid -f /dev/null
다윈 ( $pid
파일을 열어야 함) :
lsof -p $pid +r 1 &>/dev/null
리눅스 :
timeout $timeout tail --pid=$pid -f /dev/null
다윈 ( $pid
파일을 열어야 함) :
lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)
tail
입니다.
tail
kill(pid, SIG_0)
프로세스 로 폴링하여 후드에서 작동 합니다 (를 사용하여 발견 strace
).
+r 1
, 시간 초과입니다. 개인적으로 폴링을 사용하지 않는 MacOS 솔루션을 찾고 있습니다.
tail
라인이 kill (pid, 0) != 0 && errno != EPERM
있습니다.
caffeinate -w $pid
트릭을 수행합니다.
내장이 없습니다. kill -0
실행 가능한 솔루션을 위해 루프에서 사용하십시오 .
anywait(){
for pid in "$@"; do
while kill -0 "$pid"; do
sleep 0.5
done
done
}
또는 한 번 사용하기 쉬운 더 간단한 oneliner로 :
while kill -0 PIDS 2> /dev/null; do sleep 1; done;
여러 주석 작성자가 언급 한 것처럼 신호를 보낼 권한이없는 프로세스를 기다리려면 kill -0 $pid
통화 를 대체하기 위해 프로세스가 실행 중인지 감지하는 다른 방법을 찾으십시오 . Linux에서 test -d "/proc/$pid"
작동하면 다른 시스템에서 (사용 pgrep
가능한 경우) 또는 이와 유사한 것을 사용해야 할 수도 있습니다 ps | grep "^$pid "
.
sleep 0.5
프로세스가 종료 $pid
되고 다른 프로세스가 동일한 프로세스로 생성 될 수 있습니다 $pid
. 그리고 우리는 같은 두 개의 다른 프로세스 (또는 그 이상)를 기다릴 것 $pid
입니다.
프로세스가 루트 (또는 다른) 소유인 경우 "kill -0"이 작동하지 않는다는 것을 알았으므로 pgrep을 사용하여 다음을 수행했습니다.
while pgrep -u root process_name > /dev/null; do sleep 1; done
이것은 아마도 좀비 프로세스를 일치시키는 단점이 있습니다.
kill(pid, sig=0)
에서 호출자 프로세스에 강제 종료 권한이 없으면 시스템 호출 이 실패합니다. 따라서 / bin / kill -0과 "kill -0"(bash 내장)도 동일한 조건에서 실패합니다.
프로세스가 존재하지 않거나 좀비 인 경우이 bash 스크립트 루프가 종료됩니다.
PID=<pid to watch>
while s=`ps -p $PID -o s=` && [[ "$s" && "$s" != 'Z' ]]; do
sleep 1
done
편집 : 위의 스크립트 는 Rockallite에 의해 아래 에 주어 졌습니다 . 감사!
아래의 저의 정답은 Linux에서 작동하며 procfs
ie에 의존합니다 /proc/
. 이식성에 대해 잘 모르겠습니다.
while [[ ( -d /proc/$PID ) && ( -z `grep zombie /proc/$PID/status` ) ]]; do
sleep 1
done
쉘에만 국한되지는 않지만 OS 자체에는 자식 프로세스가 아닌 프로세스 종료를 감시하는 시스템 호출이 없습니다.
grep /proc/$PID/status
큰 따옴표 ( bash: test: argument expected
) 로 둘러 싸야했지만
while s=`ps -p $PID -o s=` && [[ "$s" && "$s" != 'Z' ]]; do sleep 1; done
ps
,도 -p
또는 s=
지원
FreeBSD와 Solaris는이 편리한 pwait(1)
유틸리티를 가지고 있습니다.
다른 현대 OS에도 필요한 시스템 호출 (예 : MacOS, BSD 구현 kqueue
)도 있지만 명령 줄에서 모두 사용할 수있는 것은 아닙니다.
> BSD and Solaris
: 떠오르는 세 가지 큰 BSD 검사. man.openbsd.org에서 쉽게 확인할 수 있듯이 OpenBSD 나 NetBSD는이 기능을 (Man 페이지에서) FreeBSD 만 가지고 있습니다.
kqueue
하므로 FreeBSD를 컴파일하는 pwait(1)
것은 쉽지 않습니다. 다른 BSD의 가져 오기 기능이 왜 나를 피하지
plink me@oracle box -pw redacted "pwait 6998";email -b -s "It's done" etc
지금부터 몇 시간이 아닌 지금 집에 갈 수있게 해주었습니다.
bash 맨 페이지에서
wait [n ...]
Wait for each specified process and return its termination status
Each n may be a process ID or a job specification; if a
job spec is given, all processes in that job's pipeline are
waited for. If n is not given, all currently active child processes
are waited for, and the return status is zero. If n
specifies a non-existent process or job, the return status is
127. Otherwise, the return status is the exit status of the
last process or job waited for.
wait
인수가 없으면 자식 프로세스가 끝날 때까지 프로세스가 차단됩니다 . 솔직히, 나는 기다릴 어떤 지점이 표시되지 않는 어떤 진행 systemprocesses 항상 이후 과정.
sleep 1000
ctrl-z
wait [sleep pid]
즉시 반환
이 모든 솔루션은 Ubuntu 14.04에서 테스트되었습니다.
해결책 1 (ps 명령을 사용하여) : Pierz 답변까지 추가하려면 다음을 제안합니다.
while ps axg | grep -vw grep | grep -w process_name > /dev/null; do sleep 1; done
이 경우 grep -vw grep
grep이 grep 자체가 아닌 process_name 과만 일치하는지 확인하십시오. process_name이에 줄 끝에 있지 않은 경우를 지원하는 이점이 ps axg
있습니다.
해결 방법 2 (최고 명령 및 프로세스 이름 사용) :
while [[ $(awk '$12=="process_name" {print $0}' <(top -n 1 -b)) ]]; do sleep 1; done
에 process_name
나타나는 프로세스 이름으로 바꾸십시오 top -n 1 -b
. 인용 부호를 유지하십시오.
프로세스가 완료되기를 기다리는 프로세스 목록을 보려면 다음을 실행하십시오.
while : ; do p=$(awk '$12=="process_name" {print $0}' <(top -n 1 -b)); [[ $b ]] || break; echo $p; sleep 1; done
해결 방법 3 (최고 명령 및 프로세스 ID 사용) :
while [[ $(awk '$1=="process_id" {print $0}' <(top -n 1 -b)) ]]; do sleep 1; done
교체 process_id
프로그램의 프로세스 ID.
grep -v grep
파이프 라인은 방대한 반 패턴이며, 같은 이름의 관련없는 프로세스가 없다는 것을 전제로합니다. PID를 아는 경우 제대로 작동하는 솔루션에 적합 할 수 있습니다.
-w
의 문제를 피하기 위해 플래그 를 추가했습니다 . 또한 귀하의 의견에 따라 두 가지 솔루션을 추가했습니다. grep -v grep
알았어요. 대답은 아닙니다. 도구가 내장되어 있지 않습니다.
설정 한 후 /proc/sys/kernel/yama/ptrace_scope
에 0
, 사용할 수 있습니다 strace
프로그램. 추가 스위치를 사용하여 자동으로 설정하여 실제로 수동적으로 대기 할 수 있습니다.
strace -qqe '' -p <PID>
Operation not permitted
번째 strace 인스턴스를 얻 습니다). 확인할 수 있습니까?
(...)"tracee" always means "(one) thread"
과 같이 말합니다 . 더 많은 프로세스가 이런 식으로 기다리게하려면 체인을 만들어야합니다.
wait
모든 프로세스 종료를 기다리는 동안 in 루프를 사용하십시오 .
function anywait()
{
for pid in "$@"
do
wait $pid
echo "Process $pid terminated"
done
echo 'All processes terminated'
}
이 기능은 모든 프로세스가 종료되면 즉시 종료됩니다. 이것이 가장 효율적인 솔루션입니다.
kill -0
in 루프를 사용하여 모든 프로세스가 종료 될 때까지 기다리십시오.
function anywait_w_status()
{
for pid in "$@"
do
while kill -0 "$pid"
do
echo "Process $pid still running..."
sleep 1
done
done
echo 'All processes terminated'
}
sleep
CPU 사용률이 높아야하기 때문에 반응 시간이 시간으로 단축되었습니다 .
현실적인 사용법 :
모든 프로세스 종료 대기 중 및 실행중인 모든 PID 에 대해 사용자에게 알립니다 .
function anywait_w_status2()
{
while true
do
alive_pids=()
for pid in "$@"
do
kill -0 "$pid" 2>/dev/null \
&& alive_pids+="$pid "
done
if [ ${#alive_pids[@]} -eq 0 ]
then
break
fi
echo "Process(es) still running... ${alive_pids[@]}"
sleep 1
done
echo 'All processes terminated'
}
이 함수는 인수를 통해 PID를 $@
BASH 배열로 가져 옵니다.
프로세스가 종료 될 때 inotifywait를 사용하여 닫히는 파일을 모니터링하십시오. 예 (Linux) :
yourproc >logfile.log & disown
inotifywait -q -e close logfile.log
-e는 대기 할 이벤트를 지정합니다. -q는 종료시에만 최소 출력을 의미합니다. 이 경우 다음과 같습니다.
logfile.log CLOSE_WRITE,CLOSE
단일 대기 명령을 사용하여 여러 프로세스를 기다릴 수 있습니다.
yourproc1 >logfile1.log & disown
yourproc2 >logfile2.log & disown
yourproc3 >logfile3.log & disown
inotifywait -q -e close logfile1.log logfile2.log logfile3.log
inotifywait의 출력 문자열은 어떤 프로세스가 종료되었는지 알려줍니다. 이것은 / proc /의 무언가가 아닌 '실제'파일에서만 작동합니다.
OSX와 같은 시스템에서는 pgrep이 없을 수 있으므로 이름으로 프로세스를 찾을 때이 접근법을 시도 할 수 있습니다.
while ps axg | grep process_name$ > /dev/null; do sleep 1; done
$
프로세스 이름 끝에 있는 기호는 grep이 자체가 아니라 ps 출력의 행 끝과 process_name 만 일치하도록합니다.
/dev/null
, -q
사용해야합니다 grep
. 루프가 잠자는 동안 프로세스의 다른 인스턴스가 시작되어 알 수 없을 것입니다.
-q
내 대답에서 언급했듯이 제안이 유효 하지만 구체적으로 종료 $
수단 grep은 "명령 줄 어딘가"라는 이름과 일치하지 않으며 자체적으로 일치하지 않습니다. 실제로 OSX에서 사용해 보셨습니까?
대한 라우 노는 Palosaari의 솔루션 Timeout in Seconds
Darwin
에 대한 훌륭한 해결책이다 GNU를 가지고 있지 않는 OS UNIX-같은 tail
(이 특정되지 않습니다 Darwin
). 그러나 UNIX와 유사한 운영 체제의 연령에 따라 제공되는 명령 줄은 필요 이상으로 복잡하여 실패 할 수 있습니다.
lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)
하나 이상의 이전 UNIX에서 lsof
인수 +r 1m%s
가 실패합니다 (슈퍼 유저 인 경우에도).
lsof: can't read kernel name list.
는 m%s
출력 포맷 규격이다. 더 간단한 포스트 프로세서는 필요하지 않습니다. 예를 들어 다음 명령은 PID 5959에서 최대 5 초 동안 대기합니다.
lsof -p 5959 +r 1 | awk '/^=/ { if (T++ >= 5) { exit 1 } }'
이 예에서 PID 5959가 5 초가 경과하기 전에 자체 협정을 종료하는 경우 ${?}
입니다 0
. 5 초 후에도 ${?}
돌아 오지 않으면1
그것은 명시한다는 점에서를 지적 가치가있을 수 있습니다 +r 1
의는 1
그 상황에 맞게 변경 될 수 있으므로, (초) 폴링 간격이다.