2台のコンピューター、localpc
とremoteserver
があります。
localpc
でいくつかのコマンドを実行するには、remoteserver
が必要です。必要なことの1つは、何時間も実行されるバックアップスクリプトを開始することです。 localpc
のコマンドを「実行」して、remoteserver
が最初から存在しなかったように、localpc
で完全に独立して実行したいと思います。
これは私がこれまでに行ったことです:
remoteserver
containsには次のスクリプトがあります。
/root/backup.sh
localpc
はこれを実行するようにスケジュールされています:
ssh root@remoteserver 'Nohup /root/backup.sh' &
私はこれを正しい方法で行っていますか?これを行うより良い方法はありますか?この方法で問題が発生しますか?
実際の切り離されたコマンドを使用するには、おそらくリモートホストでscreen
を使用する必要があります。
ssh root@remoteserver screen -d -m ./script
近いですが、正確ではありません。
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
を呼び出すことにより、スクリプトが実行されているターミナルに再接続できます。
セキュリティを少し向上させるために、直接リモート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番目のファイルはエラーメッセージを収集し、最初のファイルは通常のアクティビティメッセージを収集することをお勧めします。これにより、すべてが正しく機能していることを確認しやすくなります。
&
は、このプロセスを切り離して、デーモンプロセスとしてバックグラウンドで実行するように指示します。
このスレッドは非常に役に立ちましたが、私の解決策は少し異なる必要がありました。
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コマンドはすぐに戻り、接続は終了し、スクリプトは実行されたままになります。
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
$
remoteserver
のリモートコマンドをバックグラウンドで実行する必要があります。その方法では、localpc
のsshコマンドをバックグラウンドで実行します。
それとは別に、root-sshを許可することは悪い考えです。
したがって、remoteserver
をセットアップします。ユーザーbackup
がrootとして/root/backup.sh
を実行するsudoers行。
「良い」パスワードなしでそのユーザーを作成できます。
コマンドSudo /root/backup.sh &
をコマンドとして~backup/.ssh/authorized_keys
に入れます— localpc
(そのスクリプトをトリガーする人)からの公開鍵と一緒に。