Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 可以在调用时检查其是否是后台的Shell脚本_Bash_Shell_Zsh - Fatal编程技术网

Bash 可以在调用时检查其是否是后台的Shell脚本

Bash 可以在调用时检查其是否是后台的Shell脚本,bash,shell,zsh,Bash,Shell,Zsh,我已经编写了一个依赖于其他服务器响应的脚本(使用wget提取数据),我希望它始终在后台运行。我知道一种解决方案是只编写一个包装器脚本,它将调用我的脚本并附加一个“&”,但我希望避免这种混乱 bash(或zsh)脚本是否有办法确定是否使用say./foo.sh&调用它,如果没有,则退出并重新启动它本身 谢谢大家 我不知道该怎么做,但您可以在父脚本中设置变量并在子脚本中检查它: if [[ -z "$_BACKGROUNDED" ]] ; then _BACKGROUND

我已经编写了一个依赖于其他服务器响应的脚本(使用wget提取数据),我希望它始终在后台运行。我知道一种解决方案是只编写一个包装器脚本,它将调用我的脚本并附加一个“&”,但我希望避免这种混乱

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


谢谢大家

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

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

可以在bash和zsh中使用。

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

后台进程的定义(我认为)它有一个控制终端,但不属于该终端的前台进程组。我不认为任何shell,即使是zsh,都可以通过内置的方式访问这些信息

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

case $(ps -o stat= -p $$) in
  *+*) main "$@" &;;
  *) main "$@";;
esac
但您还是可以运行
main“$@”和
。在Unix上,fork很便宜

然而,我强烈建议不要照你的建议去做。这使得有人不可能运行您的脚本并在之后执行其他操作-人们希望能够编写
您的_脚本;my_后处理
您的脚本和my_后处理
,但将脚本的主要任务分成两部分是不可能的。考虑到在调用脚本时偶尔会节省一个字符,因此不值得以这种方式显著降低脚本的可用性


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

请记住,您不能(或不建议)编辑正在运行的脚本。给出解决方法。

如果您在后台,“tty”命令会显示“notatty”,如果您在前台,则会给出控制终端名称(例如/dev/pts/1)。一种简单的判断方法。

jobs-l
无法访问父进程的作业列表,请检查
zsh-c'jobs-l的输出;回声$$;sleep 1s'&
:除了
$
,它什么也不回显。我编写了一个小shell脚本来测试我所说的,我还编写了jobs-l和echo$$。当我在fg中运行脚本时,没有&当然是jobs-l没有返回任何内容,但是当我在bg中运行脚本时,它返回与$$相同的内容。。。我正在使用bash,您如何运行脚本?我在bash和zsh中都没有看到这种行为。我将接受这个答案,它似乎做了我想做的事情,除了在您的解决方案中,“endif”应该是“fi”;-)非常感谢。额外的思考:我意识到一个挑剔的人可能会争辩说,即使在调用时以背景为基础,这个snipplet也会重新启动脚本,但我不需要额外的检查复杂性。请注意,
exec$0$@
会把您的参数弄得一团糟。引用必须是安全的:
exec“$0”“$@”
——否则您会得到
/yourprogram“argument one”或“argument two”
,与
/yourprogram“argument”“one”“argument”“two”运行相同的
——这是在我们开始讨论通配符之前。@CharlesDuffy抱歉,当时对zsh太习惯了,但我不知道有一些角落的案子。由于您所述的原因(假设默认的zsh选项),您不需要在zsh中使用额外的引号,除了为了让每个人的生活更加困难,不引用
$@
将删除所有等于空字符串且不引用
$0
的参数,如果
$0
扩展为空字符串,则它将起到不存在的作用。也就是说,没有通配符、空格或其他问题,但由于字符串为空,您仍然需要引用。嗨,Gilles,感谢您的详细回复。您提供的解决方案与ZyX配合使用,但我接受了他的解决方案,因为它更独立,不依赖于ps或任何分支。作为记录,该脚本仅为我自己编写,不会被其他用户触及,并且位于/etc/init.d中,因此不会有终端关闭。Thank=)+1我的情况似乎不是这样:调用
tty
的shell脚本为我返回一个终端,而不管我是在前台调用脚本还是在脚本末尾添加
&