本文介绍了编写 Linux shell 脚本以安全地从终端分离程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个 Linux shell 脚本(最好是 bash),应该命名为 detach.sh,以安全地从终端分离程序,使得:

I'm trying to write a Linux shell script (preferably bash),supposedly named detach.sh, to safely detach programs from a terminal,such that:

  1. 调用:./detach.sh prog [arg1 arg2 ...].

exec-able,例如.通过在你的 shell 中运行它:

Is exec-able, eg. by running this in your shell:

exec ./detach.sh prog [arg1 arg2 ...]

  • 适当引用(主要处理包含空格的参数).

  • With proper quoting (mainly handling of arguments containing whitespaces).

    丢弃输出(因为它们不需要).

    Discards the outputs (since they are unneeded).

    不使用screentmux等.(与 4 的原因相同,而且不需要额外的保姆过程).

    Does not use screen, tmux, etc.(same reason with 4, plus no need for an extra babysitting process).

    使用(合理地)可移植的命令和程序,没有像 start-stop-daemon 这样的发行版特定的东西.

    Uses (reasonably) portable commands and programs,and no things like start-stop-daemon which is quite distro-specific.

    我想了几种方法(shebang行#!/bin/bash忽略为简洁起见):

    I have thought of several ways (shebang lines #!/bin/bash neglectedfor the sake of briefness):

    1. nohup:

    nohup "$@" >& /dev/null &
    

  • 否认:

    "$@" >& /dev/null &
    disown
    

  • setsid:

    setsid "$@" >& /dev/null &
    

  • 使用子shell:

  • Using a subshell:

    ("$@" >& /dev/null &)
    

  • nohup/setsid 结合子shell:

  • nohup/setsid combined with subshell:

    # Or alternatively:
    # (nohup "$@" >& /dev/null &)
    (setsid "$@" >& /dev/null &)
    

  • 当使用gedit作为测试程序时(替换"$@"部分),上述所有方法都可以满足条件1,但条件 2 可以不满足.

    When using gedit as the test program (substituting the "$@" part),condition 1 can be satisfied with all the above methods,but condition 2 can be satisfied with none.

    但是,如果将任意程序(但不是内置的 shell)附加到脚本 5,所有条件似乎都得到满足(至少在 gedit 案例中对我而言).例如:

    However, if an arbitrary program (but not a shell builtin) is appended to script 5,all the conditions seem to be satisfied (at least for me in the gedit case).For example:

    (setsid "$@" >& /dev/null &)
    # Not just `true' because it is also a shell builtin.
    /bin/true
    

    任何对上述现象的解释有想法的人以及如何正确执行要求?

    Anyone with an idea about an explanation of the above phenomenonsand how to correctly implement the requirements?

    在条件 2 中,我的意思是程序应该与终端分离,否则照常运行.例如,对于 gedit 情况,如果 gedit 在脚本进程结束后立即退出,则条件失败.

    With condition 2, I mean the program should be detached from the terminal but runs as usual otherwise. For example, with the gedit case, the condition fails if gedit just exits immediately right after the process of the script has ended.

    推荐答案

    经过仔细调查,发现了这些以前未被注意到的事实:

    Upon closer investigation, these previously unnoticed facts were revealed:

    1. 脚本 3 和 5(仅限 setsid 变体)都将如果将 /bin/true 附加到脚本,则满足所有条件.

    1. Both scripts 3 and 5 (the setsid variant only) willsatisfy all the conditions if a /bin/true is appended to the script.

    这些脚本,如在事实 1 中修改的那样,在以下情况下也能正常工作/bin/true 替换为 for i in {0..9999};做 :;完成.

    These scripts, as modified in fact 1, will work as well if/bin/true is replaced with for i in {0..9999}; do :; done.

    因此我们可以得出结论:

    Therefore we can conclude that:

    • (来自事实 1)

    • (From fact 1)

    不需要多级分离(如脚本 5),关键是使用正确的实用程序(setsid).

    Multiple levels of detaching (as in script 5) is unnecessary,and the key is to use the right utility (setsid).

    (来自事实 2)

    bash 退出前适当的延迟是脚本成功所必需的.(调用外部程序/bin/true 需要一些时间,就像纯 bash 时间消费者 for i in {0..9999};做 :;完成.)

    A suitable delay before bash exit is necessary for the success of the script.(Calling external program /bin/true consumes some time,just like the pure-bash time consumer for i in {0..9999}; do :; done.)

    我没有看过源代码,但我想一个可能的解释bash 可能会在 setsid 完成配置执行之前退出程序运行的环境,如果没有应用适当的延迟.

    I have not looked at the source code, but I guess a possible explanationis that bash may exit before setsid finishes configuring the executionenvironment of the program to run, if an appropriate delay is not applied.

    最后,最佳解决方案应该是

    And finally, an optimal solution should be

    #!/bin/bash
    setsid "$@" >& /dev/null &
    sleep 0.01
    

    编辑 1:

    已在此处解释了延迟的必要性.非常感谢@wilx!

    The necessity of a delay has been explained here. Many thanks to @wilx!

    编辑 2:

    (感谢@MateiDavid)我们似乎忘记了重定向标准输入,更好的方法是:

    (Thanks to @MateiDavid) we seem to have forgotten to redirect the standard input, and a better way would be:

    #!/bin/bash
    setsid "$@" >& /dev/null < /dev/null &
    

    这篇关于编写 Linux shell 脚本以安全地从终端分离程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-14 22:07