LinuxLinux [リナックス / ライナックス]オープンソースのOSカーネル環境で時間のかかるスクリプトやプログラムを実行している途中に、SSHSSH [エスエスエイチ]Secure Shell。暗号化されたリモート接続プロトコル接続が切れたりターミナルを閉じたりして処理が途中で止まってしまった経験はないでしょうか?
そのような事態を防ぐために役立つのが nohupコマンド です。
本記事では、nohupコマンドの基本的な使い方から、標準出力(ログ)のリダイレクト、バックグラウンド実行(&)との違いやプロセスの終了方法まで、実務でよく使うパターンをわかりやすく解説します。
nohupコマンドとは?
nohupは「no hangup(ハングアップしない)」の略で、ログアウトしたりターミナルを閉じたりしても、コマンドの実行を継続させるためのLinuxコマンドです。
通常、ターミナル上で実行しているコマンドは、ターミナルやSSHセッションが終了すると、SIGHUP(ハングアップシグナル)の影響で終了する場合があります。
nohupを使うと、実行するコマンドがSIGHUPを受けても終了しないようにできます。そのため、SSH切断やログアウトによるSIGHUPの影響を受けにくくなります。
バックアップ処理や機械学習の学習処理など、数時間〜数日かかるような時間のかかる処理を実行する際によく利用されます。
nohupコマンドの基本構文
構文は非常にシンプルです。実行したいコマンドの先頭にnohupを付けるだけです。
nohup コマンド [引数]しかし、実務ではほとんどの場合、末尾に&をつけてバックグラウンド実行と組み合わせて使用されます。
nohup コマンド &バックグラウンド実行(&)とnohupの違い
「末尾に&をつければ裏で動くのでは?」と思う方もいるかもしれませんが、&とnohupには明確な役割の違いがあります。
&(バックグラウンド実行): ターミナルの操作をブロックせずに、裏で処理を実行します。しかし、ターミナルを閉じると処理は終了してしまいます。 (※正常なログアウト(exit)であれば&のみでもプロセスは生存し続けることが多いですが、不意の回線切断やウィンドウの強制クローズ時にはカーネルからシグナルが送られて落ちるため、予防策としてnohupを最初から付けるのが安全です)nohup: ターミナルを閉じても処理が終了しないようにします(SIGHUPを無視)。しかし、これだけだと処理が終わるまでターミナルの操作ができなくなります。
つまり、「ターミナルを操作可能にしたまま(&)、ターミナルを閉じても処理を継続させる(nohup)」 ために、両方を組み合わせて使うのが一般的です。
nohupコマンドの使い方と実行例
基本的な実行方法
時間がかかるシェルスクリプト backup.sh を実行する例です。
nohup ./backup.sh &実行すると、以下のようなメッセージが表示されます。
$ nohup ./backup.sh &[1] 12345nohup: ignoring input and appending output to 'nohup.out'[1]はジョブ番号、12345はプロセスID(PID)です。ignoring inputは、「標準入力が端末に接続されている場合、nohupが自動的に標準入力を/dev/nullにリダイレクトして無視する」ことを意味しています。appending output to 'nohup.out'は、「コマンドの出力(ログ)をnohup.outというファイルに追記します」という意味です。
nohupをデフォルトのまま実行すると、コマンドの標準出力と標準エラー出力は自動的にカレントディレクトリの nohup.out というファイルに保存されます。
(※カレントディレクトリに書き込み権限がない場合は、自動的にユーザーのホームディレクトリ配下の $HOME/nohup.out に保存される仕様になっています。稀にハマるポイントなので覚えておくと便利です)
出力先(ログファイル)を変更する
デフォルトの nohup.out ではなく、指定したファイルにログを出力したい場合は、リダイレクト(>)を使用します。
nohup ./backup.sh > backup.log &標準エラー出力もログに含める(2>&1)
プログラムがエラーを吐いた場合のエラーメッセージ(標準エラー出力)も同じログファイルに記録したい場合は、コマンドの末尾に 2>&1 を追加します。実務ではこの書き方が最もよく使われます。
nohup ./backup.sh > backup.log 2>&1 &| 記述 | 意味 |
|---|---|
> | 標準出力を指定したファイルに書き込む |
2>&1 | 標準エラー出力(2)を標準出力(1)と同じ場所に出力する |
& | バックグラウンドで実行する |
ログを全く残さない場合(/dev/null)
ログを出力する必要がない場合は、出力先を /dev/null に指定して破棄します。
nohup ./backup.sh > /dev/null 2>&1 &nohupで実行中のプロセスを確認・終了する方法
ターミナルを閉じても裏で実行され続けるため、処理が現在どうなっているかを確認したり、途中でやめさせたりしたい場合があります。
プロセスの実行状況(ログ)を確認する
ログファイルの中身を見ることで、処理の進行状況を確認できます。
リアルタイムでログを追いたい場合は tail -f コマンドが便利です。
tail -f backup.log(終了するには Ctrl + C を押します)
実行中のプロセスID(PID)を確認する
バックグラウンドで動いているプロセスを確認するには ps コマンドを使います。
ps aux | grep backup.shuser 12345 0.0 0.1 12345 6789 pts/0 S 10:00 0:00 bash ./backup.sh上記の場合、12345 がプロセスID(PID)です。
プロセスを終了する
実行中のプロセスを途中で止めたい場合は、ps コマンドで調べたプロセスID(PID)を指定して kill コマンドを実行します。
kill 12345kill コマンドはデフォルトで SIGTERM を送信して通常終了を要求します。それでも終了しない場合に、最後の手段として -9(SIGKILL)オプションを使用します。プロセス自身が後処理する機会を与えずに強制終了するため、最初から -9 を使うことは推奨されません。
kill -9 12345実務でハマりがちな罠とトラブルシューティング
現場で nohup を使う際によく発生するトラブルとその解決策を紹介します。
パイプライン(|)を使うと右側のコマンドが落ちる
単に nohup cmd1 | cmd2 & と実行した場合、nohup の保護対象になるのは左側の cmd1 のみです。そのため、SSHが切断されると右側の cmd2 は保護されずに落ちてしまいます。
パイプライン全体を保護したい場合は、コマンド全体を一つのシェルで実行するように包む必要があります。
nohup sh -c 'cmd1 | cmd2' > output.log 2>&1 &どこにも書き込み権限がないとコマンド自体が起動しない
カレントディレクトリにも、フォールバック先の $HOME にも書き込み権限がない(nohup.out を作成・追記できない)場合、nohup はコマンドを起動できずにエラー(終了ステータス125)で強制終了してしまいます。
このような環境では、明示的に書き込み可能な場所へリダイレクトするか、/dev/null に破棄する指定が必須になります。
nohup ./backup.sh > /tmp/output.log 2>&1 &現代のLinux環境(systemd)での強制終了
AlmaLinuxなど一部のモダンなLinuxディストリビューションでは、systemd-logind の設定で KillUserProcesses=yes になっている場合があります。
この設定が有効だと、ログアウト時にユーザープロセスが問答無用で丸ごとクリーンアップ(強制終了)されるため、SIGHUPを無視する nohup では防ぐことができません。
プロセスがどうしても落ちてしまう場合は、loginctl show-session などで設定を確認し、必要に応じて systemd-run を利用してユーザーセッション外で実行するなどの対策をご検討ください。
まとめ
nohup コマンドは、時間のかかるバッチ処理やスクリプトを実行する際の必須知識です。
最後に、最もよく使う定型文を振り返っておきましょう。
nohup 実行したいコマンド > 出力ファイル名.log 2>&1 &SSHでLinuxサーバーに接続して処理を実行している場合、SSH接続を切断したり、手元のPCをシャットダウンしたりしても、サーバー上の処理を継続させたいときに活用できます。
以上で本記事の解説を終わります。
よいITライフを!
人気記事
- 1
- 2
- 3
- 4
- 5
Rocky Linux対応。実際にWebサーバーを公開するまでのプロセスを体験できる、最も確実で実践的なガイドブックです。