Coloque um processo iniciado com! no fundo

8

Se eu fizer isso a partir do shell:

$ sleep 100

Eu posso fazer isso ir para segundo plano, fazendo:

^Z
$ bg

E então continue usando meu shell. Você pode obter o mesmo efeito adicionando &a ao final do comando, mas geralmente esqueço isso.

No Vim, costumo:

:!sleep 100

E aqui também, muitas vezes esqueço de adicionar o &. Posso colocar esse processo em segundo plano e continuar usando o Vim como no shell?

Martin Tournoij
fonte
1
Para evitar esquecê-lo novamente, você pode pedir ao Vim para anexar &todas as vezes: :nnoremap :! :!&<Left>... Mas é claro, às vezes você não deseja o &e precisa pressionar <Del> para removê-lo.
Joeytwiddle
@joeytwiddle Essa é uma boa ideia, e soa como algo que você poderia escrever como uma resposta, em vez de apenas um comentário :-)
Martin Tournoij

Respostas:

5

Como <C-z>irá suspender o próprio Vim, não apenas o comando shell lançado, que não funcionará.

O que eu faria é abortar o comando de longa duração e <C-c>, em seguida, reiniciar o mesmo comando em segundo plano via

:!! &

(O :!!comando é útil para recuperar o comando externo anterior aqui; você também pode usar o histórico de comandos Ex via <Up>.)

Ingo Karkat
fonte
1
Esse é exatamente o fluxo de trabalho que espero melhorar. O problema é que você precisa perto o que você começou ...
Martin Tournoij
1

Você pode colocar o comando em um script de shell que se autodenomina. O conteúdo, por exemplo, pode ser:

#!/bin/sh
sleep 100 &
Jon Carter
fonte
3
O que seria de pouco uso uma vez que o comando já foi iniciado.
muru
Quero dizer que é possível executar o script de shell em vez do comando lento. Tê-lo em segundo plano evita a necessidade de lembrar de fazê-lo em tempo de execução. Acho que não estou entendendo muito bem o caso de uso. Se for o mesmo comando que continuo esquecendo em segundo plano, usaria o script de shell. Se isso estiver acontecendo com comandos arbitrários, eu consideraria criar o hábito de mudar para um shell real para fazer isso.
Jon Carter
Eu uso tmuxpor padrão, mas o problema é que minha sessão do Vim (com arquivos abertos e outras) ainda é inútil. Eu poderia mudar para outro painel e executar meu script lá, mas são muito mais ações do que :!gitk %por exemplo ... O problema com o uso de scripts é que eu teria que pré-criar muitos desses scripts para todos os comandos possíveis. Talvez não seja uma má idéia para alguns dos comandos mais usados ​​(como gitk& mupdf).
Martin Tournoij 24/02
1

Normalmente, quando um processo é iniciado, você não tem muito controle sobre ele, exceto encerrá-lo ( Ctrl+ c) ou suspendê-lo ( Ctrl+ z, mas incluindo o processo pai).

No entanto, dependendo do tipo de processo e sistema operacional, aqui estão alguns truques que você pode tentar:

  • O envio SIGTSTPou SIGSTOPinterromperá o processo (o mesmo sinal enviado por Ctrl+ z) e SIGCONTcontinuará (continuará) o processo. Testar com sleepnão funciona, então você deve testá-lo com um software específico sobre como ele lida com os sinais. Por exemplo

    killall -SIGSTOP sleep
    killall -SIGTSTP sleep
    kill -SIGTSTP PID
    

    SIGSTOP stop process stop (não pode ser capturado ou ignorado)

    Processo de parada SIGTSTP sinal de parada gerado a partir do teclado

  • Enviando SIGHUPpara o processo. Por padrão, esse sinal finaliza o processo, no entanto, se o processo implementa o sinal SIGHUP, ele deve desconectar o controle de tty e executar novamente em segundo plano com o novo ID do processo (geralmente é usado com daemons). Infelizmente, muitos aplicativos não lidam com isso corretamente e simplesmente morrem (inclusive sleep). Por exemplo

    killall -SIGHUP sleep
    

    SIGHUP encerrar processo terminal line hangup

  • Outra solução poderia usar ferramentas como retty(reconectar a um pseudo-tty), detach( desconectar um processo do terminal), nohup( desconectar o processo do terminal ) ou gdb(anexar ao processo existente -pe fechar seus descritores de arquivo como tty, exemplo semelhante )

Para mais informações, consulte: Controle de tarefas (Unix) - Implementação na Wikipedia.

Veja também: man killou man sigaction.

kenorb
fonte
É estranho que isso funcione para você - não deveria. STOP / CONT deve apenas pausar e retomar o processo, nada mais. Não funciona aqui, no console vim ou no gvim.
Derobert 24/02
1

Nota : Esta resposta parece funcionar apenas com as conchas tcshe fish. Eu também tentei bash, dash, mksh, e zsh, e não trabalhar lá; Eu não sei por que, porque se eu faço as mesmas ações dessas conchas sem Vim, que faz trabalho como esperado ... ( :!comandos são executados embora o shell).

Eu uso tcsh, por isso funciona para mim ...

Você pode usar :set shell=/bin/tcshpara definir seu shell; isso é global, no entanto. Portanto, use-o somente se você acha que esse é um recurso muito importante :-)


^Zenvie um SIGTSTPsinal, você pode enviar esse sinal com kille, em seguida, use-o SIGCONTpara continuar (retomar) o processo. Isso irá desanexar o processo do Vim.

Como é difícil mostrar com isso sleep(como você sabe que a execução continuou?), Usarei gitkcomo exemplo (mas qualquer programa GUI o fará):

Por exemplo, no Vim:

:!gitk %

E então em outro terminal:

$ ps ax | grep gitk
30105 pts/10   S+     0:00 -bin/tcsh -c gitk
30108 pts/10   Sl+    0:00 wish /sbin/gitk --

$ kill -TSTP 30108
$ kill -CONT 30108

Obviamente, você também pode usar killall, ou pkill; por exemplo:

$ killall -TSTP wish
$ killall -CONST wish

Você precisa abrir outro terminal para isso, o que não é o ideal, mas permitirá que você continue usando o Vim e o processo externo.

Martin Tournoij
fonte