мітка часу перед відлунням


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

Відповіді:


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можна просто використати дату ОП + конструкція відлуння
Izkata

я просто змінив би "$ *" на "$ @" (щоб звикнути використовувати пізніше)
Олів'є Дулак

як це використовувати в трубі?
erikbwork

6

Ось більш надійний і портативний (POSIX) спосіб зробити це, особливо той, який дозволяє %залишатися необробленим як аргумент:

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

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
Це приємно, оскільки він називає дату лише один раз, а не три рази.
зол

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

(зауважте, що вони перегукуються на більш жорсткий, що насправді може бути кращим).


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команду, яка входить до складу додаткових програм. Це схожий сценарій Perl, але з різними варіантами формату часової позначки тощо
derobert

@derobert - чому ти не напишеш, як це зробити за допомогою ts? Здається, це було б найкращим варіантом тут.
slm

1

Створення часових позначок за допомогою ts

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

sudo apt-get install moreutils

Додавання часової позначки до виводу:

echo "foo" | ts

вихід:

Sep 03 14:51:44 foo

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

1
Це не вийшло, коли я просто спробував це.
slm

Так само, як писав @slm. Ви повинні захистити рядок від передчасних команд і змінних розширень.
манастирство
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.