shashank shukla shashank shukla - 1 year ago 45
Perl Question

How to use a variable in command while running from perl?

This script is using netem on netwrok interface for packet drop.
This script uses configuration file and serverlist.cfg file and runs on all the servers mentioned in serverlist.cfg.
It takes one server and run all the commands on that server.
But the issue I am facing, sleep is not working for the above script.

use strict;
use warnings;
use List::Util qw( shuffle );
use Net::SSH::Perl;
use lib qw("/usr/share/Net-SSH-Perl-1.42/Net-SSH-Perl-1.42/lib/Net/SSH/");

require "";

my $filename = 'serverlist.cfg';
my $line_count = 0;
my $hostname;
my $username;
my $password;
my @lines;

open(my $data, '<', $filename) or die "could not open '$filename' $!\n";
push @lines, join(' ', shuffle split) for <$data>;

my @line = shuffle <@lines>;

while (my $line = <@line>)
foreach ($line)
my @fields = split ",",$line;
my $hostname = "$fields[0]";
my $network_interface = get_network_interface();
my $packet_drop = get_packet_drop();
my $do_nothing= get_do_nothing();

print "The server with packet loss of $packet_drop will be\:$hostname";

my $username = "$fields[1]";
my $password = "$fields[2]";

my $cmd1 = "tc \-s qdisc ls dev $network_interface";
my $cmd2 = "tc qdisc add dev $network_interface root netem loss $packet_drop";
my $cmd3 = "tc \-s qdisc ls dev $network_interface";
my $cmd4 = "sleep 30";
my $cmd5 = "tc qdisc del dev $network_interface root netem";
my $cmd6 = "tc \-s qdisc ls dev $network_interface";

my $ssh = Net::SSH::Perl->new("$hostname");

my ($stdout,$stderr,$exit) = $ssh->cmd("$cmd1 && $cmd2 && $cmd3 && $cmd4 && $cmd5 && $cmd6");

print $stdout;


sub get_network_interface {return "eth4"};
sub get_packet_drop {return "30%"};
sub get_do_nothing{return "30"};

These variables are used in above script and declared under

script is working fine but it completes the process within msec despite giving sleep of 30secs for each server.

Script should implement it on one server and then wait for sleep declared and then it should delete the rule and run the same for next server.

Answer Source

Since you are using && chaining, the sleep ($cmd4) will not be executed if any of the earlier commands ($cmd1, $cmd2, $cmd3) fails, so print your $stderr and $exit variables to see if there are any errors.

If you want to check status of each command, you should do separate cmd calls. Then you can also use Perl sleep instead of shell sleep between commands 3 and 5:

my ($stdout,$stderr,$exit) = $ssh->cmd($cmd1);
($stdout,$stderr,$exit) = $ssh->cmd($cmd2);
($stdout,$stderr,$exit) = $ssh->cmd($cmd3);
($stdout,$stderr,$exit) = $ssh->cmd($cmd5);
($stdout,$stderr,$exit) = $ssh->cmd($cmd6);