Notificação da área de trabalho quando comandos de longa execução são concluídos

48

Eu gostaria de ter uma notificação de área de trabalho sempre que um comando executado por mais de 15 segundos terminar em um shell interativo.

Em outras palavras, gostaria que todos os comandos fossem envolvidos em algo como isto

start=$(date +%s);
ORIGINAL_COMMAND;
[ $(($(date +%s) - start)) -le 15 ] || notify-send "Long running command finished"

Qual é a melhor maneira de conseguir isso em bash?

    
por aioobe 23.01.2014 / 12:57

9 respostas

20

Você quer o link (instalável dos arquivos do Ubuntu com sudo apt-get install undistract-me ) que faz exatamente o que você está pedindo, incluindo trabalhando automaticamente (isto é, sem ter que se lembrar de adicionar algo extra a comandos potencialmente longos).

    
por sil 03.05.2015 / 17:37
30

Até onde eu entendi, você quer um wrapper . E você quer usar um comando através dele para que você receba a notificação desejada se o tempo de execução do seu comando for maior que 15 segundos. Então aqui está.

wrapper(){
    start=$(date +%s)
    "$@"
    [ $(($(date +%s) - start)) -le 15 ] || notify-send "Notification" "Long\
 running command \"$(echo $@)\" took $(($(date +%s) - start)) seconds to finish"
}

Copie essa função em ~/.bashrc e source ~/.bashrc as,

. ~/.bashrc

Uso

wrapper <your_command>

Se demorar mais de 15 segundos, você receberá a notificação do desktop descrevendo o comando e seu tempo de execução.

Exemplo

wrapper sudo apt-get update

    
por souravc 23.01.2014 / 20:29
23

Em ~/.bashrc , há um alias alert definido como:

alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

que pode ser usado para notificar a conclusão da execução do comando.

Uso:

$ the_command; alert

por exemplo.

$ sudo apt-get update; alert

Você pode personalizar o alias de acordo com sua necessidade e desejo.

    
por precise 23.01.2014 / 20:23
13

Além de um wrapper como o souravc sugerido, não há realmente nenhuma boa maneira de fazer isso no bash. Você pode contornar isso com uma armadilha DEBUG e um PROMPT_COMMAND. Um trap DEBUG é acionado sempre que você executa um comando, e PROMPT_COMMAND é executado logo antes do prompt ser escrito.

Então, coisas para ~/.bashrc se tornam algo como

trap '_start=$SECONDS' DEBUG
PROMPT_COMMAND='(if (( SECONDS - _start > 15 )); then notify-send "Long running command ended"; fi)'

Isso é um hack, então não se surpreenda se você encontrar estranhos efeitos colaterais com isso.

    
por geirha 23.01.2014 / 21:07
4

EDITAR

TL; DR : cria um atalho de preenchimento automático em .inputrc e funciona em .bashrc . Execute o comando como de costume, digite, mas ao invés de ENTER , pressione o atalho que você especificou em .inputrc

A pessoa que colocou recompensas nessa pergunta disse:

  

"Todas as respostas existentes exigem a digitação de um comando adicional   após o comando. Eu quero uma resposta que faça isso automaticamente. "

Enquanto pesquisava as soluções para este problema, me deparei com esta questão do stackexchange, que permite vincular Ctrl J para uma seqüência de comandos: Ctrl a (mova para o início da linha), coloque a string "mesure" na frente do comando que você digitou, Ctrl m (executar)

Assim você obtém funcionalidade de preenchimento automático e separa o comando ENTER para medir o tempo, enquanto mantém o propósito original da função segundo que eu postei abaixo.

A partir de agora, aqui está o conteúdo do meu arquivo ~/.inputrc :

"\C-j": "\C-a measure \C-m"

E aqui está o conteúdo de .bashrc (note, eu não uso bash para sempre - eu uso o mksh como meu shell, e é isso que você vê no post original. A funcionalidade ainda é a mesma)

PS1=' serg@ubuntu [$(pwd)]
================================
$ '
function measure () 
{

/usr/bin/time --output="/home/xieerqi/.timefile" -f "%e" $@ 

if [ $( cat ~/.timefile| cut -d'.' -f1 ) -gt 15 ]; then

    notify-send "Hi , $@ is done !"

fi


}

Publicação original

Aqui está minha ideia - use uma função em .bashrc . Princípio básico - use /usr/bin/time para medir o tempo que o comando leva para ser concluído e, se for mais de 15 segundos, envie uma notificação.

function measure () 
{

if [ $( /usr/bin/time -f "%e" $@ 2>&1 >/dev/null ) -gt 15 ]; then

    notify-send "Hi , $@ is done !"

fi


}

Aqui estou redirecionando a saída para /dev/null , mas para visualizar a saída, o redirecionamento para o arquivo também pode ser feito.

Uma abordagem muito melhor, IMHO, é enviar a saída de tempo para algum arquivo na sua pasta pessoal (só assim você não polui o seu sistema com timefiles, e sempre sabe onde procurar). Aqui está essa segunda versão

function measure () 
{

/usr/bin/time --output=~/.timefile -f "%e" $@ 

if [ $( cat ~/.timefile | cut -d'.' -f1 ) -gt 15 ]; then

    notify-send "Hi , $@ is done !"

fi


}

E aqui estão as capturas de tela da primeira e segunda versão, nessa ordem

Primeira versão, sem saída

Segunda versão, com saída

    
por Sergiy Kolodyazhnyy 04.05.2015 / 01:31
3

Eu criei recentemente uma ferramenta que serve esse propósito. Ele pode ser executado como um wrapper ou automaticamente com a integração shell. Confira aqui: link

Para instalá-lo:

sudo pip install ntfy

Para usá-lo como um wrapper:

ntfy done sleep 3

Para receber notificações automaticamente, adicione isso ao seu .bashrc ou .zshrc :

eval "$(ntfy shell-integration)"
    
por Daniel Schep 04.03.2016 / 22:51
1

Seu script funciona muito bem, apenas certifique-se de incluir o 'shebang' ( #!/bin/bash ) linha. Outros para #!/bin/bash são mencionados aqui , mas na maioria das vezes, #!/bin/bash funciona bem para Scripts bash do Unix. É exigido pelo interpretador de script para que ele saiba que tipo de script é.

Isso parece funcionar como um script de teste:

#!/bin/bash
start=$(date +%s);
   echo Started
   sleep 20;
   echo Finished!
[ $(($(date +%s) - start)) -le 15 ] || notify-send -i dialog-warning-symbolic "Header" "Message"

Para modificar este script, coloque o (s) comando (s) onde as linhas echo e sleep são.

Nota com notify-send , você pode usar -i para especificar um ícone também: -)

Além disso, verifique se ele é executável executando chmod +x /PATH/TO/FILE primeiro.

    
por Wilf 23.01.2014 / 18:54
1

Você pode modificar o Bash para implementar a funcionalidade do wrapper desejada.

Se você está inclinado a fazer muitas dessas modificações em seu shell interativo, você pode considerar mudar para um shell intrinsecamente hackable como o eshell, que é construído usando o Emacs elisp e tem toda a sua capacidade de personalização:

link

    
por Ryan Prior 30.04.2014 / 14:21
-2

Você também pode fazer isso com uma simples declaração if como esta

#!/bin/bash

START=$(date +%s)

TIME=$(($START+15))

ORIGINAL_COMMAND;

END=$(date +%s)

if [ $END -gt $TIME ]
then
    notify-send "Task Completed"
fi

Você pode usar seus próprios nomes de variáveis.

Posso confirmar que isso funciona, testei com um comando que demora muito para terminar e outro que não e a notificação vem para o que demora muito tempo

Você também pode fazer isso com qualquer comando substituindo ORIGINAL_COMMAND por $@ e executando o script como ./script command .

    
por Rumesh 03.05.2015 / 17:31