Originally Posted by ineloquucius
... You mention a script, but is that an efficient and reliable (i.e. elegant) method? Assuming that is the suggestion, how would I run this--rc2.d? ...
I would run the script via crontab. I have read that some users think this is inefficient because the system has to load the program into memory every time, but we are talking about a small program that executes in milliseconds, so I am not worried about it slowing down the system. (If I should worry about this, someone please explain.)
I was thinking about your question because I recently wrote a bash script to analyze the output of ck-list-sessions in order to determine whether any X session is active, and suspend the system after 5 minutes of inactivity, or 90 minutes if lsusb shows that a printer (which is shared) is attached and powered up.
For your question, I had to use the w command. Here is a script which I shall call suspend_after_idle:
# script to suspend the system if there has been
# no activity on any terminal for the time in minutes
# specified in the first command-line argument $1
# Example for 5 minute idle time:
# /path_to/suspend_after_idle 5
idle_time=$(w -sh | tr -s ' ' | cut -d ' ' -f 4 | tee >(grep -q [0-9]s && echo 0) | (grep -v [a-z] | cut -d ':' -f 1) | sort -n | head -n 1)
if [ "$idle_time" -ge "$1" ]
(sleep 5; /usr/sbin/pm-suspend) &
It is run by the following line in the crontab of root or another user who is authorized to run the pm-suspend utility:
* * * * * /path_to/suspend_after_idle 5 > /dev/null 2>&1
It is invoked every minute. Inelegant, maybe, but it works.
The line that extracts the idle time works as follows:
w -sh | tr -s ' ' | cut -d ' ' -f 4 # cut the idle time column from the output of w
tee > # splits the output into two grep-based filters:
(grep -q [0-9]s && echo 0) # idle times less than 1 minute yield output of 0
(grep -v [a-z] | cut -d ':' -f 1) # ignore formats of HH:MMmin or DDdays
# and then cut minute field from times in MM:SS format
# outputs of the two filters merge when both are completed
sort -n | head -n 1 # extract the minimum idle time of all terminals
I included the sleep 5 command and the ampersand, not sure if it is necessary, to allow the script to finish, and hopefully other processes started by crontab, before the suspension is started.
Minor bugs: The script will not suspend the system if any of the following are true:
- There are no terminals at all
- The script is executed after all terminals have been idle 1 hour or more
- The script is executed with a non-integer argument, or no argument at all
The script will not detect activity if a terminal was opened and closed within a single 1 minute interval as clocked by cron.
There may be other bugs or "unintended features."