回声之前的时间戳


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

Answers:


22

您可以跳过echo,然后将消息放入date命令中。date允许您将文本插入格式字符串(+%R在您的示例中)。例如:

date +"%R usb device already mounted"

为了方便起见,也可以将其放入shell函数中。例如:

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

echo_time "usb device already mounted"

如果您要多次重复使用它,它会更清洁。


6
echo_time会按照您的期望进行操作,直到您的邮件中有%签名。这不是一个非常可靠的解决方案。
derobert 2013年

1
@derobert因为实现隐藏在函数中,所以echo_time可以只使用OP的date + echo构造
Izkata

我只是将“ $ *”改为“ $ @”(以养成使用后者的习惯)
Olivier Dulac 2013年

如何在管道中使用它?
erikbwork 2016年

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
很好,因为它只调用一次日期,而不是三次。
evilsoup

2
当脚本不会持续很长时间时,这是很好的选择,但是当脚本的时间更长时,它将具有错误的日期。
TaXXoR 2013年

4

使用ksh93和最新版本bash

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

zsh

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

或为避免"$@"零件迅速扩展:

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

旧版本的hacky方法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()."] $_"'

正如Stephane在下面指出的那样,各个程序在发送到管道时可能会缓冲其输出。当然,这些缓冲区在程序退出时将被刷新,因此最坏的情况是在程序退出时会显示时间戳(如果它缓冲其输出并且打印不足以填充该缓冲区)。但是,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.

但是请注意,一旦将输出发送到管道,应用程序便开始缓冲其输出,因此时序可能无法反映其打印时间。
2013年

2
我建议检查出tsmoreutils中的命令。它是一种类似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写道。您必须保护字符串免受过早的命令和变量扩展的影响。
manatwork 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.