可以检查它是否在调用时被回调的Shell脚本

时间:2010-08-31 14:30:55

标签: bash shell zsh

我编写了一个依赖于其他服务器响应的脚本(使用wget来提取数据),我希望它总能毫无疑问地在后台运行。我知道一个解决方案就是编写一个包装脚本,用“&”调用我的脚本附上,但我想避免那种混乱。

bash(或zsh)脚本是否有办法确定是否使用say ./foo.sh&来调用它,如果没有,则退出并重新启动它本身?

全部谢谢!

5 个答案:

答案 0 :(得分:7)

后台进程的定义(我认为)是它有一个控制终端,但它不是该终端的前台进程组的一部分。我不认为任何shell,甚至zsh,都可以通过内置函数访问该信息。

在Linux(可能还有其他unices)上,STAT ps列包含+,当进程是其终端的前台进程组的一部分时。因此,对您的问题的字面答案是您可以将脚本的内容放在main函数中并使用以下函数调用它:

case $(ps -o stat= -p $$) in
  *+*) main "$@" &;;
  *) main "$@";;
esac

但你还是可以运行main "$@" &。在Unix上,fork很便宜。

但是,我强烈建议不要做你的建议。这使得某人无法运行您的脚本并在之后执行其他操作 - 人们希望能够编写your_script; my_postprocessingyour_script && my_postprocessing,但分支脚本的主要任务会使这变得不可能。考虑到在调用脚本时,增益偶尔会保存一个字符,所以不值得以这种方式使脚本显得不那么有用。

如果你的意思是让脚本在后台运行以便用户可以关闭他的终端,那么你需要做更多的工作 - 你需要 daemonize 这个脚本,不仅包括后台处理,还包括关闭所有打开终端的文件描述符,使该过程成为会话领导者等等。我认为这需要将您的脚本拆分为守护程序包装脚本和主脚本。但是,除非明确停止,否则通常会对永远不会终止的程序执行守护程序,这不是您描述的行为。

答案 1 :(得分:2)

我不知道,怎么做,但你可以在父脚本中设置变量并在子项中检查它:

if [[ -z "$_BACKGROUNDED" ]] ; then
    _BACKGROUNDED=1 exec $0 $@ & exit
fi
# Put code here

在bash和zsh中都可以使用。

答案 2 :(得分:1)

如果你在后台,“tty”命令会说“不是tty”,或者如果你在前台,则给出控制终端名称(例如/ dev / pts / 1)。一个简单的说法。

答案 3 :(得分:0)

请记住,您不能(或不建议)编辑正在运行的脚本。 This question and the answers提供解决方法。

答案 4 :(得分:-2)

我很久以前不写shell脚本,但我可以给你一个很好的主意(我希望)。您可以检查$$的值(这是进程的PID)并与命令“jobs -l”的输出进行比较。最后一个命令将返回所有后台进程(作业)的PID,如果$$的值包含在“jobs -l”的结果中,则表示当前脚本在后台运行。