I had a need to know what was writing disk, how much it was writing, and how often it was writing. iotop does a pretty good job of giving you a top like view of disk I/O activity. I decided I wanted to graph this to hopefully make it easier for me to see how heavy writing to the disk might correlate to sluggish CLI response.
The output is in CSV so you can drop it in Excel (if you so wish) and create a simple PivotChart with it. You can do so by selecting all data from the csv (after it is imported/converted to rows/columns using data import or text to columns) then choose insert pivotchart.
Choose fields timestamp, tid, read, write and cmd.
Timestamp goes in AxisFields Categories.
Values, cmd, and tid go in Legend Fields
Sum of read and Sum of write goes in Values.
I never quite got to the smoking gun (just yet) but I was able to see what applications were busy little apps writing to the disk.
I do no warranty this code in any way. Use it as you wish. If you find it useful then please write back saying so. If you find it incorrect or improve/fix it please write back on that as well.
Here is the code
#/usr/bin/perl -w use strict; # Enabling strict with strict refs breaks the summary output (when ctrl+c is pressed) # because of the error Can't use string ("") as a HASH ref while "strict refs" in use. no strict 'refs'; #Initialize an empty hashref my $hash_ref = {}; #Catch CTRL+C and then call printsummary subroutine $SIG{'INT'} = \&printsummary; #Pipe the output from iotop to a file handle open fh, "iotop -bt|" or die $!; # Build the initial Total Value key/values $hash_ref->{'tsample'} = 0; $hash_ref->{'tread'} = 0; $hash_ref->{'twrite'} = 0; # Divider of columns my $div = ","; #Print the header print "#" x 50 . "\n"; print "Output from iotop -bt\n"; print "#" x 50 . "\n"; print "timestamp" . $div . "tid" . $div . "user" . $div . "read" . $div . "total read each tid" . $div . "write" . $div . "total write each tid" . $div . "cmd" . $div . "sample number" . $div . "Percent of Total Read" . $div . "Percent of Total Write" . "\n"; #While data from iotop process it. Since we get lots of 0.00 read and write values #don't waste time storing/printing values that are useless. Only store lines that #have a value to read/write. while(<fh>) { my ($ts,$tid,$prio,$user,$read,undef,$write,undef,undef,undef,undef,undef,$cmd) = split(/\s+/, "$_"); chomp($cmd); #Make sure we fill each tid with dummy values if the tid is a real valid number if ( !$hash_ref->{$tid} && ( $tid =~ m/^-?\d+$/ || $tid =~ m/^-?\d+[\/|\.]\d+$/ ) ) { $hash_ref->{$tid}->{'user'} = 'null'; $hash_ref->{$tid}->{'read'} = 0; $hash_ref->{$tid}->{'write'} = 0; $hash_ref->{$tid}->{'cmd'} = 'null'; $hash_ref->{$tid}->{'samples'} = 0; } #Continue if we have already created a key for the tid and the tid is a real valid number if ( $hash_ref->{$tid} && ( $tid =~ m/^-?\d+$/ || $tid =~ m/^-?\d+[\/|\.]\d+$/ ) ) { $hash_ref->{$tid}->{'user'} = $user; $hash_ref->{$tid}->{'read'} += $read if $read =~ m/^-?\d+$/ || $read =~ m/^-?\d+[\/|\.]\d+$/; $hash_ref->{$tid}->{'write'} += $write if $write =~ m/^-?\d+$/ || $write =~ m/^-?\d+[\/|\.]\d+$/; $hash_ref->{$tid}->{'cmd'} = $cmd; $hash_ref->{$tid}->{'samples'}++; # create totals key/value pair $hash_ref->{'tsample'}++; $hash_ref->{'tread'} += $read if $read =~ m/^-?\d+$/ || $read =~ m/^-?\d+[\/|\.]\d+$/; $hash_ref->{'twrite'} += $write if $write =~ m/^-?\d+$/ || $write =~ m/^-?\d+[\/|\.]\d+$/; # Print values of the read/write as they happen if ( ( $read =~ m/^-?\d+$/ || $read =~ m/^-?\d+[\/|\.]\d+$/ || $write =~ m/^-?\d+$/ || $write =~ m/^-?\d+[\/|\.]\d+$/ ) && ( $read > 0 || $write > 0 ) ) { my $ptr = 0; my $ptw = 0; $ptr = ( $hash_ref->{$tid}->{'read'} / $hash_ref->{'tread'} ) * 100 if ( $read > 0 ) && ( $hash_ref->{'tread'} > 0 ); $ptw = ( $hash_ref->{$tid}->{'write'} / $hash_ref->{'twrite'} ) * 100 if ( $write > 0 ) && ( $hash_ref->{'twrite'} > 0 ); print $ts . "$div"; print $tid . "$div"; print $hash_ref->{$tid}->{'user'} . "$div"; print $read . "$div"; print "$hash_ref->{$tid}->{'read'}" . "$div"; print $write . "$div"; print "$hash_ref->{$tid}->{'write'}" . "$div"; print $hash_ref->{$tid}->{'cmd'} . "$div"; print $hash_ref->{$tid}->{'samples'} . "$div"; print sprintf("%.2f", $ptr) . "$div"; print sprintf("%.2f", $ptw) . "\n"; } } } # Close the filehandle when we are done. close(fh); #Sub routine to print out a summary of disk I/O. sub printsummary { print "#" x 50 . "\n"; print "Caught Ctrl+C. Printing Disk I/O summary.\n"; print "#" x 50 . "\n"; print "Total Bytes Read: $hash_ref->{'tread'}\n"; print "Total Bytes Write: $hash_ref->{'twrite'}\n"; print "#" x 50 . "\n"; for my $id ( keys %$hash_ref ) { if ( $hash_ref->{$id}->{'read'} > 0 || $hash_ref->{$id}->{'write'} > 0 ) { my $psptr = 0; my $psptw = 0; $psptr = ( $hash_ref->{$id}->{'read'} / $hash_ref->{'tread'} ) * 100 if ( $hash_ref->{'tread'} > 0 ); $psptw = ( $hash_ref->{$id}->{'write'} / $hash_ref->{'twrite'} ) * 100 if ( $hash_ref->{'twrite'} > 0 ); print "$id" . " "; print $hash_ref->{$id}->{'user'} . " "; print $hash_ref->{$id}->{'read'} . " "; print $hash_ref->{$id}->{'write'} . " "; print $hash_ref->{$id}->{'cmd'} . " "; print $hash_ref->{$id}->{'samples'} . " "; print sprintf("%.2f", $psptr) . " "; print sprintf("%.2f", $psptw); print "\n" } } print "#" x 50 . "\n"; }
Here is the csv output
sudo perl iotop2csv.pl ################################################## Output from iotop -bt ################################################## timestamp,tid,user,read,total read each tid,write,total write each tid,cmd,sample number,Percent of Total Read,Percent of Total Write 16:27:00,6003,mysql,0.00,0,318.04,318.04,mysqld,2,0.00,100.00 16:27:00,4959,root,0.00,0,3.74,3.74,nailslogd,2,0.00,1.16 16:27:00,5992,mysql,0.00,0,3.74,3.74,mysqld,2,0.00,1.15 16:27:00,5994,mysql,0.00,0,314.30,314.3,mysqld,2,0.00,49.12 16:27:01,511,root,0.00,0,101.83,101.83,[kjournald],3,0.00,13.73 16:27:01,6557,mysql,0.00,0,3.77,3.77,mysqld,3,0.00,0.51 16:27:02,6530,mysql,0.00,0,7.55,7.55,mysqld,4,0.00,1.00 16:27:03,6009,mysql,0.00,0,7.54,7.54,mysqld,5,0.00,0.99 16:27:03,25220,mysql,3.77,3.77,11.31,11.31,mysqld,5,100.00,1.47 16:27:04,6534,mysql,3.77,3.77,97.94,97.94,mysqld,6,50.00,11.26 16:27:04,1864,root,0.00,0,199.65,199.65,[kjournald],6,0.00,18.67
Reblogged this on Gigable – Tech Blog.
Comment by Bosstiger — September 12, 2012 @ 11:42 pm