How long has a process been idle?

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Post Reply
Message
Author
Wognath
Posts: 423
Joined: Sun 19 Apr 2009, 17:23

How long has a process been idle?

#1 Post by Wognath »

I have a script to start fpm2 password manager and then close it 10 minutes later (unless a dialog is answered), so I don't walk away and leave my password file open (again).

Of course it would be better to close 10 minutes after fpm was last used. Is there a way to determine how long a process has been idle, or test if it is currently idle? Or if its window has lost focus?

Thanks

learnhow2code

Re: How long has a process been idle?

#2 Post by learnhow2code »

Wognath wrote:it would be better to close 10 minutes after fpm was last used. Is there a way to determine how long a process has been idle, or test if it is currently idle?
Thanks
if attached to a tty (even if its a gui program,) you can use this:

http://www.unix.com/shell-programming-a ... ocess.html

the script is written for ksh, but up to and including line 24 (the one that gives you the info youre looking for) it works in bash.

Wognath
Posts: 423
Joined: Sun 19 Apr 2009, 17:23

#3 Post by Wognath »

learnhow2code, thank you for that link. I had seen it, but I gave up on it since

Code: Select all

w | sed -n -e "/pts\/$TTNo/p" |  awk '{ print $5 }'
returns "0.01s" every time. I guess this is because I was starting fpm from a script--so not "attached to a tty". (?)

If I start fpm2 from a terminal, then

Code: Select all

w | grep fpm2 
is useful. The times in columns 5 and 6 increase when fpm is in use but freeze when it's idle. Oddly, column 4, "IDLE", simply marks clock time.

Anyway, now I have a clue how to proceed. Thanks again.

Having an idle process timeout seems like a useful thing--why is it so hard? :(

learnhow2code

#4 Post by learnhow2code »

Wognath wrote:Having an idle process timeout seems like a useful thing--why is it so hard? :(
heh, i was having another look at this thread and thinking about your question, and i thought "you know, theres probably a timeout command." try timeout --help, it already does what youre trying to do, right?

i mean you were asking if you knew how to tell how long a process is running idle. sure, we found an answer to that.

but you can probably just run your program from the timeout command :)

Wognath
Posts: 423
Joined: Sun 19 Apr 2009, 17:23

#5 Post by Wognath »

Timeout shuts down without warning, whether or not the application is being used. So I'll stick with my script, which has the option to abort the shutdown and restart the clock, in case I'm still using fpm.
Shut down after 10 minutes idle is almost working :roll: ; that will be even better. Shouldn't take a dozen lines of script, though :( The timer occasionally resets to 0 even though I haven't touched fpm. Any suggestions?

Code: Select all

rxvt -iconic -e /usr/bin/fpm2 & 

while [[ $count -lt 600 ]] ; do
	Z=$(w | grep /usr/bin/fpm2 | awk '{print $5}')
	if [[ $Y = $Z ]] ; then
		let count=count+30
	else 
		count=0
		Y=$Z
	fi
if [[ $count -eq 600 ]] ; then [warning with option to reset count]
sleep 30
done

killall fpm2
Last edited by Wognath on Fri 24 Jun 2016, 18:52, edited 4 times in total.

learnhow2code

#6 Post by learnhow2code »

Wognath wrote:Timeout shuts down without warning, whether or not the application is being used. So I'll stick with my script, which has the option to abort the shutdown and restart the clock, in case I'm still using fpm.
even better!
The timer occasionally resets to 0 even though I haven't touched fpm. Any suggestions?
i wouldnt know a better way to do it, and i wouldnt change the code. it looks like i wrote it, and you added newlines to my usual oneliner, and indented it. :)

so no, no suggestions here-- looks good (from anything i can tell you!)

Wognath
Posts: 423
Joined: Sun 19 Apr 2009, 17:23

#7 Post by Wognath »

Sorry, I didn't see your post before I edited mine. So I'll move my edit here:
As near as I can tell, w | grep fpm2 very occasionally picks up the "grep fpm2" process as well, causing the count to reset.

learnhow2code

#8 Post by learnhow2code »

Wognath wrote:Sorry, I didn't see your post before I edited mine. So I'll move my edit here:
As near as I can tell, w | grep fpm2 very occasionally picks up the "grep fpm2" process as well, causing the count to reset.
ah, thats fixable as you may already know. what you do is put part of the qrep line in brackets like this:

grep "[f]pm2"

or some variation like that. i dont usually do this, because it only matters in scripts and then only in some cases like this one. also, nice catch!

Wognath
Posts: 423
Joined: Sun 19 Apr 2009, 17:23

#9 Post by Wognath »

learnhow2code, thanks again. I did not know about grep [f]pm (I still don't, but I'm working on it!)
My tentative solution was more awkward:
Z=$(w | grep /usr/bin/fpm2 | grep -v grep | awk '{print $5}')

learnhow2code

#10 Post by learnhow2code »

Wognath wrote:My tentative solution was more awkward:
the solution is the easy part. you found the cause (grep was resetting it) and the cause was the tricky part i wouldnt have guessed. i have also piped grep into grep -v grep like you did-- its one extra process, which might matter in some cases (not this one!) but i think its a very straightforward, if nominally inefficient solution.

Wognath
Posts: 423
Joined: Sun 19 Apr 2009, 17:23

#11 Post by Wognath »

Thanks again, learnhow2code. I've learned a lot from this conversation, so you're living up to your moniker.

I think I have topped my original scheme using top command instead of w:

Code: Select all

fpm2 & fpm=$!
Y=0
while [[ $count -lt 600 ]] ; do
	sleep 30
	Z=$(top -b -n 1 | grep $fpm | awk '{print $11}' | cut -d: -f2)   #cumulative cpu time
	[[ -z $Z ]] && exit   # fpm is already shut down, so quit
	if  [[  $(echo "scale=2;$Z-$Y>0.05" | bc) -eq 1 ]] 
		then count=0 
		else let count=count+30
	fi
	Y=$Z
	if [[ $count -ge 600 ]] ; then [dialog--close fpm or reset count?]
done
kill $fpm
This does not require fpm to run from a terminal. I also found it necessary to include a tolerance (tentatively 0.05) because simply passing the cursor over inactive fpm window causes cpu time to increase slightly. Works as intended, so far :D
Last edited by Wognath on Sun 26 Jun 2016, 20:55, edited 1 time in total.

learnhow2code

#12 Post by learnhow2code »

Wognath wrote:Thanks again, learnhow2code. I've learned a lot from this conversation, so you're living up to your moniker.
that means a lot. ive been a hobbyist for decades, it was a teacher/tutor i dated that convinced me i would be happier teaching/tutoring-- thats not why i came back to puppy land but yours is the second compliment ive read today (and thanks very much)
elsewhere, someone wrote:Thanks for this. The gear analogy is an excellent one, and the assigning of colors is a great example.
i enjoy this, and subscribe to the "everyone is a teacher/learner" philosophy. one of the things i always liked about this forum is the collaborative learning that goes on without people paying close attention to the fact that its happening all day. imo one of puppys greatest legacies (still going a decade later) and to a lesser degree, it also happens on other distro-related forums.
I think I have topped my original scheme using top command instead of w:
nicely done! thats a definite improvement.
I also found it necessary to include a tolerance (tentatively 0.05) because simply passing the cursor over inactive fpm window causes cpu time to increase slightly. Works as intended, so far :D
very nice. one of the reasons i didnt suggest top (its more work) is that ive found it doesnt give as accurate results on a single pass unless you put a delay in. even then, ive sometimes needed to add a second pass. but youve got it working, which makes the potential issue a non-issue. (top is imo the better option.) congrats!

dont forget to license your code either gpl2/3 or mit, etc so that everyone that cares about such things knows its legit to change/distribute/bundle in their own packages/distros. its a formality here, though if someone wants to follow the rules for a larger project, they need something formal from you like (at minimum) a comment that says which license you are using.

for larger projects, including text of the license is a good idea. (gpl projects should be bundled with a copy of the gpl.)

Wognath
Posts: 423
Joined: Sun 19 Apr 2009, 17:23

#13 Post by Wognath »

I'm adding this because it has been so hard to find info on this topic.

Having learned that most puppies do not have TIME+ (process cpu time) in the output of top, :oops: it was back to drawing board. The latest idea to monitor process cpu time retrieves stime and utime from /proc/[pid]/stat:

Code: Select all

	utime=$(echo $(cat /proc/$proc/stat) | awk '{print $14}') 
	stime=$(echo $(cat /proc/$proc/stat) | awk '{print $15}')
	let Z=utime+stime
These measure process cpu time in user and kernel modes respectively, in clock ticks.
A tolerance of about 30 clock ticks per 30s sleep seems to work well for my purposes, allowing window to be minimized or moved without exceeding the tolerance for idleness.
This has been tried in several puppies and seems to work as intended. :roll:

http://man7.org/linux/man-pages/man5/proc.5.html
https://stackoverflow.com/questions/142 ... s-in-linux

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#14 Post by MochiMoppel »

Based on your idea I've created me a little test script to measure the tolerances for different applications and situations. When tested with leafpad, moving the window may use more CPU time than typing text. The user and the system may have very different ideas of what constitutes idleness. Biggest problem is the handling of subprocesses. I measured the time used by my streaming radio player (see screenshot). The application was busy streaming a concert, but the CPU time was close to zero. Idle? Of course not, since the mplayer, for which it is a frontend, was very busy.

Your approach to measure idle time certainly is interesting, but it has to be carefully calibrated for each application it is used for and for some applications it may not work at all.

To run the test script, open a console, start the script and with the cross cursor click on the window of an application to be tested. Script will run for 60 sec and will calculate CPU time every second.

Code: Select all

#!/bin/bash
WPID=$(xprop _NET_WM_PID)
WPID=${WPID##* }
PROCESS="/proc/$WPID/stat"
echo -n "Time values for process "
awk '{print $1,$2}' $PROCESS
echo -e "\nSEC\tu+stime\tCHANGE\tACCUM"
for i in {1..60} ;do
    Z=$(awk '{print $14+=$15}' $PROCESS)
    Y=${Y:-Z}                   # On  first run Y is empty. Let it be =$Z
    CHANGE=$((Z-Y))             # Change during last second in accum CPU time 
    ACCUM=$((ACCUM+CHANGE))     # Accumulate changes
    Y=$Z                        # Save current time value
    echo -e "$i\t$Z\t$CHANGE\t$ACCUM"
    sleep 1
done
Attachments
idletime.png
(38.15 KiB) Downloaded 181 times

Wognath
Posts: 423
Joined: Sun 19 Apr 2009, 17:23

#15 Post by Wognath »

Thanks once again, MochiMoppel. I'm grateful for your assessment and I have edited my other post so as, I hope, not to mislead anyone about this. Thanks for sharing your script; I learned a lot of new syntax from it.

Following up on what you say, I found that "libreoffice --impress" for example calls soffice.bin, which does all the work but has a different pid. So my script completely fails in this case.

This has been educational for me, and I hope not to have caused problems for anyone.

User avatar
Pete
Posts: 660
Joined: Sun 02 Mar 2014, 18:36

#16 Post by Pete »

@MochiMoppel

Great script, many uses.

Wognath
Posts: 423
Joined: Sun 19 Apr 2009, 17:23

#17 Post by Wognath »

MochiMoppel, learnhow2code,
This finds cpu usage of child processes, using libreoffice as a test case. Do you think it works generally, e.g. on MochiMoppel's radio program? What have I missed this time? :wink: I'll appreciate your comments.

Code: Select all

#! /bin/bash
proc=$$

libreoffice --writer & 

#"goofy"  https://stackoverflow.com/questions/17743879/how-to-get-child-process-from-parent-process
function getcpid() {
    cpids=`pgrep -P $1|xargs`
    for cpid in $cpids;
    do
        a=$a" "$cpid
        getcpid $cpid
    done
}

while true ; do
sleep 30
a=""
getcpid $proc
Z=0
for i in $a ; do
	[[ -f /proc/$i/stat ]] && let Z=Z+$(awk '{print $14+$15}' /proc/$i/stat)
done
let D=Z-Y ; let Y=Z
echo "processes "$a" Z "$Z"  diff "$D
done
Output:
processes 20560 20583 20653 Z 248 diff 248
processes 20560 20583 20739 Z 303 diff 55
processes 20560 20583 20817 Z 479 diff 176
processes 20560 20583 20903 Z 480 diff 1
processes 20560 20583 20979 Z 482 diff 2

learnhow2code

#18 Post by learnhow2code »

awesome. if i leave a child process alone, the diff is 0. if i switch to it or do anything with it, the diff is non-zero.

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#19 Post by MochiMoppel »

Wognath wrote:Do you think it works generally, e.g. on MochiMoppel's radio program? What have I missed this time? :wink:
Background processes ("jobs")? :wink:
My radio script starts several processes in the background, e.g. the mplayer. The mplayer would get its own PID, but the PID of the dialog that started mplayer would not be mplayer's PPID, likewise pgrep -P would not return mplayer's PID because technically mplayer is not running in a child process. To make it short: All commands started with a trailing "&" will run parallel in the background and will not be captured by your script. :cry:

Post Reply