Zeitstempel vor einem Echo

12

Gibt es eine schönere Möglichkeit, einen Zeitstempel vor einem echo?

Derzeit mache ich es so:

#!/bin/sh

if mount | grep -q /mnt/usb; then
        echo `date +%R\ ` "usb device already mounted"
else
        echo `date +%R\ ` "mounting usb device..."
        mount -t msdosfs /dev/da0s1 /mnt/usb

        if mount | grep -q /mnt/usb; then
                echo `date +%R\ ` "usb device successfully mounted"
        fi
fi

Die Ausgabe sollte ungefähr so ​​aussehen:

10:36 usb device already mounted
TaXXoR
quelle

Antworten:

22

Sie können das überspringen echound einfach die Nachricht in den dateBefehl einfügen. dateMit dieser Option können Sie Text in die Formatzeichenfolge einfügen ( +%Rin Ihrem Beispiel). Beispielsweise:

date +"%R usb device already mounted"

Sie können es auch bequem in eine Shell-Funktion werfen. Beispielsweise:

echo_time() {
    date +"%R $*"
}

echo_time "usb device already mounted"

Dies ist ein Reiniger, wenn Sie ihn mehrmals wiederverwenden möchten.

David Baggerman
quelle
6
echo_timewird tun, was Sie erwarten, bis Ihre Nachricht ein %Zeichen enthält. Keine sehr robuste Lösung.
Derobert
1
@derobert Da die Implementierung in einer Funktion versteckt ist, echo_timekönnte nur das Datum + Echo-Konstrukt des OP verwendet werden
Izkata
Ich würde einfach "$ *" durch "$ @" ändern (um es mir zur Gewohnheit zu machen, das spätere zu verwenden)
Olivier Dulac
Wie benutzt man das in einem Rohr?
Erikbwork
6

Hier ist eine robustere und portablere Methode (POSIX), insbesondere eine, die es ermöglicht %, als Argument unverarbeitet zu bleiben:

echo_time() {
    date +"%H:%M $(printf "%s " "$@" | sed 's/%/%%/g')"
}
jlliagre
quelle
5

Sie können eine Variable erstellen für date +%R:

#!/bin/sh

T=$(date +%R)

if mount | grep -q /mnt/usb; then
        echo "$T usb device already mounted"
else
        echo "$T mounting usb device..."
        mount -t msdosfs /dev/da0s1 /mnt/usb

        if mount | grep -q /mnt/usb; then
                echo "$T usb device successfully mounted"
        fi
fi
Radu Rădeanu
quelle
3
Das ist schön, weil das Datum nur einmal und nicht dreimal aufgerufen wird.
Evilsoup
2
Dies ist schön, wenn das Skript nicht lange dauert, aber das falsche Datum hat, wenn es länger ist.
TaXXoR
4

Mit ksh93und aktuelle Versionen von bash:

ts_echo() {
  printf '%(%R)T: %s\n' -1 "$*"
}

Mit zsh:

ts_echo() print -P %T: "$@"

Oder um eine sofortige Erweiterung des "$@"Teils zu vermeiden :

ts_echo() echo ${(%):-%T}: "$@"

Ein hackiger Weg für ältere Versionen von bash:

ts_echo() (
  PS4="\A"
  set -x; : "$@"
)

Eigentlich, wenn es darum geht:

echo "<timestamp>: doing cmd args..."
cmd args...

Du könntest es tun:

ts() (
  PS4='\A: doing '
  set -x; "$@"
)
ts cmd args...

Oder um das Verzweigen einer Unterschale zu vermeiden:

ts() {
  local PS4='\A: doing ' ret
  set -x; "$@"
  { ret=$?; set +x; } 2> /dev/null
  return "$ret"
}

Dann:

$ ts echo whatever
14:32: doing echo whatever
whatever

(Beachten Sie, dass diese auf stderr wiedergegeben werden, was tatsächlich vorzuziehen ist).

Stéphane Chazelas
quelle
1

Wenn ich solche Dinge mache, möchte ich normalerweise, dass alle Zeilen (einschließlich aller Programmausgaben) mit einem Zeitstempel versehen werden. Daher würde ich so etwas verwenden:

#!/bin/sh

(
    if mount | grep -q /mnt/usb; then
        echo "usb device already mounted"
    else
        echo "mounting usb device..."
        mount -t msdosfs /dev/da0s1 /mnt/usb

        if mount | grep -q /mnt/usb; then
            echo "usb device successfully mounted"
        fi
    fi
) 2>&1 | perl -ne 'print "[".localtime()."] $_"'

Wie Stephane weiter unten ausführt, können einzelne Programme ihre Ausgabe puffern, wenn sie an eine Pipe gesendet werden. Natürlich werden diese Puffer geleert, wenn das Programm beendet wird. Im schlimmsten Fall werden die Zeitstempel angezeigt, wenn das Programm beendet wird (wenn es seine Ausgabe puffert und nicht genug druckt, um den Puffer zu füllen). Die echoZeitstempel sind jedoch alle korrekt.

Als ausführbares Beispiel zum Testen:

#!/bin/sh

(
    echo "Doing something"
    sleep 5
    echo "Doing something else..."
    ls /some/file
    sleep 8
    echo "Done."
) 2>&1 | perl -ne 'print "[".localtime()."] $_"'

Ausgabe:

[Thu Aug 29 07:32:37 2013] Doing something
[Thu Aug 29 07:32:42 2013] Doing something else...
[Thu Aug 29 07:32:42 2013] ls: cannot access /some/file: No such file or directory
[Thu Aug 29 07:32:50 2013] Done.
Dean Serenevy
quelle
Beachten Sie jedoch, dass Anwendungen ihre Ausgabe puffern, sobald die Ausgabe an eine Pipe gesendet wird, sodass die Timings möglicherweise nicht die Zeit widerspiegeln, zu der sie gedruckt wurden.
Stéphane Chazelas
2
Ich schlage vor, den tsBefehl zu überprüfen, der Teil von moreutils ist. Es ist ein ähnliches Perl-Skript, aber mit verschiedenen Optionen für das Zeitstempelformat usw.
derobert
@derobert - warum schreibst du nicht auf, wie das geht ts? Scheint, als wäre es hier die beste Option.
slm
1

Zeitstempel erstellen mit ts

Installieren Sie das Tool ts(Teil des Pakets moreutils):

sudo apt-get install moreutils

Hinzufügen eines Zeitstempels zu einer Ausgabe:

echo "foo" | ts

Ausgabe:

Sep 03 14:51:44 foo
TaXXoR
quelle
-1
alias echo="d=$(date +%Y-%m-%d); echo $d "
echo hola
iiii
quelle
1
Das hat nicht funktioniert, als ich es gerade ausprobiert habe.
slm
Genau wie @slm geschrieben hat. Sie müssen die Zeichenfolge vor vorzeitigen Befehls- und Variablenerweiterungen schützen.
Manatwork