在下面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
为管道中的每个进程分别指定。)
笔记:
在交互式 shell 中,类似这样的别名
alias ts='TZ=UTC-8 ts'
可能会很有用。(请记住,如果您现在尝试运行,TZ=UTC-5 ts
则别名将把它更改为TZ=UTC-5 TZ=UTC-8 ts
,并且别名中的值将获胜。)如果
ts
从脚本运行则:- 您可以
TZ
为整个脚本指定(TZ=… ./the_script
);可能您不希望这样做,因为一般来说脚本的其他部分都会受到影响。 - 或者你需要调整脚本并变成
ts
。TZ=… 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/bin
中PATH
(您可能需要创建这样的目录并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
和 aformat
,现有时间戳将转换为指定格式。
你可以这样做:
echo 'Aug 20 23:59:59 whatever' | TZ=UTC-8 ts -r '%H:%M:%S %z'
并且语句意味着Aug 20 23:59:59
将被解释为好像它也在中TZ=UTC-8
。
旁注:手册上说“支持许多常见的时间戳格式”(作为输入),但我未能找到包含时区信息且受支持的格式。