znacznik czasu przed echem

12

Czy istnieje lepszy sposób na utworzenie znacznika czasu przed echo?

Obecnie robię to w ten sposób:

#!/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

Dane wyjściowe powinny wyglądać mniej więcej tak:

10:36 usb device already mounted
TaXXoR
źródło

Odpowiedzi:

22

Możesz pominąć echoi po prostu wstawić wiadomość do datepolecenia. datepozwala wstawić tekst do ciągu formatu ( +%Rw twoim przykładzie). Na przykład:

date +"%R usb device already mounted"

Możesz również wrzucić ją do funkcji powłoki dla wygody. Na przykład:

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

echo_time "usb device already mounted"

Jest to czystsze, jeśli zamierzasz go wielokrotnie używać.

David Baggerman
źródło
6
echo_timezrobi to, czego oczekujesz, dopóki twoja wiadomość nie będzie miała %znaku. Niezbyt solidne rozwiązanie.
derobert
1
@derobert Ponieważ implementacja jest ukryta w funkcji, echo_timemogłaby po prostu użyć konstrukcji daty + echa OP
Izkata
po prostu zmienię „$ *” na „$ @” (aby przyzwyczaić się do późniejszego korzystania)
Olivier Dulac
jak używać tego w rurze?
erikbwork
6

Oto bardziej niezawodny i przenośny (POSIX) sposób, aby to zrobić, szczególnie taki, który pozwala %pozostać nieprzetworzonym jako argument:

echo_time() {
    date +"%H:%M $(printf "%s " "$@" | sed 's/%/%%/g')"
}
jlliagre
źródło
5

Możesz utworzyć zmienną dla 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
źródło
3
Jest to miłe, ponieważ wywołuje datę tylko raz, a nie trzy razy.
evilsoup
2
Jest to miłe, gdy skrypt nie trwa długo, ale będzie miał niepoprawną datę, kiedy będzie dłuższy.
TaXXoR,
4

W ksh93najnowszych wersjach bash:

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

Z zsh:

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

Lub, aby uniknąć szybkiego rozszerzenia w "$@"części:

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

Hacky sposób dla starszych wersji bash:

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

Właściwie, jeśli chodzi o to, aby:

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

Mógłbyś:

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

Lub, aby uniknąć rozwidlenia podpowłoki:

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

Następnie:

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

(zauważ, że są one powtarzane na stderr, co w rzeczywistości może być lepsze).

Stéphane Chazelas
źródło
1

Kiedy robię takie rzeczy, zwykle chcę, aby wszystkie linie (w tym dane wyjściowe programu) były oznaczone znacznikiem czasu. Dlatego użyłbym czegoś takiego:

#!/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()."] $_"'

Jak wskazuje Stephane poniżej, poszczególne programy mogą buforować swoje dane wyjściowe po wysłaniu do potoku. Oczywiście bufory te zostaną opróżnione po wyjściu z programu, więc w najgorszym przypadku znaczniki czasu pokażą, kiedy program zakończy działanie (jeśli buforuje dane wyjściowe i nie drukuje wystarczająco dużo, aby wypełnić bufor). Jednak wszystkie echoznaczniki czasu będą dokładne.

Jako próbka do przetestowania:

#!/bin/sh

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

Wynik:

[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
źródło
Należy jednak pamiętać, że gdy dane wyjściowe trafią do potoku, aplikacje zaczynają buforować swoje dane wyjściowe, więc czasy mogą nie odzwierciedlać czasu, w którym zostały wydrukowane.
Stéphane Chazelas,
2
Sugeruję sprawdzenie tspolecenia, które jest częścią moreutils. Jest to podobny skrypt perla, ale z różnymi opcjami formatu znacznika czasu itp.
derobert
@derobert - dlaczego nie napiszesz, jak to zrobić ts? Wygląda na to, że byłaby to najlepsza opcja tutaj.
slm
1

Tworzenie znaczników czasu za pomocą ts

zainstaluj narzędzie ts(część pakietu moreutils):

sudo apt-get install moreutils

Dodanie znacznika czasu do wyniku:

echo "foo" | ts

wynik:

Sep 03 14:51:44 foo
TaXXoR
źródło
-1
alias echo="d=$(date +%Y-%m-%d); echo $d "
echo hola
iiii
źródło
1
To nie zadziałało, kiedy właśnie tego spróbowałem.
slm
Tak jak napisał @slm. Musisz chronić ciąg przed przedwczesnym rozszerzaniem poleceń i zmiennych.
manatwork