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

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.


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')"
}

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

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).


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.

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

-1
alias echo="d=$(date +%Y-%m-%d); echo $d "
echo hola

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.