SSHでリモートサーバーに接続して長時間かかるスクリプトやバッチ処理を実行中、ネットワークの切断やターミナルの誤終了によって処理が強制終了してしまった経験はないでしょうか。nohup(ノーハップ)コマンドを使えば、SSH接続を切断(ログアウト)した後もプロセスを中断させずにバックグラウンドで継続実行させることができます。
ただし、「nohup 単体ではバックグラウンド化しない」「& だけだと回線切断時に落ちる」「標準出力が nohup.out に溢れる」といった落とし穴も存在します。本記事では、実務で即コピペできる鉄板コマンド構文、nohup.out のログ制御、実行中プロセスの確認(ps / pgrep)および安全な停止(kill / pkill)の手順まで網羅して解説します。
【最速コピペ】nohup の鉄板コマンド
# 1. ログをファイルに記録してバックグラウンド実行(標準出力・標準エラー出力を統合)
nohup ./long-task.sh > task.log 2>&1 &
# 2. ログが不要な場合(/dev/null に破棄し、nohup.out も生成させない)
nohup ./long-task.sh > /dev/null 2>&1 &
# 3. 再接続後にプロセスが動いているか確認
pgrep -a -f long-task.sh
ps aux | grep long-task.sh
# 4. 実行中のプロセスを停止
kill $(pgrep -f long-task.sh)
即コピペで使える nohup 鉄板コマンド構文早見表
実務でよく使われる nohup の代表的なユースケースと構文をまとめました。
| 用途・ユースケース | コマンド構文 | 解説 |
|---|---|---|
| 標準出力・エラーをログ保存(上書き) | nohup command > app.log 2>&1 & |
app.log に標準出力・エラー出力をまとめて保存しバックグラウンド実行 |
| ログを追記保存 | nohup command >> app.log 2>&1 & |
既存ログを残したまま末尾に追記(定期バッチ向け) |
| ログ完全破棄(nohup.out 不要) | nohup command > /dev/null 2>&1 & |
ディスク容量を消費せずに出力をすべて破棄 |
| 入力も完全遮断(警告メッセージなし) | nohup command < /dev/null > app.log 2>&1 & |
nohup: ignoring input メッセージを出さずに完全デタッチ |
| Pythonスクリプトの即時ログ出力 | nohup python -u app.py > app.log 2>&1 & |
-u で標準出力のバッファリングを無効化し、ログを即時反映 |
| Node.js / アプリのバックグラウンド起動 | nohup npm start > app.log 2>&1 & |
Node.js サーバー等を切断後も稼働継続 |
| root権限が必要な処理 | sudo nohup command > app.log 2>&1 & |
管理者権限で実行(ログファイルの所有者は root になります) |
| パイプライン全体の保護 | nohup bash -c 'cmd1 | cmd2' > app.log 2>&1 & |
パイプ後続コマンドも含めて切断耐性を持たせる |
nohup とは?仕組みと基本構文
nohup(「no hang up」の略称、読み方:ノーハップ)は、Linux/Unix 環境で端末切断時に送信される SIGHUP(ハングアップシグナル・シグナル番号 1)を無視(ignore)してコマンドを実行するためのユーティリティです。
通常、SSH クライアントを終了したり回線が切断されたりすると、カーネルおよび親シェルからそのセッション配下のすべてのプロセスに対して SIGHUP が送信され、処理が道連れで終了(強制切断)します。nohup を前置して起動されたプロセスは SIGHUP を無視するため、親シェルや端末が消滅してもプロセスが孤立(init / systemd が親プロセス PID 1 として引き取り)した状態で実行を継続できます。
構文
nohup コマンド [引数...] [&]
nohup 単体には動作を変更する特別なオプションはなく、--help と --version のみが用意されています。
重要:nohup は「バックグラウンド化」するコマンドではありません
nohup が行うのは「SIGHUPシグナルを無視させる」ことだけです。末尾に &(バックグラウンド実行)を付けずに nohup ./script.sh と実行すると、現在の端末のフォアグラウンドを占有したままになります。実務では必ず末尾に & を付けて実行してください。
「nohup コマンド > 出力先 2>&1 &」の書き方を完全分解
現場で最も使われる定型文 nohup command > output.log 2>&1 & の各パーツがどのような役割を果たしているかを分解して確認します。
nohup command > output.log 2>&1 &
(1) (2) (3) (4) (5)
| 番号 | パーツ | 役割 | 詳細 |
|---|---|---|---|
| (1) | nohup |
SIGHUP シグナルを無視 | SSH切断やターミナル終了時の道連れ終了を防止する |
| (2) | command |
実行対象のコマンド・スクリプト | シェルスクリプト、Python、Node.js、DBバックアップなど |
| (3) | > output.log |
標準出力(fd 1)のリダイレクト | 画面に出力される通常メッセージを output.log に書き込む(上書き) |
| (4) | 2>&1 |
標準エラー出力(fd 2)の合流 | 標準エラー出力を標準出力(fd 1)と同じ書き込み先に統合する |
| (5) | & |
バックグラウンド実行 | シェルからプロセスをバックグラウンドに回し、即座にプロンプトを復帰させる |
なぜ「2>&1」は「> output.log」の後ろに書くのか?
リダイレクトは左から右へ順番に解釈されます。
- 正しい順序(
> output.log 2>&1):
まず標準出力(1)がoutput.logを向きます。次に2>&1により、標準エラー(2)が「現在標準出力が向いている先(output.log)」に向けられます。結果として、両方がoutput.logに集約されます。 - 誤った順序(
2>&1 > output.log):
まず標準エラー(2)が「現在の標準出力の向き先(端末画面)」に向けられます。その後に標準出力(1)だけがoutput.logに変更されるため、エラーメッセージがファイルに記録されず画面に漏れてしまいます。
nohup.out の仕組みとログの制御方法
リダイレクト先を自分で指定せずに nohup command & を実行すると、nohup は出力を自動的に nohup.out というファイルへリダイレクトします。
nohup.out が作成される場所のルール
- 第1候補:コマンドを実行したカレントディレクトリの
./nohup.out - 第2候補(フォールバック):カレントディレクトリに書き込み権限がない場合、実行ユーザーのホームディレクトリ
$HOME/nohup.outに作成されます。
ホームディレクトリにも書き込み権限がない場合は起動エラー(Permission denied)となります。
nohup.out を作成させない・肥大化させない方法
nohup.out が意図せず肥大化してサーバーのディスク容量(ストレージ)を圧迫するトラブルは非常によくあります。以下の対策を使い分けましょう。
# 【対策1】出力先を明示的に指定する(nohup.out は生成されません)
nohup ./my_script.sh > /var/log/my_app/app.log 2>&1 &
# 【対策2】ログが一切不要な場合は /dev/null に破棄する
nohup ./my_script.sh > /dev/null 2>&1 &
# 【対策3】日付付きログファイルに分けて出力する
nohup ./my_script.sh > "backup_$(date +%Y%m%d_%H%M%S).log" 2>&1 &
「nohup: ignoring input」メッセージを非表示にする方法
nohup は標準入力が端末に接続されている場合、自動的に入力を切り離して nohup: ignoring input... という案内メッセージを出力します。このメッセージを完全に消したい場合は、標準入力にも < /dev/null を指定します。
nohup ./script.sh < /dev/null > app.log 2>&1 &
実行中のプロセス確認手順(ps / pgrep / jobs)
nohup でバックグラウンド起動した後は、プロセスが正しく稼働しているかを確認する必要があります。
1. 起動直後の PID を取得・記録しておく(推奨)
コマンドを実行した直後に、シェル変数 $!(直前にバックグラウンド実行されたプロセスのPID)をファイルに保存しておくと、後からの確認や停止が極めてスムーズになります。
nohup python -u batch.py > batch.log 2>&1 &
echo $! > /tmp/batch.pid
# 記録した PID で状態を確認
cat /tmp/batch.pid
# 出力例: 48210
2. 同一セッション内での確認:jobs コマンド
SSH接続を切断する前の同一ターミナルセッション内であれば、jobs コマンドで実行中のバックグラウンドジョブ一覧を確認できます。
jobs -l
# 出力例:
# [1]+ 48210 Running nohup python -u batch.py > batch.log 2>&1 &
※ 一度ログアウトして再接続した新しいシェルセッションでは、jobs の管理テーブルが引き継がれないため、後述の ps や pgrep を使用します。
3. SSH再接続後・別端末からの確認:ps / pgrep コマンド
SSHに再接続した後は、pgrep や ps コマンドでプロセスを検索します。
# pgrep でプロセス名・引数付きで検索
pgrep -a -f batch.py
# 出力例: 48210 python -u batch.py
# ps コマンドで詳細なCPU/メモリ使用率と起動状態を確認
ps aux | grep batch.py | grep -v grep
4. ログのリアルタイム追跡:tail -f
tail -f を使うことで、プロセスの出力ログをリアルタイムに監視できます。
tail -f batch.log
プロセスの停止と強制終了(kill / pkill)
nohup で起動したプロセスは SIGHUP(1)を無視するだけであり、通常の終了シグナル SIGTERM(15) や強制終了 SIGKILL(9) は正常に受け付けます。
1. PID を指定して安全に停止(kill)
まずは通常の終了シグナル(SIGTERM)を送信し、プロセス側に終了処理(ファイルの保存やDB接続のクローズ)を行わせます。
# 通常停止(SIGTERM)
kill 48210
# PIDファイルから停止する場合
kill $(cat /tmp/batch.pid)
2. 終了しない場合の強制停止(kill -9)
プロセスが応答しない場合やループに入って停止しない場合は、強制終了シグナル(SIGKILL)を送ります。
# 強制終了(SIGKILL)
kill -9 48210
3. プロセス名を指定して一括停止(pkill)
PIDを調べる手間を省きたい場合は、pkill を使ってコマンド名や引数でまとめて停止できます。
# batch.py に一致するプロセスを通常終了
pkill -f batch.py
# 止まらない場合は強制終了
pkill -9 -f batch.py
安全な停止のベストプラクティス
- まず
kill <PID>(またはpkill -f <name>)を実行する。 kill -0 <PID>やpgrep -f <name>でプロセスが終了したか確認する。- 5〜10秒経過してもプロセスが残存している場合のみ
kill -9 <PID>を使用する。
【実測検証】「&」だけ vs nohup vs disown vs setsid の切断耐性
「& だけを付けたバックグラウンド実行と、nohup や disown、setsid は何が違うのか?」という疑問について、Ubuntu 24.04 LTS / Bash 5.2 環境で実際の切断挙動を実測検証しました。
検証結果の比較表
| 起動方法 | 突然の回線断・SSH強制切断 | 正常なログアウト(exit) |
SIGHUPシグナルの無視 | 実行後の後付け適用 |
|---|---|---|---|---|
command & のみ |
❌ 強制終了 | ⭕ 生存(既定設定時) | なし | 不可 |
nohup command & |
⭕ 生存 | ⭕ 生存 | あり(無視) | 不可(起動時のみ) |
command & + disown |
⭕ 生存 | ⭕ 生存 | なし(ジョブ表から除外) | 可能(後付け可) |
setsid command |
⭕ 生存 | ⭕ 生存 | なし(新セッション化) | 不可(起動時のみ) |
なぜ「&」だけでも exit ログアウトなら生き残るのか?
Bash には huponexit というシェルオプションが存在します。これが off(デフォルト)の場合、ユーザーが exit コマンドで正常にログアウトした際には Bash は配下のジョブに SIGHUP を送信しません。そのため、command & だけでもプロセスが残ります。
しかし、Wi-Fiの瞬断、PCのスリープ、SSHクライアントのクラッシュなど「予期せぬ切断」が発生した場合は、OSカーネルが制御端末の消滅を検知してセッション全体へ容赦なく SIGHUP を送信します。このとき nohup が付いていないプロセスは即座に道連れ終了してしまいます。これが実務で「必ず nohup を付けるべき」とされる最大の理由です。
プロセスが SIGHUP を無視しているか確認する方法
Linux では /proc/<PID>/status 内の SigIgn(無視しているシグナルの16進マスク)を見ることで、そのプロセスが本当に SIGHUP を無視しているかを客観的に確認できます。
# nohup ありで起動
nohup sleep 300 > /dev/null 2>&1 &
# [1] 50123
grep SigIgn /proc/50123/status
# SigIgn: 0000000000000001 ← 最下位ビットが 1(末尾が奇数)なら SIGHUP を無視している
実務で役立つ応用テクニックと注意点
1. Pythonスクリプト実行時は「python -u」を付ける
Python を nohup python script.py > script.log 2>&1 & で実行すると、標準出力が端末ではなくファイルに向けられたことで Python 側がバッファリングモードに入り、tail -f script.log を見てもログがリアルタイムに更新されない現象が発生します。
これを防ぐには、-u オプション(非バッファモード) を付与します。
nohup python -u script.py > script.log 2>&1 &
2. パイプライン全体を保護する場合は「bash -c」で包む
単に nohup cmd1 | cmd2 & と書くと、nohup は左側の cmd1 にしか適用されず、右側の cmd2 は SIGHUP を受けて終了してしまいます。
パイプライン全体を切断から保護するには、bash -c(または sh -c)で1つのコマンドとしてラップします。
nohup bash -c 'mysqldump -u root mydb | gzip > /backup/mydb.sql.gz' > dump.log 2>&1 &
3. すでに起動してしまったプロセスを救済する(disown)
「nohup を付け忘れて command & で動かしてしまったが、今すぐログアウトしたい」という場合は、シェル組み込みコマンドの disown を使います。
# 1. 実行中のジョブ番号を確認
jobs
# [1]+ Running ./long-task.sh &
# 2. ジョブをシェルの管理対象から外す
disown %1
※ disown で切断耐性は付きますが、すでに出力先が端末に向いている場合、切断後の標準出力は失われます。重要なログを残したい場合は最初から nohup command > log 2>&1 & で起動してください。
4. tmux / screen / systemd との使い分け
| ツール / 手段 | 最適なユースケース | 特徴・メリット |
|---|---|---|
| nohup | 単発のバッチ処理、DB移行、スクリプト実行 | 追加インストール不要、1行で手軽に即実行可能 |
| tmux / screen | 対話的操作が必要な作業、進捗画面を見ながらの作業 | ログアウト後も同じ端末画面(セッション)に再接続(アタッチ)して作業再開できる |
| systemd | Webサーバー、常駐デーモン、自動起動が必要なサービス | OS再起動時の自動起動、異常終了時の自動再起動(Restart=always)など本格的な管理が可能 |
トラブルシューティング(よくある疑問・FAQ)
Q1. nohup を付けたのにSSHログアウト後にプロセスが停止していました
以下の原因を順に確認してください:
- systemd-logind の KillUserProcesses 設定:
一部のディストリビューション(RHEL系等)ではKillUserProcesses=yesに設定されており、ログアウト時にユーザープロセスが全停止させられます。loginctl show-session | grep KillUserProcessesで確認し、該当する場合はsystemd-run --user --scopeまたは systemd サービス化を検討してください。 - OOM Killer(メモリ不足)による強制終了:
SIGHUP 以外の原因(メモリ枯渇)でカーネルに殺された可能性があります。dmesg -T | grep -i oomまたはjournalctl -k | grep -i oomで確認してください。 - OS/サーバーの再起動:
uptimeコマンドでサーバー自体が再起動していないか確認してください(nohupはOS再起動には耐えられません)。
Q2. nohup.out のログが肥大化してディスクを圧迫しています
実行時に /dev/null へ捨てるか、logrotate 等でローテーション管理される専用ディレクトリへ出力先を指定してください。
# ログ破棄
nohup ./worker.sh > /dev/null 2>&1 &
Q3. コマンドの起動自体に失敗したか確認するには?
nohup は起動失敗時に固有の終了ステータスを返します。
127:指定したコマンドが見つからない(パスの間違いなど)126:コマンドは見つかったが実行権限がない(chmod +xが必要)125:nohup自体のエラー(出力先への書き込み権限不足など)
バックグラウンド実行時はログファイルの先頭行に nohup: failed to run command... と記録されているかを確認してください。
まとめ
nohup コマンドは、SSH接続の切断に左右されずにバックグラウンドで安全に処理を完遂させるための基本ツールです。
- 鉄板の基本形:
nohup command > output.log 2>&1 &を定型として覚える - nohup はバックグラウンド化しないため、必ず末尾に
&を付ける - nohup.out の肥大化防止には明示的なリダイレクト(または
/dev/null)を指定する - プロセスの確認は
pgrep -a -f <名前>やps aux、停止はkill <PID>やpkill -f <名前>を使う - 永続的なサービス稼働や再起動後の自動復帰が必要な場合は、
systemdの利用を検討する
実務での長時間バッチやサーバーメンテナンスにぜひ役立ててください。

コメント