Process start time with time zone

processpstimestampstimezone

I'm trying to identify if a file is created after starting the process or not. I'm getting the process start time using command ps -f -p PID -o lstart=. This gives me a result such as Fri May 5 09:15:35 2017 that doesn't have any time zone information.

On the other hand, file system gives me dates with timezone. When I compare dates I get the wrong result. Example:

  • process start: 2017-05-05 10:26:57 +0000 UTC
  • file modified: 2017-05-05 10:26:57.679508679 +0200 CEST

Is it possible to get the process start time with a different format, for instance as unix date? (Having milliseconds would help, too)

Context: I'm running the ps command from a go application and parsing the outcome.

Best Answer

The file system doesn't give you a time with timezone, it's whatever command that you use to display that time in a human friendly format that may give you a timezone if it chooses to display the time in local time (as specified by /etc/localtime, $TZ or other).

Generally, timestamps on Unix are expressed in a way that is irrelevant of timezones. The unix epoch time is the number of seconds (seconds expressed as the 86400th part of a day, so varying in length but more useful for calendar calculation) since a precise event in history (1970-01-01 00:00:00 UTC, an unambiguous time). Timezones only come into the picture when displaying a date in a calendar format to a human.

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

both give you the local time. date might output the timezone offset or not depending on the locale. If you want the UTC time, run them under TZ=UTC0:

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

GNU date is able to parse the date reported by ps, so you can convert it to any format, like the unix epoch time:

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

(above using UTC time. It would also work with whatever the local time is in your environment except for one hour in the year where a time output without TZ indication is ambiguous (in zones that implement DST)).

In any case, the start time of a process doesn't have to be (and never is exactly) the time that process executed the command it is currently running. For instance:

$ 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

That 9397 process is running 4 commands in its life time: strace (forked there), sh, env, ps. The time reported by ps corresponds to the time when it was forked by strace, not when it executed ps.

If you want to get subsecond precision (up to 1/$(getconf CLK_TCK)), with zsh, you could do:

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

That is we get the start time of the $pid and of a newly created subshell (that's the 20th fields after the last occurrence of a ) character in /proc/pid/stat expressed in CLK_TCK in modern versions of Linux), divide the difference by CLK_TCK and add to the current time.

Related Question