Tarefas em segundo plano silenciosas em zsh

1

Eu corro archey no meu .zshrc. O problema é que, devido à exibição do IP atual, às vezes pode ser executado como dois segundos. Para tornar isso menos perceptível, eu coloco em segundo plano assim:

# .zshrc
archey &
# lots of foo
wait

Desta forma, pode buscar o IP enquanto muitas outras coisas são feitas no meu zshrc. Mas agora o zsh exibe o ID do trabalho e do processo, e aquele archey termina todas as vezes:

Last login: Mon Jul 10 11:12:07 on ttys002
[1] 40436

# archey output

[1]  + done       archey

~
❯

Como o doc afirma que isso está sendo enviado para o stderr, tentei usar 2 > / dev / null, sem sucesso.

Como posso remover essas duas linhas?

    
por Dikti 10.07.2017 / 11:36

4 respostas

2

O Zsh fornece as MONITOR e NOTIFY opções, e você pode desativá-las para silenciar o relatório de status de trabalhos em segundo plano.

() {
  setopt LOCAL_OPTIONS NO_NOTIFY NO_MONITOR
  archey &
  # ...
  wait
}
    
por 13.01.2018 / 22:27
1

Essas duas linhas são enviadas para stderr do shell, não do processo. Você não pode fazê-los desaparecer do zsh.

Compreendendo pelos comentários, que você deseja ver a saída exibida, é necessário seguir três etapas:

  1. Para evitar o ruído de começar archey em segundo plano, você deve iniciá-lo a partir de um script
  2. Para comunicar os resultados do archey ao script principal, você deve usar um arquivo temporário ou algo semelhante
  3. Para entender, quando tiver terminado, você não poderá usar wait , pois isso depende do começo barulhento do plano de fundo

wrap-archey.sh:

#/bin/sh
archey >"$1" 2>&1
rm "$2"

start-archey.sh:

/path/to/wrap-archey.sh "$1" "$2" >/dev/null 2>&1 &

.zshrc:

ARCHEYOUT=$(mktemp)
ARCHEYFLAG=$(mktemp)
/path/to/start-archey.sh "$ARCHEYOUT" "$ARCHEYFLAG" >/dev/null 2>&1
#
# lots of foo
#
while test -f "$ARCHEYFLAG"; do sleep 0.1 ; done
cat "$ARCHEYOUT"
rm "$ARCHEYOUT"

wrap-archey.sh redirecionará a saída para um arquivo temporário e, quando feito, removerá um flagfile. Isso é necessário para a comunicação de volta.

start-archey.sh iniciará o wrap-archey.sh em segundo plano, eliminando o ruído no script principal e retornando imediatamente.

.zshrc irá configurar flagfile e resultfile, executar start-archey.sh silenciosamente em segundo plano, então fazer foo, então esperar que archey termine pesquisando o flagfile. Então limpa.

    
por 10.07.2017 / 11:50
1

Se você não quiser usar um subshell, poderá usar:

# Run the command given by "$@" in the background
silent_background() {
  if [[ -n $ZSH_VERSION ]]; then  # zsh:  https://superuser.com/a/1285272/365890
    setopt local_options no_notify no_monitor
    # We'd use &| to background and disown, but incompatible with bash, so:
    "$@" &
  elif [[ -n $BASH_VERSION ]]; then  # bash: https://stackoverflow.com/a/27340076/5353461
    { 2>&3 "$@"& } 3>&2 2>/dev/null
  else  # Unknownness - just background it
    "$@" &
  fi
  disown &>/dev/null  # Close STD{OUT,ERR} to prevent whine if job has already completed
}

Então:

silent_background archey #  Or whatever command you want to background
    
por 27.06.2018 / 13:09
0

Isso deve funcionar sem arquivos de script adicionais:

tmpf='mktemp'
{ archey ; echo 1 > "$tmpf" ; } &|

# foo

while [ ! -s "$tmpf" ] ; do sleep 0.1 ; done
rm "$tmpf"
unset tmpf

A chave é &| operator. Ele executa o comando fornecido em segundo plano, mas o comando não é um trabalho, portanto, sua exibição não é spam. Você não pode usar wait embora. Eu usei um arquivo temporário para detectar se archey terminou.

Se o seu # foo também produzir saída, você poderá ter uma condição de corrida. Nesse caso, é razoável capturar archey output em outro arquivo temporário (como nesta outra resposta ) e imprimi-lo em o fim.

Eu não recomendo usar um único arquivo temporário para archey de saída e como um acionador. Se você fizer isso, então while test pode retornar true quando archey ainda gravar no arquivo, eu acho.

    
por 10.07.2017 / 13:39

Tags