Desktop-Benachrichtigung, wenn lange ausgeführte Befehle ausgeführt werden

59

Ich möchte eine Desktop-Benachrichtigung erhalten, wenn ein Befehl, der länger als beispielsweise 15 Sekunden ausgeführt wurde, in einer interaktiven Shell ausgeführt wird.

Mit anderen Worten, ich möchte, dass alle Befehle in so etwas eingeschlossen sind

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

Was ist der beste Weg, um dies in bash zu erreichen?

aioobe
quelle
1
Mögliches selbes auf Superuser
Ciro Santilli am
Warum haben Sie gerade "in Interactive Shell" hinzugefügt? Möglicherweise werden einige der vorhandenen Antworten ungültig, die im Kontext Ihres ursprünglichen Beitrags über ein Jahr lang vorhanden waren. Wenn Sie eine Lösung speziell für die interaktive Shell benötigen, ziehen Sie in Betracht, eine separate Frage zu stellen, die auf diese verweist.
Sergiy Kolodyazhnyy
Der Teil "Interaktive Shell" wurde im ersten Kommentar vor der Bearbeitung geklärt. Ich habe die Frage einfach bearbeitet und den Kommentar entfernt. Außerdem funktionieren die 3 Zeilen in den Fragen gut für ein Skript.
Aioobe

Antworten:

24

Sie möchten, dass https://launchpad.net/undistract-me (aus den Ubuntu-Archiven installierbar sudo apt-get install undistract-me) genau das tut, was Sie sich wünschen , einschließlich der automatischen Arbeit (d. H. Ohne daran zu denken, dass Sie potenziell langwierigen Dateien etwas hinzufügen müssen). laufende Befehle).

sil
quelle
1
Es scheint nicht zu funktionieren. Ich habe es installiert, mein System neu gestartet und mit sleep 30, aber ohne Benachrichtigung getestet .
Galgalesh
4
Sie müssen die folgenden zwei Zeilen hinzufügen .bashrc: . /usr/share/undistract-me/long-running.bash notify_when_long_running_commands_finish_install. Es scheint ein Fehler zu sein: github.com/jml/undistract-me/issues/23
Ludenticus
32

Soweit ich verstanden habe, möchten Sie einen Wrapper . Sie möchten einen Befehl verwenden, damit Sie benachrichtigt werden, wenn die Laufzeit Ihres Befehls mehr als 15 Sekunden beträgt. Also hier ist es.

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

Kopieren Sie diese Funktion in Ihre ~/.bashrcund Quelle ~/.bashrcals,

. ~/.bashrc

Verwendung

wrapper <your_command>

Wenn es länger als 15 Sekunden dauert, erhalten Sie eine Desktop-Benachrichtigung, die den Befehl und seine Ausführungszeit beschreibt.

Beispiel

wrapper sudo apt-get update

Screenshot der Desktop-Vernichtung

souravc
quelle
1
"$@"nicht $@. Großer Unterschied.
Geirha
4
Ich möchte jedoch vermeiden, wrappervor jedem von mir eingegebenen Befehl zu schreiben .
Aioobe
2
@aioobe Sie können einen kürzeren Funktionsnamen verwenden, auch wenn es sich um einen Buchstaben handelt. Aber ein Wrapper funktioniert auf diese Weise.
Souravc
3
command; alertist in der Tat kürzer als wrapper command:-)
aioobe
1
Wenn Sie nicht möchten, dass das notify-sendZeitlimit für längere Zeit abläuft, geben Sie notify-send ein benutzerdefiniertes Zeitlimit (in Millisekunden). zBnotify-send --expire-time 999999999 ...
Bryce Guinta
26

In ~/.bashrcgibt es einen Alias alert, der wie folgt definiert ist:

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

Hiermit kann der Abschluss der Befehlsausführung gemeldet werden.

Verwendungszweck:

$ the_command; alert

z.B

$ sudo apt-get update; alert

snap1

Sie können den Alias ​​nach Bedarf und Wunsch anpassen.

präzise
quelle
3
Das ist gut zu wissen. Gibt es eine Möglichkeit, eine Warnung nach jedem von mir eingegebenen Befehl anzufügen (und sie auch nur dann anzuzeigen, wenn der Befehl länger als 15 Sekunden gedauert hat)?
Aioobe
seltsam, dass es bereits zu meiner .bashrc hinzugefügt wurde, ist es in Ubuntu voreingestellt?
Vignesh
13

Abgesehen von einem Wrapper wie dem von Souravc vorgeschlagenen gibt es keine wirklich gute Möglichkeit, dies in bash zu tun. Sie können sich mit einer DEBUG-Falle und einem PROMPT_COMMAND zurechtfinden. Ein DEBUG-Trap wird ausgelöst, wenn Sie einen Befehl ausführen, und PROMPT_COMMAND wird unmittelbar vor dem Schreiben der Eingabeaufforderung ausgeführt.

So ~/.bashrcwird sowas für sowas

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

Dies ist ein Hack, also wundern Sie sich nicht, wenn Sie dabei auf merkwürdige Nebenwirkungen stoßen.

geirha
quelle
4

BEARBEITEN

TL; DR : Erstellt eine Verknüpfung zur automatischen Vervollständigung in .inputrcund funktioniert in .bashrc . Führen Sie den Befehl wie gewohnt aus, geben Sie ihn ein, ENTERund drücken Sie stattdessen die von Ihnen angegebene Verknüpfung.inputrc

Die Person, die Kopfgeld auf diese Frage setzte, sagte:

"Für alle vorhandenen Antworten muss nach dem Befehl ein zusätzlicher Befehl eingegeben werden. Ich möchte eine Antwort, die dies automatisch ausführt."

Bei der Suche nach Lösungen für dieses Problem bin ich auf diese Frage von stackexchange gestoßen, die das Binden CtrlJan eine Folge von Befehlen ermöglicht: Ctrla(zum Zeilenanfang gehen), "mesure" -String vor den von Ihnen eingegebenen Befehl setzen, Ctrlm(ausführen)

So erhalten Sie die Funktionalität der automatischen Vervollständigung und einen separaten ENTERBefehl zum Messen der Zeit, während der ursprüngliche Zweck der zweiten Funktion, die ich unten gepostet habe, beibehalten wird.

Ab sofort sind hier die Inhalte meiner ~/.inputrcDatei:

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

Und hier sind die Inhalte von .bashrc(Anmerkung: Ich habe Bash nicht für immer verwendet - ich verwende MKSH als meine Shell, daher ist das, was Sie im ursprünglichen Beitrag sehen. Die Funktionalität ist immer noch die gleiche).

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


}

Ursprünglicher Beitrag

Hier ist meine Idee - benutze eine Funktion in .bashrc. Grundprinzip - Verwenden Sie /usr/bin/timediese Option, um die Zeit zu messen, die der Befehl benötigt, und senden Sie eine Benachrichtigung, wenn er länger als 15 Sekunden dauert.

function measure () 
{

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

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

fi


}

Hier leite ich die Ausgabe um, /dev/nullaber um die Ausgabe anzuzeigen, kann auch die Umleitung in eine Datei erfolgen.

Ein viel besserer Ansatz, IMHO, ist es, die Ausgabe der Zeit an eine Datei in Ihrem Home-Ordner zu senden (nur damit Sie Ihr System nicht mit Zeitdateien beschmutzen und immer wissen, wo Sie suchen müssen). Hier ist die zweite Version

function measure () 
{

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

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

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

fi


}

Und hier sind die Screenshots der ersten und zweiten Version, in dieser Reihenfolge

Erste Version, keine Ausgabe Bildbeschreibung hier eingeben

Zweite Version mit Ausgabe Bildbeschreibung hier eingeben

Sergiy Kolodyazhnyy
quelle
Funktioniert übrigens auch mit sudo-Befehlen. Ich habe es mit sudo lsofund meistens mit getestet ping -c20 google.com.
Sergiy Kolodyazhnyy
3

Ich habe vor kurzem ein Tool gebaut, das diesen Zweck erfüllt. Es kann entweder als Wrapper oder automatisch mit Shell-Integration ausgeführt werden. Überprüfen Sie es hier: http://ntfy.rtfd.io

So installieren Sie es:

sudo pip install ntfy

So verwenden Sie es als Wrapper:

ntfy done sleep 3

Um Benachrichtigungen automatisch zu erhalten, fügen Sie diese zu Ihrem .bashrcoder hinzu .zshrc:

eval "$(ntfy shell-integration)"
Daniel Schep
quelle
1

Ihr Skript funktioniert ganz gut, stellen Sie jedoch sicher, dass Sie die Zeile 'shebang' ( #!/bin/bash) einfügen. Andere, die #!/bin/bashhier erwähnt werden , #!/bin/bashfunktionieren jedoch meistens gut für Unix-Bash-Skripte. Es wird vom Skriptinterpreter benötigt, damit er weiß, um welche Art von Skript es sich handelt.

Dies scheint als Testskript zu funktionieren:

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

Um dieses Skript zu ändern, setzen Sie die Befehle an die Positionen echound sleep.

Beachten Sie mit notify-send, dass Sie auch -iein Symbol angeben können :-)

Stellen Sie außerdem sicher, dass es ausführbar ist, indem Sie chmod +x /PATH/TO/FILEes zuerst ausführen .

Wilf
quelle
1

Sie können Bash ändern, um die gewünschte Wrapper-Funktionalität zu implementieren.

Wenn Sie dazu neigen, viele derartige Änderungen an Ihrer interaktiven Shell vorzunehmen, können Sie in Erwägung ziehen, auf eine eigenhackbare Shell wie eshell zu wechseln, die mit Emacs elisp erstellt wurde und deren Anpassungsmöglichkeiten alle Erwägungen erfüllen:

http://www.masteringemacs.org/articles/2010/12/13/complete-guide-mastering-eshell/

Ryan Prior
quelle
-2

Sie können dies auch mit einer einfachen if-Anweisung wie dieser tun

#!/bin/bash

START=$(date +%s)

TIME=$(($START+15))

ORIGINAL_COMMAND;

END=$(date +%s)

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

Sie können Ihre eigenen Variablennamen verwenden.

Ich kann bestätigen, dass dies funktioniert. Ich habe es mit einem Befehl getestet, dessen Beendigung lange dauert, und einem, der es nicht tut. Die Benachrichtigung wird für den Befehl gesendet, der lange dauert

Sie können dies auch mit jedem Befehl tun durch Ersetzen ORIGINAL_COMMANDmit $@und Ausführen des Skripts wie ./script command.

Rumesh
quelle
Warum wurde meine Antwort abgelehnt? Ich möchte wissen, wo ich in der Antwort einen
Fehler gemacht habe
Ich habe es nicht abgelehnt, aber ich werde Ihnen sagen, was daran falsch ist: Zunächst muss ein zusätzlicher Befehl eingegeben werden. Ich habe ausdrücklich in meinem Kopfgeld angegeben, dass ich das nicht tun möchte. Zweitens, warum calc? $((2+2))ist eine Bash, die keine zusätzlichen Programme benötigt. Drittens: Es funktioniert nicht mit Befehlen, die Leerzeichen enthalten. tl; dr: es ist schlimmer als die anderen 1-jährigen Antworten
Galgalesh
Naja ..... Start- und Endzeit werden immer unterschiedlich sein, oder? Auch für einen kurzen Befehl, der 1 Sekunde lang ist
Sergiy Kolodyazhnyy