Como funciona o botão de cancelamento do diálogo de progresso do Zenity?

0

Ao tentar fazer com que o botão Cancel em uma janela Zenity --progress funcione para meus scripts, percebi que não entendo como o botão Cancel funciona no exemplo dado na página do Manual do Zenity : link

#!/bin/sh
(
echo "10" ; sleep 1
echo "# Updating mail logs" ; sleep 1
echo "20" ; sleep 1
echo "# Resetting cron jobs" ; sleep 1
echo "50" ; sleep 1
echo "This line will just be ignored" ; sleep 1
echo "75" ; sleep 1
echo "# Rebooting system" ; sleep 1
echo "100" ; sleep 1
) |
zenity --progress \
  --title="Update System Logs" \
  --text="Scanning mail logs..." \
  --percentage=0

if [ "$?" = -1 ] ; then
        zenity --error \
          --text="Update canceled."
fi

Quando esse script é executado, por que o processo é interrompido quando o botão Cancel é pressionado quando não há exit ou break ou qualquer outro comando visível?

Eu achava que Zenity era apenas um programa para exibir interfaces gráficas e códigos de saída de retorno que podem ser usados para lançar os comandos reais desejados (como exit se cancelado, etc), mas parece que a Zenity deve estar fazendo algo muito mais complicado porque não parece haver qualquer razão para os comandos no exemplo pararem quando o botão for pressionado.

O Zenity está fazendo algo mais complicado ou estou entendendo mal alguma coisa? Eu sou novo em bash / sh scripting, então parece que eu sou provavelmente mal-entendido. Se é apenas uma função complexa e exclusiva do Zenity, então não é necessária uma descrição técnica completa de como funciona. apenas o suficiente de uma explicação para que possa ser usado de forma confiável é o que eu gostaria. Obrigado.

(Eu também gostaria de perguntar por que este exemplo do manual oficial não funciona de fato [no Ubuntu 14.04] porque nenhuma janela --error Zenity é mostrada, mas eu não acho que o StackExchange gosta de perguntas conjuntas, então deixe isso de lado, a menos que esteja relacionado a como eu posso ser um mal entendido.)

Postagem relacionada: Encerrar o script usando a barra de progresso do zenity (não responde a minha pergunta porque o resposta top lá disse para usar --auto-kill quando, neste exemplo, o processo é cancelado sem usar --auto-kill

    
por InverseTelecine 07.02.2016 / 18:30

1 resposta

0

A sintaxe () em sh scripts permite que você inicie um subshell . Você pode pensar em subshells como se as duas linhas seguintes fossem as mesmas:

(echo foo)
sh -c "echo foo"

, ou seja, há um segundo processo dentro de seu script de shell que lida com tudo entre o () . Por meio do símbolo pipe (" | "), a saída padrão dessa sub-rede é conectada à entrada padrão do zenity.

Quando você clicar no botão "Cancelar" na janela zenity, isso fará com que o zenity saia imediatamente. Nesse ponto, a saída padrão da subshell se torna inválida. Isso não mata imediatamente a subcamada; no entanto, quando o próximo comando echo nessa sub-camada quiser gravar no stdout, ele receberá um sinal SIGPIPE , significando que o canal ao qual está tentando gravar não possui leitores. O comportamento padrão de um processo em SIGPIPE é terminar.

Você notará que se você iniciar seu script a partir de um terminal e clicar no botão "cancelar" apenas após uma atualização ser enviada para o zenity, seu prompt do shell não retornará imediatamente; já que o comando sleep ainda está em execução e, como o sono não produz saída, leva um momento até que qualquer saída seja produzida e o SIGPIPE seja emitido.

Se você não quiser este comportamento, você deve dizer ao shell para não sair ao receber o SIGPIPE:

#!/bin/sh
(
    trap -- '' PIPE
    echo "10"; sleep 1
    # ... etc, your normal script goes here
) |
zenity --progress ...

Esta versão ignorará SIGPIPE e continuará feliz quando o zenity sair. No entanto, observe que, nesse caso, o botão "cancelar" será muito confuso para o usuário; isso fará com que o zenity saia, mas não fará com que a operação seja abortada. Pode ser melhor apenas passar --no-cancel .

    
por 07.02.2016 / 19:33

Tags