Como adicionar uma GUI aos scripts de shell do Linux
Publicados: 2022-01-29 Você pode usar janelas GUI, controles deslizantes, botões de opção, barras de progresso e muito mais em seus scripts Bash. Aprenda a usar o kit de ferramentas zenity
e dê uma repaginada nos seus scripts Bash. Nós vamos te mostrar como.
O script Bash é uma linguagem de programação poderosa e, como está embutido no shell Bash, está prontamente disponível para todos. É uma linguagem fácil de começar a programar. Por ser interpretada, você não precisa compilar seus scripts. Assim que você editar o arquivo de script e torná-lo executável, você poderá executá-lo. Isso torna o ciclo de codificação, execução e depuração bastante eficiente.
Existem duas queixas principais que as pessoas têm com os scripts Bash, e a primeira é a velocidade. Como o shell Bash interpreta os comandos no script, eles não são executados tão rapidamente quanto o código compilado. No entanto, isso é como reclamar que um trator não é tão rápido quanto um carro; eles são feitos para coisas diferentes.
Existem dois tipos de velocidade, no entanto. Muitas vezes, você pode criar um script rápido e usá-lo para executar uma tarefa muito mais rapidamente do que desenvolver uma solução em uma linguagem compilada, como C.
A segunda reclamação que as pessoas têm com os scripts Bash é a interface do usuário – é uma janela de terminal. Claro, às vezes a interface não importa. Se a única pessoa que usará o script for seu autor, a interface provavelmente não será tão importante. Também não importa para scripts que executam processamento em segundo plano e em lote. Normalmente, esses scripts não precisam de muita (se houver) interação do usuário.
Há ocasiões em que você precisa de algo um pouco mais intuitivo e moderno do que a janela do terminal. A maioria das pessoas está familiarizada com uma interface gráfica do usuário (GUI). Para dar às pessoas uma experiência o mais simples possível, você precisa criar e usar elementos GUI de seus scripts.
O Aplicativo Zenity
zenity
permite que você incorpore uma ampla variedade de elementos de interface gráfica em seus scripts Bash. É um poderoso kit de ferramentas que dá aos seus scripts uma sensação moderna e uma aparência contemporânea e familiar.
zenity
está pré-instalado nas distribuições Ubuntu, Fedora e Manjaro. Faz parte do GNOME. Se você usa o KDE, talvez queira dar uma olhada no kdialog
, embora o zenity
seja executado em qualquer ambiente de desktop.
Os exemplos neste artigo mostram como criar as diferentes janelas de diálogo a partir da linha de comando, como capturar seus valores de retorno e seleções de usuário em variáveis e como usar as janelas de diálogo em scripts.
Finalizamos com um pequeno aplicativo que utiliza todos os três tipos de janelas de diálogo.
A janela de diálogo do calendário
Uma janela de diálogo de calendário permite que alguém selecione uma data. Para criar um com zenity
requer um único comando de duas palavras:
zenity --calendário
A janela de diálogo do calendário é exibida. Isso tem toda a funcionalidade que você esperaria de um selecionador de data padrão. Você pode alterar o mês e o ano e clicar em um dia para selecionar essa data. Por padrão, a data de hoje é destacada quando a janela é exibida.
Clique em “OK” para fechar a janela de diálogo e selecione a data destacada. Clicar duas vezes em uma data faz a mesma coisa.
Se você não quiser fazer uma seleção de data, clique em “Cancelar”, pressione a tecla “Esc” no teclado ou feche a janela de diálogo.
No exemplo acima, 19 de agosto de 2019 está selecionado. Se o usuário clicar em “OK”, o calendário fecha e a data selecionada é impressa na janela do terminal.
Você pode ignorar a linha “GTKDialog mapeado sem um pai transitório. Isso é desencorajado.”
GTK significa GIMP Tool Kit, que é o kit de ferramentas usado para desenvolver a interface do GNOME. Foi originalmente concebido pelos autores do GNU Image Manipulation Program (GIMP). GNU significa GNU's Not Unix.
O mecanismo GTK está avisando os autores do zenity
que eles usaram um componente GTK de maneira não padrão.
Capturando o valor da data
Imprimir a data no terminal não faz muito por nós. Se vamos chamar esse calendário de um de nossos scripts, precisamos capturar o valor de data selecionado para que possamos fazer algo útil com ele em nosso script. Também personalizaremos um pouco o calendário.
Usaremos as seguintes opções com o calendário. Todos eles devem ser usados com o sinalizador “–” de traço duplo:
- –text : Especifica uma sequência de texto a ser exibida no calendário. Ele substitui o padrão "Selecione uma data abaixo".
- –title : define o título da janela de diálogo do calendário.
- –day : define o dia selecionado quando o calendário é aberto.
- –month : define o mês selecionado quando o calendário é aberto.
- –year : define o ano selecionado quando o calendário é aberto.
Estamos usando uma variável chamada ChosenDate
para capturar a data retornada do calendário. E estamos usando echo $ChosenDate
para imprimir essa data na janela do terminal.
Sim, obtivemos o mesmo resultado no exemplo anterior, mas aqui temos a data selecionada armazenada em uma variável. No exemplo anterior, foi impresso e esquecido.
ChosenDate=$(zenity -- calendar --text "Escolha uma data" --title "How-To Geek Rota" --day 1 -- month 9 -- year 2019); echo $ChosenDate
Agora, o calendário exibe nosso prompt e o título da janela. A data é definida para a data de início escolhida em vez da data de hoje.
Também podemos personalizar o formato da string de data retornada quando uma seleção é feita. A opção --date-format
deve ser seguida por um especificador de formato. Esta é uma sequência de tokens que definem os dados e formatos que devem ser incluídos na saída. Os tokens são os mesmos usados com a função de linguagem C strftime()
e há uma grande variedade deles.
Os tokens que estamos usando são:
- %A : O nome completo do dia da semana.
- %d : O dia do mês como um dígito.
- %m : O mês como um dígito.
- %y : O ano como dois dígitos (sem século).
ChosenDate=$(zenity -- calendar --text "Escolha uma data" --title "How-To Geek Rota" --date-format="%A %d/%m/%y" --day 1 -- mês 9 --ano 2019); echo $ChosenDate
Alguém seleciona uma data:
E a data é retornada usando nosso formato. Mostra o nome do dia da semana, seguido da data na ordem europeia: dia, mês, ano.
A Janela de Diálogo de Seleção de Arquivo: Escolhendo um Arquivo
As janelas de diálogo de seleção de arquivos são bastante complexas. As pessoas podem navegar pelo sistema de arquivos, destacar um arquivo ou arquivos e clicar em “OK” para selecionar esses arquivos ou cancelar a seleção por completo.
zenity
fornece toda essa funcionalidade e muito mais. E é tão fácil de usar quanto a janela de diálogo do calendário.
As novas opções que vamos usar são:
- –file-selection : Diz
zenity
que queremos usar uma janela de diálogo de seleção de arquivo. - –multiple : Permite que alguém selecione mais de um arquivo.
- –file-filter : Informa à janela de diálogo de arquivo quais tipos de arquivo exibir.
zenity --file-selection --tile "How-To Geek" --multiple --file-filter='*.mm *.png *.page *.sh *.txt'
A janela de diálogo de seleção de arquivo é tão funcional quanto qualquer outra janela de seleção de arquivo.
O usuário pode navegar pelo sistema de arquivos e selecionar o arquivo de sua escolha.
Navegamos para um novo diretório e selecionamos um arquivo chamado “button_hybrid.png”.
Quando você clica em “OK”, a janela de diálogo de seleção de arquivo é fechada e o nome do arquivo e o caminho são impressos na janela do terminal.
Se você precisar usar o nome do arquivo em qualquer processamento adicional, poderá capturá-lo em uma variável, assim como fez para a data do calendário.
A janela de diálogo de seleção de arquivo: salvando um arquivo
Se adicionarmos uma opção, podemos transformar a janela de diálogo de seleção de arquivo em uma janela de diálogo de salvamento de arquivo. A opção é --save
. Também vamos usar a opção --confirm-overwrite
. Isso solicita que a pessoa confirme que deseja substituir um arquivo existente.
Resposta=$(zenity --file-selection --save --confirm-overwrite); echo $Resposta
A janela de diálogo de salvamento de arquivo é exibida. Observe que há um campo de texto onde alguém pode digitar um nome de arquivo.
O usuário pode navegar até o local de sua escolha no sistema de arquivos, fornecer um nome para o arquivo ou clicar em um arquivo existente para sobrescrevê-lo.
No exemplo acima, o usuário destacou um arquivo existente.
Quando ele clica em “OK”, uma janela de diálogo de confirmação aparece solicitando que ele confirme se deseja substituir o arquivo existente. Observe que o nome do arquivo aparece na caixa de diálogo de aviso. Esse é o tipo de atenção aos detalhes que dá zenity
sua aparência profissional.
Se não tivéssemos usado a opção --confirm-overwrite
, o arquivo teria sido substituído silenciosamente.
O nome do arquivo é armazenado na variável Response
, que é impressa na janela do terminal.
Janelas de diálogo de notificação
Com zenity
, é fácil incluir janelas de diálogo de notificação em seus scripts. Existem janelas de diálogo de ações que você pode chamar para fornecer informações, avisos, mensagens de erro e perguntas para o usuário.
Para criar uma janela de diálogo de mensagem de erro, use o seguinte comando:
zenity --error --width 300 --text "Permissão negada. Não é possível gravar no arquivo."
As novas opções que estamos usando são:
- –error : Diz
zenity
que queremos usar uma janela de diálogo de erro. - –width : Define a largura inicial da janela.
A janela de diálogo de erro aparece na largura especificada. Ele usa o ícone de erro GTK padrão.
Para criar uma janela de diálogo de informações, use o seguinte comando:
zenity --info --width 300 --text "Atualização concluída. Clique em OK para continuar."
A nova opção que estamos usando é --info
, que diz ao zenity
para criar uma janela de diálogo de informações.
Para criar uma janela de diálogo de perguntas, use o seguinte comando:
zenity --question --width 300 --text "Você está feliz em continuar?"; eco $?
A nova opção que estamos usando é --question
, que diz ao zenity
para criar uma janela de diálogo de perguntas.
O $?
é um parâmetro especial. Ele contém o valor de retorno do pipeline de primeiro plano executado mais recentemente. Em termos gerais, este é o valor do processo fechado mais recentemente. Um valor zero significa "OK" e um valor de um ou mais significa "Cancelar".
Esta é uma técnica geral que você pode aplicar a qualquer uma das janelas de diálogo do zenity
. Ao verificar esse valor em seu script, você pode determinar se os dados retornados de uma janela de diálogo devem ser processados ou ignorados.
Clicamos em "Sim", então o código de retorno é um zero indicando "OK".
Para criar uma janela de diálogo de aviso, use o seguinte comando:
zenity --warning --title "Pouco espaço no disco rígido" --width 300 --text "Pode não haver espaço suficiente no disco rígido para salvar o backup."
A nova opção que estamos usando é --warning
, que diz ao zenity
para criar uma janela de diálogo de aviso.
A janela de diálogo de aviso é exibida. Não é uma pergunta, então só tem um botão.
A Janela de Diálogo de Progresso
Você pode usar a janela de diálogo de progresso do zenity
para exibir uma barra de progresso que indica o quanto seu script está próximo da conclusão.
A barra de progresso é avançada de acordo com os valores que são canalizados para ela do seu script. Para demonstrar o princípio, use o seguinte comando:
(para i em $(seq 0 10 100); faça echo $i; durma 1; feito)
O comando se divide assim:
- O comando
seq
percorre uma sequência de 0 a 100, em passos de 10. - A cada passo, o valor é armazenado na variável
i
. Isso é impresso na janela do terminal. - O comando pausa por um segundo, devido ao comando
sleep 1
.
Podemos usar isso com a janela de diálogo de progresso do zenity
para demonstrar a barra de progresso. Observe que estamos canalizando a saída do comando anterior para o zenity:
(para i em $(seq 0 10 100); faça echo $i; durma 1; feito) | zenity --progress --title "How-To Geek" -- fechamento automático
As novas opções que estamos usando são:
- –progress : Diz
zenity
que queremos usar uma janela de diálogo de progresso. - –auto-close : Fecha a caixa de diálogo quando a barra de progresso atinge 100 por cento.
A janela de diálogo de progresso é exibida e a barra avança para 100%, pausando por um segundo entre cada etapa.
Podemos usar esse conceito de canalizar valores no zenity
para incluir a janela de diálogo de progresso em um script.
Digite este texto em um editor e salve-o como “progress.sh”.
!/bin/bash função lista de trabalho () { echo "# Primeiro item de trabalho" eco "25" dormir 1 echo "# Segundo item de trabalho" eco "50" dormir 1 echo "# Terceiro item de trabalho" eco "75" dormir 1 echo "# último item de trabalho" eco "100" dormir 1 } lista de trabalho | zenity --progress --title "How-To Geek" --auto-close saída 0
Aqui está um detalhamento do script:
- O script define uma função chamada
work-list
. É aqui que você coloca seus comandos e instruções para realizar um trabalho real. Substitua cada um dos comandossleep 1
pelos seus reais. -
zenity
aceita as linhasecho "# ..."
e as exibe na janela de diálogo de progresso. Altere o texto dessas linhas, para que passem mensagens informativas ao usuário. - As linhas de
echo
que contêm números, comoecho "25"
, também são aceitas pelozenity
e definem o valor da barra de progresso. - A função de lista de trabalho é chamada e canalizada para
zenity
.
Use este comando para tornar o script executável:
chmod +x progresso.sh
Use este comando para executar o script:
./progress.sh
O script é executado e a mensagem de texto muda conforme cada fase do script é executada. A barra de progresso se move em etapas para 100%.
A Janela de Diálogo de Escala
A janela de diálogo de escala permite que alguém mova um controle deslizante para escolher um valor numérico. Isso significa que ela não pode inserir um valor muito alto ou baixo.
As novas opções que estamos usando são:
- –scale : Diz
zenity
que queremos usar uma janela de diálogo de escala. - –min-value : Define o valor mínimo para a escala.
- –max-value : Define o valor máximo para a escala.
- –step : Define a quantidade de movimento do controle deslizante quando as teclas de seta são usadas. Isso não afeta os movimentos do controle deslizante se alguém usar o mouse.
- –value : Define o valor inicial e a posição do controle deslizante.
Este é o comando que estamos usando:
Resposta=$(zenity --scale --title "How-To Geek" --text "Selecionar ampliação." --min-value=0 --max-value=30 --step=3 --value15); echo $Resposta
A janela de diálogo do controle deslizante aparece com o controle deslizante definido como 15.
O usuário pode mover o controle deslizante para selecionar um novo valor.
Quando ela clica em “OK”, o valor é transferido para a variável Response
e impresso na janela do terminal.
A janela de diálogo de entrada
A janela de diálogo de entrada permite que alguém insira texto.
As novas opções que estamos usando são:
- –entry : Diz
zenity
que queremos usar uma janela de diálogo de entrada. - –entry-text : Você pode usar isso se quiser digitar um valor sugerido no campo de entrada de texto. Estamos usando “” para forçar um campo vazio. Isso não é estritamente necessário, mas queríamos documentar a opção.
O comando completo fica assim:
Response=$(zenity --entry --text "Digite seu termo de pesquisa" --title "Howe-To Geek" --entry-text=""); echo $Resposta
Uma janela de diálogo simples aparece, contendo um campo de entrada de texto.
Alguém pode digitar e editar texto.
Ao clicar em “OK”, o valor digitado é atribuído à variável Resposta. Usamos echo para imprimir o valor da variável na janela do terminal.
Juntando tudo
Vamos juntar essas técnicas e criar um script funcional. O script executará uma verificação de informações de hardware e apresentará os resultados ao usuário em uma janela de texto de rolagem. Ela pode escolher um tipo de escaneamento longo ou curto.
Para este script, usaremos três tipos de janelas de diálogo, duas das quais são novas para nós:
- A primeira é uma janela de diálogo de lista. Ele permite que alguém faça uma escolha.
- A segunda é uma janela de diálogo de progresso que permite ao usuário saber que algo está acontecendo e que ele deve esperar.
- A terceira é uma janela de informações de texto, que exibe os resultados para o usuário.
Digite este texto em um editor e salve-o como “hardware-info.sh”.
#!/bin/bash # Exibe a listagem de hardware para este computador TempFile=$(mktemp) ListType=`zenity --width=400 --height=275 --list --radiolist \ --title 'Verificação de Hardware' \ --text 'Selecione o tipo de escaneamento:' \ --coluna 'Selecionar' \ --column 'Tipo de digitalização' VERDADEIRO "Curto" FALSO "Longo"` se [[ $? -eq 1 ]]; então # eles pressionaram Cancelar ou fecharam a janela de diálogo zenity --error --title="Verificação recusada" --width=200 \ --text="Verificação de hardware ignorada" saída 1 elif [ $ListType == "Short" ]; então # eles selecionaram o botão de rádio curto Flag="--curto" senão # eles selecionaram o botão de rádio longo Sinalizar="" fi # busca por informações de hardware com o valor apropriado em $Flag hwinfo $Flag | tee >(zenity --width=200 --height=100 \ --title="Agrupando informações" --progress \ --pulsate --text="Verificando hardware..." \ --auto-kill --auto-close) >${TempFile} # Exibe as informações de hardware em uma janela de rolagem zenidade --largura=800 --altura=600 \ --title "Detalhes do Hardware" \ --text-info --filename="${TempFile}" saída 0
Use este comando para torná-lo executável:
chmod +x hardware-info.sh
Este script cria um arquivo temporário, e o nome do arquivo é mantido na variável TempFile:
TempFile=$(mktemp)
O script usa a opção --list
para criar uma janela de diálogo zenity
chamada janela de diálogo de lista. Os caracteres “\” no final das linhas dizem ao script para tratá-los como uma longa linha enrolada. Aqui está o processo:
- Especificamos uma largura e uma altura para a janela.
- A janela de diálogo de lista suporta colunas. A opção
--radiolist
faz com que a primeira coluna seja uma coluna de botões de opção. - Definimos um título e um prompt de texto para a janela.
- Definimos o título da primeira coluna como "Selecionar". O conteúdo desta coluna serão os botões de opção.
- Definimos o título da segunda coluna como "Selecionar" e fornecemos o conteúdo da segunda coluna. Esta coluna contém dois rótulos de texto: "Curto" e "Longo". Os indicadores TRUE e FALSE significam que a opção “Short” é selecionada por padrão quando a janela de diálogo aparece.
- Estamos armazenando o resultado dessa janela de diálogo em uma variável chamada
ListType
.
ListType=`zenity --width=400 --height=275 --list --radiolist \ --title 'Verificação de Hardware' \ --text 'Selecione o tipo de escaneamento:' \ --coluna 'Selecionar' \ --column 'Tipo de digitalização' VERDADEIRO "Curto" FALSO "Longo"`
Se o usuário pressionar “Cancelar”, não precisamos verificar o valor em ListType,
podemos simplesmente sair. Se ele pressionar "OK", precisamos descobrir se ele selecionou o botão de opção "Curto" ou "Long":
- O parâmetro especial
$?
é igual a zero se o usuário pressionou “OK”. É igual a um se ele pressionou “Cancelar” ou fechou a janela. - Se for igual a um, o script exibe uma janela de diálogo de informações de erro e sai. Se ele pressionar “OK”, passamos a testar o valor na variável
ListType
. - Se a variável
ListType
tiver o valor “Short”, o script definirá uma variável chamadaFlag
para igual a “–short”. - Se a variável
ListType
não tiver o valor "Short", ela deverá conter o valor "Long". O script define uma variável chamadaFlag
para igual a “”, que é uma string vazia. - O script usa a variável
Flag
na próxima seção.
se [[ $? -eq 1 ]]; então # eles pressionaram Cancelar ou fecharam a janela de diálogo zenity --error --title="Verificação recusada" --width=200 \ --text="Verificação de hardware ignorada" saída 1 elif [ $ListType == "Short" ]; então # eles selecionaram o botão de rádio curto Flag="--curto" senão # eles selecionaram o botão de rádio longo Sinalizar="" fi
Agora que o script sabe qual tipo de varredura o usuário deseja, podemos realizar a varredura de informações de hardware:
- O script chama o comando
hwinfo
e passa o valor na variávelFlag
. - Se
Flag
contiver “–short”, o comandohwinfo
realizará uma varredura curta. Se o valor deFlag
for “”, nada passa para ohwinfo
e um padrão, uma varredura longa é executada. - O script canaliza a saída de
hwinfo
paratee
.tee
envia a saída para ozenity
e oTempFile
. - O script cria uma janela de diálogo da barra de progresso. Ele define a largura e a altura da janela de diálogo e os textos de título e prompt.
- O script não pode saber antecipadamente quanta informação o comando
hwinfo
produzirá, portanto, não pode definir a barra de progresso para avançar corretamente para 100%. A opção--pulsate
faz com que a caixa de diálogo de progresso exiba um indicador de movimento. Isso informa ao usuário que algo está acontecendo e ele deve esperar. - A opção
--auto-kill
encerra o script se alguém clicar em "Cancelar". - A opção
--auto-close
faz com que a caixa de diálogo de progresso feche automaticamente quando o processo que está sendo monitorado for concluído.
# busca por informações de hardware com o valor apropriado em $Flag hwinfo $Flag | tee >(zenity --width=200 --height=100 \ --title="Agrupando informações" --progress \ --pulsate --text="Verificando hardware..." \ --auto-kill --auto-close) >${TempFile}
Quando a verificação do hwinfo
concluída, o script chama o zenity
para criar uma janela de diálogo de informações de texto com a opção --text-info
. A janela de diálogo de informações de texto exibe o conteúdo do arquivo TempFile
:
- O script define a largura e a altura da janela de diálogo e o texto do título.
- A opção
--flename
é usada para ler o conteúdo do arquivo contido na variávelTempFIle
.
# Exibe as informações de hardware em uma janela de rolagem zenidade --largura=800 --altura=600 \ --title "Detalhes do Hardware" \ --text-info --filename="${TempFile}"
Quando o usuário fecha a janela de diálogo de informações de texto, o script é encerrado.
saída 0
Vamos acendê-lo e dar uma olhada.
./hardware-info.sh
A caixa de listagem é exibida. A opção “Curto” é selecionada por padrão.
Vamos selecionar "Long" e clique em "OK".
A janela de progresso aparece com um indicador deslizante. Ele permanece na tela até que a verificação de hardware seja concluída.
Quando a verificação de hardware estiver concluída, a janela de diálogo de informações de texto aparecerá com os detalhes da verificação.
Clique OK."
Mesmo um jóquei de linha de comando obstinado tem que admitir que algumas janelas de diálogo GUI podem dar a um humilde script Bash um toque profissional.