ksh 脚本中的后台进程在启动后消失

ksh 脚本中的后台进程在启动后消失

我遇到了一个 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

相关内容