How to have PID printed to the terminal at the start of *every* process

processzsh

If I start an asynchronous ("backgrounded") process, some info, including the new process's PID, gets printed to the terminal before the process runs; for example

$ sleep 3 &
[1] 8217
$ 
[1]  + done       sleep 3
$ 

Is there a way to have such info (especially the PID) printed at the start of every process, not just those that get started asynchronously?


Background

The reason for wanting this is that, due to the peculiarities of my everyday working set up, often enough it happens that a synchronous long-running process fails to respond to Ctrl-C. (Invariably, what makes these processes "long-running" is that they produce a lot more output than I had anticipated.) The surest way to stop such a process is to kill -9 it from a different window, and it would be nice to have its PID readily on hand for this.

UPDATE: In my original post I neglected to mention that Ctrl-Z is not an option. (I'm working on a shell running under Emacs, so Ctrl-Z just suspends Emacs.)

Best Answer

As Stephen Kitt explains, making zsh print the PID would be rather difficult. But you can get at the information in other ways.

You can press Ctrl+Z to suspend the process, then zsh displays its PID. And if you want to kill it, try pressing Ctrl+C first, to kill it directly. If Ctrl+C fails, try Ctrl+\ for a “harder” kill (Ctrl+C sends SIGINT, which conventionally tells a program to stop its current action and hand back control to the user; Ctrl+\ sends SIGQUIT, which conventionally tells a program to crash hard). You can do this even from within Emacs: in Shell mode, press C-c C-z to pass C-z to the terminal, C-c C-c to pass C-c, C-c C-\ to pass C-\. In Term mode, C-z and C-\ are passed directly, but you need C-c C-c to pass a single C-c.

If the process changes the terminal settings or blocks the signals, a convenient way to locate it for killing is by terminal. Find out what the terminal is; you can do this with the tty command inside the terminal. You might make this part of your prompt or part of the terminal title (I put it in the terminal title). Emacs doesn't display the terminal title, but it gives you access to the information by evaluating the following expression:

(process-tty-name (get-buffer-process (current-buffer)))

To evaluate an expression in most modes including Shell mode, type M-: then enter the expression. In Term mode, type C-c M-x eval-expression RET then enter the expression. If you use this often, bind the following command to a key in the relevant modes:

(defun buffer-process-tty-name ()
  (interactive)
  (let ((tty (process-tty-name (get-buffer-process (current-buffer)))))
    (if (interactivep) (message "%s" tty))
    tty))

Once you know the terminal name, you can use e.g. ps -t pts/42 or pgrep -t pts/42 to list the processes that are attached to that terminal.