执行远程命令,完全脱离ssh连接

执行远程命令,完全脱离ssh连接

我有 2 台电脑,localpc并且remoteserver.

我需要localpc在 上执行一些命令remoteserver。它需要做的事情之一是启动一个运行数小时的备份脚本。我希望命令localpc“启动”,然后完全独立地运行remoteserver,就像localpc一开始就不存在一样。

这是我到目前为止所做的:

remoteserver包含脚本:

/root/backup.sh

localpc计划运行此:

ssh root@remoteserver 'nohup /root/backup.sh' &

我这样做的方式正确吗?有一个更好的方法吗?我这样做会遇到麻烦吗?

答案1

接近,但不完全是。

独立于任何终端

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

您需要关闭连接到 ssh 套接字的所有文件描述符,因为只要某个远程进程打开套接字,ssh 会话就不会关闭。如果您对脚本的输出不感兴趣(可能是因为脚本本身负责写入日志文件),请将其重定向到/dev/null(但请注意,这将隐藏错误,例如无法启动脚本)。

使用nohup在这里没有任何有用的效果。nohup如果程序的控制终端消失,则安排其运行的程序不接收 HUP 信号,但这里首先没有终端,因此不会突然向进程发送 SIGHUP 信号。此外,nohup将标准输出和标准错误(但不是标准输入)重定向到文件,但前提是它们连接到终端,但事实并非如此。

从终端分离

 aaron@localpc$ ssh root@remoteserver
 root@remoteserver# nohup /root/backup.sh </dev/null &
 nohup: appending output to `nohup.out'
 [1] 12345
 root@remoteserver# exit
 aaron@localpc$ 

用于nohup将脚本与其控制终端分离,以便它不会收到叹息当终端消失时。nohup还将脚本的标准输出和标准错误重定向到一个名为的文件(nohup.out如果它们连接到终端);你必须自己处理标准输入。

保留远程终端

如果您想让命令在远程终端中运行,但不将其附加到 SSH 会话,请在终端多路复用器中运行它,例如屏幕或者多路复用器

ssh root@remoteserver 'screen -S backup -d -m /root/backup.sh'

screen -S backup -rd您稍后可以通过在该计算机上以 root 身份调用来重新连接到运行脚本的终端。

自动化一个远程命令

为了获得更好的安全性,不要过于广泛地开放直接远程 root 登录。创建一个专用密钥对并给它一个强制命令/root/.ssh/authorized_keys。公钥文件的内容是;添加以逗号分隔的选项列表,其中指定该键只能用于执行此特定命令。确保将选项和密钥全部放在一行上。AAAA…== [email protected]command="…"

command="/root/backup.sh </dev/null >/dev/null 2>/dev/null &",no-port-forwarding,no-agent-forwarding,no-x11-forwarding,no-pty,no-user-rc AAAA…== [email protected]

答案2

您可能应该screen在远程主机上使用,以获得真正的独立命令:

ssh root@remoteserver screen -d -m ./script

答案3

该线程非常有帮助,但我的解决方案必须有所不同。

我不喜欢屏幕解决方案,因为它让我不需要的屏幕进程继续运行。重定向和 nohups 的使用如下:

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

与 ssh 命令一起使用时对我不起作用。

我在远程计算机上创建了一个运行实际脚本的包装脚本。包装器脚本设置重定向和 nohup。像这样的东西:

backupwrapper.sh:
nohup backup.sh > /dev/null 2>&1 &

然后在我的客户端计算机上运行(注意没有重定向):

# ssh remotemachine "backupwrapper.sh"
#

ssh 命令立即返回,连接终止,脚本继续运行。

答案4

作为尼尔斯 说,允许root通过ssh登录存在安全风险。我建议不要在没有日志的机器上运行任何实质性作业。如果出现任何问题,您会希望收到一些故障排除消息。还有其他答案向您展示如何做到这一点。但我建议您如何完成您所要求的事情。它全部内置于 sh(1) 中。不需要 GNU 屏幕(尽管我认为这是一个聪明的解决方案)。将此字符串附加到您的命令中:>&- 2>&- <&- &>&-表示关闭标准输出。2>&-意味着关闭stderr。<&-表示关闭标准输入。&意味着在后台运行,例如

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$

相关内容