Como exibir uma caixa de diálogo (zenity / GUI) para o usuário depois que uma tarefa cron do root for concluída

3

Eu tenho uma tarefa Cron periódica simples que deve ser executada como root. Eu quero usar o Zenity (ou similar) para exibir uma caixa de diálogo informativa da GUI para o usuário 1000 (ou usuário conectado ou todos os usuários) quando a tarefa Cron for concluída.

Estou à procura de uma solução simples, fácil e rápida. Eu vou me adaptar aos requisitos de uma solução tão simples.

Aqui é onde eu estou até agora. Meu script bash funciona bem se for executado manualmente, mas quando o Anacron o executa, nada acontece e vejo Gtk-WARNING **: cannot open display nos logs. Eu esperava que ele exibisse meu diálogo para o usuário depois de ser executado pelo cron.

Eu percebo (depois de ler questões relacionadas) que o cron precisa ser dissociado da GUI. Se o usuário 1000 não estiver logado, eu posso escolher uma das várias opções:

  1. não faz nada (possivelmente aceitável porque eu quero mantê-lo simples)
  2. exibe a caixa de diálogo com a mensagem de conclusão para o usuário quando ele faz login na próxima vez (melhor)
  3. exibe algum outro tipo de notificação (OBSERVAÇÃO: o computador é um sistema de desktop sem um servidor de correio instalado)

Encontrei estas questões relacionadas: x11 - O trabalho do Anacron reclama "Gtk-WARNING **: não é possível abrir o display" - Unix & Troca de pilha do Linux O trabalho do Anacron reclama "Gtk-WARNING **: não é possível abrir o display"

shell - Como passar dados fora do processo para o progresso do zenity? - Unix & Troca de pilha do Linux Como passar dados fora do processo para o progresso do zenity?

Exemplo de código (de outra pergunta que é essencialmente igual à minha):

#!/bin/bash
# Backs up the local filesystem on the external HDD

sleep 60

DISPLAY=:0.0

zenity --question --text "Do you want to backup? Be sure to turn on the HDD."
if [ $? -ne 0 ]
    then exit 1
fi

*Do backup stuff here*

Erro:

(zenity:9917): Gtk-WARNING **: cannot open display: 
run-parts: /etc/cron.daily/backup-on-external exited with return code 1

(Eu estou rodando o Kubuntu, então uma solução do KDE seria ainda melhor que o Zenity, mas eu já instalei o Zenity, então posso continuar usando-o.)

    
por MountainX 21.06.2013 / 22:54

4 respostas

0

Com base na resposta de Mel Boyce, aqui está o que funcionou para mim. Isto é baseado no KDE. Mas também testei com o Zenity e a mesma abordagem funciona. É basicamente a mesma coisa que Mel Boyce recomendou, mas com alguns ajustes para que funcionasse para mim. Eu não excluo o arquivo updateNotification.txt, por exemplo. E eu não uso printf.

O script de atualização inclui isto:

DATE_STAMP=' date'
echo "\t***The software has been updated to version ${LATEST} on ${DATE_STAMP}***"
echo "The software has been updated to version ${LATEST} on ${DATE_STAMP}. Please close and reopen the program if it is current running. If you have any issues or questions, please write us at [email protected]. Thank you." > /home/$USERN/.updateNotification.txt

Em seguida, temos um script em execução em /home/$USERN/.kde/Autostart/updateNotificationChecker.sh

#!/bin/bash
while true; do
    if [[ -s ~/.updateNotification.txt ]]; then
                read MSGFE < ~/.updateNotification.txt 
                kdialog --title 'The software has been updated' --msgbox "$MSGFE"
                cat /dev/null > ~/.updateNotification.txt
    fi
    sleep 300
done
exit 0
    
por 27.06.2013 / 19:12
1

Tente adicionar algo como o seguinte ao seu ~/.xinitrc (ou ~/.xsession se você usar um gerenciador de login):

while true; do
    if [[ -a ~/.messages ]]; then
        zenity --info --text="$(printf "%q" $(cat ~/.messages))"
        rm ~/.messages
    fi
    sleep 10
done &

Eu não testei isso com zenity pois não o tenho e suponho que .xsession funciona como esperado - nunca usei um gerenciador de login.

O bloco while / done será executado indefinidamente com um atraso de dez segundos entre as verificações (a parte sleep 10 ). Toda vez que houver uma verificação, o if guarda será bem-sucedido se houver um arquivo não vazio chamado .messages no homedir do usuário. Em caso de sucesso, o conteúdo do arquivo é lido no zenity e o arquivo é removido.

Não estou muito satisfeito com o printf vomit, mas tudo bem.

O conteúdo colocado em ~/.messages deve ser redirecionado do cron e você precisará alterar o proprietário e o grupo do arquivo apropriadamente. Talvez algo como:

10 * * * * /usr/bin/mything && echo "mything completed" > /home/username/.messages && chown username:groupname /home/username/.messages
    
por 25.06.2013 / 14:52
1

Meu sistema é o Ubuntu 13.04. Eu corri um script semelhante ao seu via anacrontab e funciona. Tente isso ..

Configure seu crontab ..

$ cat /path/crontabfile
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

*   *   *   *   *   /bin/bash /path/anacron-tst/s1.sh

ALTERNATIVA: configure seu anacrontab ...

$ cat /etc/anacrontab
### original
.. ,, ..
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
HOME=/root
LOGNAME=root

# These replace cron's entries
1   5   cron.daily  run-parts --report /etc/cron.daily
7   10  cron.weekly run-parts --report /etc/cron.weekly
@monthly    15  cron.monthly    run-parts --report /etc/cron.monthly
### end-original

### my custom lines ..
SHELL=/bin/bash
HOME=/home/me
LOGNAME=me

1   2   me1 /bin/bash /path/anacron-tst/s1.sh

No seu script ...

$ cat /path/anacron-tst/s1.sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

export DISPLAY=:0.0
export XAUTHORITY=/home/me/.Xauthority

zenity --question --text "Backup time .. is HDD connected?"

if [ $? -ne 0 ]; then
    echo "No confirmation .. quiting"
    exit 1
else
    echo "Will attempt backup now .."
fi

Isso é do man 5 anacrontab ..

.. lines can be of three kinds:  job-description lines, environment assignments, or empty lines.

Environment assignment lines are of the form: VAR = VALUE
.. ,, ..
The assignment takes effect from the next line to the end of the  file,  or
to the next assignment of the same variable.

Isto está trabalhando com o crontab instalado para o root. Por favor, note que eu editei o script para incluir a linha "export XAUTHORITY = / home / me / .Xauthority" . Precisa disso para funcionar.

    
por 22.09.2013 / 22:08
0

Aqui está um relatório sobre tudo o que encontrei até agora:

Esta solução do Ask Ubuntu

Isso está funcionando para mim e ainda não vi nenhum problema:

        ACTIVE=$(ck-list-sessions | awk -F' = ' '
            function f(){if(A=="TRUE"){P=U"\t"D;gsub("'"'"'","",P);print P}}
            $1=="\tunix-user"{U=$2} 
            $1=="\tx11-display"{D=$2} 
            $1=="\tactive"{A=$2} 
            END{f()} /^[^\t]/{f()}
        ')
        USERID=${ACTIVE%    *} # tab
        USERNAME=$(getent passwd $USERID|cut -f1 -d':')
        DISPLAY=${ACTIVE#*  } # tab

        DISPLAY="$DISPLAY" su $USERNAME -c "zenity --info --title='My Title' --text='My text. Notice the single quotes.'"

Mas eu testei o comando notify-send (mencionado aqui ) e parece ser ainda mais apropriado para minha situação ....

Infelizmente, a desvantagem do KDE é que as notificações se escondem em breve e eu não encontrei uma maneira de desabilitar esse tempo limite (-t 0 não funcionou). Para meu caso de uso atual, tenho a tendência de gostar de uma caixa de diálogo que precisa ser dispensada com um clique no botão. Enfim, aqui estão os detalhes de notificar-enviar:

comando notify-send

O comando notify-send permite que você envie notificações da área de trabalho para o usuário por meio de um daemon de notificação a partir da linha de comando. Isso é útil para informar o usuário do desktop sobre um evento ou exibir alguma forma de informação sem ficar no caminho do usuário. Você precisa instalar o seguinte pacote:

$ sudo apt-get install libnotify-bin

Neste exemplo, envie uma notificação simples na área de trabalho pela linha de comando, digite:

notify-send "rsnapshot done :)"

No entanto, no processo de busca de soluções, também encontrei algo que eu absolutamente amo! Eu removerei todas as chamadas para o Zenity em todos os meus scripts e os substituirei pelo easybashgui.

easybashgui

link

EasyBashGUI is a Bash functions library for *BSD and GNU/Linux that aims to give simple GUI functions using yad, gtkdialog, kdialog, zenity, Xdialog, (c)dialog, whiptail or bash builtins depending on KDE or GNOME running or not, Yad/Gtkdialog/Xdialog installed or not and, eventually, X server running or not.

Eu também encontrei o Yad, que substituirá o Zenity para mim no futuro. easybashgui pode usar / chamar Zenity, yad, gtkdialog, kdialog, Xdialog, (c) diálogo, whiptail ou bash builtins. Então, estarei descontinuando o Zenity e usando o yad onde for apropriado.

yad

Exibir diálogos gráficos a partir de scripts de shell ou linha de comando - Google Project Hosting link

O Yad (outra caixa de diálogo) é uma bifurcação do Zenity com muitas melhorias, como botões personalizados, diálogos adicionais, menu pop-up no ícone de notificação e muito mais.

There were two main reasons to make this fork. The first one is to remove dependencies on deprecated libraries, such as libglade and gnome-canvas. And the second one - as for me, Zenity looks like an abandoned project. Its ChangeLog consists of just "bump version to..." and "translation updated" for the long time, but many interesting ideas which are ignored by developers/maintainers were in GNOME Bugzilla.

uma nota

Como don_crissti menciona, as soluções neste unix.stackexchange.com são provavelmente relevantes:

Abra uma janela em um display X remoto (por que "Não é possível abrir o display")?

    
por 22.06.2013 / 20:31