Skip to content

Instantly share code, notes, and snippets.

@fskale
Created August 6, 2018 08:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fskale/80025103d1215d24f21d258778f48fef to your computer and use it in GitHub Desktop.
Save fskale/80025103d1215d24f21d258778f48fef to your computer and use it in GitHub Desktop.
Non-blocking disk stats using Mojolicious Framework
#!/usr/bin/env perl
use Mojo::Base -strict;
use Mojo::File 'path';
use Mojo::Collection 'c';
use Mojo::IOLoop;
use Mojo::JSON 'j';
use Mojo::Util 'getopt';
use Number::Bytes::Human;
BEGIN {
#only linux is supported !
#!linux
die( sprintf( "OS %s not supported !\n", $^O ) ) if $^O ne 'linux';
}
sub get_stats {
my $disk = shift;
return if !$disk;
my $file = q{/proc/diskstats};
my $fh = path($file)->open('r+');
while (<$fh>) {
chomp;
if (/$disk/ig) {
($_) = $_ =~ /^\s+(.*)$/;
close($fh) and return c( split(/\s+/) );
}
}
close $fh;
return 0;
}
sub print_help {
my $usage = "
$0 -d [disk|partition]
options: -r|--recurring for recurring output (1s)
";
printf( STDERR "%s\n", $usage );
}
sub cls {
printf("\033[2J"); #clear the screen
printf("\033[0;0H"); #jump to 0,0
}
getopt
'd|disk=s' => \my $disk,
'r|recurring' => \my $recurring;
print_help and die( sprintf("No partition or disk supplied !") ) if !$disk;
print_help and die( sprintf( "Not a block device: %s\n", qq{/dev/$disk} ) ) if !-b qq{/dev/$disk};
my $get_stats;
$get_stats = sub {
my $delay = Mojo::IOLoop::Delay->new;
$delay->steps(
sub {
my $delay = shift;
my $collection = get_stats($disk);
if ( $collection and ref $collection eq 'Mojo::Collection' and $collection->size ) {
if ( my ( $reads, $writes ) = ( $collection->[5], $collection->[9] ) ) {
$delay->pass( $reads, $writes );
}
}
else { $delay->pass; }
},
sub {
my ( $delay, $reads, $writes ) = @_;
if ( $reads and $writes ) {
Mojo::IOLoop->timer( 1 => $delay->begin );
$delay->pass( $reads, $writes );
}
else { $delay->pass; }
},
sub {
my ( $delay, $reads_prev, $writes_prev ) = @_;
my $h = Number::Bytes::Human->new( si => 0, bs => 1024 )->set_options( zero => '0B' );
my $collection = get_stats($disk);
if ( $collection and ref $collection eq 'Mojo::Collection' and $collection->size ) {
if ( $reads_prev and $writes_prev ) {
if ( my ( $reads, $writes ) = ( $collection->[5], $collection->[9] ) ) {
printf(
"Disk: %s Read: %s Write: %s\n",
$disk,
$h->format( ( $reads - $reads_prev ) * 512 ),
$h->format( ( $writes - $writes_prev ) * 512 )
);
}
}
}
cls and $get_stats->() if $recurring;
}
)->wait;
};
$recurring ? ( cls and $get_stats->() ) : $get_stats->();
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment