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


48

我有2台计算机,localpc并且remoteserver

我需要localpc在上执行一些命令remoteserver。它需要做的一件事情就是启动一个运行数小时的备份脚本。我希望命令localpc“启动”,然后完全在上运行remoteserver,就像localpc从来没有出现过一样。

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

remoteserver 包含具有以下脚本:

/root/backup.sh

localpc 按计划运行:

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

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


stackoverflow.com/questions/19996089/…stackoverflow.com/questions/29142/…提供了许多有用的方法来解决此问题,而无需使用screen / tmux等...
Paul

Answers:


47

您可能应该screen在远程主机上使用一个真正的分离命令:

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

我喜欢这个主意。脚本完成后,屏幕仍将继续运行...而下一次我想运行它时,我必须以某种方式重新连接到它,对吗?
LVLAaron

@AaronJAnderson:否,因为该命令不是shell,所以当它终止时,屏幕会话也会终止。
enzotib'2

52

关闭,但不完全是。

独立于任何终端

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从它的控制终端分离的脚本,以便它不会收到SIGHUP当终端消失。nohup如果脚本nohup.out连接到终端,还将脚本的标准输出和标准错误重定向到一个名为的文件;您必须自己照顾标准输入。

保留远程终端

如果要使该命令在远程终端上运行但不将其附加到SSH会话,请在终端多路复用器(例如ScreenTmux)中运行它。

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

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

自动执行一个远程命令

为了获得更好的安全性,请不要过于广泛地打开直接远程root用户登录名。创建一个专用密钥对,并在中给它一个强制命令/root/.ssh/authorized_keys。公钥文件的内容是AAAA…== wibble@example.com;添加逗号分隔的选项列表,其中包括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…== wibble@example.com

我已经尝试了您列出的第一个命令。它在执行命令的框上没有背景。光标只是坐在那里等待完成……也许是一个错误?
LVLAaron

您可能需要将stdin重定向到远程系统上的/ dev / null。这也许就是为什么ssh没有退出的原因。
KeithB 2012年

我将添加-f使ssh到达本地端的“后台”(即终止,关闭连接)的选项。这将与配合使用&nohup在这种情况下是可选的,但您可以考虑使用setsid代替。
Alexios

@KeithB重定向stdin是它的一部分,但是我还需要重定向stdout和stderr:nohup在这里不会这样做,因为它们不是终端,实际上nohup在这里没有用。
吉尔(Gilles)'所以

1
@erikbwork请注意,我对这些事情一无所知,但在讨论和评论之后:Gilles在其命令中未使用-t选项,因此不会在客户端或服务器上均未建立伪终端。侧。因此,将不会发送HUP。
比纳罗斯(Binarus)'17年

12

通过SSH之类的远程登录运行远程命令的标准方法如下:

nohup command </dev/null >command.log 2>&1 &

如果commandshell脚本负责记录文件本身,则可以更改command.log/dev/null。一旦开始,请立即注销。

您需要那条线上的一切。

nohup 告诉外壳程序在登录会话断开连接时不要打扰该过程。

</dev/null 告诉它永不等待输入

>command.log 告诉它向该命名日志文件发送任何消息

2>&1告诉它将任何stderr消息发送到同一日志文件。在某些情况下,最好有两个文件,第二个收集错误消息,第一个收集正常活动消息。这样可以更轻松地验证一切正常。

& 告诉它分离该过程,并在后台将其作为守护进程运行。


10

这个线程非常有用,但是我的解决方案必须有所不同。

我不喜欢屏幕解决方案,因为它会使我不需要的屏幕进程继续运行。重定向和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命令立即返回,连接终止,脚本保持运行状态。


6

正如Nils所说,允许root用户通过ssh登录存在安全隐患。而且我建议不要在没有日志的机器上运行任何实质性的工作。如果有任何问题,希望您收到一些故障排除消息。还有其他答案向您展示如何做到这一点。但是,这就是我建议按照您的要求完成的方式。它全部内置在sh(1)中。不需要GNU屏幕(尽管我认为这是一个聪明的解决方案)。将此字符串追加到您的命令:中>&- 2>&- <&- &>&-表示关闭标准输出。2>&-表示关闭标准错误。<&-表示关闭标准输入。&表示在后台运行,例如

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

0

您应该将远程命令放在上remoteserver。您执行此操作的方式将使ssh-command处于后台localpc

除此之外,允许root-ssh是一个坏主意。

因此,设置为remoteserver:一个sudoers行,该行/root/backup.sh将由用户以root用户身份运行backup

您可以创建没有“好”密码的用户。

将命令sudo /root/backup.sh &作为命令放入~backup/.ssh/authorized_keys—与来自的公钥localpc(触发该脚本的人)一起。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.