Como ter o PID impresso no terminal no início do processo * every *?

5

Se eu iniciar um processo assíncrono ("em segundo plano"), algumas informações, incluindo o PID do novo processo, serão impressas no terminal antes que o processo seja executado; por exemplo

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

Existe uma maneira de ter essas informações (especialmente o PID) impressas no início de todo processo, não apenas aquelas que são iniciadas de forma assíncrona?

Plano de fundo

O motivo para querer isso é que, devido às peculiaridades de minha configuração de trabalho diária, muitas vezes acontece que um processo de longa execução síncrono falha em responder a Ctrl-C . (Invariavelmente, o que torna esses processos "de longa duração" é que eles produzem muito mais produção do que eu esperava.) O modo mais seguro de parar esse processo é kill -9 it de uma janela diferente, e seria bom ter seu PID prontamente disponível para isso.

ATUALIZAÇÃO: No meu post original, deixei de mencionar que Ctrl-Z não é uma opção. (Estou trabalhando em um shell rodando sob o Emacs, então Ctrl-Z apenas suspende o Emacs.)

    
por kjo 10.04.2017 / 15:02

2 respostas

3

Como Stephen Kitt explica , tornando a impressão em zsh o PID seria bastante difícil. Mas você pode obter as informações de outras maneiras.

Você pode pressionar Ctrl + Z para suspender o processo, depois zsh exibe seu PID. E se você quiser matá-lo, tente pressionar Ctrl + C primeiro, para eliminá-lo diretamente. Se Ctrl + C falhar, tente Ctrl + \ para um kill mais difícil ( Ctrl + C envia SIGINT, que convencionalmente diz ao 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 com força). Você pode fazer isso até mesmo dentro do Emacs: no modo Shell, pressione C-c C-z para passar C-z para o terminal, C-c C-c para passar C-c , C-c C-\ para passar C-\ . No modo Prazo, C-z e C-\ são passados diretamente, mas você precisa de C-c C-c para passar um único C-c .

Se o processo alterar as configurações do terminal ou bloquear os sinais, uma maneira conveniente de localizá-lo para matar é por terminal. Descubra o que é o terminal; você pode fazer isso com o comando tty dentro do terminal. Você pode fazer esta 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 Prazo, digite C-c M-x eval-expression RET e insira a expressão. Se você usar 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/42 ou pgrep -t pts/42 para listar os processos anexados a esse terminal.

    
por 11.04.2017 / 00:29
3

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

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

O problema de design é escolher o que registrar. Se registrarmos todos os processos iniciados pelo shell, acabamos com muitos logs externos, por exemplo, para 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 comandos internos ou para circunstâncias em que o shell substitui se com o filho (embora eu não ache que isso possa acontecer para um shell interativo, a menos que você manualmente exec ).

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

    
por 10.04.2017 / 21:18

Tags