我正在尝试编写一个 Linux shell 脚本(最好是 bash),
应该命名为 detach.sh
,以安全地从终端分离程序,
这样:
调用:
./detach.sh prog [arg1 arg2 ...]
。exec
是否可用,例如。通过在你的 shell 中运行它:exec ./detach.sh prog [arg1 arg2 ...]
使用适当的引号(主要处理包含空格的参数)。
丢弃输出(因为不需要)。
不使用
screen
、tmux
等。 (与 4 相同的原因,而且不需要额外的保姆过程)。(合理地)使用可移植的命令和程序, 并且没有像
start-stop-daemon
这样的发行版特定的东西。
我想到了几种方法(shebang lines #!/bin/bash
忽略
为了简洁起见):
nohup
:nohup "$@" >& /dev/null &
否认
:"$@" >& /dev/null & disown
setsid
:setsid "$@" >& /dev/null &
使用子 shell:
("$@" >& /dev/null &)
nohup
/setsid
结合子shell:# Or alternatively: # (nohup "$@" >& /dev/null &) (setsid "$@" >& /dev/null &)
当使用gedit
作为测试程序时(替换"$@"
部分),
上述所有方法都可以满足条件1,
但条件 2 可以不满足。
但是,如果将任意程序(但不是内置的 shell)附加到脚本 5,
所有条件似乎都已满足(至少在 gedit
案例中对我而言)。
例如:
(setsid "$@" >& /dev/null &)
# Not just `true' because it is also a shell builtin.
/bin/true
任何对上述现象的解释有想法的人 以及如何正确执行要求?
编辑:
对于条件 2,我的意思是程序应该与终端分离,但否则将照常运行。例如,对于 gedit
情况,如果 gedit
在脚本进程结束后立即退出,则条件失败。
最佳答案
经过仔细调查,揭示了这些以前未注意到的事实:
脚本 3 和 5(仅限
setsid
变体)将 如果将/bin/true
附加到脚本,则满足所有条件。这些脚本在事实 1 中进行了修改,如果
/bin/true
替换为for i in {0..9999};做 :;完成
。
因此我们可以得出结论:
(来自事实 1)
不需要多级分离(如脚本 5 中所示), 关键是使用正确的实用程序 (
setsid
)。(来自事实 2)
bash 退出之前的适当延迟对于脚本的成功是必要的。 (调用外部程序
/bin/true
会消耗一些时间, 就像纯 bash 时间消费者for i in {0..9999};做 :;完成
。)我没有看过源码,但我猜一个可能的解释 是 bash 可能会在
setsid
完成配置执行之前退出 如果未应用适当的延迟,则程序运行的环境。
最后,一个最优解应该是
#!/bin/bash
setsid "$@" >& /dev/null &
sleep 0.01
编辑 1:
已经解释了延迟的必要性here .非常感谢@wilx!
编辑 2:
(感谢@MateiDavid)我们似乎忘记了重定向标准输入,更好的方法是:
#!/bin/bash
setsid "$@" >& /dev/null < /dev/null &
关于bash - 编写 Linux shell 脚本以安全地从终端分离程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10247721/