sshがターゲットマシンのバックグラウンドでコマンドを実行するようにする


304

これは、シェルスクリプトでsshをどのように使用するのに関する後続の質問です。質問。リモートマシンで、そのマシンのバックグラウンドで実行されているコマンドを実行する場合、sshコマンドを返すにはどうすればよいですか?コマンドの最後にアンパサンド(&)を含めようとすると、ハングします。コマンドの正確な形式は次のとおりです。

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

何か案は?ターゲットマシンへのログインでは常にテキストバナーが生成され、パスワードが不要なSSHキーが設定されていることに注意してください。

回答:


315

1年前に書いたプログラムでこの問題が発生しました。答えはかなり複雑であることがわかりました。便宜上、ここにコピーされたnohupのwikipedia artcleで説明されているように、nohupと出力リダイレクトを使用する必要があります。

nohupingバックグラウンドジョブは、たとえば、SSH経由でログインする場合に役立ちます。バックグラウンドジョブは、競合状態のためにログアウト時にシェルをハングさせる可能性があるためです[2]。この問題は、3つすべてのI / Oストリームをリダイレクトすることでも解決できます。

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

1
これらのファイルは、現在のディレクトリに作成されます。したがって、制限はパーティションの空き容量です。もちろん、にリダイレクトすることもできます/dev/null
フランクKusters 2013

2
プロンプトの要求が終了した後のプロセスの背景について何かアイデアはありますか?(gpgのように--decryptはパスワードの入力を求めて終了します)
isaaclw

nohupを使用してバックグラウンドでresque workerを起動しようとしましたが、動作しません。.:(
Infant Dev

1
どういう< /dev/null意味ですか?ありがとう。
銭チェン

1
また、nohupに関するWikipediaの記事から:「SSHセッションを閉じると、依存するプロセスに常にHUPシグナルが送信されるとは限らないことに注意してください。とりわけ、これは、疑似ターミナルが割り当てられているかどうかによって異なります。」したがって、厳密にはnohupが必ずしも必要とは限らないかもしれませんが、nohupを使用するよりも、使用しない場合よりも長期的に使用する方が優れています。
Jax

254

これは私にとってそれを行う最もきれいな方法でした:-

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

この後に実行される唯一のものは、リモートマシンでの実際のコマンドです。


7
-n-f意味するように必要ありません-n
blissini 2016年

6
ssh -fsshプロセスを接続したままにします。/ dev / nullソリューションを使用すると、sshをすばやく切断できます。
Beni Cherniavsky-Paskin

このソリューションは、sshを介してSyonology NASにコマンドを送信する場合にも機能します
Stefan F

"ls -l"の結果をリモートに表示する必要があります。このコマンドでは実行できません。
Siddharth、

@Siddharth次に、/ dev / nullではなく、名前の付いたファイルにリダイレクトします。
sherrellbc

29

fdをリダイレクトする

&>/dev/nullstderrとstdoutの両方を/ dev / null にリダイレクトする出力をリダイレクトする必要があり、>/dev/null 2>/dev/nullまたはの同義語です>/dev/null 2>&1

かっこ

最善の方法はsh -c '( ( command ) & )'、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を使用することです:

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

8
私はこれがあなたの非常に古い答えであることを知っていますが、括弧の方法が最善の方法である理由、(もしあれば)何が違いをnohup生むのか、そしてなぜそしていつ使用するのかについてコメントを追加できますniceか?それはこの答えに多くを追加すると思います。
K博士

多分これに部分的に答えるでしょう:nohupを使用すると、実行するコマンドに&を追加する必要はありません。
カドワ

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 &

screenセッションを切り離すには: ctrl-a d

スクリーンセッションを一覧表示するには:

screen -ls

セッションを再接続するには:

screen -d -r remote-command

screenは各セッション内で複数のシェルを作成することもできることに注意してください。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 2013年

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 "at now -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を実行している1台のマシンで、バックグラウンドで(nohupを使用して)別のマシンでスクリプトを実行しようとしました。

コマンドラインから、これが機能しました:(ホストにsshする必要がない場合は、「-i keyFile」は必要ない場合があります)

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

私のコマンドラインでは、 "-c"の後に引数が1つあり、すべて引用符で囲まれていることに注意してください。しかし、それが反対側で機能するためには、まだ引用符が必要なので、その中にエスケープされた引用符を入れる必要がありました。

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コマンドがほぼ瞬時にシェルに戻ります。その後、リモートホストとtmux attachそのセッションにSSHで接続できます。ローカルのtmuxの実行については何もないことに注意してください。リモートのみです。

また、ジョブが完了した後もセッションを維持したい場合は、コマンドの後にシェルランチャーを追加するだけですが、引用符で囲むことを忘れないでください。

ssh someone@elsewhere 'tmux new -d "~/myscript.sh; bash"'

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

これにより、コマンドが実行され、プロセスIDが割り当てられます。プロセスIDを割り当てると、-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; program-to-execute&"


1
問題は、dagorymがすでにパスワードを必要としないようにキーを設定しているが、それはまだ掛かっているということです
Max Nanasy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.