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


48

私は2台のコンピュータを持っている、localpcremoteserver

localpcいくつかのコマンドを実行する必要がありますremoteserver。必要なことの1つは、数時間実行するバックアップスクリプトを開始することです。私はコマンドlocalpcを「発火」させてから、完全に独立して実行したいremoteserverと思いlocalpcます。

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

remoteserver 次を含むスクリプト:

/root/backup.sh

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

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

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


stackoverflow.com/questions/19996089/...stackoverflow.com/questions/29142/...スクリーン/ tmuxのなどを使用していないこの問題のために有用なアプローチ...の数を提供
ポール・

回答:


47

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

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

私はこのアイデアが好きです。スクリプトが終了しても、画面はまだ実行中です...そして、次に実行したいときに、どういうわけか再接続する必要がありますか?
LVLAaron

@AaronJAnderson:いいえ、コマンドがシェルではない場合、スクリーンセッションも終了すると終了します。
enzotib

52

閉じますが、正確ではありません。

ターミナルに依存しない

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$ 

ターミナルが消えたときにSIGHUPをnohup受け取らないように、制御ターミナルからスクリプトをデタッチするために使用します。また、スクリプトの標準出力と標準エラーを、端末に接続されている場合に呼び出されるファイルにリダイレクトします。自分で標準入力を処理する必要があります。nohupnohup.out

リモート端末を維持する

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

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

screen -S backup -rdそのマシンでrootとして起動することにより、後でスクリプトが実行されている端末に再接続できます。

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

セキュリティを若干向上させるために、直接リモートルートログインをあまり広く開かないでください。特殊な目的のキーペアを作成し、に強制コマンドを与え/root/.ssh/authorized_keysます。公開鍵ファイルの内容は次のとおりですAAAA…== wibble@example.comcommand="…"この特定のコマンドの実行にのみキーを使用できることを指定するオプションを含む、オプションのコンマ区切りリストを追加します。オプションとキーはすべて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…== wibble@example.com

リストした最初のコマンドを試しました。コマンドを実行したボックスの背景にはなりません。カーソルはただそこにあり、完了するのを待ちます...おそらくバグでしょうか?
LVLAaron

リモートシステムの/ dev / nullにstdinをリダイレクトする必要がある場合があります。それがsshが終了しない理由かもしれません。
KeithB

-fローカル側でsshを「バックグラウンド」(つまり、終了、接続を閉じる)にするオプションを追加します。これはと連携して機能し&ます。nohupこの場合はオプションですが、setsid代わりに使用することを検討できます。
-Alexios

@KeithB stdinのリダイレクトもその一部ですが、stdoutとstderrもリダイレクトする必要があります。nohupはターミナルではないため、ここでは実行しません。実際、nohupはここでは役に立ちません。
ジル「SO-停止されて悪」

1
@erikbworkこれらのことについては全く手がかりがないことに注意してくださいが、議論とコメントに従うと:Gillesはコマンドで-tオプションを使用しないため、クライアントでもサーバーでも擬似端末は確立されません側。したがって、HUPは送信されません。
ビナルス

12

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

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

場合はcommand、ファイル自体へのロギングの世話をするシェルスクリプトがあり、その後は変更される可能性command.log/dev/null。これを開始したら、すぐにログオフします。

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

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

</dev/null 入力を待たないことを伝えます

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

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

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


10

このスレッドは非常に役に立ちましたが、私の解決策は少し異なっていなければなりませんでした。

スクリーンソリューションは、私が必要としないスクリーンプロセスを実行したままにするため、好きではありません。リダイレクトと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コマンドはすぐに戻り、接続は終了し、スクリプトは実行されたままになります。


6

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

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

0

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

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

したがって、次のようにセットアップします。ユーザーがrootとしてremoteserver実行するsudoers行。/root/backup.shbackup

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

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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.