스크립트를 종료하기 전에 백그라운드 프로세스가 완료되기를 기다리는 중
스크립트 (TCL / Bash)를 종료하기 전에 모든 백그라운드 프로세스가 실행을 완료했는지 확인하려면 어떻게해야합니까?
내 모든 백그라운드 프로세스 pid를 pidfile에 쓸 생각이었습니다. 그리고 끝에서 pgrep pidfile을 사용하여 종료하기 전에 프로세스가 아직 실행 중인지 확인합니다.
이 작업을 수행하는 더 간단한 방법이 있습니까? 이를 수행하는 TCL 특정 방법이 있습니까?
작업이 완료 될 때까지 기다리려면을 사용하십시오 wait
. 이렇게하면 모든 백그라운드 작업이 완료 될 때까지 셸이 대기합니다. 그러나 작업이 스스로 데몬 화되면 더 이상 셸의 자식이 아니며 기다림은 효과가 없습니다 (셸에 관한 한 자식은 이미 완료되었습니다. 실제로 프로세스가 스스로 데몬 화하면 그렇게합니다. 역할을 상속하는 새 프로세스를 종료하고 생성하여).
#!/bin/sh
{ sleep 5; echo waking up after 5 seconds; } &
{ sleep 1; echo waking up after 1 second; } &
wait
echo all jobs are done!
kill -0
특정 pid가 실행 중인지 여부를 확인하는 데 사용할 수 있습니다 .
pwd pid
라는 파일 에 숫자 목록이 있다고 가정합니다.pid
while true;
do
if [ -s pid ] ; then
for pid in `cat pid`
do
echo "Checking the $pid"
kill -0 "$pid" 2>/dev/null || sed -i "/^$pid$/d" pid
done
else
echo "All your process completed" ## Do what you want here... here all your pids are in finished stated
break
fi
done
경고 : 긴 스크립트가 앞에 있습니다.
얼마 전에 비슷한 문제에 직면했습니다. Tcl 스크립트에서 여러 프로세스를 시작한 다음 모든 프로세스가 완료 될 때까지 기다립니다. 다음은이 문제를 해결하기 위해 작성한 데모 스크립트입니다.
main.tcl
#!/usr/bin/env tclsh
# Launches many processes and wait for them to finish.
# This script will works on systems that has the ps command such as
# BSD, Linux, and OS X
package require Tclx; # For process-management utilities
proc updatePidList {stat} {
global pidList
global allFinished
# Parse the process ID of the just-finished process
lassign $stat processId howProcessEnded exitCode
# Remove this process ID from the list of process IDs
set pidList [lindex [intersect3 $pidList $processId] 0]
set processCount [llength $pidList]
# Occasionally, a child process quits but the signal was lost. This
# block of code will go through the list of remaining process IDs
# and remove those that has finished
set updatedPidList {}
foreach pid $pidList {
if {![catch {exec ps $pid} errmsg]} {
lappend updatedPidList $pid
}
}
set pidList $updatedPidList
# Show the remaining processes
if {$processCount > 0} {
puts "Waiting for [llength $pidList] processes"
} else {
set allFinished 1
puts "All finished"
}
}
# A signal handler that gets called when a child process finished.
# This handler needs to exit quickly, so it delegates the real works to
# the proc updatePidList
proc childTerminated {} {
# Restart the handler
signal -restart trap SIGCHLD childTerminated
# Update the list of process IDs
while {![catch {wait -nohang} stat] && $stat ne {}} {
after idle [list updatePidList $stat]
}
}
#
# Main starts here
#
puts "Main begins"
set NUMBER_OF_PROCESSES_TO_LAUNCH 10
set pidList {}
set allFinished 0
# When a child process exits, call proc childTerminated
signal -restart trap SIGCHLD childTerminated
# Spawn many processes
for {set i 0} {$i < $NUMBER_OF_PROCESSES_TO_LAUNCH} {incr i} {
set childId [exec tclsh child.tcl $i &]
puts "child #$i, pid=$childId"
lappend pidList $childId
after 1000
}
# Do some processing
puts "list of processes: $pidList"
puts "Waiting for child processes to finish"
# Do some more processing if required
# After all done, wait for all to finish before exiting
vwait allFinished
puts "Main ends"
child.tcl
#!/usr/bin/env tclsh
# child script: simulate some lengthy operations
proc randomInteger {min max} {
return [expr int(rand() * ($max - $min + 1) * 1000 + $min)]
}
set duration [randomInteger 10 30]
puts " child #$argv runs for $duration miliseconds"
after $duration
puts " child #$argv ends"
main.tcl 실행을위한 샘플 출력
Main begins
child #0, pid=64525
child #0 runs for 17466 miliseconds
child #1, pid=64526
child #1 runs for 14181 miliseconds
child #2, pid=64527
child #2 runs for 10856 miliseconds
child #3, pid=64528
child #3 runs for 7464 miliseconds
child #4, pid=64529
child #4 runs for 4034 miliseconds
child #5, pid=64531
child #5 runs for 1068 miliseconds
child #6, pid=64532
child #6 runs for 18571 miliseconds
child #5 ends
child #7, pid=64534
child #7 runs for 15374 miliseconds
child #8, pid=64535
child #8 runs for 11996 miliseconds
child #4 ends
child #9, pid=64536
child #9 runs for 8694 miliseconds
list of processes: 64525 64526 64527 64528 64529 64531 64532 64534 64535 64536
Waiting for child processes to finish
Waiting for 8 processes
Waiting for 8 processes
child #3 ends
Waiting for 7 processes
child #2 ends
Waiting for 6 processes
child #1 ends
Waiting for 5 processes
child #0 ends
Waiting for 4 processes
child #9 ends
Waiting for 3 processes
child #8 ends
Waiting for 2 processes
child #7 ends
Waiting for 1 processes
child #6 ends
All finished
Main ends
GNU parallel
및xargs
스크립트를 간단하게, 또한 스레드의 최대 수 (스레드 풀)을 제어 할 수있는 두 개의 도구입니다. 예 :
seq 10 | xargs -P4 -I'{}' echo '{}'
또는:
seq 10 | parallel -j4 echo '{}'
'programing' 카테고리의 다른 글
Visual Studio / C # : Nuget 원격 서버에 연결할 수 없음 (0) | 2021.01.17 |
---|---|
Dalvik 가상 머신 인스턴스가 각 애플리케이션에 대해 생성됩니까? (0) | 2021.01.17 |
jQuery Ajax 요청을 유발하는 Javascript를 찾는 방법은 무엇입니까? (0) | 2021.01.17 |
RecyclerView에서 선택한 위치를 어떻게 얻습니까? (0) | 2021.01.17 |
속성이 '{}'유형에 없습니다. (0) | 2021.01.17 |