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


304

这是“ 如何在shell脚本中使用ssh”的后续问题题。如果要在在该计算机的后台运行的远程计算机上执行命令,如何获取ssh命令以返回?当我尝试在命令末尾仅包含&符号时,它就会挂起。该命令的确切形式如下所示:

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

有任何想法吗?需要注意的一件事是,登录到目标计算机始终会生成文本横幅,并且我设置了SSH密钥,因此不需要密码。

Answers:


315

我在一年前写的程序中遇到了这个问题-答案很复杂。您将需要使用nohup以及输出重定向,如wikipedia中有关nohup的文章中所述,为方便起见,将其复制到此处。

例如,通过SSH登录时,Nohuping后台作业很有用,因为后台作业会由于竞争条件而导致Shell在注销时挂起[2]。通过重定向所有三个I / O流,也可以解决此问题:

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

1
这些文件在当前目录中创建。因此限制是分区上的可用空间量。当然,您也可以重定向到/dev/null
Frank Kusters

2
在要求提示完成后将流程作为背景的任何想法?(例如gpg --decrypt,已要求输入密码)
isaaclw 2013年

试图使用nohup在后台启动Resque工作者,但没有用.. :(
Infant Dev 2014年

1
你能解释什么< /dev/null意思吗?谢谢。
钱琛

1
同样来自维基百科有关nohup的文章:“还要注意,关闭的SSH会话并不总是向相关进程发送HUP信号。除其他外,这取决于是否分配了伪终端。” 因此,尽管严格来说不一定需要nohup,但长期而言,总比没有好。
Jax

254

这是为我做的最干净的方法:

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

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


7
-n并不需要-f暗示-n
blissini

6
ssh -f使ssh进程保持连接状态,仅在后台运行。/ dev / null解决方案允许ssh快速断开连接,这可能是更可取的。
贝尼·切尔尼亚夫斯基-帕斯金,

此解决方案还适用于通过ssh将命令发送到Syonology NAS
Stefan F,

我需要将“ ls -l”的结果显示在我的遥控器上,但此命令无法执行。
Siddharth

@Siddharth然后重定向到某个命名文件,而不是/ dev / null。
sherrellbc

29

重定向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启动外壳程序:

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

8
我知道这是您的一个很老的答案,但是您能否添加一些注释,说明为什么括号方法是最好的方法,添加方法(如果有的话)有什么不同nohup以及为什么以及何时使用nice?我认为这将大大增加这个答案。
K博士

也许可以部分回答这个问题:使用nohup,您不需要将&附加到要运行的命令上。
Cadoiz

21

如果您没有/无法保持连接打开,则可以使用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配置。


3
有什么用screen呢?
Quamis

18

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

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

非常有帮助。谢谢。
Michael Martinez

8

最快,最简单的方法是使用“ at”命令:

ssh user @ target“现在-f /home/foo.sh”


2
如果at在此之后并且不仅是从文件中接受了命令行参数,这将是一个很好的通用解决方案。
泰勒·科利尔

3
您可以使用<<<模拟文件,例如:ssh user @ target“ -f <<<'my_comnads'”
Nico

6

我认为您必须结合几个答案才能获得所需的内容。如果将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。


5

这可能对我有用:

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

2

你可以这样

sudo /home/script.sh -opt1 > /tmp/script.out &

完美,可用于PuTTY SSH会话。我可以退出,并且脚本在计算机上继续。谢谢。
萨特里亚

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"

0

我试图做同样的事情,但是增加了复杂性,我试图从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.

要使此功能正常运行,需要经过反复试验,但现在看来效果很好。


0

使用以下语法进行远程 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"'

0
YOUR-COMMAND &> YOUR-LOG.log &    

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


0

您可以不使用nohup来执行此操作:

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

-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

-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上的用户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;要执行的程序&”


1
问题是dagorym已经设置了密钥,不需要密码,但是仍然挂着
Max Nanasy 2014年
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.