3

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.

  • 1
    There is no way to tell ps to use other start date/time format than the ones defined (bsdstart, lstart, start, start_time). But when the process is started, the folder /proc/$pid is created (well, with all current linux versions I deal with; don't know about other *nixes, see en.wikipedia.org/wiki/Procfs). So ls -ld /proc/$pid should give you the time in the same format as the file modification time. If you use --time-style option with ls, you are able to define the format as you want. – ridgy May 5 '17 at 9:49
  • stat /proc/$pid/cmdline – Archemar May 5 '17 at 9:51
  • @ridgy and Archemar, no, the mtime of /proc/pid/files is the time those files were instantiated. Not the start time of the process. See Get process age from command line or When was a process started – Stéphane Chazelas May 5 '17 at 10:04
  • The actual start time is field 22 of /proc/$PID/stat, see stackoverflow.com/a/38740102/6372809 and man7.org/linux/man-pages/man5/proc.5.html (look for starttime) – ilkkachu May 5 '17 at 10:07
  • 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. – Stéphane Chazelas May 5 '17 at 10:10
4

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.

  • Thanks. In my case, missing timezone was defaulted to UTC, so adding the TZ=UTC0 solved my problem. Generally speaking, time zone handling is a little different in both cases as ` date -r file` returns Fri May 5 14:26:26 CEST 2017 and TZ=UTC0 ps -o lstart= -p pid returns Fri May 5 07:15:35 2017 – rosencreuz May 5 '17 at 12:36
  • @rosencreuz, yes but Fri May 5 07:15:35 2017 was Fri May 5 07:15:35 2017 CEST that is, still a date in local time, not UTC, even if ps doesn't give you a CEST or +0200 to indicate that it is indeed a local time. With TZ=UTC0 ps -o lstart= -p "$pid", ps is still giving a time in local time, but this time, we're telling it that the local time is UTC. – Stéphane Chazelas May 5 '17 at 12:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.