![ksh 脚本中的后台进程在启动后消失](https://linux22.com/image/81181/ksh%20%E8%84%9A%E6%9C%AC%E4%B8%AD%E7%9A%84%E5%90%8E%E5%8F%B0%E8%BF%9B%E7%A8%8B%E5%9C%A8%E5%90%AF%E5%8A%A8%E5%90%8E%E6%B6%88%E5%A4%B1.png)
我遇到了一个 KSH 脚本问题,该脚本应该在后台并行启动四个进程,然后轮询它们的状态。
简而言之,顺序运行这四个进程会花费相当多的时间,我认为通过并行运行它们可以节省大量时间。理论上我不认为这很难实现,我已经编写了下面的代码。每个进程都在后台启动,其 pid 存储在变量中。
一旦所有进程启动,我想使用检查每个 pidps -p $PID查看该进程是否仍然存在。如果没有,它将退出循环并转到下一个循环。这将按顺序完成。
抛开我仍然想尽可能优化流程不谈,此刻我遇到了一个非常持久的问题:我的流程消失了。我在后台启动一个进程,它的 pid 被分配给变量(并且我可以验证相应的变量是否已填充),但如果在使用相同的 PID 后直接查找进程,则不会返回任何内容。进程就这样消失了。
所有 4 个进程都会发生这种情况。不在后台运行它们(因此删除&符号)不会给我带来任何问题;命令工作正常。因此,问题似乎特定于将所需的命令作为后台进程运行。
例如,如果我运行睡眠 180在后台并以类似的方式存储其 PID 并以相同的方式查询它,我确实得到了所需的结果。
因此,我能够在前台运行进程,并且能够在后台运行其他进程。只是由于某种我不清楚的原因,我无法在后台运行这些特定进程。将我想要运行的命令的所有输出写入日志文件会返回空日志文件。使用设置-x没有表现出任何奇怪的东西。
下面发布的脚本调用一个不同的脚本,该脚本执行大量检查,然后调用包含大量函数的第三个脚本。到目前为止,我在脚本中绝对找不到任何东西表明它会造成这样的麻烦,并且我直接在 shell 的后台运行与下面启动的完全相同的命令行,它正常启动。
所以基本上情况是这样的:
- 在这个脚本的前台运行所需的命令工作正常。
- 在此脚本中在后台运行另一个命令(例如 sleep)效果很好。
- 直接在 shell 中在后台运行所需的命令可以正常工作。
- 在此脚本中在后台运行所需的命令不起作用,并且不会产生可识别的错误。
此时我对这个问题完全迷失了。有人能给我至少一个模糊的想法为什么这行不通吗?
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