タイトルを簡潔にしようとしましたが、質問を完全にカプセル化する方法が思いつきませんでした。私がやりたいことは次のとおりです。perlスクリプトを実行するとき、同じSTDERRストリームに接続している「自分」以外のプロセスがあるかどうかを知りたいです(現在のttyで、または同じストリームに追加/リダイレクトされる可能性があります) STDERR ファイル) であり、そうであれば、私の目標は、私のSTDERR エラー/警告/詳細メッセージ、および他の同時実行プログラムからのその他のメッセージ。これが可能性として検出されたら、STDERR に出力するすべてのメッセージにスクリプト名を追加して、メッセージがどのプロセスから来たか (または少なくともどのプロセスが私が書いたスクリプトからのものか) をユーザーが認識できるようにします。現時点では、これをどのように達成するか、またはソリューションがすべての可能性をカプセル化するかどうかは気にしません-今のところ、適切なデフォルト動作の適切な数のユースケースをキャプチャする概念実証と呼びましょう. そして、システムコールを介してこれを実行しようとしています。
説明したいシナリオが 2 つあります。兄弟プロセスからのメッセージは、パイプ処理された一連のコマンドで同時に実行され、他の子プロセスからのメッセージは、同じ親スクリプトによって連続して実行されます。同じ STDERR ストリームのハンドルを使用してバックグラウンド プロセスのケースを処理しようとするつもりはありませんが、それらがキャプチャされた場合、それはおまけになります。
最初のシナリオである兄弟プロセスについては、かなりうまく処理できていると思います。を使用して、兄弟プロセスのすべての PID を取得できますpgrep -P $ppid。兄弟プロセスが単純に存在するだけで、スクリプト名をメッセージの先頭に追加することを保証するのに十分ですが、さらに一歩進んで lsof を使用して、それらの stderr が自分と同じ STDERR ストリームに送られているかどうかを確認することもできます。それらはバックグラウンドで実行されており、STDERR が同じ TTY に送信されます (ファイル記述子 '2' によって推測されます)。perl の -p または -t 関数を使用して一連のパイプ コマンドの一部であるかどうかを確認することもできます (ただし、'<' または ' >' であるため、-p または -t だけでは機能しません)。関係なく、
私が十分に理解していないシナリオは、親スクリプトによって制御されるプロセスを連続して実行することです。私の考えは、親プロセスが対話型シェルなのか、それともスクリプトなのかについて、合理的な推測を試みることです。
これを行う方法があるかどうかを調べるために、lsof を読んでみました。インタラクティブなシェル/ターミナルからのエラーは、スクリプトと同じ STDERR ストリームに出力されないのではないかと推測していましたが、どうやらそうであるようです。 2 つのシナリオを区別するための親。
さまざまなコンテキストでのテストに使用するワンライナーを作成しました。
perl -e '$ppid=getppid();print("lsof -p $ppid:\n",`lsof -p $ppid`)'
2 つのコンテキストで実行しました。1 つはコマンド ラインで直接実行し、もう 1 つはシェル スクリプト内から実行しました。親の PID で実行された lsof で確認できた唯一の違いは、コマンド ラインで実行すると、tty への 5 つの読み取り/書き込み接続があり、シェル スクリプトから実行すると、tty への 3 つの接続があり、シェル スクリプトの 1 つの読み取り専用読み取り。いずれの場合も、0、1、または 2 のファイル記述子はありませんでした。
インタラクティブシェル:
...
tcsh 87854 me 15u CHR 16,2 0t3625 13083 /dev/ttys002
tcsh 87854 me 16u CHR 16,2 0t3625 13083 /dev/ttys002
tcsh 87854 me 17u CHR 16,2 0t3625 13083 /dev/ttys002
tcsh 87854 me 18u CHR 16,2 0t3625 13083 /dev/ttys002
tcsh 87854 me 19u CHR 16,2 0t3625 13083 /dev/ttys002
内部シェルスクリプト:
tcsh 89384 me 16r REG 1,3 363 19758500 /whatever/tmpdelete2.tcsh
tcsh 89384 me 17u CHR 16,2 0t4721 13083 /dev/ttys002
tcsh 89384 me 18u CHR 16,2 0t4721 13083 /dev/ttys002
tcsh 89384 me 19u CHR 16,2 0t4721 13083 /dev/ttys002
私の質問は次のとおりです。親プロセスが対話型シェルであるかどうかを合理的に推測するのに十分な情報はありますか?
親プロセスがインタラクティブな端末セッションではないファイルからの親プロセスの通常の読み取り専用読み取りから合理的に推測できますか? または、tty への 5 つの読み取り/書き込み接続の存在から、親が対話型シェルであると推測できますか?
このアイデアを少しテストするためにsleep 1、ワンライナーの上の行に a を追加して、長いスクリプトの実行中のある時点でスクリプトの読み取りが lsof 出力から消えるかどうかを確認してみました。また、実行時にシェルスクリプトへのリダイレクトとシェルスクリプトからのリダイレクトを試みました。
私の使用例では、違いはわかりますが、他のシェルがどのように動作するかはわかりません。私は本当にシェルスクリプトについてのみ心配しています。誰かが他の何かの中から perl スクリプトを呼び出す合理的なシナリオは考えられません...