通过包含nohup的ssh启动远程脚本

starting remote script via ssh containing nohup

我想通过ssh远程启动脚本,如下所示:

1
ssh user@remote.org -t 'cd my/dir && ./myscript data [email protected]'

该脚本可以执行各种操作,直到与nohup对齐:

1
nohup time ./myprog $1 >my.log && mutt -a ${1%.*}/`basename $1` -a ${1%.*}/`basename ${1%.*}`.plt $2 < my.log 2>&1 &

它应该启动程序myprog,将其输出传输到mylog,并发送一封电子邮件,其中包含myprog创建的一些数据文件作为附件,日志作为主体。尽管当脚本到达此行时,ssh输出:

Connection to remote.org closed.

这里有什么问题?

谢谢你的帮助


您的命令在后台运行一系列进程,因此调用脚本将立即退出(或很快退出)。这将导致ssh关闭连接。这反过来将导致SIGHUP发送到连接到-t选项导致创建的终端的任何进程。

您的time ./myprog进程受nohup的保护,因此应该继续运行。但你的mutt不是,这很可能就是问题所在。我建议您将命令行更改为:

1
nohup sh -c"time ./myprog $1 >my.log && mutt -a ${1%.*}/`basename $1` -a ${1%.*}/`basename ${1%.*}`.plt $2 < my.log 2>&1" &

所以整个管道都得到了保护。(如果这不能解决问题,可能需要对文件描述符做些什么-例如,mutt可能在终端不在的情况下有其他问题-或者报价可能需要根据参数进行调整-但现在就试试…)


这个答案可能会有帮助。总之,要达到预期效果,您必须执行以下操作:

  • 重定向远程nohup'ed命令上的所有I/O
  • 告诉本地ssh命令在启动远程进程后立即退出。
  • 引用我之前提到的答案,然后引用维基百科:

    Nohuping backgrounded jobs is for example useful when logged in via SSH, since backgrounded jobs can cause the shell to hang on logout due to a race condition [2]. This problem can also be overcome by redirecting all three I/O streams:

    1
    nohup myprogram > foo.out 2> foo.err < /dev/null &amp;

    更新

    我刚刚在这种模式下取得了成功:

    1
    ssh -f user@host 'sh -c"( (nohup command-to-nohup 2>&1 >output.file </dev/null) & )"'


    在我需要通过ssh远程启动回接脚本的情况下,我设法解决了这个问题,使用类似于这里其他答案的技术,但在某种程度上,我觉得更简单、更干净(至少,它使我的代码更短,而且--我相信--更好看),通过使用stream close重定向语法显式关闭所有三个流(a讨论地点如下:

  • https://unix.stackexchange.com/questions/131801/closing-a-file-descriptor-vs

  • https://unix.stackexchange.com/questions/70963/difference-between-2-dev-null-dev-null-and-dev-null-21

  • http://www.tldp.org/ldp/abs/html/io redirection.html cfd

  • https://www.gnu.org/software/bash/manual/html_node/redirections.html网站

  • 而不是更广泛使用,但(imho)黑客"重定向到/来自/dev/null",从而导致欺骗性的简单:

    1
        nohup script.sh >&- 2>&- <&-&

    2>&1的工作原理和2>一样,但我觉得后者更加清晰。;)大多数人可能在最后的"后台作业"和号之前有一个空格,但是由于它不是必需的(因为和号本身在正常使用中的功能类似于分号),所以我宁愿省略它。:)