通过SSH启动不含nohup的远程脚本

7
我想通过ssh远程启动一个脚本,就像这样:

ssh user@remote.org -t 'cd my/dir && ./myscript data my@email.com'

这个脚本做了很多事情,直到遇到一个带有nohup的命令行:

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会输出:

连接到remote.org已关闭。

这里出了什么问题呢?

感谢您的帮助。


没有启动myprog,mutt也没有发送。为了测试,我通过ssh连接到远程服务器查看发生了什么。同时,我的日志文件my.log是空的(在脚本中之前已经touch过)。 - litro
如果./myprog的参数不正确,它会向标准输出写入什么内容?当您编写./myprog $1 >my.log 2>myerr.log时,myerr.log包含什么内容? - thejh
我的程序首先执行一些不需要参数的操作,例如将可用系统资源限制为64GB,并输出其成功信息,然后检查参数是否为正确的文件名并尝试打开它们,并输出其成功信息等等。如果其中任何一个步骤失败,它会首先将错误信息输出到stdout,然后输出到stderr。虽然我的程序不是问题所在,因为当我手动登录到远程服务器并运行nohup myprog && mutt时,一切都正常工作。 - litro
我应该补充说明,在手动登录到远程系统并启动时,我的脚本可以按预期工作。但是,就像上述所描述的那样,当我尝试通过ssh启动它时,它会失败。 - litro
你尝试过不使用nohup运行它来查看会发生什么吗?我感觉脚本myprog出错了,应该被记录在nohup.out文件中。 - Version Control Buddy
你可以尝试在使用 -t 选项打开 ssh 后手动运行命令吗?也许它与 nohup 冲突了? - mpapis
3个回答

6
您的命令在后台运行一系列进程,因此调用脚本将立即退出(或很快退出)。这将导致ssh关闭连接。这反过来又会导致发送一个SIGHUP信号到与-t选项创建的终端连接的任何进程。
您的time ./myprog进程受到nohup的保护,因此它应该继续运行。但是您的mutt并没有得到保护,这可能是问题所在。我建议您将命令行更改为:
nohup sh -c "time ./myprog $1 >my.log && mutt -a ${1%.*}/`basename $1` -a ${1%.*}/`basename ${1%.*}`.plt $2 < my.log 2>&1 " &

因此,整个管道都得到了保护。(如果这样不能解决问题,可能需要对文件描述符进行操作 - 比如说mutt可能存在终端不可用的其他问题 - 或者引号需要进行调整,具体取决于参数 - 但现在先试试这个...)


5

这个答案可能会有所帮助。 简而言之,要实现所需的效果,您必须执行以下操作:

  1. 重定向远程nohup命令上的所有I/O
  2. 告诉您的本地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:

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

更新

我刚刚使用了以下模式并取得了成功:

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

1
“/dev/null” 是什么意思?谢谢。 - user1663023

-1

我成功解决了一个使用情况,其中我需要通过ssh远程启动后台脚本,使用类似于其他答案的技术,但我觉得更加简单和清晰(至少,这使我的代码更短,而且--我相信--外观更好),通过使用流关闭重定向语法显式地关闭所有三个流(如下所述:

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

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

  3. http://www.tldp.org/LDP/abs/html/io-redirection.html#CFD

  4. https://www.gnu.org/software/bash/manual/html_node/Redirections.html

与其使用更广泛但(在我看来)更糟糕的“重定向到/从/dev/null”,导致看似简单的:

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

2>&1 和 2>&- 一样有效,但我觉得后者稍微更清晰一些。;) 大多数人可能在最后一个“background job”和符号之前有一个空格,但由于它不是必需的(因为符号本身在正常使用中就像分号一样起作用),所以我更喜欢省略它。:)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接