отметка времени перед эхом

12

Существует лучший способ создать метку времени перед echo?

В настоящее время я делаю это так:

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

Вывод должен выглядеть примерно так:

10:36 usb device already mounted
TaXXoR
источник

Ответы:

22

Вы можете пропустить echoи просто вставить сообщение в dateкоманду. dateпозволяет вставлять текст в строку формата ( +%Rв вашем примере). Например:

date +"%R usb device already mounted"

Вы также можете добавить его в функцию оболочки для удобства. Например:

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

echo_time "usb device already mounted"

Это очиститель, если вы собираетесь использовать его много раз.

Дэвид Баггерман
источник
6
echo_timeбудет делать то, что вы ожидаете, пока ваше сообщение не будет %подписано. Не очень надежное решение.
Дероберт
1
@derobert Поскольку реализация скрыта в функции, echo_timeможно просто использовать конструкцию даты + эхо OP
Izkata
я бы просто изменил «$ *» на «$ @» (чтобы привыкнуть использовать более поздние)
Оливье Дюлак
как использовать это в трубе?
erikbwork
6

Вот более надежный и переносимый (POSIX) способ сделать это, особенно тот, который позволяет %оставаться необработанным в качестве аргумента:

echo_time() {
    date +"%H:%M $(printf "%s " "$@" | sed 's/%/%%/g')"
}
jlliagre
источник
5

Вы можете создать переменную для 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
Это хорошо, потому что он называет дату только один раз, а не три раза.
evilsoup
2
Это хорошо, когда скрипт длится недолго, но у него будет неправильная дата, когда он будет длиннее.
TaXXoR
4

С ksh93и последние версии bash:

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

С zsh:

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

Или чтобы избежать быстрого расширения в "$@"части:

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

Хакерский способ для старых версий bash:

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

На самом деле, если дело в том, чтобы:

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

Вы могли бы сделать:

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

Или чтобы избежать разветвления вложенной оболочки:

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

Потом:

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

(обратите внимание, что они отображаются на stderr, что на самом деле может быть предпочтительнее).

Стефан Шазелас
источник
1

Когда я делаю подобные вещи, я обычно хочу, чтобы все строки (включая любой вывод программы) были помечены временем. Таким образом, я бы использовал что-то вроде этого:

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

Как указывает Стефан ниже, отдельные программы могут буферизовать свой вывод при отправке в канал. Конечно, эти буферы будут сброшены при выходе из программы, поэтому в худшем случае отметки времени будут отображаться при выходе из программы (если она буферизует свой вывод и не печатает достаточно для заполнения буфера). Однако echoметки времени будут точными.

В качестве пригодного для тестирования образца:

#!/bin/sh

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

Выход:

[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.
Декан сереневый
источник
Однако обратите внимание, что как только выходные данные передаются в канал, приложения начинают буферизовать свои выходные данные, поэтому время может не отражать время, которое они были напечатаны.
Стефан Шазелас
2
Я предлагаю проверить tsкоманду, которая является частью moreutils. Это аналогичный Perl-скрипт, но с различными вариантами формата отметки времени и т. Д.
derobert
@ derobert - почему бы тебе не написать, как это сделать, используя ts? Похоже, это будет лучший вариант здесь.
SLM
1

Создание отметок времени с ts

установить инструмент ts(часть пакета moreutils):

sudo apt-get install moreutils

Добавление метки времени к выводу:

echo "foo" | ts

выход:

Sep 03 14:51:44 foo
TaXXoR
источник
-1
alias echo="d=$(date +%Y-%m-%d); echo $d "
echo hola
IIII
источник
1
Это не сработало, когда я просто попробовал.
SLM
Так же, как @slm написал. Вы должны защитить строку от преждевременного расширения команд и переменных.
manatwork