如何从bash脚本中获取进程ID和退出代码?

Bob*_*b B 32 bash shell

我需要一个执行以下操作的bash脚本:

  • 启动后台进程,将所有输出定向到文件
  • 将进程的退出代码写入文件
  • 返回进程的pid(立即返回,而不是进程退出时).
  • 该脚本必须退出

我可以得到pid而不是退出代码:

$ executable >>$log 2>&1 &
pid=`jobs -p`
Run Code Online (Sandbox Code Playgroud)

或者,我可以捕获退出代码,但不能捕获pid:

$ executable >>$log;
# blocked on previous line until process exits
echo $0 >>$log;
Run Code Online (Sandbox Code Playgroud)

我怎么能同时做所有这些?

Wil*_*ell 56

pid在$!,不需要运行jobs.返回状态由wait以下方式返回:

$executable >> $log 2>&1 &
pid=$!
wait $!
echo $?  # return status of $executable
Run Code Online (Sandbox Code Playgroud)

编辑1

如果我理解注释中所述的附加要求,并且您希望脚本立即返回(无需等待命令完成),那么将无法让初始脚本写入命令的退出状态.但是,一旦孩子完成,让中间人写出退出状态就很容易了.就像是:

sh -c "$executable"' & echo pid=$! > pidfile; wait $!; echo $? > exit-status' &
Run Code Online (Sandbox Code Playgroud)

应该管用.

编辑2

正如评论中指出的那样,该解决方案具有竞争条件:主脚本在写入pidfile之前终止.OP通过进行轮询睡眠循环来解决这个问题,这是一种令人厌恶的事情,我担心我会在晚上睡觉时遇到麻烦,因为我知道我可能有这种讽刺的动机.IMO,正确的做法是等到孩子完成.由于这是不可接受的,这里有一个解决方案,阻止读取直到pid文件存在而不是循环睡眠:

{ sh -c "$executable > $log 2>&1 &"'
echo $! > pidfile
echo   # Alert parent that the pidfile has been written
wait $!
echo $? > exit-status
' & } | read
Run Code Online (Sandbox Code Playgroud)

  • 如果您希望脚本在子项完成之前退出,则无法在不调用某种时间异常的情况下编写子项的退出代码. (2认同)