#!/usr/bin/perl #desc{ calm -- sleeps until the system is relatively calm. } #====================================================================== # The way I often use it: # some_huge_app & ; calm && another_huge_app & #====================================================================== # Time-stamp: "2008-10-11 17:55:58 ADT" # -*-coding:latin-1;-*- « sburke@cpan.org » µ use constant DEBUG => 0; use strict; use warnings; $| = 1; #====================================================================== my $Trial_Period = $ARGV[0] || 300; # max seconds. 300 = 5 minutes my $Min_Samples = 3; my $Time_Between_Samples = 1; # max percentage of usage percentages that count as "calm": my $Total_Proc_Calm_Max = 50; my $Total_IOWait_Calm_Max = 25; #End of configurables #====================================================================== my $Heading_Checker = qr{ ^ \s* ([\:0-9]+ # time \s+ \w+) # am/pm or whatever \s+ CPU \s+ %user \s+ %nice \s+ %sys \s+ %iowait \s+ %irq \s+ %soft \s+ %steal \s+ %idle \s+ intr/s }smx; #Linux 2.6.15-51-386 (..........) 05/06/2008 # #12:40:42 AM CPU %user %nice %sys %iowait %irq %soft %steal %idle intr/s #12:40:43 AM all 6.93 0.00 0.00 0.00 0.00 0.00 0.00 93.07 294.06 #12:40:44 AM all 6.93 0.00 1.98 0.00 0.00 0.00 0.00 91.09 311.88 #Average: all 6.93 0.00 0.99 0.00 0.00 0.00 0.00 92.08 302.97 my $Fields_Extractor = qr{ ^ \s* Average: \s+ (\w+) #CPU name \s+ ([\.0-9]+) #%user \s+ [\.0-9]+ #%nice \s+ ([\.0-9]+) #%sys \s+ ([\.0-9]+) #%iowait \s+ [\.0-9]+ #%irq \s+ [\.0-9]+ #%soft \s+ [\.0-9]+ #%steal \s+ [\.0-9]+ #%idle \s+ [\.0-9]+ #intr/s }smx; my $Max_Time = $Trial_Period + $^T; my $Command_V = "mpstat -V 2>&1"; my $Command = "mpstat $Time_Between_Samples $Min_Samples"; main(); exit; #====================================================================== sub main { check_prog_avail(); wait_for_calm(); } sub check_prog_avail { my $output = qx[$Command_V]; unless( defined $output and $output =~ m/\d/) { die "mpstat isn't available on your system.\n Aborting"; } DEBUG > 10 and print "$Command_V => {{$output}}\n"; return 1; } sub wait_for_calm { my( $now, $line, $total_proc, $iowait, $now_from_heading ); while(1) { $now = time(); if( $now >= $Max_Time ) { die join '', "It's ", scalar(localtime($now)), " and I've been waiting for calm since ", scalar(localtime($^T)), " (" , $now - $^T, " seconds). So I'm aborting.\n "; } chomp($line = qx[$Command]); die "I can't find the expected header line in here:\n$line\nAborting" unless $line =~ $Heading_Checker; $now_from_heading = $1; DEBUG > 5 and print "$Command =>\n $line\n"; if( $line =~ $Fields_Extractor ) { print "I expected the CPU name to be 'all', not: $1" unless $1 eq 'all'; $iowait = $4; $total_proc = ($2 + $3); if($total_proc > $Total_Proc_Calm_Max) { if(DEBUG > 2) { print " $now_from_heading: Busy because proc $total_proc% > $Total_Proc_Calm_Max%\n"; } next; } if($iowait > $Total_IOWait_Calm_Max) { if(DEBUG > 2) { print " $now_from_heading: Busy because iowait $iowait% > $Total_IOWait_Calm_Max%\n"; } next; } DEBUG and print " [Calm now (cpu:$total_proc, io:$iowait). Exiting okay after ", time() - $^T, " seconds.]\n"; last; } else { die "But \"$line\" is in an unexpected format\nAborting" } } return 1; } __END__ =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =head1 AUTHOR Sean M. Burke, Esburke@cpan.orgE