1035

すでに長時間実行されているプロセスがあり、終了したくありません。

nohup の下に置くにはどうすればよいですか (つまり、ターミナルを閉じても実行し続けるにはどうすればよいでしょうか?)

4

10 に答える 10

1477

bashのジョブ コントロールを使用して、プロセスをバックグラウンドに送信します。

  1. Ctrl+Zプログラムを停止 (一時停止) し、シェルに戻ります。
  2. bgバックグラウンドで実行します。
  3. disown -h [job-spec]ここで、 [job-spec] はジョブ番号です (%1最初に実行されているジョブの場合と同様に、コマンドで番号を見つけてくださいjobs)。これにより、ターミナルが閉じたときにジョブが強制終了されません。
于 2009-03-09T08:41:58.320 に答える
209

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

kill -SIGSTOP PID 
kill -SIGCONT PID

SIGSTOPプロセスを一時停止しSIGCONT、バックグラウンドでプロセスを再開します。したがって、両方の端末を閉じてもプロセスは停止しません。

于 2012-04-23T08:01:00.143 に答える
100

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

于 2009-03-09T08:38:41.417 に答える
78

これらは上記の良い答えです。明確化を追加したかっただけです。

disownpid やプロセスはできませんdisown。ジョブは重要です。これは重要な違いです。

ジョブは、シェルにアタッチされたプロセスの概念であるため、ジョブをバックグラウンドにスローして (中断しないで)、所有権を放棄する必要があります。

問題:

%  jobs
[1]  running java 
[2]  suspended vi
%  disown %1

Unix ジョブ制御の詳細については、http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/を参照してください。

于 2009-11-19T15:48:01.557 に答える
56

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

nohupUnixの特定のフレーバー(AIXやSolarisなど)には、実行中のプロセスに適用できるコマンド自体のオプションがあります。

nohup -p pid

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

于 2013-03-16T23:49:15.940 に答える
28

ノードの答えは本当に素晴らしいですが、標準出力と標準エラー出力をリダイレクトするにはどうすればよいかという疑問が残りました。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' と表示されます。FDO_RDWR

/usr/include/bits/fcntl.h ヘッダー ファイルの値を確認しました。

出力ファイルは で開くことができますが、NFS の問題が発生する可能性があるため、 では推奨さO_APPENDnohupません。man open(2)

戻り値として -1 を取得するとcall perror("")、エラー メッセージが出力されます。errno が必要な場合は、p errnogdb コマンドを使用します。

これで、新しくリダイレ​​クトされたファイルを確認できます。/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>

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

于 2014-10-10T09:35:14.927 に答える
6

実行中のプロセスを 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

于 2013-09-27T06:48:57.817 に答える
3

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

nohup -p  processid>

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

于 2014-03-03T16:16:52.543 に答える