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

发布于 2024-09-30 13:57:52 字数 761 浏览 8 评论 0原文

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

ssh [email protected] -t 'cd my/dir && ./myscript data [email protected]'

该脚本会执行各种工作正常的事情,直到它与 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的连接已关闭。

这里有什么问题呢?

感谢您的帮助

I want to start a script remotely via ssh like this:

ssh [email protected] -t 'cd my/dir && ./myscript data [email protected]'

The script does various things which work fine until it comes to a line with nohup:

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

it is supposed to do start the program myprog, pipe its output to mylog and send an email with some datafiles created by myprog as attachment and the log as body. Though when the script reaches this line, ssh outputs:

Connection to remote.org closed.

What is the problem here?

Thanks for any help

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你对谁都笑 2024-10-07 13:57:52

您的命令在后台运行进程管道,因此调用脚本将立即退出(或很快退出)。这将导致 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 可能会因终端不在周围而出现其他问题 - 或者引用可能需要根据参数进行调整 - 但请尝试一下现在...)

Your command runs a pipeline of processes in the background, so the calling script will exit straight away (or very soon afterwards). This will cause ssh to close the connection. That in turn will cause a SIGHUP to be sent to any process attached to the terminal that the -t option caused to be created.

Your time ./myprog process is protected by a nohup, so it should carry on running. But your mutt isn't, and that is likely to be the issue here. I suggest you change your command line to:

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

so the entire pipeline gets protected. (If that doesn't fix it it may be necessary to do something with file descriptors - for instance mutt may have other issues with the terminal not being around - or the quoting may need tweaking depending on the parameters - but give that a try for now...)

与之呼应 2024-10-07 13:57:52

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

  1. 重定向远程 nohup 命令上的所有 I/O
  2. 告诉本地 SSH 命令在启动远程进程完成后立即退出。

引用我已经提到的答案,依次引用 wikipedia

例如,当通过 SSH 登录时,Nohuping 后台作业非常有用,因为后台作业可能会导致 shell 由于竞争条件而在注销时挂起 [2]。这个问题也可以通过重定向所有三个 I/O 流来解决:

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) & )"'

This answer may be helpful. In summary, to achieve the desired effect, you have to do the following things:

  1. Redirect all I/O on the remote nohup'ed command
  2. Tell your local SSH command to exit as soon as it's done starting the remote process(es).

Quoting the answer I already mentioned, in turn quoting wikipedia:

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 &

UPDATE

I've just had success with this pattern:

ssh -f user@host 'sh -c "( (nohup command-to-nohup 2>&1 >output.file </dev/null) & )"'
安静被遗忘 2024-10-07 13:57:52

设法解决这个用例,我需要使用类似于此处其他答案的技术通过 ssh 远程启动后台脚本,但在某种程度上我觉得更简单和干净(至少,它使我的代码更短,并且 -我相信 - 更好看),通过使用流关闭重定向语法显式关闭所有三个流(如以下位置所述:

  1. https://unix.stackexchange.com/questions/131801/ending-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

而不是更广泛使用但(恕我直言)更黑客的“重定向到/from /dev/null”,结果看似简单:

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

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

Managed to solve this for a use case where I need to start backgrounded scripts remotely via ssh using a technique similar to other answers here, but in a way I feel is more simple and clean (at least, it makes my code shorter and -- I believe -- better-looking), by explicitly closing all three streams using the stream-close redirection syntax (as discussed at the following locations:

  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

Rather than the more widely used but (IMHO) hackier "redirect to/from /dev/null", resulting in the deceptively simple:

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

2>&1 works just as well as 2>&-, but I feel the latter is ever-so-slightly more clear. ;) Most people might have a space preceding the final "background job" ampersand, but since it is not required (as the ampersand itself functions like a semicolon in normal usage), I prefer to omit it. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文