ts-时间戳输入实用程序:设置时间戳的时区

ts-时间戳输入实用程序:设置时间戳的时区

在下面ENVIRONMENT[ts(1)]man的章节页面内容如下:ts

如果未将时区指定为日期的一部分,则标准 TZ 环境变量控制日期所处的时区。

我理解它使用 TZ 环境变量中指定的任何时区。但是,我不明白如何将时区指定为日期的一部分,我的理解是可以以某种方式使用format中的字段ts [-r] [-i | -s] [format]来指定时区。

问题是,如何ts在不改变环境变量的情况下使用实用程序为时间戳指定所需的时区?

背景信息:

我的服务器与我位于不同的时区。因此,每当我习惯ts向输出添加时间戳时,我都希望它以我当前的时区显示。我不想更改TZ环境变量,因为它可能会干扰当前正在运行的脚本或将要运行的脚本。

答案1

关于format

format字符串不是选择时区的接口。在我的 Debian 中man 1 ts

可选format参数控制时间戳的格式,如所用strftime(3)

并且man 3 strftime不包含任何让我认为您可以在format字符串中指定时区的内容。它提到TZ环境变量。据我所知,该变量是界面选择时区。

format是一个字符串,其中某些标记被扩展,其余的保持文字。例如,%H扩展%H:%M:%S为小时,但:保持不变。在这个模型中,没有空间容纳“配置”字符串,该字符串可以选择时区和消失。理论上,它可以设计为与令牌集成,因此(例如)%H(CEST)将扩展到所选时区的小时(此处CEST)。无论如何,这都是一个糟糕的解决方案。我们希望编写format在任何时区都能工作的代码(包括字符串),我们希望能够在运行时指定时区。TZ环境变量就是方法,一个巧妙的设计。


使用TZ“本地”

在类似 POSIX 的 shell 中为一个命令专门指定环境变量的一般语法是:

var=value executable …

这会将其置于var正在运行的环境中executable,而不会改变 shell 的环境。

请注意,如果一个进程(如executable)产生了一个子进程,那么子进程将继承该变量,除非父进程被设计成阻止这种情况。ts但不会创建子进程。

使用示例ts

date '+%H:%M:%S %z' | TZ=UTC-8 ts '<%H:%M:%S %z>'

甚至:

TZ=UTC+3 date '+%H:%M:%S %z' | TZ=UTC-8 ts '<%H:%M:%S %z>'

(后者表明您可以TZ为管道中的每个进程分别指定。)

笔记:

  • 为什么会TZ=UTC-8产生这样的日期UTC+8

  • 在交互式 shell 中,类似这样的别名alias ts='TZ=UTC-8 ts'可能会很有用。(请记住,如果您现在尝试运行,TZ=UTC-5 ts则别名将把它更改为TZ=UTC-5 TZ=UTC-8 ts,并且别名中的值将获胜。)

  • 如果ts从脚本运行则:

    • 您可以TZ为整个脚本指定(TZ=… ./the_script);可能您不希望这样做,因为一般来说脚本的其他部分都会受到影响。
    • 或者你需要调整脚本并变成tsTZ=… ts您更改格式字符串的想法将需要类似的修改,所以我想这对您来说不是问题。
    • 或者您可以使用包装器。见下文。

包装器

如果你想影响ts脚本没有修改脚本,您可以创建一个将被调用的包装器,而不是真正的ts。这是一个示例包装器脚本:

#/bin/sh
if [ -n "$TS_TZ" ]; then
   TZ="$TS_TZ"
   export TZ
fi
exec /usr/bin/ts "$@"

笔记:

  • 上述代码用作/usr/bin/ts真实的ts;如果需要,调整此路径。
  • 如果您想在交互式 shell 中测试包装器,并且刚刚测试了上面提到的别名,请不要忘记unalias ts

将脚本命名为ts,使其可执行(chmod +x ts),并将其移动到您之前的目录/usr/binPATH(您可能需要创建这样的目录并PATH相应地扩展您的目录;我使用$HOME/bin)。

TS_TZ从现在开始,环境变量的非空值将TZ覆盖ts。这意味着您可以执行以下操作:

TS_TZ=UTC-8
export TS_TZ

并且对于您ts将自动使用TZ=UTC-8。即使在新启动的脚本中也会发生这种情况,只要ts脚本根据您的情况进行解析即可PATH

如果TS_TZ未设置或为空,则包装器将执行到实际,ts没有任何技巧,就像包装器不存在一样。换句话说,包装器是透明的,除非TS_TZ在环境中并且它不为空。


可是等等!

但请稍等。man 1 ts包含以下声明:

如果未指定时区作为日期的一部分,则标准TZ环境变量控制日期所处的时区。

这是否意味着时区可以或不可以作为日期的一部分指定?如果不在,可以在哪里指定format

嗯,看起来这适用于提供的日期输入当你使用-r

如果-r传递了开关,它会将输入中现有的时间戳转换为相对时间 [...]。如果传递了两者-r和 a format,现有时间戳将转换为指定格式。

你可以这样做:

echo 'Aug 20 23:59:59 whatever' | TZ=UTC-8 ts -r '%H:%M:%S %z'

并且语句意味着Aug 20 23:59:59将被解释为好像它也在中TZ=UTC-8

旁注:手册上说“支持许多常见的时间戳格式”(作为输入),但我未能找到包含时区信息且受支持的格式。

相关内容