我编写了一个脚本,用于将新服务推送并部署到我控制下的几台机器上,并且为了执行该过程,我使用 ssh 远程启动该过程。
不幸的是,每当我使用 SSH 启动该过程时,SSH 命令似乎都不会返回,从而导致脚本停滞。
该命令指定为:
ssh $user@$host "/root/command &"
每当我运行简单命令(例如 ps 或 who)时,SSH 命令都会立即返回,但是当我尝试启动我的进程时它不会返回。
我尝试过一些技巧,比如将我的进程包装在一个简单的 bash 脚本中,该脚本启动该进程然后退出,但是这也会挂起 SSH 命令(即使 bash 脚本回显成功消息并正常退出)。
是否有人知道导致这种行为的原因是什么,以及如何让 SSH 命令在进程启动后立即返回?
答案1
SSH 将远程 shell 的 stdin、stdout 和 stderr 连接到您的本地终端,以便您可以与远程端运行的命令进行交互。
作为副作用,它将一直运行,直到这些连接被关闭,这只有当远程命令及其所有子命令(!)终止时才会发生(因为子命令(以“&”开头)从其父进程继承 std* 并保持其打开)。
所以你需要使用类似
ssh user@host "/script/to/run < /dev/null > /tmp/mylogfile 2>&1 &"
<、> 和 2>&1 将 stdin/stdout/stderr 从您的终端重定向。然后“&”使您的脚本进入后台。在生产中,您当然会将 stdin/err 重定向到合适的日志文件。
看
http://osdir.com/ml/network.openssh.general/2006-05/msg00017.html
编辑:
刚刚发现< /dev/null
上面的操作是没有必要的(但是重定向 stdout/err是)。不知道为什么...
答案2
你可以尝试禁止. 更多细节请参见 man nohup。
ssh host "nohup script &"
如果你想保留远程机器上的输出,这是一个变体。
ssh user@host 'export REMOTE=myname; nice nohup ./my-restart >
logfile.log 2>&1 &'
答案3
另一种选择是启动一个分离的screen(1)
,例如:
ssh -l user host "screen -d -m mycommand"
这将启动一个独立的屏幕(捕获其中的所有交互),然后立即返回,终止 ssh 会话。
只要再聪明才智一点,您就可以通过这种方式解决相当复杂的远程命令调用。
答案4
我认为正确的方法是
ssh user@host exec script.sh &