我编写了一个依赖于其他服务器响应的脚本(使用wget来提取数据),我希望它总能毫无疑问地在后台运行。我知道一个解决方案就是编写一个包装脚本,用“&”调用我的脚本附上,但我想避免那种混乱。
bash(或zsh)脚本是否有办法确定是否使用say ./foo.sh&来调用它,如果没有,则退出并重新启动它本身?
全部谢谢!
答案 0 :(得分:7)
后台进程的定义(我认为)是它有一个控制终端,但它不是该终端的前台进程组的一部分。我不认为任何shell,甚至zsh,都可以通过内置函数访问该信息。
在Linux(可能还有其他unices)上,STAT
ps
列包含+
,当进程是其终端的前台进程组的一部分时。因此,对您的问题的字面答案是您可以将脚本的内容放在main
函数中并使用以下函数调用它:
case $(ps -o stat= -p $$) in
*+*) main "$@" &;;
*) main "$@";;
esac
但你还是可以运行main "$@" &
。在Unix上,fork很便宜。
但是,我强烈建议不要做你的建议。这使得某人无法运行您的脚本并在之后执行其他操作 - 人们希望能够编写your_script; my_postprocessing
或your_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”的结果中,则表示当前脚本在后台运行。