もし私が非同期(「バックグラウンド」)プロセスの場合、プロセスが実行される前に、新しいプロセスのPIDを含むいくつかの情報が端末に表示されます。たとえば、
$ sleep 3 &
[1] 8217
$
[1] + done sleep 3
$
このような情報(特にPID)を、毎非同期に開始されるものだけでなく、プロセス全体も開始されますか?
背景
これを望む理由は、私の日常的な仕事環境の特殊性により、同期長時間実行プロセスが に応答しませんCtrl-C
。(これらのプロセスが「長時間実行」になるのは、予想していたよりもはるかに多くの出力を生成するためです。) このようなプロセスを停止する最も確実な方法は、kill -9
別のウィンドウから停止することです。そのためには、その PID をすぐに手元に用意しておくとよいでしょう。
更新: 元の投稿では、それがCtrl-Z
オプションではないことを言及し忘れていました。(私は Emacs で実行されるシェルに取り組んでいるので、Ctrl-Z
Emacs を一時停止するだけです。)
答え1
としてスティーブン・キットが説明するzsh に PID を印刷させるのはかなり難しいでしょう。しかし、他の方法で情報を取得することは可能です。
Ctrl+を押すZとプロセスを一時停止でき、zsh はそのプロセスの PID を表示します。プロセスを強制終了したい場合は、まずCtrl+ を押してC直接終了してみてください。Ctrl+Cが失敗した場合は、より強力な強制終了のためにCtrl+ を試してください ( +は SIGINT を送信します。これは通常、プログラムに現在のアクションを停止して制御をユーザーに戻すように指示します。+は SIGQUIT を送信します。これは通常、プログラムにハードクラッシュするように指示します)。これは Emacs 内からでも実行できます。Shell モードでは、 を押すとターミナルに渡され、 を押すと に渡され、を押すと に渡されます。Term モードでは、とが直接渡されますが、 を1 つ渡す必要があります。\CtrlCCtrl\C-c C-z
C-z
C-c C-c
C-c
C-c C-\
C-\
C-z
C-\
C-c C-c
C-c
プロセスが端末の設定を変更したり、シグナルをブロックしたりする場合、終了するためにそのプロセスを見つける便利な方法は、端末を使用することです。端末が何であるかを調べます。これは、tty
端末内のコマンドを使用して行うことができます。これをプロンプトの一部にしたり、端末のタイトルの一部にしたりすることができます (私は端末のタイトルに入れました)。Emacs は端末のタイトルを表示しませんが、次の式を評価することで情報にアクセスできます。
(process-tty-name (get-buffer-process (current-buffer)))
シェル モードを含むほとんどのモードで式を評価するには、 と入力してM-:
から式を入力します。 Term モードでは、 と入力してC-c M-x eval-expression RET
から式を入力します。 これを頻繁に使用する場合は、関連するモードで次のコマンドをキーにバインドします。
(defun buffer-process-tty-name ()
(interactive)
(let ((tty (process-tty-name (get-buffer-process (current-buffer)))))
(if (interactivep) (message "%s" tty))
tty))
端末名がわかれば、ps -t pts/42
たとえばまたは を使用してpgrep -t pts/42
、その端末に接続されているプロセスを一覧表示できます。
答え2
この情報を記録する方法はないようで、詳しく調べてみると、正しく設計するのは難しいようです(最初は実装も難しいと思いましたが、イルカチュ修正しました。
実装上の問題は、情報を適切な場所に記録することだと思いました。シェルが子プロセスを開始すると、フォークして、その子プロセスを実行します (ただし、シェルが子プロセスで置き換えられる場合はフォークしません)。フォークすると、プロセスが複製されます。コピーの 1 つは、呼び出しから戻りコード 0 を受け取りますfork()
。これは、それが子プロセスであることを示します。もう 1 つは、子プロセスのプロセス ID を受け取ります。これは、それが親プロセスであることを示します。子プロセスは親プロセスのファイル記述子を継承するため、 を設定する前に、自身の pid をログに記録できますexec()
。
設計上の問題は、何をログに記録するかを選択することです。シェルによって開始されたすべてのプロセスをログに記録すると、多くの無関係なログが残ります。例えばプロンプトの構築に関係するプロセス用です。「実際の」コマンドの場合でも、パイプラインやその他の複合コマンドについて何をログに記録するかを決定する必要があります...そして一貫性を保つために、組み込みコマンド用、またはシェルが子に置き換わる状況用 (ただし、対話型シェルでは手動で行わない限り、これは発生しないと思いますexec
) のログに記録するものを用意する必要があります。
これをさらに詳しく調べたい場合は、のaddproc()
と、および のを参照してください。printjobs()
jobs.c
zexecve()
exec.c