获取ssh以在目标计算机上的后台执行命令

时间:2008-08-26 22:55:59

标签: bash ssh csh

这是How do you use ssh in a shell script?问题的后续问题。如果我想在该机器的后台运行的远程机器上执行命令,我该如何获取ssh命令?当我尝试在命令末尾包含&符号(&)时它就会挂起。命令的确切形式如下所示:

ssh user@target "cd /some/directory; program-to-execute &"

有什么想法吗?需要注意的一点是,登录目标计算机始终会生成文本标题,并且我设置了 SSH 键,因此无需密码。

16 个答案:

答案 0 :(得分:278)

我在一年前写的一个程序中遇到了这个问题 - 事实证明答案相当复杂。您需要使用nohup以及输出重定向,如nohup上的维基百科artcle中所述,为方便起见,复制到此处。

  

Nohuping后台工作是为了   通过SSH登录时有用的示例,   由于后台工作可以导致   由于比赛而在登出时挂起的shell   条件[2]。这个问题也可以   通过重定向这三个来克服   I / O流:

nohup myprogram > foo.out 2> foo.err < /dev/null &

答案 1 :(得分:241)

这对我来说是最干净的方式: -

ssh -n -f user@host "sh -c 'cd /whereever; nohup ./whatever > /dev/null 2>&1 &'"

此后唯一运行的是远程计算机上的实际命令

答案 2 :(得分:26)

重定向fd的

输出需要使用&>/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 Shell

您也可以直接使用nohup启动shell:

ssh askapache 'nohup sh -c "( ( chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

Nice Launch

另一个技巧是使用nice来启动命令/ shell:

ssh askapache 'nice -n 19 sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

答案 3 :(得分:18)

我只想展示一个可以剪切和粘贴的工作示例:

ssh REMOTE "sh -c \"(nohup sleep 30; touch nohup-exit) > /dev/null &\""

答案 4 :(得分:17)

如果您没有/无法保持连接打开,则可以使用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一起提供,你可以试试。

答案 5 :(得分:9)

最快捷最方便的方法是使用&#39; at&#39;命令:

  

ssh user @ target&#34; at -f /home/foo.sh"

答案 6 :(得分:6)

我认为你必须将这些答案结合起来才能得到你想要的东西。如果你将nohup与分号结合使用,并将整个内容用引号括起来,那么你得到:

ssh user@target "cd /some/directory; nohup myprogram > foo.out 2> foo.err < /dev/null"

这似乎对我有用。有了nohup,你不需要附加&amp;要运行的命令。此外,如果您不需要读取命令的任何输出,则可以使用

ssh user@target "cd /some/directory; nohup myprogram > /dev/null 2>&1"

将所有输出重定向到/ dev / null。

答案 7 :(得分:5)

这对我有用了一段时间:

ssh -x remoteServer "cd yourRemoteDir; ./yourRemoteScript.sh </dev/null >/dev/null 2>&1 & " 

答案 8 :(得分:1)

实际上,每当我需要在一台复杂的远程机器上运行命令时,我喜欢将命令放在目标机器上的脚本中,然后使用ssh运行该脚本。

例如:

# simple_script.sh (located on remote server)

#!/bin/bash

cat /var/log/messages | grep <some value> | awk -F " " '{print $8}'

然后我在源计算机上运行此命令:

ssh user@ip "/path/to/simple_script.sh"

答案 9 :(得分:1)

您可以不做任何事情:

ssh user@host 'myprogram >out.log 2>err.log &'

答案 10 :(得分:0)

我试图做同样的事情,但是我试图用Java来增加复杂性。所以在运行java的一台机器上,我试图在后台运行一个脚本(使用nohup)。

从命令行,这是有用的:(如果你不需要它来ssh到主机你可能不需要“-i keyFile”)

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.

经过了一些尝试和试验错误让这个工作,但它现在似乎运作良好。

答案 11 :(得分:0)

您可以这样做...

knex

答案 12 :(得分:0)

使用tmux new -d <shell cmd>语法进行远程 tmux会话对我来说似乎很方便:

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"'

答案 13 :(得分:0)

YOUR-COMMAND &> YOUR-LOG.log &    

这应该运行命令并分配一个进程ID,您可以简单地在-f YOUR-LOG.log中添加tail -f,以查看结果写入结果的过程。您可以随时注销,该过程将继续进行

答案 14 :(得分:-2)

我认为这就是你所需要的: 首先,您需要在计算机上安装sshpass。 然后你可以编写自己的脚本:

while read pass port user ip; do
sshpass -p$pass ssh -p $port $user@$ip <<ENDSSH1
    COMMAND 1
    .
    .
    .
    COMMAND n
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP
      .      .       .       .
      .      .       .       .
      .      .       .       .
    PASS    PORT    USER    IP    
____HERE

答案 15 :(得分:-3)

首先遵循以下程序:

以用户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上创建一个目录〜/ .ssh作为用户b。(该目录可能已经存在,这很好):

a@A:~> ssh b@B mkdir -p .ssh
b@B's password: 

最后将一个新的公钥附加到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; program-to-execute&amp;”