Deth

Here's a new script for the new year.

It sometimes happens when I need to, say generate a dot file from a SableCC grammar to have a nice little diagram showing me how the damn thing is supposed to work. When you do one of those, not only does it tent to facilitate using your laptop as a simple toaster, or perhaps a very expensive heating system, but also usually eats up a lot of time. Something like 7 hours, for instance, and you don't know at all when it's going to end... or if it's going to generate anything, or maybe die out of lack of memory.

So it's not something that you want to wait up for until 2 AM - just let it run on it's own, and go to sleep instead. Good plan, yeah?

On the other hand, maybe it's wise to take those electricity bill into account? How about turning it off right after the process finishes (or dies)?

Ah, and did you have the foresight to actually write the shabang which shuts the computer down when the process is done? I never do...

That's where this script comes in. You just tell it to watch the process, and do stuff if it happens to die. It's as simple as that.

So, in the particular case that I described, I'd use it like this:

sudo ./deth sablecc "shutdown -h now";


And it won't work. The script is not prepared to handle the sudo-ing out of the box. Why? Well... you know, because I suck. But it's not a problem, all you need to do is take a peek at line 40 and change `whoami` to just your username, for instance: joe (with no spaces, no inverted commas, no nothing... well, double quotes, if you have to). Problem solved.

There's another variable that you can handle as well, in line 37. The sleep time between checks is here, in seconds. If 5 minutes doesn't cut it for you, modify it right there; no worries, she'll be right.

Yeah, for some reason I didn't feel like doing the entire getopt thing, and make these things settable... that's laziness, that is.

Here's the code.

1  #!/bin/bash
2  #
3  # Deth
4  #
5  # A watchdog for the death of processes. After specifying 
6  # the list of processes to watch (either by name of PID)
7  # the script waits for them to turn off, in which case the 
8  # specified command is run (and sent into the background).
9  # When all watched processes die, the script exits.
10 
11 # The commands are translated into PIDs at the beginning 
12 # only, so if you want to watch gcalctool, and, while this
13 # script is already running, turn on another instance of
14 # gcalctool, the new instance will be completely ignored.
15 #
16 # The script checks for the death of the specified processes
17 # and then goes to sleep for a specified period of time. 
18 # Since this does not need to be a very precise script, it's 
19 # currently set to checking every 5 minutes - this can be
20 # changed by modyfing the value of SLEEP_TIME.
21 #
22 # The script only watches processes which belong to the
23 # current user. To modify this set the value of USERNAME.
24 
25 # Potential issues:
26 #   When selecting by command name, all fitting PIDs
27 #   are watched, without any further discrimination.
28 # Parameters:
29 #   List of running commands and/or PIDs.
30 #   The last argument is always the command to run when
31 #       each of them turns off.
32 # Author:
33 #   Konrad Siek
34 #
35 
36 # How long to wait between pings. In seconds.
37 SLEEP_TIME=300
38 
39 # Limit the watched processes to the current user.
40 USERNAME=`whoami`
41 
42 # Check if enough arguments to even try getting the PIDs.
43 if [ $# -lt 2 ] 
44 then
45     echo -e "Usage: \n\t$0 [pids] [commands] action\n"
46     exit -1
47 fi
48 
49 # Convert all arguments to a PID array
50 declare -a array
51 while [ "$2" != "" ]
52 do 
53     if [ `expr "$1" : "[0-9][0-9]*"` != 0 ]
54     then
55         # Add PIDs to the array as they are.
56         if [ $(\
57             ps U $USERNAME -u $USERNAME -o pid \
58                         | grep "^ *$1 *\$" | wc -l) != 0 ]
59         then
60             array=${array[@]} $1 )
61         else
62             echo "PID $1 is not valid, ignoring." >& 2
63         fi
64     else
65         # Extract PIDs from name and add them to the array.
66         array=${array[@]} $(\
67             ps U $USERNAME -u $USERNAME -o pid,comm \
68             | awk -v f=$1 '$2==f {printf($1" ")}' ) )
69     fi    
70     shift
71 done
72 
73 # The last parameter is the action done on death of processes.
74 ACTION=$1
75 
76 # No array can be generated - no PIDs were discerned.
77 if [ ${#array[@]} = 0 ] 
78 then
79     echo "No PIDs were supplied." >& 2
80     exit -2
81 fi
82 
83 # Work the magic. 
84 while [ 1 ]
85 do
86     # Check if anything changed, and act.
87     i=0len=${#array[@]}
88     while [ $len -gt 0 ]
89     do                
90         # Ignore empty elements.
91         if [ "${array[$i]}" = '' ] 
92         then
93             # Point to next element
94             i=$(($i + 1))    
95             continue
96         fi    
97 
98         # Fewer elements to visit left.
99         len=$((len - 1))
100
101        # Check if process dies.
102        if [ $(\
103                        ps U $USERNAME -u $USERNAME -o pid \
104                        | grep "^ *${array[$i]} *\$" | wc -l) = 0 ]
105        then
106            # Process is dead, execute action.
107            $ACTION &
108            unset array[$i]
109        fi
110
111        # Point to next element
112        i=$(($i + 1))
113    done    
114
115    # If nothing left to do, quit.
116    if [ ${#array[@]} = 0 ] 
117    then
118        exit 0;
119    fi
120
121    # Wait a bit before continuing.
122    sleep $SLEEP_TIME;
123done



The code is also available at GitHub as bash/deth.

P.S. I hate those gorram, depressing date changes.

lala moulati ana9a maghribia

seo

 

Blogroll

Site Info

Text

telechargementz Copyright © 2009 WoodMag is Designed by Ipietoon for Free Blogger Template