Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.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 编写Linux shell脚本以安全地从终端分离程序_Bash_Shell_Scripting - Fatal编程技术网

Bash 编写Linux shell脚本以安全地从终端分离程序

Bash 编写Linux shell脚本以安全地从终端分离程序,bash,shell,scripting,Bash,Shell,Scripting,我正在尝试编写一个Linux shell脚本(最好是bash), 假定命名为detach.sh,用于安全地从终端分离程序, 以便: 调用:/detach.sh prog[arg1 arg2…] exec-可执行,例如,通过在shell中运行此命令: exec ./detach.sh prog [arg1 arg2 ...] 正确引用(主要处理包含空格的参数) 丢弃输出(因为它们是不需要的) 不使用屏幕,tmux等。 (与4相同的原因,再加上不需要额外的保姆程序) 使用(合理)可移植的命令和程

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

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

  • exec
    -可执行,例如,通过在shell中运行此命令:

    exec ./detach.sh prog [arg1 arg2 ...]
    
  • 正确引用(主要处理包含空格的参数)

  • 丢弃输出(因为它们是不需要的)

  • 不使用
    屏幕
    tmux
    等。 (与4相同的原因,再加上不需要额外的保姆程序)

  • 使用(合理)可移植的命令和程序, 没有类似于特定于发行版的启动-停止守护程序的东西

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

  • nohup

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

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

    setsid "$@" >& /dev/null &
    
  • 使用子shell:

    ("$@" >& /dev/null &)
    
    # Or alternatively:
    # (nohup "$@" >& /dev/null &)
    (setsid "$@" >& /dev/null &)
    
  • nohup
    /
    setsid
    与子shell组合:

    ("$@" >& /dev/null &)
    
    # Or alternatively:
    # (nohup "$@" >& /dev/null &)
    (setsid "$@" >& /dev/null &)
    
  • 当使用
    gedit
    作为测试程序时(替换
    “$@”
    部分), 上述所有方法均可满足条件1, 但条件2不能满足任何条件

    但是,如果脚本5中附加了任意程序(但不是shell内置程序), 所有条件似乎都得到了满足(至少对我来说,在
    gedit
    案例中是这样)。 例如:

    (setsid "$@" >& /dev/null &)
    # Not just `true' because it is also a shell builtin.
    /bin/true
    
    有人对上述现象的解释有想法吗 如何正确实施这些要求

    编辑:


    对于条件2,我的意思是程序应该与终端分离,但在其他情况下运行正常。例如,在
    gedit
    情况下,如果
    gedit
    在脚本进程结束后立即退出,则该条件将失败。

    您正在尝试创建一个UNIX守护进程(即,一个没有控制终端的进程,它是自己的领导者)。
    setsid
    命令应该为您执行此操作,但您有责任关闭在要放弃的终端上打开的所有文件描述符。这可以通过将它们重定向到
    /dev/null
    或使用shell的语法关闭文件描述符(例如,
    2>&-
    0)来实现。经过更仔细的调查,发现了这些以前未被注意到的事实:

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

  • 这些脚本,如事实1中所修改的,如果
    /bin/true
    被{0..9999};do:;done
  • 中的i替换为

    因此,我们可以得出结论:

    • (来自事实1)

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

    • (来自事实2)

      bash退出之前的适当延迟对于脚本的成功是必要的。 (调用外部程序
      /bin/true
      需要花费一些时间, 就像{0..9999}中i的纯bash时间消费者
      ;do:;done

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

    最后,一个最优的解决方案应该是

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

    已经解释了延迟的必要性。非常感谢@wilx

    编辑2

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

    #!/bin/bash
    setsid "$@" >& /dev/null < /dev/null &
    
    !/bin/bash
    setsid“$@”>&/dev/null
    我认为您需要执行
    setsid“$@”>和/dev/null&wait
    ,以便在
    setsid
    设法分叉孩子之前,控制终端不会消失

    更新

    在我看来,这既适用于命令行,也适用于
    -c
    的参数:

    (setsid tail -F /var/log/messages >& /dev/null) & disown
    

    假设您拥有shebang,那么解决方案5在哪些方面不满足要求2?或者,近似地说,解决方案5不满足要求2意味着什么?当
    gedit
    在后台运行时,您预计会发生什么情况?因为
    gedit
    是一个交互式运行的编辑器,但后台进程是可用的,或多或少,根据定义,一些在没有用户交互的情况下运行的东西,可能问题在于您选择的测试程序。处理基于X11的程序与处理编译器之类的程序有很大的不同。当您在后台运行
    gedit
    时,您看到了什么情况?很抱歉对我的想法进行了不正确的解释。我的意思是在说“背景”时使用“分离”。请查看此问题的更新版本。感谢您的帮助:)字符串“shebang lines
    #/bin/bash
    忽略了为StackExchange的服务器节省磁盘空间“占用的磁盘空间比实际的Shebang多。@Pumbaa80:也许原因应该是“为了简洁”:)谢谢,但我认为脚本3和5(请参阅我的问题)我已经做了这两件事,但仍然没有解决问题。此外,调用
    /bin/true
    左右解决问题的现象的原因仍然无法解释。非常感谢:)我更新了我自己的答案以反映您的建议。解释非常合理。但是
    bash-c'setsid sleep 1>和/dev/null&wait'
    以某种方式阻塞(虽然它在interactive
    bash
    中没有阻塞),因此目前还不能解决问题。但是
    $exec bash-c'(setId geany>&/dev/null)&disown'
    失败;我认为最好看看为什么
    setId
    'd进程的PID与
    setId
    不同