LoginSignup
0
0
お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

SSH接続を閉じてもリモートのサーバでプログラムが動作し続けるようにする

Posted at

要約

リモートのコンピュータでプログラムを実行し、そのプログラムをバックグラウンドで継続したいということがあるかと思います。例えば、時間のかかるスクリプトを実行して一度パソコンを閉じるときや、APIサーバのような常駐させるプログラムを実行するときです。

その時には、以下のようにコマンドを実行することで、リモート接続を切断してもプログラムが動作し続けます。

nohup 実行したいコマンド &

例)
nohup python main.py &

環境によってはnohupがなくてもバックグラウンドで持続するのですが、違いをあまり理解できていないです…。参考にあげたこちらの記事が詳しく説明してありました。

背景

実行に時間のかかるスクリプトがあり、研究室のサーバで実行をしておくことにしました。VSCodeのRemote SSHからサーバに接続し、python main.py &のように実行してVSCodeを閉じ、少し後に確認をするとプログラムの実行がキャンセルされて止まっていました。

プログラムをサーバ上で動かし続けてローカルのVSCodeは閉じておきたかったので、その方法を確認しました。

原因

ターミナルが終了したときにSIGHUPというシグナルが送られるようです。

元々、コマンドの後ろに&と付けることでプログラムをバックグラウンドで実行できると聞いたことがあったので、python main.py &と実行していました。ですが、このように実行した場合でも上記のSIGHUPのシグナルを受け取るとプログラムが停止されてしまうそうです。

したがって以下のような流れでプログラムの実行がキャンセルされていたようです。

  1. VSCodeを閉じたことによりターミナルが終了しSIGHUPのシグナルが送られる。
  2. バックグラウンドで実行されていたプログラムがSIGHUPのシグナルにより終了させられる。

対策

一番シンプルだったのが、SIGHUPを受け取っても実行が止まらないように設定することです。実行コマンドの前にnohupと付けることで、そのコマンドはSIGHUPを受け取っても終了しないようになるそうです。

したがって、nohup python main.py &のように実行することで、pythonのスクリプトがバックグラウンドで実行され、かつターミナルが終了しても実行され続けるようになりました。

動作の確認

今までの実行方法

まず、VSCodeのリモートSSHを使ってサーバに接続します。

サーバ内で確認のために以下のようなプログラムを作成しました。このプログラムは3秒おきに現在時刻を出力し続けます。print関数のflush=Trueは、printの出力のバッファリングをしないようにしています。これをしないと後述のnohup.outに出力が記録されませんでした。

python main.py &としてプログラムを実行します。この際、プログラムはバックグラウンドで実行され、ps aux | grep pythonなどでプロセスを確認するとpythonのプログラムが実行されていました。

main.py
import time
from datetime import datetime

while True:
    now = datetime.now()
    print(now.strftime("%Y-%m-%d %H:%M:%S"), flush=True)

    time.sleep(3)

一度VSCodeを閉じてターミナルを終了します。

再度リモートSSHでサーバに接続し、ps aux | grep pythonのようにプロセスを確認してみると、先ほどのPythonのプロセスは見られませんでした。

nohupを付けた実行方法

上と同様のプログラムを、今度はnohup python main.py &として実行します。ps aux | grep pythonで該当のプログラムを確認できます。

ここで一度VSCodeを閉じて、再度リモートSSHでサーバに接続します。

ps aux | grep pythonでプロセスを確認すると、まだ先ほどのPythonのプログラムが実行され続けていました!

nohupのときの標準出力

nohupを使ってプログラムを実行すると、出力はターミナルには表示されなくなります。代わりに実行したディレクトリにnohup.outというファイルが作成されて、そこに出力が記録されるようです。

ただ、Pythonの標準のprint関数だと出力がバッファリングされてnohup.outファイルに出力が記録されませんでした。そのため、上記のプログラムでは出力をバッファリングしないようにしています。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0