这是“ 如何在shell脚本中使用ssh”的后续问题。题。如果要在在该计算机的后台运行的远程计算机上执行命令,如何获取ssh命令以返回?当我尝试在命令末尾仅包含&符号时,它就会挂起。该命令的确切形式如下所示:
ssh user@target "cd /some/directory; program-to-execute &"
有任何想法吗?需要注意的一件事是,登录到目标计算机始终会生成文本横幅,并且我设置了SSH密钥,因此不需要密码。
这是“ 如何在shell脚本中使用ssh”的后续问题。题。如果要在在该计算机的后台运行的远程计算机上执行命令,如何获取ssh命令以返回?当我尝试在命令末尾仅包含&符号时,它就会挂起。该命令的确切形式如下所示:
ssh user@target "cd /some/directory; program-to-execute &"
有任何想法吗?需要注意的一件事是,登录到目标计算机始终会生成文本横幅,并且我设置了SSH密钥,因此不需要密码。
Answers:
我在一年前写的程序中遇到了这个问题-答案很复杂。您将需要使用nohup以及输出重定向,如wikipedia中有关nohup的文章中所述,为方便起见,将其复制到此处。
例如,通过SSH登录时,Nohuping后台作业很有用,因为后台作业会由于竞争条件而导致Shell在注销时挂起[2]。通过重定向所有三个I / O流,也可以解决此问题:
nohup myprogram > foo.out 2> foo.err < /dev/null &
< /dev/null
意思吗?谢谢。
这是为我做的最干净的方法:
ssh -n -f user@host "sh -c 'cd /whereever; nohup ./whatever > /dev/null 2>&1 &'"
此后唯一运行的是远程计算机上的实际命令
-n
并不需要-f
暗示-n
ssh -f
使ssh进程保持连接状态,仅在后台运行。/ dev / null解决方案允许ssh快速断开连接,这可能是更可取的。
需要重定向输出&>/dev/null
,将stderr和stdout都重定向到/ dev / null,并且是>/dev/null 2>/dev/null
或的同义词>/dev/null 2>&1
。
最好的方法是使用sh -c '( ( command ) & )'
命令是任何东西。
ssh askapache 'sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'
您还可以直接使用nohup启动外壳程序:
ssh askapache 'nohup sh -c "( ( chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'
另一个技巧是使用nice启动命令/ shell:
ssh askapache 'nice -n 19 sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'
nohup
以及为什么以及何时使用nice
?我认为这将大大增加这个答案。
如果您没有/无法保持连接打开,则可以使用screen,如果您有权安装它。
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
请注意,屏幕还可以在每个会话中创建多个shell。使用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配置。
screen
呢?
我只是想展示一个可以剪切和粘贴的示例:
ssh REMOTE "sh -c \"(nohup sleep 30; touch nohup-exit) > /dev/null &\""
我认为您必须结合几个答案才能获得所需的内容。如果将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。
我试图做同样的事情,但是增加了复杂性,我试图从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.
要使此功能正常运行,需要经过反复试验,但现在看来效果很好。
使用以下语法进行远程 tmux会话对我来说似乎很方便tmux new -d <shell cmd>
:
ssh someone@elsewhere 'tmux new -d sleep 600'
这将在elsewhere
主机上启动新会话,并且本地计算机上的ssh命令将几乎立即返回shell。然后,您可以SSH到远程主机和tmux attach
该会话。请注意,本地tmux没有任何运行,只有远程!
同样,如果您希望会话在完成工作后继续存在,只需在命令后添加一个shell启动器,但不要忘记用引号引起来:
ssh someone@elsewhere 'tmux new -d "~/myscript.sh; bash"'
首先请遵循以下步骤:
以用户a身份登录A并生成一对认证密钥。请勿输入密码:
a@A:~> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/a/.ssh/id_rsa):
Created directory '/home/a/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/a/.ssh/id_rsa.
Your public key has been saved in /home/a/.ssh/id_rsa.pub.
The key fingerprint is:
3e:4f:05:79:3a:9f:96:7c:3b:ad:e9:58:37:bc:37:e4 a@A
现在使用ssh作为B上的用户b创建目录〜/ .ssh(该目录可能已经存在,可以):
a@A:~> ssh b@B mkdir -p .ssh
b@B's password:
最后,将a的新公钥附加到b @ B:.ssh / authorized_keys,最后一次输入b的密码:
a@A:~> cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys'
b@B's password:
从现在开始,您可以使用密码从A身份以B身份登录为B身份:
a@A:~> ssh b@B
那么这将无需输入密码即可工作
ssh b @ B“ cd / some / directory;要执行的程序&”
/dev/null
。