Getting ssh to execute a command in the background

2019-01-01 11:48发布

This is a follow-on question to the How do you use ssh in a shell script? question. If I want to execute a command on the remote machine that runs in the background on that machine, how do I get the ssh command to return? When I try to just include the ampersand (&) at the end of the command it just hangs. The exact form of the command looks like this:

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

Any ideas? One thing to note is that logins to the the target machine always produce a text banner and I have SSH keys set up so no password is required.

标签: bash ssh csh
12条回答
低头抚发
2楼-- · 2019-01-01 12:05

This worked for me may times:

ssh -x remoteServer "cd yourRemoteDir; ./yourRemoteScript.sh </dev/null >/dev/null 2>&1 & " 
查看更多
大哥的爱人
3楼-- · 2019-01-01 12:08

This has been the cleanest way to do it for me:-

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

The only thing running after this is the actual command on the remote machine

查看更多
看风景的人
4楼-- · 2019-01-01 12:08

I was trying to do the same thing, but with the added complexity that I was trying to do it from Java. So on one machine running java, I was trying to run a script on another machine, in the background (with nohup).

From the command line, here is what worked: (you may not need the "-i keyFile" if you don't need it to ssh to the host)

ssh -i keyFile user@host bash -c "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\""

Note that to my command line, there is one argument after the "-c", which is all in quotes. But for it to work on the other end, it still needs the quotes, so I had to put escaped quotes within it.

From java, here is what worked:

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.

It took a bit of trial & error to get this working, but it seems to work well now.

查看更多
呛了眼睛熬了心
5楼-- · 2019-01-01 12:19

I think you'll have to combine a couple of these answers to get what you want. If you use nohup in conjunction with the semicolon, and wrap the whole thing in quotes, then you get:

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

which seems to work for me. With nohup, you don't need to append the & to the command to be run. Also, if you don't need to read any of the output of the command, you can use

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

to redirect all output to /dev/null.

查看更多
路过你的时光
6楼-- · 2019-01-01 12:21

I had this problem in a program I wrote a year ago -- turns out the answer is rather complicated. You'll need to use nohup as well as output redirection, as explained in the wikipedia artcle on nohup, copied here for your convenience.

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 &
查看更多
何处买醉
7楼-- · 2019-01-01 12:21

Actually, whenever I need to run a command on a remote machine that's complicated, I like to put the command in a script on the destination machine, and just run that script using ssh.

For example:

# simple_script.sh (located on remote server)

#!/bin/bash

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

And then I just run this command on the source machine:

ssh user@ip "/path/to/simple_script.sh"
查看更多
登录 后发表回答