web-dev-qa-db-ja.com

既に実行中のプロセスをnohupにするにはどうすればいいですか?

私はすでに長い間実行されているプロセスを持っていて、それを終わらせたくありません。

どのようにしてそれをNohupの下に置くのですか(つまり、端末を閉じてもどうやって実行し続けるのですか?)

856
flybywire

プロセスをバックグラウンドに送信するためにbashの Job Control を使用します。

  1. Ctrl+Z プログラムを停止(一時停止)してシェルに戻ります。
  2. バックグラウンドで実行する場合はbg
  3. disown -h [job-spec]ここで[job-spec]はジョブ番号です(最初に実行中のジョブの場合は%1jobsコマンドを使用して自分の番号を見つけるなど)。これにより、端末が閉じてもジョブは強制終了されません。
1278
Node

なんらかの理由で Ctrl+Z また動作していない、別の端末に移動し、(psを使用して)プロセスIDを見つけて実行します。

kill -SIGSTOP PID 
kill -SIGCONT PID

バックグラウンドで、SIGSTOPはプロセスを中断し、SIGCONTはプロセスを再開します。だから今、両方のあなたの端末を閉じることはあなたのプロセスを止めることはありません。

164
Pungs

実行中のジョブをシェルから切り離す(= 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にします。

84
serioys sam

これらは上記の良い答えです、私はちょうど説明を加えたいと思いました:

あなたは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/ を参照してください。

67
Q Boiler

残念ながらdisownはbash特有のもので、すべてのシェルで利用できるわけではありません。

ある種のUnix(例えばAIXやSolaris)は実行中のプロセスに適用できるNohupコマンド自体のオプションを持っています。

Nohup -p pid

http://en.wikipedia.org/wiki/Nohup を参照してください。

39
Dale

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>

これがソリューションのかなり完全な説明であることを願っています。

24
TrueY

実行中のプロセスをNohupに送信するには( http://en.wikipedia.org/wiki/Nohup

Nohup -p pid、私にとってはうまくいきませんでした

それから私は以下のコマンドを試してみました、そしてそれはとてもうまくいきました

  1. いくつかのSOMECOMMANDを実行し、/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1と言います。

  2. Ctrl+Z プログラムを停止(一時停止)してシェルに戻ります。

  3. バックグラウンドで実行する場合はbg

  4. 端末が閉じてもプロセスが強制終了されないようにするためのdisown -h

  5. シェルから出るにはexitと入力します。これで、操作はバックグラウンドで独自のプロセスで実行されるようになり、シェルに結び付けられなくなります。

このプロセスはNohup SOMECOMMANDを実行することと同等です。

7
minhas23

私のAIXシステムで、私は試してみました

Nohup -p  processid>

これはうまくいった。ターミナルウィンドウを閉じた後も、私のプロセスを実行し続けました。デフォルトのシェルとしてkshがあるので、bgおよびdisownコマンドは機能しませんでした。

2
guest
  1. ctrl + z - これは仕事を一時停止します(キャンセルするつもりはありません!)
  2. bg - ジョブをバックグラウンドで実行し、実行中のプロセスに戻ります
  3. disown -a - これはjobで全ての添付ファイルをカットします(それであなたは端末を閉じることができ、それはまだ実行されます)

これらの簡単な手順で、プロセスを実行したまま端末を閉じることができます。

それはNohupを付けません(あなたの質問に対する私の理解に基づいて、あなたはここでそれを必要としません)。

1
hi-zir

これはUcsでLinuxのUbuntuのLinux上で私のために働いた。

  1. CtrlZ 一時停止する

  2. バックグラウンドで実行するためのbg

  3. ジョブ番号を取得するためのjobs

  4. Nohup %n。ここで、nはジョブ番号です。

0
eshaya