

nohup付け忘れた時disown -hでSIGHUPは防げるけど標準出力は死ぬことがある
この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。
nohupを付け忘れて長時間コマンドを実行し始めてしまった時、後からバックグラウンド化して端末を閉じても生かし続ける方法。
手順
Ctrl+Zで実行中のプロセスを一時停止する(SIGTSTPが送られる)bgで停止中のジョブをバックグラウンドで再開するdisown -h [jobspec]でジョブテーブルからは残しつつ、そのプロセスにSIGHUPが送られないようにする
disown は本来 -h を付けずに使うとジョブテーブルから完全に消えて、jobs / fg / bg の対象外になる。-h を付けた場合はジョブとして管理下には残したまま、HUPシグナルだけ無視させる指定になる。
端末を閉じる(=シェルが終了する)と、その端末から起動した子プロセスにはSIGHUPが飛ぶ。disown -h はこれを無視させることで、端末を閉じてもプロセスが死なないようにする、という理屈。
nohupと同じではない
disown -h はSIGHUPを無視させるだけで、nohup と完全に同じ効果ではない。
nohup は追加で標準出力・標準エラーの向き先を変える(デフォルトでは nohup.out にリダイレクトする)。一方で disown -h だけの場合、標準出力・標準エラーは元の端末(tty)に繋がったまま。
端末を閉じた後もそのプロセスが標準出力に書き込もうとすると、書き込み先のパイプ/ttyが既に閉じているため SIGPIPE を受けて死ぬことがある。特に進捗ログをガンガン吐くようなコマンドだと危ない。
対策
事前にリダイレクトしてから disown -h する方が安全。
command > output.log 2>&1 &disown -h %1こうしておけば出力先はファイルに固定されるので、端末を閉じても書き込み先が消えることはない。
nohup付け忘れに気づいた時点で既に標準出力・標準エラーが端末に繋がったまま動いている場合、後からリダイレクト先を変える方法(exec で再割り当てするなど)もあるが、確実性でいえば最初から nohup するか、リダイレクト済みで実行し直す方が早い。