终止由 bash 脚本执行的 SSH 会话

发布于 2024-11-29 15:59:05 字数 402 浏览 1 评论 0原文

我有一个可以在本地运行以远程启动服务器的脚本:

#!/bin/bash
ssh [email protected] <<EOF
  nohup /path/to/run.sh &
EOF
echo 'done'

运行 nohup 后,它挂起。我必须按 ctrl-c 才能退出脚本。

我尝试在此处文档的末尾添加显式退出,并使用 ssh 的“-t”参数。两者都不起作用。如何让这个脚本立即退出?

编辑:客户端是OSX 10.6,服务器是Ubuntu。

I have a script I can run locally to remotely start a server:

#!/bin/bash
ssh [email protected] <<EOF
  nohup /path/to/run.sh &
EOF
echo 'done'

After running nohup, it hangs. I have to hit ctrl-c to exit the script.

I've tried adding an explicit exit at the end of the here doc and using "-t" argument for ssh. Neither works. How do I make this script exit immediately?

EDIT: The client is OSX 10.6, server is Ubuntu.

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

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

发布评论

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

评论(4

嘿哥们儿 2024-12-06 15:59:05

我认为问题是,当您从 ssh 进入时,nohup 无法重定向输出,它仅在认为已连接到终端时重定向到 nohup.out,并且我的 stdin 覆盖会阻止这种情况,即使使用 -t

解决方法可能是自己重定向输出,然后 ssh 客户端可以断开连接 - 它不会等待流关闭。类似于:

nohup /path/to/run.sh > run.log &

(这对我来说是一个从 OS X 客户端连接到 Ubuntu 服务器的简单测试。)

I think the problem is that nohup can't redirect output when you come in from ssh, it only redirects to nohup.out when it thinks it's connected to a terminal, and I the stdin override you have will prevent that, even with -t.

A workaround might be to redirect the output yourself, then the ssh client can disconnect - it's not waiting for the stream to close. Something like:

nohup /path/to/run.sh > run.log &

(This worked for me in a simple test connecting to an Ubuntu server from an OS X client.)

云雾 2024-12-06 15:59:05

问题可能是......

... ssh is respecting the POSIX standard when not closing the session 
if a process is still attached to the tty.

因此,解决方案可能是将 nohup 命令的 stdin 与 tty 分离:

nohup /path/to/run.sh </dev/null &

请参阅:使用 nohup 时 SSH 在退出时挂起

另一种方法可能即使 stdin 不是终端,也可以使用 ssh -t -t 强制伪 tty 分配。

man ssh | less -Ip 'multiple -t'

ssh -t -t [email protected] <<EOF
  nohup /path/to/run.sh &
EOF

请参阅:BASH 生成 SSH 的子 shell 并继续程序流程

The problem might be that ...

... ssh is respecting the POSIX standard when not closing the session 
if a process is still attached to the tty.

Therefore a solution might be to detach the stdin of the nohup command from the tty:

nohup /path/to/run.sh </dev/null &

See: SSH Hangs On Exit When Using nohup

Yet another approach might be to use ssh -t -t to force pseudo-tty allocation even if stdin isn't a terminal.

man ssh | less -Ip 'multiple -t'

ssh -t -t [email protected] <<EOF
  nohup /path/to/run.sh &
EOF

See: BASH spawn subshell for SSH and continue with program flow

笑红尘 2024-12-06 15:59:05

在没有显式命令的情况下调用 ssh 时从此处文档重定向远程主机的标准输入会导致消息:伪终端将不会被分配,因为标准输入不是终端。

要避免此消息,请使用 ssh-T 开关告诉远程主机无需分配伪终端或显式指定命令(例如<代码>/bin/sh)让远程主机执行此处文档提供的命令。

如果给ssh明确的命令,则默认以伪终端的形式提供no登录shell,即当指定命令(请参阅man ssh)。

另一方面,如果没有为 ssh 指定命令,则默认情况下会在远程主机上为交互式登录会话创建伪 tty。

- ssh [email protected] <<EOF
+ ssh -T [email protected] <<EOF
+ ssh [email protected] /bin/bash <<EOF

通常,仅当存在期望 stdin / stdout 成为终端的命令(例如 ssh -t -t >top 或 vim),或者是否需要在 ssh 客户端命令完成执行时终止远程 shell 及其子级(请参阅:ssh 命令在 ssh 终止后意外地在其他系统上继续运行)。

据我所知,结合不分配伪tty的 ssh 命令和写入 nohup.out 的 nohup 命令的唯一方法在远程主机上的作用是让nohup命令在ssh机制创建的伪终端中执行。例如,这可以使用 script 命令来完成,并且将避免出现 tcgetattr:不适当的 ioctl for device 消息。

#!/bin/bash
ssh localhost /bin/sh <<EOF
  #0<&-  script -q /dev/null nohup sleep 10 1>&- &
  #0<&- script -q -c "nohup sh -c 'date; sleep 10 1>&- &'" /dev/null  # Linux
  0<&- script -q /dev/null nohup sh -c 'date; sleep 10 1>&- &'        # FreeBSD, Mac OS X
  cat nohup.out
  exit 0
EOF
echo 'done'
exit 0

Redirecting the stdin of the remote host from a here document while invoking ssh without an explicit command leads to the message: Pseudo-terminal will not be allocated because stdin is not a terminal.

To avoid this message either use ssh's -T switch to tell the remote host there is no need to allocate a pseudo-terminal or explicitly specify a command (such as /bin/sh) for the remote host to execute the commands provided by the here document.

If an explicit command is given to ssh, the default is to provide no login shell in the form of a pseudo-terminal, i. e. there will be no normal login session when a command is specified (see man ssh).

Without a command specified for ssh, on the other hand, the default is to create a pseudo-tty for an interactive login session on the remote host.

- ssh [email protected] <<EOF
+ ssh -T [email protected] <<EOF
+ ssh [email protected] /bin/bash <<EOF

As a rule, ssh -t or even ssh -t -t should only be used if there are commands that expect stdin / stdout to be a terminal (such as top or vim) or if it is necessary to kill the remote shell and its children when the ssh client command finishes execution (see: ssh command unexpectedly continues on other system after ssh terminates).

As far as I can tell, the only way to combine an ssh command that does not allocate a pseudo-tty and a nohup command that writes to nohup.out on the remote host is to let the nohup command execute in a pseudo-terminal not created by the ssh mechanism. This can be done with the script command, for example, and will avoid the tcgetattr: Inappropriate ioctl for device message.

#!/bin/bash
ssh localhost /bin/sh <<EOF
  #0<&-  script -q /dev/null nohup sleep 10 1>&- &
  #0<&- script -q -c "nohup sh -c 'date; sleep 10 1>&- &'" /dev/null  # Linux
  0<&- script -q /dev/null nohup sh -c 'date; sleep 10 1>&- &'        # FreeBSD, Mac OS X
  cat nohup.out
  exit 0
EOF
echo 'done'
exit 0
错爱 2024-12-06 15:59:05

您需要在末尾添加 exit 0

You need to add a exit 0 at the end.

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