Como imprimir o PID no terminal no início de *todo* processo?

Como imprimir o PID no terminal no início de *todo* processo?

Se eu começar umassíncronoprocesso ("em segundo plano"), algumas informações, incluindo o PID do novo processo, são impressas no terminal antes da execução do processo; por exemplo

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

Existe uma maneira de imprimir essas informações (especialmente o PID) no início dotodoprocesso, não apenas aqueles que são iniciados de forma assíncrona?


Fundo

A razão para querer isto é que, devido às peculiaridades do meu ambiente de trabalho quotidiano, muitas vezes acontece que umsíncronoprocesso de longa duração não responde a Ctrl-C. (Invariavelmente, o que torna esses processos “de longa duração” é que eles produzem muito mais resultados do que eu havia previsto.) A maneira mais segura de interromper tal processo é interrompê- kill -9lo a partir de uma janela diferente, e seria bom ter seu PID prontamente disponível para isso.

ATUALIZAÇÃO: Na minha postagem original, esqueci de mencionar que isso Ctrl-Znão é uma opção. (Estou trabalhando em um shell rodando no Emacs, então Ctrl-Zapenas suspendo o Emacs.)

Responder1

ComoStephen Kitt explica, fazer zsh imprimir o PID seria bastante difícil. Mas você pode obter informações de outras maneiras.

Você pode pressionar Ctrl+ Zpara suspender o processo e então zsh exibe seu PID. E se você quiser matá-lo, tente pressionar Ctrl+ Cprimeiro, para matá-lo diretamente. Se Ctrl+ Cfalhar, tente Ctrl+ \para um kill “mais difícil” ( Ctrl+ Cenvia SIGINT, que convencionalmente diz a um programa para parar sua ação atual e devolver o controle ao usuário; Ctrl+ \envia SIGQUIT, que convencionalmente diz a um programa para travar fortemente). Você pode fazer isso até mesmo no Emacs: no modo Shell, pressione C-c C-zpara passar C-zpara o terminal, C-c C-cpara passar C-c, C-c C-\para passar C-\. No modo Term, C-ze C-\são passados ​​diretamente, mas você precisa C-c C-cpassar um único C-c.

Se o processo alterar as configurações do terminal ou bloquear os sinais, uma maneira conveniente de localizá-lo para eliminação é por terminal. Descubra o que é o terminal; você pode fazer isso com o ttycomando dentro do terminal. Você pode fazer disso parte do seu prompt ou parte do título do terminal (eu coloquei no título do terminal). O Emacs não exibe o título do terminal, mas dá acesso às informações avaliando a seguinte expressão:

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

Para avaliar uma expressão na maioria dos modos, incluindo o modo Shell, digite M-:e insira a expressão. No modo Termo, digite C-c M-x eval-expression RETe insira a expressão. Se você usa isso com frequência, vincule o seguinte comando a uma chave nos modos relevantes:

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

Depois de saber o nome do terminal, você pode usar, por exemplo, ps -t pts/42ou pgrep -t pts/42para listar os processos anexados a esse terminal.

Responder2

Não parece haver uma maneira de registrar essas informações e, analisando-as com mais detalhes, seria difícil projetar corretamente (inicialmente pensei que seria difícil implementar também, masilkkachuconsertei isso).

Achei que o problema de implementação era registrar as informações no lugar certo. Quando um shell inicia um filho, ele bifurca e depois executa o filho (a menos que possa se substituir pelo filho; nesse caso, ele não bifurca). Quando bifurca, o processo é duplicado; uma das cópias recebe um código de retorno 0 da fork()chamada, o que indica que é o filho, e a outra obtém o identificador do processo do filho, que indica que é o pai. O filho herda os descritores de arquivo do pai, para que possa registrar seu próprio pid antes de configurar o exec().

O problema de design é escolher o que registrar. Se registrarmos todos os processos iniciados pelo shell, acabaremos com muitos logs estranhos,por exemplopara processos envolvidos na construção do prompt! Mesmo para comandos “reais”, precisamos decidir o que registrar para pipelines e outros comandos compostos... E então, para consistência, precisamos criar algo para registrar para comandos integrados ou para circunstâncias em que o shell substitui com o filho (embora eu não ache que isso possa acontecer com um shell interativo, a menos que você faça isso manualmente exec).

Se você quiser explorar isso mais a fundo, confira addproc()e printjobs()em jobs.ce zexecve()em exec.c.

informação relacionada