こんにちは!データサイエンティストの青木和也(https://twitter.com/kaizen_oni)です!
この記事では、nohupと&を使ってバックグラウンド実行をしているプログラムを停止する方法を紹介いたします!
リモートのGPUを使用する際にはnohupを使用するのですが、「あ、ここのコード間違えてる!バックグラウンド実行止めて修正しなきゃ、、、」という場面が多々あったので、同じような場面に遭遇した方のお役に立てれば幸いです!
nohupとは?
nohupとは、Linuxにおいてプログラムのバックグラウンド実行をするときに使える便利なコマンドです。
通常はプログラムを実行している際にCtrl+Cを押したり、ターミナルを閉じると実行されていたプログラムは停止してしまいます。
しかし、nohup + [実行したいプログラム] + &の形でコマンドを実行することによって、Ctrl+Cを押したり、ターミナルを終了してもプログラムを実行し続けてくれるようになります。
その内容をまとめたのが以下の図です。
上記の表から、nohupは「ターミナルを終了してもプログラムを実行し続ける」、&は「Ctrl+Cを押してもプログラムを実行し続ける」という意味を持つことがわかります。
試しにnohup python3 sample_for.py &を実行してみた
実際に以下のひたすらDataFrameのdocumentカラムの中身を3秒おきに出力するプログラムをnohup +&を使って実行してみましょう。
import pandas as pd
import time
df = pd.read_json('../kaggle/mixtral-8x7b-v1.json')
for index, row in df.iterrows():
print(df.at[index, 'document'])
time.sleep(3)
実際にnohupと&を使ってコマンドを実行してみると、以下のように謎の数字とともに、「アウトプットはnohup.outに追加します」という文言が出てきます。
このようにnohupはプログラムの出力結果をnohup.outに書き込んでくれます。
実際にプログラムが動いているかどうかは「jobs」コマンドを入力することによって確かめることができます。
なお、上記では「jobs」コマンドを実行する前に「^C」つまりCtrl+Cを実行しているので、Ctrl+Cを実行してもプログラムが停止していないのが確認できますね。
nohup+&で実行しているプログラムを止める方法
Ctrl+Cを押しても、ターミナルを終了しても止まらないプログラムを止める方法はあるのでしょうか。
実は、いとも簡単に止めることができて、「kill -9」コマンドを使用します。
使い方としては、「kill -9」の後にプロセスIDを入力して使用します。
プロセスIDとは、実行中のプログラム(正しくはプロセス)を識別するための番号で、nohupを実行後に出てくる謎の数字の正体です。
つまり、上記の例で言えば、「kill -9 3174187」と入力すればnohupで実行したプログラムは終了してくれます。
ターミナルを閉じてしまって、プロセスIDが分からなくなってしまった場合の対処法
nohup + &はターミナルを終了して使うことも多いため、一度ターミナルを閉じると実行中のプロセスIDが分からなくなってしまう場合があります。
そんな時は以下のコマンドを使用しましょう。
ps -ef | grep [実行しているプログラム名]
例えば、先ほどの例で言えば、「ps -ef | grep sample_for.py」のようにして、バックグラウンド実行しているプログラムのプロセスIDを探しに行きます。
コマンドを実行すると2行の結果が返ってきますが、2行目は「grep」と書いてあることから、今現在実行した「grep sample_for.py」であることが分かります。
そして1行目こそが求めていたバックグラウンド実行中のプログラムの内容になります。
なお、「kill -9」に入力する数字は左側に書いてある「3175654」の方になります。
右側の方は「PPID(=親プロセスのID)」と言って、プログラムを実行している大元のプログラムのプロセスIDを指します。
実は、上記nohupをリモートGPU上で実行しているので、「kill -9 3173542」と入力すると、リモートGPU(=親プロセス)との接続が切れてしまうのです。
ps -ef | grep sample_for.pyの意味
「ps」は実行中のプロセスを表示するコマンドです。
「-e」はpsコマンドのオプションで、すべてのユーザーの実行中プロセスを表示します(every)
「-f」もpsコマンドのオプションで、情報を省略せずに完全な状態で表示します。(full)
例えば、-efを省略すると、かなりざっくりとした実行中プロセスの結果が返ってきます。
「|」は左のコマンドの実行結果を右のコマンドに渡す、という意味です。
つまり、「ps -ef」で出力した結果を「grep sample_for.py」に引数のような形で渡しているということです。
「grep sample_for.py」は受け取った情報のうち、「sample_for.py」という記述があるもののみを取り出す(grep)します。
まとめ
今回の記事では、nohup+&でバックグラウンド実行しているプログラムを停止する方法を紹介しました!
モデルの学習などのGPUを使って長時間プログラムを動かす必要がある場合にはnohupは重宝しますし、nohupで動かしているプログラムを修正するためにプログラムを止める機会は出てくるかと思いますので、ぜひ今回の記事のTipsを活用してください!
コメント