SSH を取得してターゲット マシンのバックグラウンドでコマンドを実行する

StackOverflow https://stackoverflow.com/questions/29142

  •  09-06-2019
  •  | 
  •  

質問

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

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

何か案は?注意すべき点の 1 つは、ターゲット マシンへのログインでは常にテキスト バナーが生成されることです。 SSH キーが設定されているため、パスワードは必要ありません。

役に立ちましたか?

解決

1 年前に書いたプログラムでこの問題が発生しましたが、答えはかなり複雑であることがわかりました。ウィキペディアの記事で説明されているように、出力リダイレクトだけでなく nohup も使用する必要があります。 ノハップ, 、便宜のためにここにコピーしました。

バックグラウンドのジョブを介してログインした場合、バックグラウンドのジョブは、バックグラウンドのジョブが人種状態のためにシェルをログアウトに掛けることができるためです[2]。この問題は、3つのI/Oストリームすべてをリダイレクトすることで克服することもできます。

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

他のヒント

これは私にとって最もクリーンな方法でした:-

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

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

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 を直接使用してシェルを起動することもできます。

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

ナイスローンチ

もう 1 つのトリックは、nice を使用してコマンド/シェルを起動することです。

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

カットアンドペーストできる実際の例を示したかっただけです。

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

接続を開いたままにしない/できない場合は、次を使用できます 画面, インストールする権限がある場合。

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

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 構成がいくつかあるので、試してみてください。

最も早くて簡単な方法は、「at」コマンドを使用することです。

ssh user@target "現在 -f /home/foo.sh"

望むものを得るには、これらの答えをいくつか組み合わせる必要があると思います。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 にリダイレクトします。

これは私にとっては何度もうまくいきました:

ssh -x remoteServer "cd yourRemoteDir; ./yourRemoteScript.sh </dev/null >/dev/null 2>&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"

私も同じことをやろうとしていましたが、Java からやろうとしたため複雑さが増しました。そこで、Java を実行しているあるマシンで、別のマシンでバックグラウンドで (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.

これを機能させるには少し試行錯誤が必要でしたが、今ではうまく機能しているようです。

こんな風にできるんですね…

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

持っていると非常に便利に思えました リモート を使用した tmux セッション tmux new -d <shell cmd> 次のような構文:

ssh someone@elsewhere 'tmux new -d sleep 600'

これにより、新しいセッションが開始されます elsewhere ローカル マシン上の host および ssh コマンドは、ほぼ瞬時にシェルに戻ります。その後、リモート ホストに SSH 接続して、 tmux attach そのセッションへ。ローカル tmux の実行については何もなく、リモートのみが実行されていることに注意してください。

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

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

これが必要なものだと思います:最初にインストールする必要があります 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

まず次の手順に従います。

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 として a から B として b にログインできます。

a@A:~> ssh b@B

これはパスワードを入力しなくても機能します

ssh b@B "cd /some/ディレクトリ;実行するプログラム &"

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top