Em zsh, como posso mais rapidamente rejeitar o processo em primeiro plano?

7

Meu método para rejeitar o processo em primeiro plano requer muito esforço.

Suponha que eu tenha um processo em primeiro plano de zsh . Eu quero disown , então eu posso fechar o shell sem o processo ser enviado a SIGHUP .

No momento, eu começo com Ctrl + z para o background e pause o processo, então

$ disown
disown: warning: job is suspended, use 'kill -CONT -32240' to resume
$ kill -CONT -32240
$

- então eu posso fechar o terminal.

Como posso automatizar isso? Idealmente, eu gostaria de poder pressionar Ctrl + j ou algo que afaste imediatamente o processo em execução. Ou, segundo melhor, gostaria de poder executar um único comando para rejeitar e SIGCONT o processo, uma vez suspenso.

    
por Anko 15.08.2015 / 23:25

2 respostas

10

É impossível ter um keybind global para rejeitar o processo de primeiro plano: Os pressionamentos de tecla são recebidos pelo processo em primeiro plano, não pelo shell. Você precisa primeiro suspendê-lo com Ctrl + z se quiser deserdá-lo.

No entanto, há uma opção de zsh para acelerar o reprovar e continuar : com setopt AUTO_CONTINUE , disown também enviará automaticamente SIGCONT .

Então você pode baixar para C-z disown .

    
por 15.08.2015 / 23:25
10

Quando você pressiona Ctrl + Z em um terminal, isso faz com que o grupo de processos em primeiro plano receba o sinal SIGTSTP (supondo que o terminal esteja no modo cozido e a tecla padrão ligações estão no lugar). Se o processo não definiu um manipulador de sinal para SIGTSTP, isso faz com que o processo seja suspenso (e mesmo que o processo tenha definido um manipulador de sinal, normalmente ele faz apenas uma pequena quantidade de processamento antes de suspender a si mesmo). Quando um processo é morto, suspenso ou retomado, seu pai é notificado por meio de um sinal SIGCHLD; isso é o que faz com que o shell exiba um novo prompt e talvez uma mensagem como [1] + 1234 suspended foo . O fluxo de informações é
chave → suspensão → shell
e não
chave → shell → suspensão
então você não pode configurar uma reação diferente para Ctrl + Z .

Você pode definir um trap para SIGCHLD, mas o trap não é executado quando o trabalho é o atual trabalho em primeiro plano. Na maioria das vezes, isso significa que a interceptação é executada somente quando um job em background é encerrado, não quando o job em primeiro plano é finalizado. Mas também significa que você não pode reagir à suspensão do trabalho em primeiro plano.

Você pode reagir indiretamente a alterações nas tarefas em segundo plano configurando um gancho precmd que compara os estados da tarefa com os estados salvos da execução anterior em precmd . Mas eu não sei o que você poderia fazer com isso: só pode haver uma única chave de suspensão, então você precisa de alguma informação extra para saber se o processo foi feito para ser pausado, com background ou deserdado.

Eu configurei o zsh para que pressionar Ctrl + Z em um prompt vazio faça o background do trabalho atual. Isso me permite pressionar Ctrl + Z duas vezes para colocar o trabalho em primeiro plano em segundo plano com apenas uma pequena suspensão.

fancy-ctrl-z () {
  if [[ $#BUFFER -eq 0 ]]; then
    bg
    zle redisplay
  else
    zle push-input
  fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z

Você pode chamar disown se desejar. Ou você poderia organizar um terceiro Ctrl + Z para chamar disown com a seguinte modificação não testada.

fancy-ctrl-z () {
  if [[ $#BUFFER -eq 0 ]]; then
    if (($fancy_ctrl_z_already_bg)); then
      disown
    else
      bg
      fancy_ctrl_z_already_bg=1
    fi
    zle redisplay
  else
    zle push-input
  fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z
fancy_ctrl_z_precmd () {
  fancy_ctrl_z_already_bg=0
}
precmd_functions+=fancy_ctrl_z_precmd
    
por 16.08.2015 / 01:13