Iniciar silenciosamente a tarefa em segundo plano

12

Eu sei que você pode usar isso para iniciar um processo em segundo plano, sem receber a notificação quando o processo é colocado em segundo plano e quando é feito da seguinte maneira:

(comando &) &> / dev / null

No entanto, isso remove a opção de interceptar quando o processo termina ( trap child_done CHLD).

Como posso ter os dois?

Tyilo
fonte

Respostas:

5

O spooler de tarefas pode ajudá-lo.

Como no freshmeat.net :

O spooler de tarefas é um sistema em lote Unix onde as tarefas em spool são executadas uma após a outra. A quantidade de trabalhos a serem executados ao mesmo tempo pode ser definida a qualquer momento. Cada usuário em cada sistema tem sua própria fila de tarefas. As tarefas são executadas no contexto correto (o de enfileiramento) a partir de qualquer shell / processo, e sua saída / resultados podem ser facilmente observados. É muito útil quando você sabe que seus comandos dependem de muita RAM, muito uso de disco, produzem muita saída ou, por qualquer motivo, é melhor não executá-los todos ao mesmo tempo, enquanto você deseja manter seus recursos ocupados para o máximo benefício. Sua interface permite usá-lo facilmente em scripts.

O spooler de tarefas está disponível no Debian , Ubuntu e outras distribuições.

Ele permite que você tenha uma fila de tarefas para executar e acesse as saídas apenas quando desejar.

Por exemplo:

$ tsp sleep 5
0 
$ tsp sleep 5 
1
$ tsp
ID   State      Output               E-Level  Times(r/u/s)   Command [run=1/1]
2    running    /tmp/ts-out.ZWn6Le                           sleep 5
1    finished   /tmp/ts-out.Fhlcle   0        5.00/0.00/0.01 sleep 5

Se você executar muitos trabalhos em segundo plano, isso definitivamente o ajudará.

Você pode executá-los sequencialmente ou em uma quantidade predefinida de slots. Você também pode estabelecer dependências entre as tarefas (executar task1 somente se task0 concluída com êxito).

Raúl Salinas-Monteagudo
fonte
3

Veja como fazer isso em ambos {ba,z}sh.

Usando uma função de ajuda não precisar salvar e restaurar o estado de zsh's monitorvariável pelo uso de setopt local_options.

# Run the command given by "$@" in the background
silent_background() {
  if [[ -n $ZSH_VERSION ]]; then  # zsh:  /superuser//a/1285272/365890
    setopt local_options no_notify no_monitor
    "$@" &
  elif [[ -n $BASH_VERSION ]]; then  # bash: /programming//a/27340076/5353461
    { 2>&3 "$@"& } 3>&2 2>/dev/null
  else  # Unknownness - just background it
    "$@" &
  fi
}

Usando isso da seguinte maneira:

trap 'echo child done' CHLD
silent_background sleep 1

Produzirá a child donemensagem esperada .

Tom Hale
fonte
consulte unix.stackexchange.com/q/456549/4778 para obter uma explicação esperançosa.
ctrl-alt-Delor
2

O redirecionamento da saída do comando parece irrelevante porque a notificação é enviada pelo shell quando um trabalho é iniciado de forma assíncrona. Mais precisamente, é um recurso de shell (funcionalidade) relacionado ao controle de tarefas .

Aqui, uma citação que vem do "Bash Reference Manual", capítulo "Job Control", seção um.

O shell associa um JOB a cada pipeline. Ele mantém uma tabela de trabalhos em execução no momento, que podem ser listados com o jobscomando Quando o Bash inicia um trabalho de forma assíncrona, ele imprime uma linha parecida com:

[1] 25647

indicando que esse trabalho é o número 1 e que o ID do último processo no pipeline associado a esse trabalho é 25647. Todos os processos em um único pipeline são membros do mesmo trabalho. O Bash usa a abstração do JOB como base para o controle do trabalho.

Observe que um script de shell não exibe esta notificação.

$ cat test
#!/bin/bash

true & echo true
$ ./test
true

Em fatos

Zsh

A documentação do Zsh fornece indicações semelhantes sobre essas notificações, consulte a man 1 zshmiscseção "TRABALHOS". Essas notificações não são exibidas quando o controle de trabalho está desativado.

MONITOR ( -m , ksh: -m )

    Permitir controle do trabalho. Definido por padrão no shell interativo.

zsh_prompt % setopt no_monitor
zsh_prompt % true & echo true
true
zsh_prompt %
zsh_prompt % 

Bater

Parece que o Bash sempre exibe, por exemplo [1] 25647. A "notificação final", por exemplo, [1]+ Done truenão é exibida quando o controle do trabalho está desativado.

bash_prompt $ true & echo true
[1] 25647
true
bash_prompt $ 
[1]+  Done                    true

Controle de trabalho desativado

bash_prompt $ set +m       # disable job control
bash_prompt $ true & echo true
[1] 25685
bash_prompt $
bash_prompt $

Conclusão

Não sei se desabilitar o controle do trabalho para ocultar as notificações é uma coisa boa?

Recursos

Fólkvangr
fonte
1

Você pode chamar zshcomo um shell não interativo para desativar as notificações de trabalho.

zsh -c '
   trap "echo trapped child_done" CHLD
   sleep 5 &
   #wait
   sleep 10 # simulate other running cmds
   echo script done
'
nad
fonte
0

Veja o seguinte exemplo:

trap 'echo "DONE"' 0
{ find /usr & } &> /dev/null
wait

Isso funciona bem. Não há necessidade ( ): isso cria um subshell não necessário. { }são apenas comandos de agrupamento.

Gilles Quenot
fonte
Isso é impresso [2] 49591e [2] + 49591 exit 1 find /usr, quando não deve ser impresso!
Tyilo
Desculpe, entendi mal sua pergunta.
Gilles Quenot
0

Esta é uma pergunta antiga, mas uma resposta possível (no bash, não testada com zsh) é usar o controle de tarefa no subshell: (command & wait)

Nota: o bash suprime as mensagens de trabalho em segundo plano de início / fim no subshell e não há necessidade de redirecionamento.

Philippe
fonte
Eu acho que você perdeu a parte da armadilha. Tanto quanto eu entendo a pergunta que o subprocesso deve ser iniciado, algo será feito enquanto o superprocesso é executado e, quando o subprocesso termina, outra coisa deve ser executada. Com sua solução, você inicia o subprocesso, aguarde-o no subshell e o shell principal aguarda o subshell. Isso elimina as mensagens, mas você não pode fazer algo em paralelo.
Raphael Ahrens
Não, (sleep 5 & wait)atrasa 5 segundos.
Tom Hale