updated on Sat Jan 21 20:03:50 UTC 2012
[aur-mirror.git] / ioniced / ioniced.pl
blob2ff01f0620ec4cf5ffb22ec0ba3df314ad21c20d
1 #!/usr/bin/perl -w
3 # version 1.1, 05.12.2005, Hauke Laging, http://www.hauke-laging.de/software/
4 # slightly edited by Jan Mette, spam-o-mat at nickname.berlin.de
5 # This software is licensed under the Gnu GPL, see http://www.fsf.org/
7 # This script has the task to prevent I/O intensive system processes from
8 # annoying the user by slowing the system down. These typical administrative
9 # processes are not required to complete within a short time so it makes sense
10 # to reduce the I/O priority of these tasks (which usually impacts the performance
11 # of user processes much more than the CPU proirity).
13 # This script does not affect processes which have been niced to a value below zero
14 # (higher priority) or already ioniced (to any value).
15 # This is the most simple way to prevent a process from being affected by this script.
16 # You can configure if a white list or black list approach is used: Either only the
17 # configured programs are affected or only those not.
19 # The script runs as a daemon and reads the current PID list from ps every few
20 # seconds. It cannot (or at least does not) prevent tasks from starting with
21 # high I/O priority (high := high enough to annoy) but this problem es solved
22 # after a few seconds.
24 # Thus this script should be started in the background. It writes to STDOUT what
25 # it does/doesn't do.
27 # This script requires kernel 2.6.13 or above and the availability of ionice.
29 # definitions
30 # signals:
31 # USR1: The current list of known processes and their I/O priotity change status
32 # is dumped into the file $dump_file. Values 1,2 and 3 represent set priorities
33 # whereas 0 represents an unchanged priority.
35 @args = ("/bin/bash","-c","type ionice");
36 system(@args);
37 if ($? != 0)
39 print "The program 'ionice' is not available; aborting.\n";
40 exit 1;
43 use integer;
46 # configuration
48 $min_user_id = 100;
49 $max_user_id = 200;
50 $syslog_tag="ioniced.pl";
51 $0=$syslog_tag;
52 # poll interval
53 $sleep = 3;
54 $leave_inid_pids_untouched=0;
55 $whitelist=1;
56 $dump_file="/tmp/ioniced.dump";
57 %known_pids = (); # Werte: 1,2,3 fuer die gesetzten, 0 fuer die unveraenderten
60 # processes that should be skipped
62 %skip_these = ("init"=>0,"ps"=>0,"sshd"=>0,"syslog-ng"=>0,"httpd2-prefork"=>0,"pdflush"=>0); # values: dummys
65 # processes that should be ioniced
67 %ionice_these = (find=>3,tar=>3,updatedb=>3,mandb=>3,cp=>3,mv=>3,rpm=>3,gzip=>3,kio_file=>3); # values: new I/O priority level
71 ############ DO NOT EDIT BELOW THIS LINE ############
73 sub dump_ioprios {
74 if (not open(FH,"> $dump_file"))
76 return;
78 foreach (keys %known_pids)
80 print FH $_," ",$known_pids{$_},"\n";
82 close(FH);
85 $SIG{USR1}="dump_ioprios";
87 # BEGIN: initialize the hash with the present pids
88 @pslines = qx/ps -eo pid,ruid,nice,comm/;
89 $i=0;
90 foreach (@pslines)
92 $i++;
93 next if $i == 1; # header line pf ps output
94 $_ =~ s/^\s+//;
95 $_ =~ s/\s+$//;
96 @elements = split(" +",$_);
97 $pid=$elements[0];
98 $ruid=$elements[1];
99 $nice=$elements[2];
100 $command=$elements[3];
101 $change_it=1;
102 $change_it=0 if ($leave_inid_pids_untouched);
103 $change_it=0 if ($ruid>=$min_user_id && $ruid<=$max_user_id);
104 $change_it=0 if ($nice<0);
105 $change_it=0 if (exists($skip_these{$command}));
106 if ($change_it) # execute this one conditionally only because it takes time
108 $ionice_status=qx/ionice -p $pid/;
109 $ionice_status =~ s/:.*$//;
110 $change_it=0 if ($ionice_status != "none");
112 if ($whitelist)
114 $change_it=0 unless (exists($ionice_these{$command}));
116 if ($change_it)
118 $io_class=3;
119 $explicit_io_class=$ionice_these{$command};
120 if ($whitelist && defined($explicit_io_class) && ($explicit_io_class eq 1 || $explicit_io_class eq 2 || $explicit_io_class eq 3))
122 $io_class=$explicit_io_class;
124 $known_pids{$pid}=$io_class;
125 system("ionice -c${io_class} -p${pid}");
126 print "PID ${pid} ($command) has been changed to I/O class ${io_class}.\n";
127 if ($whitelist)
129 system("logger -t \"${syslog_tag}\" \"PID ${pid} ($command) has been changed to I/O class ${io_class}.\"");
132 else
134 $known_pids{$pid}=0;
135 print "PID ${pid}'s ($command) I/O class has not been changed.\n"
138 print "Initialization finished.\n";
139 # END: initialize the hash with the present pids
141 while (1)
143 sleep $sleep;
144 print "\n\nChecking for new PIDs:\n";
145 @pslines = qx/ps -eo pid,ruid,nice,comm/;
146 $i=0;
147 %current_pids=(); # Werte: Dummys
148 foreach (@pslines)
150 $i++;
151 next if $i == 1; # header line pf ps output
152 $_ =~ s/^\s+//;
153 $_ =~ s/\s+$//;
154 @elements = split(" +",$_);
155 $pid=$elements[0];
156 $ruid=$elements[1];
157 $nice=$elements[2];
158 $command=$elements[3];
159 $current_pids{$pid}=0;
160 next if (exists($known_pids{$pid}));
161 next if ($command eq "ps");
162 $change_it=1;
163 $change_it=0 if ($ruid>=$min_user_id && $ruid<=$max_user_id);
164 $change_it=0 if ($nice<0);
165 $change_it=0 if (exists($skip_these{$command}));
166 if ($change_it) # execute this one conditionally only because it takes time
168 $ionice_status=qx/ionice -p $pid/;
169 $ionice_status =~ s/:.*$//;
170 chomp($ionice_status);
171 $change_it=0 if ($ionice_status ne "none");
173 if ($whitelist)
175 $change_it=0 unless (exists($ionice_these{$command}));
177 if ($change_it)
179 $io_class=3;
180 $explicit_io_class=$ionice_these{$command};
181 if ($whitelist && defined($explicit_io_class) && ($explicit_io_class eq 1 || $explicit_io_class eq 2 || $explicit_io_class eq 3))
183 $io_class=$explicit_io_class;
185 $known_pids{$pid}=$io_class;
186 system("ionice -c${io_class} -p${pid}");
187 print "PID ${pid} ($command) has been changed to I/O class ${io_class}.\n";
188 if ($whitelist)
190 system("logger -t \"${syslog_tag}\" \"PID ${pid} ($command) has been changed to I/O class ${io_class}.\"");
193 else
195 $known_pids{$pid}=0;
196 print "PID ${pid}'s ($command) I/O class has not been changed.\n"
199 print "\n\nPID check\n";
200 foreach (keys %known_pids)
202 unless (exists($current_pids{$_}))
204 delete($known_pids{$_});
205 print "PID ",$_," does not exist any more and has been deleted from the hash.\n";