在目标计算机上获取ssh以在后台执行命令
这是"如何在Shell脚本中使用ssh"的后续问题。问题。如果要在在后台计算机上运行的远程计算机上执行命令,如何获取ssh命令以返回?当我尝试在命令末尾仅包含&符时,它就会挂起。该命令的确切形式如下所示:
ssh user@target "cd /some/directory; program-to-execute &"
有任何想法吗?需要注意的一件事是,登录到目标计算机始终会生成文本横幅,并且我设置了SSH密钥,因此不需要密码。
解决方案
回答
我在一年前写的程序中遇到了这个问题-答案很复杂。我们将需要使用nohup以及输出重定向,如wikipedia中有关nohup的文章中所述,为方便起见,将其复制在此处。
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 &
回答
如果我们没有/无法保持连接的打开状态,那么我们可以使用屏幕,前提是我们有权安装它。
user@localhost $ screen -t remote-command user@localhost $ ssh user@target # now inside of a screen session user@remotehost $ cd /some/directory; program-to-execute &
分离屏幕会话:ctrl-a
d`
列出屏幕会话:
screen -ls
要重新添加会话:
screen -d -r remote-command
请注意,屏幕还可以在每个会话中创建多个外壳。使用tmux可以达到类似的效果。
user@localhost $ tmux user@localhost $ ssh user@target # now inside of a tmux session user@remotehost $ cd /some/directory; program-to-execute &
分离tmux会话:ctrl-b
d`
列出屏幕会话:
tmux list-sessions
要重新添加会话:
tmux attach <session number>
默认的tmux控制键'ctrl-b'很难使用,但是tmux附带了一些示例tmux配置,我们可以尝试使用。
回答
我认为我们必须结合几个答案才能获得所需的内容。如果将nohup与分号结合使用,并将整个内容用引号引起来,则将得到:
ssh user@target "cd /some/directory; nohup myprogram > foo.out 2> foo.err < /dev/null"
这似乎对我有用。使用nohup,我们无需将&添加到要运行的命令上。另外,如果我们不需要读取命令的任何输出,则可以使用
ssh user@target "cd /some/directory; nohup myprogram > /dev/null 2>&1"
将所有输出重定向到/ dev / null。
回答
这是为我做的最干净的方法:-
ssh -n -f user@host "sh -c 'cd /whereever; nohup ./whatever > /dev/null 2>&1 &'"
此后唯一运行的是远程计算机上的实际命令
回答
我试图做同样的事情,但是增加了我尝试用Java进行的复杂性。因此,在一台运行Java的计算机上,我试图在后台(使用nohup)在另一台计算机上运行脚本。
在命令行中,这是起作用的方法:(如果不需要它,则不需要" -i keyFile"来SSH到主机)
ssh -i keyFile user@host bash -c "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\""
请注意,在我的命令行中,"-c"后面有一个参数,所有参数都用引号引起来。但是要使它在另一端运行,它仍然需要使用引号,因此我不得不在其中添加转义的引号。
从Java,这是有效的方法:
ProcessBuilder b = new ProcessBuilder("ssh", "-i", "keyFile", "bash", "-c", "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\""); Process process = b.start(); // then read from process.getInputStream() and close it.
要使此功能正常运行,需要经过反复试验,但现在看来效果很好。