如何从nohup获取正确的退出码

7

info coreutils 'nohup invocation'中的nohup文档中,它指出:

Exit status:

 125 if `nohup' itself fails, and `POSIXLY_CORRECT' is not set
 126 if COMMAND is found but cannot be invoked
 127 if COMMAND cannot be found
 the exit status of COMMAND otherwise

然而,我从nohup中得到的唯一退出代码是1和0。我有一个在脚本内失败的nohup命令,并且我需要适当地处理异常...根据此文档,我会认为nohup退出代码应该是126。但实际上,它是0。
我正在运行的命令是:nohup perl myscript.pl & 这是因为perl成功退出吗?

1
尝试更简单的测试以查看 nohup 是否提供了文档中记录的值。从 Unix 命令行运行 nohup true; echo $?nohup false; echo $?nohup nonesuch; echo $? 应该会给您一些有效的反馈。祝好运。 - shellter
1
如果在相同的配置(环境等)下运行 perl myscript.pl,那么退出代码是什么?如果您的脚本以 0 退出,则 perl 将以 0 退出。Perl 将传递您的脚本的退出代码。如果 Perl 无法运行脚本(例如文件权限无效),则 Perl 本身将以各种错误退出(例如 13)。 - Jim Stewart
根据这里的一些建议,我已经弄清楚了发生这种情况的原因是nohup正在作为子进程运行(带有&)。当我不使用&调用它时,我得到了正确的退出代码(127)。使用&调用时,我得到了0。是否有任何方法仍然可以获得正确的退出代码并使用&? - pepper
2
这是关于Shell编程的内容;SO是用于提问有关编程的问题的;这个问题非常适合在SO上。 - Jonathan Leffler
1
你当然是对的。而且你注意到了我忽略的 &。好答案。 - Jim Stewart
显示剩余2条评论
2个回答

18

如果您的shell脚本使用以下命令运行进程:

nohup perl myscript.pl &

如果你使用 nohup,你更多或更少地放弃了收集退出状态的机会。如果 shell 成功分叉,则整个命令成功返回 0,如果 shell 未能分叉,则失败返回 1。在 bash 中,您可以等待后台进程死亡并通过 wait 收集其状态:

nohup perl myscript.pl &
oldpid=$!
...do something else or this whole rigmarole is pointless...
wait $oldpid
echo $?

回显的$?通常是指定PID的退出状态(除非指定的PID已经死亡并等待)。

如果您同步运行进程,则可以检测不同的退出状态:

(
nohup perl myscript.pl
echo "PID $! exited with status $?" >&2
) &

现在,您应该能够识别出 nohup 的不同退出状态(例如尝试不同的拼写错误:nohup pearl myscript.pl等)。

请注意,整个子shell在后台运行,但nohup在子shell中同步运行。


@arganzheng:它将等待后台进程(例如示例中的nohup perl myscript.pl)终止。当我在Bash中运行以下代码时,它的行为符合我的预期,在大约5秒后终止:sleep 5 & oldpid=$!; echo oldpid=$!; sleep 3; echo Awake; wait $oldpid; echo $?例如,它会产生:oldpid=40222,然后是Awake,最后是0 - Jonathan Leffler
@JonathanLeffler 这里的...做些其他事情或者整个繁琐的过程都没有意义...是什么意思?我能直接使用代码而不需要...做某些事情部分吗? - user3901666
nohup sleep 10 && (exit 1); echo "exited with status $?" & 看起来对我有效。 - Prashant Kalkar
@PrashantKalkar:你得到了什么结果?我在休眠10秒后得到了 exited with status 1,这正是我预期的结果。但我不清楚这与问题和答案的讨论有何关联。 - Jonathan Leffler
@JonathanLeffler 对不起,我并不是在评论中试图回答问题。只是想分享一下当我在后台运行进程时仍然捕获退出代码的方法。 - Prashant Kalkar

3

我的理解是,问题是如何在nohup运行时获取命令状态。根据我的经验,即使命令立即失败,也很少有机会获得COMMAND退出状态。大多数情况下,您只能获得“nohup COMMAND&”的退出状态,除非您等待或像Jonathan提到的那样同步。要在nohup之后立即检查COMMAND状态,我使用以下命令:

  pid=`ps -eo pid,cmd | awk '/COMMAND/ {print $1}'`
  if [ -z $pid ]; then
     echo "COMMAND失败"
  else
     echo "COMMAND正在nohup中运行"
  fi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接