回答:
bash のジョブコントロールを使用して、プロセスをバックグラウンドに送信します。
bg
バックグラウンドで実行します。disown -h [job-spec]
ここで、[job-spec]はジョブ番号です(%1
最初に実行中のジョブの場合と同様です。jobs
コマンドで自分の番号を見つけます)。これにより、ターミナルが閉じたときにジョブが強制終了されません。disown -h
おそらくより正確な答えは次のとおりです。このシェルが開始したすべてのジョブ。」([ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/…から]
disown
、disownを実行するとジョブの出力が表示されないため、プロセスがデーモンになります。つまり、標準入出力が/ dev / nullにリダイレクトされます。したがって、ジョブを取り消す予定の場合は、ファイルにログインしてジョブを開始することをおmy_job_command | tee my_job.log
なんらかの理由でCtrl+ Zも機能していないとします。別の端末に移動し、プロセスIDを(を使用してps
)見つけて実行します。
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
プロセスを一時停止し、SIGCONT
バックグラウンドで再開します。したがって、両方のターミナルを閉じてもプロセスは停止しません。
disown %1
それを閉じる前に、最初のターミナルでを実行することを忘れないでください。
kwin
、クラッシュの後で、結果を考えずにkonsoleから開始しました)。したがって、kwinを停止すると、すべてがフリーズし、実行する可能性がなくなりますbg
!
実行中のジョブをシェルから分離するコマンド(=はそれをnohupにします)はdisown
、基本的なシェルコマンドです。
bash-manpage(man bash)から:
否認[-ar] [-h] [jobspec ...]
オプションがない場合、各jobspecはアクティブなジョブのテーブルから削除されます。-hオプションを指定すると、各jobspecはテーブルから削除されませんが、シェルがSIGHUPを受信した場合にSIGHUPがジョブに送信されないようにマークされます。jobspecが存在せず、-aオプションも-rオプションも指定されていない場合、現在のジョブが使用されます。jobspecが指定されていない場合、-aオプションはすべてのジョブを削除またはマークすることを意味します。jobspec引数なしの-rオプションは、操作を実行中のジョブに制限します。jobspecが有効なジョブを指定しない限り、戻り値は0です。
つまり、単純な
disown -a
ジョブテーブルからすべてのジョブを削除し、nohupにします
disown -a
すべてのジョブを削除します。シンプルdisown
は現在のジョブを削除するだけです。答えのmanページが言うように。
これらは上記の良い答えです、私は明確化を追加したかっただけです:
あなたは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に固有であり、すべてのシェルで使用できるわけではありません。
Unixの特定の種類(AIXやSolarisなど)にはnohup
、実行中のプロセスに適用できるコマンド自体のオプションがあります。
nohup -p pid
AIX
とSolaris
。「AIXおよびSolarisバージョンのnohupには、将来のSIGHUPシグナルを無視するように実行中のプロセスを変更する-pオプションがあります。上記の非表示の組み込みbashとは異なり、nohup -pはプロセスIDを受け入れます。」出典
ノードの答えは本当に素晴らしいですが、それはどのようにstdoutとstderrをリダイレクトすることができるのかという疑問を残しました。UnixとLinuxで解決策を見つけましたが、完全ではありません。これら2つのソリューションをマージしたいと思います。ここにあります:
私のテストでは、loop.shと呼ばれる小さなbashスクリプトを作成しました。このスクリプトは、自身のpidを無限ループでのスリープ状態で出力します。
$./loop.sh
このプロセスのPIDをどうにかして取得します。通常ps -C loop.sh
は十分ですが、私の場合は印刷されています。
これで、別の端末に切り替えることができます(または、同じ端末で^ Zを押します)。これでgdb
、このプロセスにアタッチされるはずです。
$ gdb -p <PID>
これにより、スクリプトが停止します(実行中の場合)。その状態によって確認することができるps -f <PID>
場合、STAT
フィールドは「T +」(または^ Z「T」の場合)、どの手段(マニュアル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ヘッダーファイルの値を確認しました。
出力ファイルはとO_APPEND
同じようにで開くことができますが、NFSの問題が発生する可能性があるため、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
私たちが望むならば、我々が使用してする場合は、我々は、別のファイルに標準エラー出力をリダイレクトすることができます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>
これがソリューションのかなり完全な説明であることを願っています。
lsof
ます(ファイルハンドルの名前はpipe
でなく/dev/pts/1
)またはby ls -l /proc/<PID>/fd/<fd>
(これはハンドルのシンボリックリンクを示します)。また、サブプロセスはまだ出力をリダイレクトできない可能性があり、ファイルにリダイレクトする必要があります。
実行中のプロセスを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
。
bg
-これにより、ジョブがバックグラウンドになり、実行中のプロセスに戻りますdisown -a
-これにより、すべての添付ファイルがジョブでカットされます(ターミナルを閉じても実行されます)これらの簡単な手順により、プロセスを実行したままターミナルを閉じることができます。
それは上に置く習慣nohup
(あなたの質問の私の理解に基づいて、あなたはここでそれを必要としません)。
これは、tcshellでUbuntu Ubuntu linuxで動作しました。
CtrlZ 一時停止します
bg
バックグラウンドで実行する
jobs
そのジョブ番号を取得する
nohup %n
ここで、nはジョブ番号です
nohup: failed to run command '%1': No such file or directory
yourExecutable &
しても出力が画面に表示され続けCtrl+C
、何も停止しないように見えても、画面が出力でスクロールされていて何が表示されていなくても、盲目的に入力disown;
して押しEnter
てください。あなたが入力しています。プロセスは否認され、プロセスが停止することなくターミナルを閉じることができます。