web-dev-qa-db-ja.com

リモートコマンドを実行し、ssh接続から完全に切り離します

2台のコンピューター、localpcremoteserverがあります。

localpcでいくつかのコマンドを実行するには、remoteserverが必要です。必要なことの1つは、何時間も実行されるバックアップスクリプトを開始することです。 localpcのコマンドを「実行」して、remoteserverが最初から存在しなかったように、localpcで完全に独立して実行したいと思います。

これは私がこれまでに行ったことです:

remoteserver containsには次のスクリプトがあります。

/root/backup.sh

localpcはこれを実行するようにスケジュールされています:

ssh root@remoteserver 'Nohup /root/backup.sh' &

私はこれを正しい方法で行っていますか?これを行うより良い方法はありますか?この方法で問題が発生しますか?

53
LVLAaron

実際の切り離されたコマンドを使用するには、おそらくリモートホストでscreenを使用する必要があります。

ssh root@remoteserver screen -d -m ./script
50
enzotib

近いですが、正確ではありません。

端末に依存しない

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

リモートプロセスがソケットを開いている限り、sshセッションは閉じないため、sshソケットに接続されているすべてのファイル記述子を閉じる必要があります。スクリプトの出力に興味がない場合(おそらくスクリプト自体がログファイルへの書き込みを処理しているため)、それを/dev/nullにリダイレクトします(ただし、これにより、脚本)。

ここではNohupを使用しても効果はありません。 Nohupは、プログラムの制御端末が表示されなくなった場合にHUP信号を受信しないように実行するプログラムを調整しますが、ここでは最初に端末がないため、SIGHUPをプロセスの外に送信するものはありません。青い。また、Nohupは標準出力と標準エラー(ただし、標準入力ではない)をファイルにリダイレクトしますが、それらがターミナルに接続されている場合に限り、ターミナルには接続されます。

端末からの切り離し

 aaron@localpc$ ssh root@remoteserver
 root@remoteserver# Nohup /root/backup.sh </dev/null &
 Nohup: appending output to `Nohup.out'
 [1] 12345
 root@remoteserver# exit
 aaron@localpc$ 

Nohupを使用してスクリプトを制御端末から切り離し、端末が消えたときに [〜#〜] sighup [〜#〜] を受信しないようにします。 Nohupはまた、スクリプトの標準出力と標準エラーをNohup.outというファイルにリダイレクトします(それらが端末に接続されている場合)。標準入力は自分で処理する必要があります。

リモート端末を保持する

コマンドをリモートターミナルで実行したまま、SSHセッションにアタッチしない場合は、 Screen または Tmux などのターミナルマルチプレクサーで実行します。

ssh root@remoteserver 'screen -S backup -d -m /root/backup.sh'

後でそのマシンでrootとしてscreen -S backup -rdを呼び出すことにより、スクリプトが実行されているターミナルに再接続できます。

1つのリモートコマンドの自動化

セキュリティを少し向上させるために、直接リモートrootログインをあまり広く開かないでください。特別な目的のキーペアを作成し、 /root/.ssh/authorized_keys で強制コマンドを実行します。公開鍵ファイルの内容はAAAA…== [email protected]です。キーがこの特定のコマンドの実行にのみ使用できることを指定するcommand="…"を含むオプションのコンマ区切りリストを追加します。オプションとキーはすべて1行で記述してください。

command="/root/backup.sh </dev/null >/dev/null 2>/dev/null &",no-port-forwarding,no-agent-forwarding,no-x11-forwarding,no-pty,no-user-rc AAAA…== [email protected]

SSHなどのリモートログインからリモートコマンドを実行するための標準的なレシピは次のとおりです。

Nohup command </dev/null >command.log 2>&1 &

commandがファイル自体へのロギングを処理するシェルスクリプトである場合、command.log/dev/nullに変更できます。これを開始したら、すぐにログオフします。

その行のすべてが必要です。

Nohupは、ログインセッションが切断された場合にシェルがプロセスを妨害しないように指示します。

</dev/nullは、入力を待機しないように指示します

>command.logは、この名前付きログファイルにメッセージを送信するように指示します

2>&1は、stderrメッセージを同じログファイルに送信するように指示します。場合によっては、2つのファイルを用意し、2番目のファイルはエラーメッセージを収集し、最初のファイルは通常のアクティビティメッセージを収集することをお勧めします。これにより、すべてが正しく機能していることを確認しやすくなります。

&は、このプロセスを切り離して、デーモンプロセスとしてバックグラウンドで実行するように指示します。

12
Michael Dillon

このスレッドは非常に役に立ちましたが、私の解決策は少し異なる必要がありました。

Screenソリューションは、不要なscreenプロセスが実行されたままになるため、好きではありません。このように使用されるリダイレクトとnohups:

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

sshコマンドと一緒に使用すると、動作しませんでした。

実際のスクリプトを実行するラッパースクリプトをリモートマシンに作成しました。ラッパースクリプトは、リダイレクトとNohupを設定します。このようなもの:

backupwrapper.sh:
Nohup backup.sh > /dev/null 2>&1 &

次に、クライアントマシンで実行します(リダイレクトしないことに注意してください)。

# ssh remotemachine "backupwrapper.sh"
#

Sshコマンドはすぐに戻り、接続は終了し、スクリプトは実行されたままになります。

11
rui

Nilsによると のように、rootがsshを介してログインすることを許可することはセキュリティリスクです。また、ログのないマシンで実質的なジョブを実行しないことをお勧めします。何か問題が発生した場合は、トラブルシューティングメッセージが表示されていると便利です。それを行う方法を示す他の答えがあります。しかし、ここに私があなたが求めたものを達成することをお勧めする方法があります。すべてsh(1)に組み込まれています。 GNU screenの必要はありません(ただし、これは賢い解決策だと思います)。この文字列をコマンドに追加します:>&- 2>&- <&- &>&-はstdoutを閉じることを意味します。 2>&-はstderrを閉じることを意味します。 <&-は標準入力を閉じることを意味します。 &は、バックグラウンドで実行することを意味します。

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$
6
tbc0

remoteserverのリモートコマンドをバックグラウンドで実行する必要があります。その方法では、localpcのsshコマンドをバックグラウンドで実行します。

それとは別に、root-sshを許可することは悪い考えです。

したがって、remoteserverをセットアップします。ユーザーbackupがrootとして/root/backup.shを実行するsudoers行。

「良い」パスワードなしでそのユーザーを作成できます。

コマンドSudo /root/backup.sh &をコマンドとして~backup/.ssh/authorized_keysに入れます— localpc(そのスクリプトをトリガーする人)からの公開鍵と一緒に。

0
Nils