백그라운드에서 4개의 프로세스를 병렬로 시작한 다음 해당 상태를 폴링해야 하는 KSH 스크립트에 문제가 있습니다.
간단히 말해서, 이 4가지 프로세스를 순차적으로 실행하는 것은 시간이 꽤 소요되는데, 병렬로 실행하면 시간을 많이 절약할 수 있다고 생각합니다. 이론적으로는 구현하기가 어렵지 않다고 생각하여 아래 코드를 작성했습니다. 각 프로세스는 백그라운드에서 시작되고 해당 pid는 변수에 저장됩니다.
모든 프로세스가 시작되면 다음을 사용하여 각 PID를 확인하고 싶습니다.ps -p $PID프로세스가 아직 존재하는지 확인하세요. 그렇지 않은 경우 루프를 종료하고 다음 루프로 이동합니다. 이 작업은 순서대로 수행됩니다.
프로세스를 최대한 최적화하고 싶다는 사실은 제쳐두고, 이 시점에서 프로세스가 사라지는 매우 지속적인 문제에 직면하게 됩니다. 백그라운드에서 프로세스를 시작하고 해당 pid가 변수에 할당되지만(해당 변수가 채워지는 것을 확인할 수 있음) 동일한 PID를 사용한 후 직접 프로세스를 조회하면 아무것도 반환되지 않습니다. 프로세스가 사라집니다.
이는 4개 프로세스 모두에서 발생합니다. 백그라운드에서 실행하지 않아도(앰퍼샌드를 제거하면) 명령이 제대로 작동합니다. 따라서 문제는 필요한 명령을 백그라운드 프로세스로 실행하는 것과 관련된 것 같습니다.
예를 들어, 내가 실행하면수면 180뒤에서 비슷한 방식으로 PID를 저장하고 동일한 방식으로 쿼리하면 원하는 결과를 얻을 수 있습니다.
따라서 포그라운드에서 프로세스를 실행하고 백그라운드에서 다른 프로세스를 실행할 수 있습니다. 나에게는 불분명한 어떤 이유로 인해 이러한 특정 프로세스를 백그라운드에서 실행할 수 없다는 것입니다. 실행하려는 명령의 모든 출력을 로그 파일에 기록하면 빈 로그 파일이 반환됩니다. 사용세트-x이상한 점을 보여주지는 않았습니다.
아래 게시된 스크립트는 많은 검사를 수행한 다음 많은 기능이 포함된 세 번째 스크립트를 호출하는 다른 스크립트를 호출합니다. 지금까지 스크립트에서 그러한 문제가 발생할 수 있음을 나타내는 아무것도 찾을 수 없으며 쉘의 백그라운드에서 직접 아래에서 시작하는 동일한 명령줄을 실행했는데 정상적으로 시작되었습니다.
따라서 기본적으로 상황은 다음과 같습니다.
- 이 스크립트의 전경에서 필요한 명령을 실행하면 정상적으로 작동합니다.
- 이 스크립트 내에서 백그라운드로 다른 명령(예: sleep)을 실행하면 잘 작동합니다.
- 백그라운드의 셸에서 직접 필요한 명령을 실행하면 정상적으로 작동합니다.
- 이 스크립트 내에서 백그라운드로 필요한 명령을 실행하면 아무런 효과가 없으며 식별 가능한 오류가 발생하지 않습니다.
나는 이 시점에서 이 문제에 대해 완전히 넋을 잃었습니다. 누군가 나에게 이것이 왜 작동하지 않는지에 대한 막연한 생각을 줄 수 있습니까?
checkStatus(){
LV_PID=${1}
LV_COUNTER=0
while (( ${LV_COUNTER} == 0 ))
do
ps -p ${LV_PID}
if (( $? == 0 )); then
##continue loop
elif (( $? == 1 )); then
LV_COUNTER=1
fi
done
}
#################################################
# Function: intendedFunction #
#################################################
intendedFunction(){
nohup examplecommand.ksh -t exampletarget1 2> $HOME/log1.txt 1> /dev/null &
export pid1=$!
nohup examplecommand.ksh -t exampletarget2 2> $HOME/log2.txt 1> /dev/null &
export pid2=$!
nohup examplecommand.ksh -t exampletarget3 2> $HOME/log3.txt 1> /dev/null &
export pid3=$!
nohup examplecommand.ksh -t exampletarget4 2> $HOME/log4.txt 1> /dev/null &
export pid4=$!
echo "pid1 is $pid1"
echo "pid2 is $pid2"
echo "pid3 is $pid3"
echo "pid4 is $pid4"
checkStatus $pid1
if (( `wc -l < log1.txt` == 0 ))
then
#success
else
#error
fi
checkStatus $pid2
if (( `wc -l < log2.txt` == 0 ))
then
#success
else
#error
fi
checkStatus $pid3
if (( `wc -l < log3.txt` == 0 ))
then
#success
else
#error
fi
checkStatus $pid4
if (( `wc -l < log4.txt` == 0 ))
#success
else
#error
fi
답변1
명령 이름에 오타가 있거나 경로에서 examplecommand.ksh를 찾을 수 없는 것과 같은 기본적인 문제가 있는 것 같습니다.
pid 변수는 실제로 수행된 작업 여부에 관계없이 nohup에 의해 채워지며, nohup이 명령 실행에 실패하면 즉시 종료됩니다. 게다가 nohup은 완전히 실패하더라도 불쾌한 오류 메시지로 사용자를 괴롭히지 않습니다.
[ksh]$ nohup nonexistent.ksh &
[1] 32938
appending output to nohup.out
[ksh]$ echo $!
32938
[1] + Done(127) nohup nonexistent.ksh &
추신. xargs를 살펴보고 싶을 수도 있습니다. 에서와 같이
[ksh]$ seq 1 4 | xargs -n 1 -P 4 -I PART echo "part PART finished"
part 2 finished
part 1 finished
part 3 finished
part 4 finished