Powiadomienie na pulpicie po zakończeniu długotrwałych poleceń


59

Chcę otrzymywać powiadomienie na pulpicie za każdym razem, gdy polecenie uruchamiane przez ponad, powiedzmy 15 sekund, kończy się w interaktywnej powłoce.

Innymi słowy, chciałbym, aby wszystkie polecenia były zapakowane w coś takiego

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

Jaki jest najlepszy sposób na osiągnięcie tego w bash?




Dlaczego właśnie dodałeś „w powłoce interaktywnej”? Może to unieważnić niektóre z istniejących odpowiedzi, które istniały w kontekście twojego oryginalnego postu przez ponad rok. Jeśli potrzebujesz rozwiązania specjalnie dla interaktywnej powłoki, zastanów się nad zadaniem osobnego pytania dotyczącego tego.
— Sergiy Kolodyazhnyy

Część „powłoki interaktywnej” została wyjaśniona w pierwszym komentarzu przed edycją. Po prostu zredagowałem pytanie i usunąłem komentarz. Poza tym 3 wiersze zamieszczone w pytaniach działają dobrze dla skryptu.
— aioobe

Odpowiedzi:


24

Chcesz https://launchpad.net/undistract-me (instalowalny z archiwów Ubuntu za pomocą sudo apt-get install undistract-me), który robi dokładnie to, o co prosisz, w tym działa automatycznie (to znaczy, bez konieczności dodawania czegoś dodatkowego do potencjalnie długich- uruchamianie poleceń).


1
Wygląda na to, że nie działa. Zainstalowałem go, ponownie uruchomiłem system i testowałem sleep 30, ale bez powiadomienia.
— Galgalesh

4
Trzeba dodać następujące dwa wiersze .bashrc: . /usr/share/undistract-me/long-running.bash notify_when_long_running_commands_finish_install. Wydaje się, że to błąd: github.com/jml/undistract-me/issues/23
— Ludenticus

32

O ile rozumiem, chcesz opakowanie . I chcesz użyć polecenia za jego pośrednictwem, aby dało pożądane powiadomienie, jeśli czas działania polecenia jest dłuższy niż 15 sekund. Więc oto to.

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

Skopiuj tę funkcję do swojego ~/.bashrci źródła ~/.bashrcjako,

. ~/.bashrc

Wykorzystanie

wrapper <your_command>

Jeśli zajmie to więcej niż 15 sekund, otrzymasz powiadomienie na pulpicie opisujące polecenie i czas jego wykonania.

Przykład

wrapper sudo apt-get update

zrzut ekranu nitryfikacji pulpitu


1
"$@"Nie $@. Duża różnica.
— geirha

4
Chciałbym jednak unikać pisania wrapperprzed każdym poleceniem, które wpisuję.
— aioobe

2
@ aioobe możesz użyć krótszej nazwy funkcji, nawet może to być litera. ale opakowanie działa w ten sposób.
— souravc

3
command; alertjest w rzeczywistości krótszy niż wrapper command:-)
— aioobe

1
Jeśli nie chcesz, notify-sendaby wygasł przez długi czas, podaj powiadomienie-wyślij niestandardowy limit czasu (w milisekundach). np.notify-send --expire-time 999999999 ...
— Bryce Guinta

26

W ~/.bashrcjest alias alertokreślono jako:

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$//'\'')"'

które mogą być użyte do powiadomienia o zakończeniu wykonywania polecenia.

Stosowanie:

$ the_command; alert

na przykład

$ sudo apt-get update; alert

Snap1

Możesz dostosować alias do swoich potrzeb i pragnień.


3
Dobrze wiedzieć. Czy istnieje sposób na dołączenie alertu po każdym wpisaniu polecenia (a także powiadamianie go tylko wtedy, gdy polecenie trwało dłużej niż 15 sekund)?
— aioobe

dziwna rzecz, że jest już dodana do mojego .bashrc, czy jest domyślna w Ubuntu?
— Vignesh,

13

Oprócz sugerowanego opakowania takiego jak souravc, naprawdę nie ma dobrego sposobu na zrobienie tego w bashu. Możesz włamać się do niego z pułapką DEBUG i PROMPT_COMMAND. Pułapka DEBUG jest uruchamiana przy każdym uruchomieniu polecenia, a PROMPT_COMMAND jest uruchamiany tuż przed napisaniem monitu.

Rzeczy ~/.bashrcstają się czymś takim

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

To jest hack, więc nie zdziw się, jeśli spotkasz się z dziwnymi efektami ubocznymi.


4

EDYTOWAĆ

TL; DR : utwórz skrót do autouzupełniania .inputrci uruchom w .bashrc . Uruchom polecenie jak zwykle, wpisz, ale zamiast tego ENTERnaciśnij skrót określony w.inputrc

Osoba, która naliczyła nagrodę za to pytanie, powiedziała:

„Wszystkie istniejące odpowiedzi wymagają wpisania dodatkowego polecenia po poleceniu. Chcę odpowiedzi, która zrobi to automatycznie”.

Badając rozwiązania tego problemu, natknąłem się na to pytanie z stackexchange, które pozwala na powiązanie CtrlJz sekwencją poleceń: Ctrla(przejście do początku linii), umieść ciąg „mesure” przed wprowadzonym poleceniem, Ctrlm(wykonaj)

W ten sposób otrzymujesz funkcję automatycznego uzupełniania i osobne ENTERpolecenie do pomiaru czasu, zachowując oryginalny cel drugiej funkcji, którą zamieściłem poniżej.

Na razie oto zawartość mojego ~/.inputrcpliku:

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

A oto zawartość .bashrc(uwaga, nie używałem bash od zawsze - używam mksh jako mojej powłoki, stąd to widać w oryginalnym poście. Funkcjonalność jest nadal taka sama)

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


}

Oryginalny post

Oto mój pomysł - użyj funkcji w .bashrc. Podstawowa zasada - służy /usr/bin/timedo pomiaru czasu potrzebnego do wykonania polecenia, a jeśli jest on dłuższy niż 15 sekund, wyślij powiadomienie.

function measure () 
{

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

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

fi


}

Tutaj przekierowuję dane wyjściowe do, /dev/nullale aby wyświetlić dane wyjściowe, można również dokonać przekierowania do pliku.

O wiele lepszym podejściem, IMHO, jest wysyłanie wyniku czasu do jakiegoś pliku w folderze domowym (tylko po to, abyś nie zanieczyszczał systemu plikami czasowymi i zawsze wiedział, gdzie szukać). Oto druga wersja

function measure () 
{

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

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

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

fi


}

A oto zrzuty ekranu pierwszej i drugiej wersji, w tej kolejności

Pierwsza wersja, brak danych wyjściowych wprowadź opis zdjęcia tutaj

Druga wersja z wyjściem wprowadź opis zdjęcia tutaj


Nawiasem mówiąc, działa również z poleceniami sudo. Testowałem to z sudo lsofi głównie z ping -c20 google.com.
— Sergiy Kolodyazhnyy

3

Niedawno zbudowałem narzędzie, które służy temu celowi. Może być uruchamiany jako opakowanie lub automatycznie z integracją powłoki. Sprawdź to tutaj: http://ntfy.rtfd.io

Aby zainstalować:

sudo pip install ntfy

Aby użyć go jako opakowania:

ntfy done sleep 3

Aby automatycznie otrzymywać powiadomienia, dodaj to do swojego .bashrclub .zshrc:

eval "$(ntfy shell-integration)"

1

Twój skrypt działa całkiem dobrze, upewnij się tylko, że dołączasz#!/bin/bash wiersz „shebang” ( ) . Inne #!/bin/bashsą tutaj wymienione , ale przez większość czasu #!/bin/bashdziała dobrze dla skryptów bash dla Uniksa. Jest wymagany przez interpretera skryptów, aby wiedział, jaki to jest typ skryptu.

Wydaje się, że działa to jako skrypt testowy:

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

Aby zmodyfikować ten skrypt, umieść komendę w miejscu, w którym znajdują się linie echoi sleep.

Uwaga za pomocą notify-send, możesz także użyć -iikony :-)

Upewnij się także, że jest wykonywalny, uruchamiając chmod +x /PATH/TO/FILEgo najpierw.



-2

Możesz to również zrobić za pomocą takiej prostej instrukcji if

#!/bin/bash

START=$(date +%s)

TIME=$(($START+15))

ORIGINAL_COMMAND;

END=$(date +%s)

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

Możesz użyć własnych nazw zmiennych.

Mogę potwierdzić, że to działa, przetestowałem przy użyciu polecenia, które zajmuje dużo czasu, a które nie, a powiadomienie przychodzi dla tego, które zajmuje dużo czasu

Można również zrobić to z każdym poleceniem zastępując ORIGINAL_COMMANDze $@i uruchamiając skrypt jako ./script command.


Dlaczego moja odpowiedź została odrzucona? Chcę wiedzieć, gdzie popełniłem błąd w odpowiedzi
— Rumesh

Nie głosowałem za tym, ale powiem ci, co jest z nim nie tak: Po pierwsze, wymaga wpisania dodatkowego polecenia. Konkretnie stwierdziłem w mojej nagrody, że nie chcę tego robić. Po drugie, dlaczego calc? $((2+2))jest wbudowanym bash, nie wymaga żadnych dodatkowych programów. Po trzecie: nie działa z poleceniami zawierającymi spacje. tl; dr: jest gorzej niż w przypadku innych rocznych odpowiedzi
— Galgalesh

Cóż ... czas rozpoczęcia i zakończenia zawsze będzie inny, prawda? Nawet dla krótkiego polecenia trwającego 1 sekundę
— Sergiy Kolodyazhnyy
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.