2

Linux / C ++ライブラリでは、system()呼び出しを介してプロセスを起動しています。

system("nohup processName > /dev/null&");

これは、それ自体で終了する単純なテストアプリケーションで正常に機能するようですが、killシグナルを取得するNodejs / V8拡張機能の内部からこれを使用すると、子プロセスが強制終了されます。私はそれが実行されているのを見つけました、

system("sudo nohup processName > /dev/null&");

パスワードを必要としないように設定されたsudoersファイルを使用すると、親プロセス(ノード)が終了した場合でも、これを実行できます。親に送信されたシグナルと終了する親が子に影響を与えないように、子プロセスを完全に切り離す方法はありますか?できればsystem()呼び出し内で、プロセスIDを取得してそれを使って何かを行う必要のあるものではありません。

4

2 に答える 2

4

親プロセスから切り離す手順は簡単です。サブシェルのバックグラウンドで、コマンドを実行しsetsid(新しいセッションで開始されるように)、標準入力、出力、およびエラーを/dev/null(または必要に応じて別の場所に) リダイレクトします。新しいシェルを開始するためsystem()、そのようなサブシェルと同等であるため、

system("setsid COMMAND </dev/null >/dev/null 2>/dev/null &");

必要なことを正確に行います。シェルスクリプトでは、同等のものは

( setsid COMMAND </dev/null >/dev/null 2>/dev/null & )

(シェル スクリプトにはサブシェルが必要ですCOMMAND。そうしないと、 は現在のシェルのジョブ制御下に置かれるためです。 を使用する場合は重要ではありませんsystem()。いずれにせよ、コマンドのためだけに新しいシェルが開始されるためです。シェルは、コマンドが終了すると終了します。)

リダイレクトはCOMMAND、 が現在の端末に対して開いている記述子を持っていないことを確認するために必要です。(ターミナルが閉じると、そのようなすべてのプロセスに TERM シグナルが送信されます。) これは、標準入力、標準出力、および標準エラーのすべてをリダイレクトする必要があることを意味します。上記のリダイレクトは、Bash シェルと POSIX シェルの両方で機能しますが、古いバージョンの/bin/sh. 特に、すべての Linux ディストリビューションで動作するはずです。

setsid新しいセッションを開始します。COMMAND独自のプロセス グループのプロセス グループ リーダーになる。シグナルは、単一のプロセスまたはプロセス グループ内のすべてのプロセスに送信できます。終了シグナルは通常、プロセス グループ全体に送信されます (アプリケーションは技術的に複数の関連プロセスで構成されている場合があるため)。新しいセッションを開始するとCOMMAND、親プロセスが属するプロセス グループがプロセス グループ全体のシグナルによって強制終了された場合でも、確実に強制終了されません。

于 2012-10-18T10:12:13.627 に答える
2

私の推測では、プロセス グループ全体が強制終了されています。setpgid子プロセスで新しいプロセス グループを開始することができます。最初のステップは、andまたはを削除してsystem使用することです。forkexecveposix_spawn

于 2012-10-18T02:35:42.307 に答える