Find linux process start time

using «ps» to find processes in a time range

ps -eo etime,pid will list all PIDs together with the elapsed time since the process creation in the format [[DD-]hh:]mm:ss . This may come in handy as you can then search for time amounts less than 5:00:00 instead of performing trickier date comparisons.

+1 for the simple way. But as I wanted a solution that work for any amount of days and is sortable. well, see below (far, far below ^^) for my take on it (using only things available on ancient, really ancient systems. and that works on aix & solaris, for all I know)

do a ps -aef. this will show you the time at which the process started. Then using the date command find the current time. Calculate the difference between the two to find the age of the process.

will give you the start time of a process in seconds since the epoch. Compare with current time ( date +%s ) to find the age of a process in seconds.

Just for the laughs, here is what I had to do on some ancient systems (both aix and solaris), and it seems just about «ok» up to now. (but may fail when something changes in the future. Also, I think it already fails on machines where processes last for more than 999 days. I’ll fix this when I find one)

  • some options of ps don’t exist. (or differ between solaris & aix, or different versions of those).
  • Some defunct process have either no time, or have also no username, nor pty, nor time.
  • ps have a little shift for etime having days>99

The little thing below takes care of those cases (and more) . but is really ugly ^^

Edit: New version (a bit saner, and versatile, but still show you need to process ps output a lot to get something usable. thanks to it having a weird way of changing the number of information it displays. )

max_size_var_awk="399" #old awk (and nawk) limit of a var size ?! ps_output_prettifier="%10s %8s %8s %3s %-14s %11s %10s %s\n" #11s for /dev/pts, as it could also be "zoneconsole" in a solaris zone. truncated_mark="(. )" size_to_truncate=$(( $ - $ )) tmpfile= #get the ps output ssh localhost "ps -elo user,pid,ppid,nice,etime,tty,time,args" \ | awk '(NF==5) < $8=$5;$7=$4;$6="-";$5="000-00:00:0-";$4=$3;$3=$2;$2=$1;$1="-"; >< print $0>' \ | sed -e 's/^ *//' >"$" #we read the ps output, putting the first few items in their respective var, and the rest (cmd + args) in "_rest" while read _u _p _pp _n _e _tt _ti _rest ; do #special case: we just read the first line: [ "$_ti" = "TIME" ] && < printf "$" "$_u" "$_p" "$_pp" "$_n" "99999__$_e" "$_tt" "$_ti" "$_rest" continue > #for all the other lines:totrunc) < rest=rest trunc ; >rem="modify -hh:mm:ss into .hhmmss to allow sort -n to operate on all (and not just on nb-of-days)" sub(/-/,".",e) ; sub(/:/,"",e) ; sub(/:/,"",e) printf (ps_output_prettifier,u,p,pp,n,e,tt,ti,rest);>' done <"$" \ | sed -e 's/^/ /' | sort -k5,5nr \ | sed -e 's/ \(47673\)\.\(17\)\(54\)/ \1-\2:\3:/' 

The convoluted sed (like the last one) try to keep the alignement (and the output is more aligned than what ps does). (I would use awk if I could, but as changing anything on $1, $2, . or $0 recomputes the whole line, I can't easily keep the alignement. maybe I should just do simple things and process it all via a simpler printf to realign. I will do that sometime later! (but I fear that long args lines may mess things up. And I don't know how to tell printf "just format the first few args, and put everything else as-is in the last %s")

Читайте также:  Как в linux изменить диск

Adding back-in the regular ps 'time' would be quite some work, as it have 1 or 2 columns whether the process is dated of more or less than 24h, and the spacing would become all wrong again, and the last sed would fail, etc.

LC_ALL=C ps -eo user,pid,ppid,nice,etime,tty,time,args \ | sed -e 's/^\( *[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]*\) \(9-\)/\1 00\2/' \ -e 's/^\( *[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]*\) \(32-\)/\1 0\2/' \ -e 's/^\( *[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]*\) \(16:\)/\1 000-\2/' \ -e 's/^\( *[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]*\) \(46:\)/\1 000-00:\2/' \ -e 's/^\( *[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]*\) -/\1 0?_-__:__:__/' \ | sed -e 's/^/ /' | sed -e 's/\(7\)-/\1./' | sed -e 's/\(81\):\(82\):/\1\2/' \ | sed -e 's/NI ELAPSED/NI 999._ELAPSED/' \ | sort -k5,5nr \ | sed -e 's/\( 482\)\.\(39\)\(83\)\(13\) /\1-\2:\3:\4 /' \ | sed -e 's/^ *\([^ ][^ ]*\)\( *\)\([^ ][^ ]*\)\( *\)\([^ ][^ ]*\)\( *\)\([^ ][^ ]*\)\( *\)\([^ ][^ ]*\)$/ ________ \1 \3 \5 0?_-__:__:__ - \7 \9/' 

Enjoy ^^ [and it is still a work-in-progress. works so far, but I couldn't try it on other systems (linux? other versions of aix & solaris, etc)]

Источник

start time of a process on linux

How to find a process start time on ubuntu linux machine using c language. In linux there is /proc/[pid]/stat file which give information starttime %lu /*The time in jiffies the process started after system boot*/
and file /proc/stat that gives

btime %lu /*measurement of system boot time since Epoch in seconds*/ 

For adding both these values how can I convert former value into seconds because it is in jiffies unit.

1 Answer 1

Jiffies per second is configurable when one compiles the Linux kernel.

The following program uses the number of jiffies per second on the kernel you're running. It takes an optional command line parameter, which is the process number. The default is the process number of the running program itself. Each second, it outputs the start time of the specified process, both as local time and UTC. The only reason for the repeat loop is to demonstrate that the value doesn't change.

#include #include #include #include #include #include #include #include int find_nth_space(char *search_buffer, int space_ordinality ) < int jndex; int space_count; space_count=0; for(jndex=0; search_buffer[jndex]; jndex++ ) < if(search_buffer[jndex]==' ') < space_count++; if(space_count>=space_ordinality) < return jndex; >> > fprintf(stderr,"looking for too many spaces\n"); exit(1); > /* find_nth_space() */ int main(int argc, char **argv ) < int field_begin; int stat_fd; char proc_buf[80]; char stat_buf[2048]; long jiffies_per_second; long long boot_time_since_epoch; long long process_start_time_since_boot; time_t process_start_time_since_epoch; ssize_t read_result; struct tm gm_buf; struct tm local_buf; jiffies_per_second=sysconf(_SC_CLK_TCK); if(argc<2) < strcpy(proc_buf,"/proc/self/stat"); >else < sprintf(proc_buf,"/proc/%ld/stat",strtol(argv[1],NULL,0)); >for(;;) < stat_fd=open(proc_buf,O_RDONLY); if(stat_fd<0) < fprintf(stderr,"open() fail\n"); exit(1); >read_result=read(stat_fd,stat_buf,sizeof(stat_buf)); if(read_result <0) < fprintf(stderr,"read() fail\n"); exit(1); >if(read_result>=sizeof(stat_buf)) < fprintf(stderr,"stat_buf is too small\n"); exit(1); >field_begin=find_nth_space(stat_buf,21)+1; stat_buf[find_nth_space(stat_buf,22)]=0; sscanf(stat_buf+field_begin,"%llu",&process_start_time_since_boot); close(stat_fd); stat_fd=open("/proc/stat",O_RDONLY); if(stat_fd <0) < fprintf(stderr,"open() fail\n"); exit(1); >read_result=read(stat_fd,stat_buf,sizeof(stat_buf)); if(read_result <0) < fprintf(stderr,"read() fail\n"); exit(1); >if(read_result>=sizeof(stat_buf)) < fprintf(stderr,"stat_buf is too small\n"); exit(1); >close(stat_fd); field_begin=strstr(stat_buf,"btime ")-stat_buf+6; sscanf(stat_buf+field_begin,"%llu",&boot_time_since_epoch); process_start_time_since_epoch = boot_time_since_epoch+process_start_time_since_boot/jiffies_per_second; localtime_r(&process_start_time_since_epoch,&local_buf); gmtime_r (&process_start_time_since_epoch,&gm_buf ); printf("local time: %02d:%02d:%02d\n", local_buf.tm_hour, local_buf.tm_min, local_buf.tm_sec ); printf("UTC: %02d:%02d:%02d\n", gm_buf.tm_hour, gm_buf.tm_min, gm_buf.tm_sec ); sleep(1); > return 0; > /* main() */ 

Источник

Читайте также:  Какая версия кали линукс лучшая

How to find uptime of a linux process

As "uptime" has several meanings, here is a useful command.

ps -eo pid,comm,lstart,etime,time,args 

This command lists all processes with several different time-related columns. It has the following columns:

PID COMMAND STARTED ELAPSED TIME COMMAND 

PID = Process ID
first COMMAND = only the command name without options and without arguments
STARTED = the absolute time the process was started
ELAPSED = elapsed time since the process was started (wall clock time), format [[dd-]hh:]mm:ss TIME = cumulative CPU time, "[dd-]hh:mm:ss" format
second COMMAND = again the command, this time with all its provided options and arguments

If you have a limited version of ps such as is found in busybox , you can get the process start time by looking at the timestamp of /proc/ . For example, if the pid you want to look at is 55.

# ls -al /proc | grep 55 dr-xr-xr-x 7 root root 0 May 21 05:53 55 

. and then compare it with the current date.

# date Thu May 22 03:00:47 EDT 2014 

can generate the etimes= with proc entries like etime=$(date -d "$(stat -c %y /proc/$ | cut -d ' ' -f 1,2)" +%s); echo "$(date +%s) - $" | bc -l

1234 being the process id.

example with two processes started at the same hour minute seconds but not the same milliseconds:

$ stat /proc/9355 . Access: 2017-11-13 17:46:39.778791165 +0100 Modify: 2017-11-13 17:46:39.778791165 +0100 Change: 2017-11-13 17:46:39.778791165 +0100 $ stat /proc/9209 . Access: 2017-11-13 17:46:39.621790420 +0100 Modify: 2017-11-13 17:46:39.621790420 +0100 Change: 2017-11-13 17:46:39.621790420 +0100 

yes, too old and yet too hard stuff. I tried with the above proposed "stat" method but what if I had "touch"-ed the PID proc dir yesterday? This means my year-old process is shown with yesterday's time stamp. Nah, not what I need 🙁

In the newer ones, it's simple:

ps -o etimes -p ELAPSED 339521 

as simple as that. Time is present in seconds. Do whatever you need it for. With some older boxes, situation is harder, since there's no etimes. One could rely on:

ps -o etime -p ELAPSED 76-03:26:15 

which look a "a bit" weird since it's in dd-hh:mm:ss format. Not suitable for further calculation. I would have preferred it in seconds, hence I used this one:

ps -o etime -p --no-headers | awk -F '(:)|(-)' 'BEGIN;=1;i--) s=s+a[i]*$i>END' 339544 

do not parse the output of etime because busybox 1.29.3 changed the format. use the stat + /proc method instead

Such a simple thing is not properly answered after 5 years?

I don't think you can accurately get milliseconds. eg. if you see man procfs and see /proc/$$/stat which has field 22 as startime, which is in "clock ticks", you would have something more precise, but clock ticks aren't going at a perfectly constant rate (relative to 'wall clock time') and will be off. sleeping and certain things (ntpd I guess) offset it. For example on a machine running ntpd, with 8 days uptime and has never slept, dmesg -T has the same problem (I think. ), and you can see it here:

# date; echo h > /proc/sysrq-trigger; dmesg -T | tail -n1 ; date Fri Mar 3 10:26:17 CET 2017 [Fri Mar 3 10:26:16 2017] sysrq: SysRq : HELP : loglevel(0-9) reboot(b) crash(c) terminate-all-tasks(e) memory-full-oom-kill(f) kill-all-tasks(i) thaw-filesystems(j) sak(k) show-backtrace-all-active-cpus(l) show-memory-usage(m) nice-all-RT-tasks(n) poweroff(o) show-registers(p) show-all-timers(q) unraw(r) sync(s) show-task-states(t) unmount(u) force-fb(V) show-blocked-tasks(w) Fri Mar 3 10:26:17 CET 2017 
# example pid here is just your shell pid=$$ # current unix time (seconds since epoch [1970-01-01 00:00:00 UTC]) now=$(date +%s) # process start unix time (also seconds since epoch) # I'm fairly sure this is the right way to get the start time in a machine readable way (unlike ps). but could be wrong start=$(stat -c %Y /proc/"$pid") # simple subtraction (both are in UTC, so it works) age=$((now-start)) printf "that process has run for %s seconds\n" "$age" 

Источник

Читайте также:  Linux zip all files and directory

How to check how long a process has been running?

On Linux with the ps from procps(-ng) (and most other systems since this is specified by POSIX):

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:

(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. 🙂

Источник

Оцените статью
Adblock
detector