すでに長時間実行されているプロセスがあり、終了したくありません。
nohup の下に置くにはどうすればよいですか (つまり、ターミナルを閉じても実行し続けるにはどうすればよいでしょうか?)
すでに長時間実行されているプロセスがあり、終了したくありません。
nohup の下に置くにはどうすればよいですか (つまり、ターミナルを閉じても実行し続けるにはどうすればよいでしょうか?)
bashのジョブ コントロールを使用して、プロセスをバックグラウンドに送信します。
bg
バックグラウンドで実行します。disown -h [job-spec]
ここで、 [job-spec] はジョブ番号です (%1
最初に実行されているジョブの場合と同様に、コマンドで番号を見つけてくださいjobs
)。これにより、ターミナルが閉じたときにジョブが強制終了されません。何らかの理由でCtrl+Zも機能しない場合、別の端末に移動し、( を使用してps
) プロセス ID を見つけて実行します。
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
プロセスを一時停止しSIGCONT
、バックグラウンドでプロセスを再開します。したがって、両方の端末を閉じてもプロセスは停止しません。
実行中のジョブをシェルから分離する ( = nohup にする) コマンドはdisown
、基本的なシェル コマンドです。
bash-manpage (man bash) から:
disown [-ar] [-h] [ジョブスペック ...]
オプションを指定しないと、アクティブなジョブのテーブルから各ジョブスペックが削除されます。-h オプションを指定すると、各 jobspec はテーブルから削除されませんが、シェルが SIGHUP を受信した場合に SIGHUP がジョブに送信されないようにマークされます。jobspec が存在せず、-a オプションも -r オプションも指定されていない場合は、現在のジョブが使用されます。jobspec が指定されていない場合、-a オプションは、すべてのジョブを削除またはマークすることを意味します。jobspec 引数のない -r オプションは、操作を実行中のジョブに制限します。jobspec が有効なジョブを指定しない限り、戻り値は 0 です。
つまり、単純な
disown -a
ジョブテーブルからすべてのジョブを削除し、nohup にします
これらは上記の良い答えです。明確化を追加したかっただけです。
disown
pid やプロセスはできませんdisown
。ジョブは重要です。これは重要な違いです。
ジョブは、シェルにアタッチされたプロセスの概念であるため、ジョブをバックグラウンドにスローして (中断しないで)、所有権を放棄する必要があります。
問題:
% jobs
[1] running java
[2] suspended vi
% disown %1
Unix ジョブ制御の詳細については、http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/を参照してください。
残念ながらdisown
、bashに固有であり、すべてのシェルで使用できるわけではありません。
nohup
Unixの特定のフレーバー(AIXやSolarisなど)には、実行中のプロセスに適用できるコマンド自体のオプションがあります。
nohup -p pid
http://en.wikipedia.org/wiki/Nohupを参照してください
ノードの答えは本当に素晴らしいですが、標準出力と標準エラー出力をリダイレクトするにはどうすればよいかという疑問が残りました。Unix & Linuxで解決策を見つけましたが、それも完全ではありません。これら2つのソリューションをマージしたいと思います。ここにあります:
私のテストでは、loop.sh と呼ばれる小さな bash スクリプトを作成しました。このスクリプトは、無限ループで 1 分間スリープした状態で自分自身の pid を出力します。
$./loop.sh
どういうわけか、このプロセスの PID を取得します。通常ps -C loop.sh
はこれで十分ですが、私の場合は印刷されています。
これで、別のターミナルに切り替えることができます (または、同じターミナルで ^Z を押します)。今gdb
、このプロセスに添付する必要があります。
$ gdb -p <PID>
これにより、スクリプトが停止します (実行中の場合)。その状態はps -f <PID>
、STAT
フィールドが 'T+' (または ^Z 'T' の場合は 'T') で、(man ps(1)) を意味するで確認できます。
T Stopped, either by a job control signal or because it is being traced
+ is in the foreground process group
(gdb) call close(1)
$1 = 0
Close(1) は、成功するとゼロを返します。
(gdb) call open("loop.out", 01102, 0600)
$6 = 1
Open(1) は、成功した場合、新しいファイル記述子を返します。
この開きは に等しいopen(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
。代わりにO_RDWR
O_WRONLY
適用できますが、すべての std* ファイル ハンドラー (列)/usr/sbin/lsof
に対して 'u' と表示されます。FD
O_RDWR
/usr/include/bits/fcntl.h ヘッダー ファイルの値を確認しました。
出力ファイルは で開くことができますが、NFS の問題が発生する可能性があるため、 では推奨さO_APPEND
れnohup
ません。man open(2)
戻り値として -1 を取得するとcall perror("")
、エラー メッセージが出力されます。errno が必要な場合は、p errno
gdb コマンドを使用します。
これで、新しくリダイレクトされたファイルを確認できます。/usr/sbin/lsof -p <PID>
プリント:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
必要に応じて、stderr を別のファイルにリダイレクトしたり、別のファイル名を使用しcall close(2)
たり、call open(...)
再度使用したりすることができます。
ここで、添付ファイルbash
を解放する必要があり、終了できますgdb
。
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
スクリプトが他の端末から停止された場合、スクリプトはgdb
引き続き実行されます。loop.sh のターミナルに戻ることができます。画面には何も書き込まず、実行してファイルに書き込みます。それを背景に入れなければなりません。を押し^Z
ます。
^Z
[1]+ Stopped ./loop.sh
^Z
(これで、最初に が押されたのと同じ状態になりました。)
これで、ジョブの状態を確認できます。
$ ps -f 24522
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
$ jobs
[1]+ Stopped ./loop.sh
したがって、プロセスはバックグラウンドで実行され、端末から切り離されている必要があります。コマンド出力の角括弧内の番号は、jobs
内のジョブを識別しますbash
。次の組み込みbash
コマンドで、ジョブ番号の前に「%」記号を適用して使用できます。
$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
これで、呼び出し元の bash を終了できます。プロセスはバックグラウンドで実行され続けます。PPID を終了すると 1 になり (init(1) プロセス)、制御端末が不明になります。
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID> 1 0 11:16 ? S 0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey 0u CHR 136,36 38 /dev/pts/36 (deleted)
loop.sh <PID> truey 1u REG 0,26 1127 15008411 /home/truey/loop.out
loop.sh <PID> truey 2u CHR 136,36 38 /dev/pts/36 (deleted)
コメント
gdb の内容は、コマンドと run を含むファイル (例: loop.gdb) を作成して自動化できますgdb -q -x loop.gdb -p <PID>
。私の loop.gdb は次のようになります。
call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit
または、代わりに次の 1 つのライナーを使用できます。
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
これがソリューションのかなり完全な説明であることを願っています。
実行中のプロセスを nohup に送信するには ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
、それは私にとってはうまくいきませんでした
次に、次のコマンドを試してみましたが、非常にうまく機能しました
SOMECOMMAND を実行します/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
。
Ctrl+Zプログラムを停止 (一時停止) し、シェルに戻ります。
bg
バックグラウンドで実行します。
disown -h
ターミナルが閉じたときにプロセスが強制終了されないようにします。
exit
操作は独自のプロセスでバックグラウンドで実行されるため、シェルに関連付けられていないため、シェルから抜け出すように入力します。
このプロセスは、 を実行するのと同じですnohup SOMECOMMAND
。
私のAIXシステムで、試しました
nohup -p processid>
これはうまくいきました。ターミナル ウィンドウを閉じた後もプロセスを実行し続けました。デフォルトのシェルとして ksh があるため、bg
anddisown
コマンドは機能しませんでした。