私はすでに長い間実行されているプロセスを持っていて、それを終わらせたくありません。
どのようにしてそれをNohupの下に置くのですか(つまり、端末を閉じてもどうやって実行し続けるのですか?)
プロセスをバックグラウンドに送信するためにbashの Job Control を使用します。
bg
。disown -h [job-spec]
ここで[job-spec]はジョブ番号です(最初に実行中のジョブの場合は%1
、jobs
コマンドを使用して自分の番号を見つけるなど)。これにより、端末が閉じてもジョブは強制終了されません。なんらかの理由で Ctrl+Z また動作していない、別の端末に移動し、(ps
を使用して)プロセスIDを見つけて実行します。
kill -SIGSTOP PID
kill -SIGCONT PID
バックグラウンドで、SIGSTOP
はプロセスを中断し、SIGCONT
はプロセスを再開します。だから今、両方のあなたの端末を閉じることはあなたのプロセスを止めることはありません。
実行中のジョブをシェルから切り離す(= Nohupにする)コマンドは、disown
と基本的なShellコマンドです。
Bash-manpageから(man bash):
disown [-ar] [-h] [jobspec ...]
オプションを指定しないと、各jobspecはアクティブジョブのテーブルから削除されます。 -hオプションを指定すると、各jobspecはテーブルから削除されませんが、シェルがSIGHUPを受け取った場合にSIGHUPがジョブに送信されないようにマークされます。 jobspecが存在せず、-aオプションも-rオプションも指定されていない場合は、現在のジョブが使用されます。 jobspecが指定されていない場合、-aオプションはすべてのジョブを削除またはマークすることを意味します。 jobspec引数を指定せずに-rオプションを指定すると、実行中のジョブに操作が制限されます。 jobspecで有効なジョブが指定されていない限り、戻り値は0です。
つまり、単純な
disown -a
ジョブテーブルからすべてのジョブを削除し、それらをNohupにします。
これらは上記の良い答えです、私はちょうど説明を加えたいと思いました:
あなたはpidやプロセスをdisown
することはできず、仕事をdisown
することはできません。それが重要な違いです。
ジョブは、シェルにアタッチされているプロセスの概念であるため、ジョブをバックグラウンドに投入し(中断しないで)、それを拒否する必要があります。
問題:
% jobs
[1] running Java
[2] suspended vi
% disown %1
Unix Job Controlの詳細については、 http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ を参照してください。
残念ながらdisown
はbash特有のもので、すべてのシェルで利用できるわけではありません。
ある種のUnix(例えばAIXやSolaris)は実行中のプロセスに適用できるNohup
コマンド自体のオプションを持っています。
Nohup -p pid
http://en.wikipedia.org/wiki/Nohup を参照してください。
Nodeの答えは本当に素晴らしいのですが、stdoutとstderrをどのようにリダイレクトできるのかという疑問を残しました。 nix&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'の場合)です。つまり、(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
を適用できますが、/usr/sbin/lsof
はすべてのstd *ファイルハンドラー(FD
列)に対して 'u'と言います。これはO_RDWR
です。
/usr/include/bits/fcntl.hヘッダーファイルの値を確認しました。
Nohup
が行うように、出力ファイルはO_APPEND
で開くことができますが、NFSの問題の可能性があるため、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
必要に応じて、call close(2)
とcall open(...)
を別のファイル名で再度使用する場合は、stderrを別のファイルにリダイレクトできます。
添付の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を自動化して、コマンドを含むファイル(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
およびdisown
コマンドは機能しませんでした。
bg
- ジョブをバックグラウンドで実行し、実行中のプロセスに戻りますdisown -a
- これはjobで全ての添付ファイルをカットします(それであなたは端末を閉じることができ、それはまだ実行されます)これらの簡単な手順で、プロセスを実行したまま端末を閉じることができます。
それはNohup
を付けません(あなたの質問に対する私の理解に基づいて、あなたはここでそれを必要としません)。
これはUcsでLinuxのUbuntuのLinux上で私のために働いた。
CtrlZ 一時停止する
バックグラウンドで実行するためのbg
ジョブ番号を取得するためのjobs
Nohup %n
。ここで、nはジョブ番号です。