I would like to avoid doing this by launching the process from a monitoring app.
12 Answers
On Linux with the ps from procps(-ng) (and most other systems since this is specified by POSIX):
ps -o etime= -p "$$"
Where $$ is the PID of the process you want to check. This will return the elapsed time in the format [[dd-]hh:]mm:ss.
Using -o etime tells ps that you just want the elapsed time field, and the = at the end of that suppresses the header (without, you get a line which says ELAPSED and then the time on the next line; with, you get just one line with the time).
Or, with newer versions of the procps-ng tool suite (3.3.0 or above) on Linux or on FreeBSD 9.0 or above (and possibly others), use:
ps -o etimes= -p "$$"
(with an added s) to get time formatted just as seconds, which is more useful in scripts.
On Linux, the ps program gets this from /proc/$$/stat, where one of the fields (see man proc) is process start time. This is, unfortunately, specified to be the time in jiffies (an arbitrary time counter used in the Linux kernel) since the system boot. So you have to determine the time at which the system booted (from /proc/stat), the number of jiffies per second on this system, and then do the math to get the elapsed time in a useful format.
It turns out to be ridiculously complicated to find the value of HZ (that is, jiffies per second). From comments in sysinfo.c in the procps package, one can A) include the kernel header file and recompile if a different kernel is used, B) use the posix sysconf() function, which, sadly, uses a hard-coded value compiled into the C library, or C) ask the kernel, but there's no official interface to doing that. So, the ps code includes a series of kludges by which it determines the correct value. Wow.
So it's convenient that ps does that all for you. :)
(Note: stat -c%X /proc/$$ does not work. See this answer from Stéphane Chazelas to a related question.)
- 39,535
- 18
- 99
- 133
-
2Hi! Is `etime=` a typo? I can only find `etime` in the man pages. – Kent Pawar Jun 27 '13 at 13:01
-
18@KentPawar It's not a typo. The empty `=` suppresses the header. Try it without, or try `ps -p $$ -o etime="Silly Header Here"` – mattdm Jun 27 '13 at 13:28
-
4ps -p $(pgrep find) -o etime= – mafrosis Sep 11 '13 at 23:07
-
1Nice. I prefer `etimes` myself as then it's machine readable – Asfand Qazi Jul 15 '15 at 09:35
-
@AsfandYarQazi That's a relatively new option, starting in procps-ng-3.3.0, after this answer was written. Useful, though! – mattdm Jul 15 '15 at 09:54
-
this doesnt work for pthreaded apps. In a redhat server – Laksith Dec 31 '15 at 09:25
-
Getting HZ is easy - `getconf CLK_TCK` – alexmurray Apr 01 '16 at 01:47
-
1@alexmurray That just calls `sysconf()` and therefore gives you the hard-coded value from the C library, as noted, doesn't it? – mattdm Apr 01 '16 at 01:55
-
@mattdm - ah indeed you are right - thanks for clearing up my confusion. – alexmurray Apr 01 '16 at 04:55
-
1Hmm I was using the `stat -c%X /proc/$$` option in a script to monitor process age, but I actually observe the access time, change time, and modification time changing for a process. – Alvin Oct 04 '18 at 02:37
-
@Alvin `%X` means last access time. I'm not sure what you mean...? – mattdm Oct 04 '18 at 03:51
-
1@mattdm it means the last access time of /prod/$$ actually changes. It may have to do with that I have swap enabled on a host with small memory. – Alvin Oct 04 '18 at 03:53
-
@Alvin What kernel version on what distribution? – mattdm Oct 04 '18 at 03:55
-
@mattdm I am using: 4.14.62-65.117.amzn1.x86_64 (output of `uname -r`) This corresponds to Amazon Linux 2018.03, which is using kernel 4.14. Can this be something to do with Amazon Linux? – Alvin Oct 04 '18 at 03:56
-
This is incredibly cryptic and apparently quite debated. Why isn't this basic information provided by default in the `ps` output? Instead we see "VSZ" and "RSS" that I have yet to find useful in 25 years of using Linux. – Dan Dascalescu May 22 '20 at 16:47
-
@Dan Probably because ps was written as a sysadmin's diagnostic tool, and in most classic Unix server situations, how long a process has been running isn't nearly as useful as memory consumption. And in ancient Unix systems `VSZ` and `RSS` were more practically useful than they are now. – mattdm May 22 '20 at 18:09
-
Ah, whoops. I missed that part. – Daniel Walker Nov 14 '22 at 14:55
Portable:
% ps -o stime,time $$
STIME TIME
Jan30 00:00:06
i.e. that shell was started on January 30 and totaled about 6 seconds of CPU time.
There may be more precise or more parseable but less portable ways to get this information. Check the documentation of your ps command or your proc filesystem.
Under Linux, this information lives in /proc/$pid/stat.
awk '{print "CPU time: " $14+$15; print "start time: " $22}' /proc/$$/stat
The CPU time is in jiffies; I don't know offhand how to find the jiffy value from the shell. The start time is relative to the boot time (found in /proc/uptime).
- 807,993
- 194
- 1,674
- 2,175
-
3Finding the value of HZ (that is, jiffies per second) turns out to be ridiculously complicated! From comments in the `sysinfo.c` in the procps package, one can a) include the kernel header file (and recompile if a different kernel is used, b) use the posix sysconf() function, which, sadly, uses a hard-coded value compiled into the c library, or c) ask the kernel, and there's no official interface to doing that. So, the code includes a series of kludges by which it determines the correct value. Wow. – mattdm Feb 22 '11 at 21:54
-
1The `ps` manpage states that `time` is "cumulative CPU time". I think what the OP was looking for is `etime`, or "the elapsed time since the process was started". http://pubs.opengroup.org/onlinepubs/000095399/utilities/ps.html – rinogo Apr 23 '14 at 20:35
-
1Not so "portable" after all: *"ps: stime: keyword not found"* on FreeBSD. It does at least support `etime`, though. – n.st May 23 '16 at 11:34
If you dont know the PID of the process, just the name:
ps -eo pid,comm,cmd,start,etime | grep -i <name of the process>
If you know the PID:
ps -o pid,comm,cmd,start,etime -p <PID>
- 411,918
- 54
- 1,065
- 1,164
- 922
- 1
- 12
- 17
ps takes a -o option to specify the output format, and one of the available columns is etime. According to the man page:
etime - elapsed time since the process was started, in the form [[dd-]hh:]mm:ss.
Thus you can run this to get the PID and elapsed time of every process:
$ ps -eo pid,etime
If you want the elapsed time of a particular PID (e.g. 12345), you can do something like:
$ ps -eo pid,etime | awk '/^12345/ {print $2}'
(Edit: Turns out there's a shorter syntax for the above command; see mattdm's answer)
- 91,316
- 38
- 238
- 232
Unsure why this has not yet been suggested: on Linux you can stat() the /proc/[nnn] directory for your PID.
This behavior is explicitly designed to return the process start time, which it can do at high resolution, and which the kernel can do accurately without the jiffies hacks since the kernel can (obviously) simply check the relevant information. The access, data-modification and status change fields all return the process start time.
Best of all, you can use stat(1) at the shell, or the appropriate binding to stat(2) from $favorite_programming_language, so you may not even need to launch an external process.
NOTE that this does not work with /usr/compat/linux/proc on FreeBSD; the access/modification/status-change times returned are the current time, and the birth time is the UNIX epoch. Quite stupid the support isn't there if you ask me.
- 1,007
- 1
- 10
- 28
-
Where in the output of stat do I see the info? I only see Access, Modify, and Change. – tshepang Jan 08 '17 at 22:52
-
@Tshepang Note that those values are all the same, and they _are_ the process start time. You still have to do the math, but this is definitely better than trying to figure out jiffies as noted in my answer. – mattdm Mar 02 '17 at 16:53
-
You call it like this: `stat /proc/4480` This will give you the Birth, Change, Modify and Access dates of the process. If you need the process id, just use "top" – user890332 Aug 21 '19 at 17:05
-
1No, that's plain wrong, the mtime of those files are the time the files in `/proc` were instantiated, which will be whenever something tried to list the directories there. Nothing to do with the process start time. See also [When was a process started](https://unix.stackexchange.com/q/62154) – Stéphane Chazelas Apr 25 '23 at 11:42
$ ps -eo lstart get start time
$ ps -eo etime get duration/elapsed time
$ ps -eo pid,lstart,etime | grep 61819
PID STARTED ELAPSED
61819 Mon Sep 17 03:01:35 2018 07:52:15
61819 is the process id.
- 129
- 3
-
1Use of lstart can be problematic, it skews - https://unix.stackexchange.com/questions/274610/output-of-ps-lstart-changed – slm Jun 20 '19 at 15:05
If you can run time and then execute a command you will get exactly what you are looking for. You cannot do this against an already-running command.
[0] % time sleep 20
sleep 20 0.00s user 0.00s system 0% cpu 20.014 total
- 666
- 5
- 3
-
Do you know how can I do it on a running process monitoring until it ends? – lrkwz Nov 21 '12 at 22:56
you can get the start time of the process by looking at the stat of the stat file produced by proc, format it using date and subtract it from the current time:
echo $(( $(date +%s) - $(date -d "$(stat /proc/13494/stat | grep Modify | sed 's/Modify: //')" +%s) ))
where 13494 is your process' pid
- 11
- 1
Time elapsed in seconds: expr $(date +"%s") - $(stat -c%X /proc/<PID HERE>)
- 140
- 11
-
This seems to me to be a very slight variation of one that [mattdm mentioned already](https://unix.stackexchange.com/a/7871/117549): `date +%s --date="now - $( stat -c%X /proc/$$ ` – Jeff Schaller Mar 28 '19 at 17:17
-
That one didn't work for me on my very minimal Alpine docker instance so I wrote this one – Shardj Mar 28 '19 at 17:31
-
No, timestamps in `/proc/pid` have nothing to do with the process start time. See comments to [the other answer above](/a/335688) and [When was a process started](https://unix.stackexchange.com/q/62154) – Stéphane Chazelas Apr 25 '23 at 11:46
A handy function based on "ps -o etime=" and "bc" to help with the maths and the zero left padded numbers.
Give it the pid and get the running minutes back.
function running_time (){
# correct up to 100 days! #08:28:40 #53:32 #15-01:23:00
p=$1 ; i=$(ps -o etime= $p) ; i=$(echo $i) ;
len=${#i}
[[ $len == 5 ]] && i="00-00:$i" ; [[ $len == 8 ]] && i="00-$i"
[[ $len == 10 ]] && i="0$i"
mins=$(echo ${i:0:2}*24*60+${i:3:2}*60+${i:6:2}|bc)
echo $mins
}
I wanted it in seconds and I came up with (pure bash):
runtime=$(ps -o etime= -p <pid>)
runtime=$(date -d "1970-01-01 $((10#${runtime: -8: 2})):$((10#${runtime: -5: 2})):$((10#${runtime: -2: 2}))Z + $((10#$(echo "$runtime" | grep -oP "[0-9]+(?=-)"))) days" +%s)
The problem with etime is, that some values are optional.
Because of that I used $((10#string)) to convert empty strings to 0 and by that the final date string will be something like this for a short running process:
date -d "1970-01-01 0:0:7Z + 0 days" +%s
and like this for a long runnning processs:
date -d "1970-01-01 12:45:11 + 253 days" +%s
Using date to convert to seconds was inspired by this answer.
- 377
- 2
- 16
On FreeBSD, you have to use the command keyword instead of comm:
root@freebsd:~ # ps x -o etime,command | grep -e sshd -e syslogd -e cron
53-00:42:12 /usr/sbin/syslogd -s
57-01:26:52 /usr/sbin/cron -s
10:02:09 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups (sshd)
20:29 sshd: charlie [priv] (sshd)
00:00 grep -e sshd -e syslogd -e cron
The first column now contains the information on how long the process is running. It is in the following format:
[days-][hours:]minutes:seconds
You may want to use etimes instead of etime to get that information in seconds.
- 4,623
- 5
- 36
- 70