带时区的进程开始时间

带时区的进程开始时间

我试图确定启动进程后是否创建了文件。我正在使用 command 获取进程开始时间ps -f -p PID -o lstart=。这给了我一个Fri May 5 09:15:35 2017没有任何时区信息的结果。

另一方面,文件系统为我提供带有时区的日期。当我比较日期时,我得到错误的结果。例子:

  • 进程开始:2017-05-05 10:26:57 +0000 UTC
  • 文件修改:2017-05-05 10:26:57.679508679 +0200 CEST

是否可以使用不同的格式获取进程开始时间,例如 unix 日期? (有毫秒也会有帮助)

上下文:我正在ps从 go 应用程序运行命令并解析结果。

答案1

文件系统不会为您提供带有时区的时间,它是您用来以人类友好的格式显示该时间的任何命令,如果它选择以本地时间显示时间(由 ,/etc/localtime$TZ指定),则可能会为您提供时区其他)。

通常,Unix 上的时间戳以与时区无关的方式表示。 unix 纪元时间是自历史上的精确事件(1970-01-01 00:00:00 UTC,明确的时间)。仅当以日历格式向人们显示日期时,时区才会出现。

ps -o lstart= -p "$pid"
date -r /some/file

两者都为您提供当地时间。date可能会输出时区偏移量或不输出,具体取决于区域设置。如果您想要 UTC 时间,请在以下位置运行它们TZ=UTC0

TZ=UTC0 ps -o lstart= -p "$pid"
TZ-UTC0 date -r /some/file # or use date -u

GNUdate能够解析 报告的日期ps,因此您可以将其转换为任何格式,例如 unix 纪元时间:

(export TZ=UTC0
date -d "$(ps -o lstart -p "$pid") +%s
date -r /some/file +%s)

(以上使用 UTC 时间。它也适用于您环境中的任何本地时间,除了一年中的一个小时,其中没有 TZ 指示的时间输出不明确(在实施 DST 的区域中)。

在任何情况下,进程的启动时间不必是(并且永远不会完全是)进程执行当前正在运行的命令的时间。例如:

$ TZ=UTC0 strace -qtt -e execve sh -c 'sleep 3; exec env ps -o lstart= -p "$$"'
10:27:24.877397 execve("/bin/sh", ["sh", "-c", "sleep 3; exec env ps -o lstart= "...], [/* 28 vars */]) = 0
10:27:27.882553 execve("/usr/bin/env", ["env", "ps", "-o", "lstart=", "-p", "9397"], [/* 28 vars */]) = 0
10:27:27.885272 execve("/bin/ps", ["ps", "-o", "lstart=", "-p", "9397"], [/* 28 vars */]) = 0
Fri May  5 10:27:24 2017

9397 进程在其生命周期中运行 4 个命令:(在那里strace分叉)sh、、、、envps报告的时间ps对应于它被 fork 的时间strace,而不是它执行的时间ps

如果你想获得亚秒级精度(高达1/$(getconf CLK_TCK)),使用zsh,你可以这样做:

zmodload zsh/datetime
tick=$(getconf CLK_TCK)
(echo $((EPOCHREALTIME + (${${=$(</proc/self/stat)##*)}[20]}. -
          ${${=$(</proc/$pid/stat)##*)}[20]})/tick)))

也就是说,我们获取 $pid 和新创建的子 shell 的开始时间(这是现代版本 Linux 中以 CLK_TCK 表示的字符最后一次出现后的第 20 个字段)/proc/pid/stat,将差值除以CLK_TCK并添加到当前时间。

相关内容