blondie_72 has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I've some problems with the Perl "system" command. I've written a perl script to power down virtual machines, back up the files to a FTP backup storage, and power up the VMs again.
The information about the VMs are stored in a array and 2 hashes. A foreach loop should run 3 time to store all VMs.
The problem is, that after two loop cycles the script aborts after powering on the second VM (comment "PROBLEM"). the if block (that should evaluate the system exit code) is not executed, according to the logfile. The second VM is powered on though. Could this be some kind of timeout problem (it can take about 15 minutes to power up the VM)?
Surprisingly the first loop cycle runs without any problems...

Here is the script:


#!/usr/bin/perl -w # # upload VMs automatically # use Net::FTP; # # ----------------- Begin Subroutines -------------------------- # sub clean_up { print "Program has been interrupted by user... \n"; print LOGFTP "Program has been interrupted by user... \n\n"; close LOGFTP; die "logfile written, some VMs possibly down -check state - have a + nice day... \n\n"; } # ############# FTP Upload ################# # sub ftpup { my $server="192.168.1.200"; my $username="myftplogin"; my $password="myftppassword"; my $dir_name=""; my $trans_counter=0; my @dateiliste = (); (my $lo_dir, my $re_dir) = @_; chomp($lo_dir); chomp($re_dir); if (($lo_dir eq "") or $lo_dir =~ (m/^\s+/)) { $dir_name = "/home"; } elsif ($lo_dir =~(m#^/?\w+.*#) or $lo_dir =~ (m#^/$#) or $lo +_dir =~ (m#^.{1,2}/.*#)) { print "local directory name: $lo_dir \n"; print LOGFTP "local directory name: $lo_dir \n"; } else { print "invalid local directory name \n"; print LOGFTP "invalid local directory name \n"; die; } if (($re_dir eq "") or $re_dir =~ (m/^\s+/)) { $dir_name = "/home"; } elsif ($re_dir =~ (m#^/?\w+.*#) or $re_dir =~ (m#^/$#) or $r +e_dir =~ (m#^.{1,2}/.*#)) { print "remote directory name: $re_dir \n"; print LOGFTP "remote directory name: $re_dir \n"; } else { print "invalid remote directory name \n"; print LOGFTP "invalid remote directory name \n"; die; } if ($lo_dir eq "") { chdir or die "Unable changing to homedir."; } else { chdir $lo_dir or die "Unable changing to local directory: $lo_ +dir $!"; } @dateiliste = glob "*"; print "Logging in to FTP server: $server \n\n"; print LOGFTP "Logging in to FTP server: $server \n\n"; print LOGFTP "passive mode will bwe used for transfer \n\n"; $ftp=Net::FTP->new($server, Debug=>0, Passive=>1) || die "Unable to co +nnect to FTP server: $server.\n"; $ftp->login($username, $password) || die "invalid login credentials \n +"; $ftp->cwd($re_dir) || die "remote directory does not exist yet.\n";; $ftp->pasv(); $ftp->binary(); print "Successfully logged in to FTP server, lets go... \n\n\n"; print LOGFTP "Successfully logged in to FTP server, lets go... \n\n\n +"; for (sort @dateiliste) { print "Starting upload process for $_ , that will take a while +... \n"; print LOGFTP "Starting upload process for $_ , that will take +a while...... \n"; if ($ftp->put($_)) { print "The file $_ has been uploaded successfully.\n\n +"; print LOGFTP "The file $_ has been uploaded successful +ly.\n\n"; $trans_counter++; } else { print "Upload for file $_ FAILED.\n\n"; print LOGFTP "Upload for file $_ FAILED..\n\n"; } } print "Upload complete... Cheers ! \n"; print LOGFTP "Upload complete... Cheers ! \n"; $ftp->quit() || print LOGFTP "Unable to disconnect from FTP server: $ +server.\n\n"; my $anz_dateiliste = @dateiliste; return ( $anz_dateiliste, $trans_counter); } # # ----------------- End Subroutines -------------------------- # # # ------------------ Begin Main --------------------------------- # $SIG{'INT'} = 'clean_up'; open LOGFTP, ">>", "/home/backup1.log"; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime t +ime; my @week_day = qw( Sunday Monday Tuesday Wednesday Thursday Friday Sat +urday ); my $datestring = sprintf("%s ,the %02d.%02d.%04d at %02d:%02d h", $wee +k_day[$wday], $mday, $mon+1, $year+1900, $hour, $min); if ($wday == 6) { printf LOGFTP "Starting backup job for VM on ${datestring}. \n\n"; print "Starting backup job for VM on ${datestring}. \n\n"; } else { print LOGFTP "Stupid Cron : Aborting Job on ${datestring}. \n\n"; print "Stupid Cron : Aborting Job on ${datestring}. \n\n"; close LOGFTP; die "Thats it !"; } # Hash fuer VMs mit Pfad für Quelle und Ziel # my @vbackup_order = qw( VM_Server1 VM_Server2 VM_Server3 ); my $backup_counter = 0; my %vpath_sou = ( "VM_Server1" => "/vmfs/volumes/SASintern2/VM_Server1", "VM_Server2" => "/vmfs/volumes/SASintern1/VM_Server2", "VM_Server3" => "/vmfs/volumes/SASintern1/VM_Server3", ); my %vpath_dest = ( "VM_Server1" => "/array1/ESXBACKUP/current_vm/VM_Server1", "VM_Server2" => "/array1/ESXBACKUP/current_vm/VM_Server2", "VM_Server3" => "/array1/ESXBACKUP/current_vm/VM_Server3", ); # ############# VM stoppen / starten ################# # foreach my $vmachine (@vbackup_order) { my $cresult = ""; # chomp($vmachine); print "stopping Virtual Machine $vmachine ... \n"; print LOGFTP "stopping Virtual Machine $vmachine ... \n"; my $merker1 = $vpath_sou{"$vmachine"} . "/" . $vmachine . ".vmx"; my $merker2 = "vmware-cmd ".$merker1." getstate"; $cresult =`$merker2`; # expected value : getstate() = off chomp($cresult); print "$vmachine has state: $cresult \n"; if ($cresult =~ m/^getstate(.*)? (off)$/) { print "VM $vmachine has state $2 \n"; } elsif ($cresult =~ m/^getstate(.*)? (on)$/) { print "VM $vmachine has state $2 \n"; # VM shutdown $merker2 = "vmware-cmd ".$merker1." stop trysoft"; system $merker2; $cresult = $?; if ($cresult>0) { print "Error during shutdown $vmachine : $cresult \n"; print LOGFTP "Error during shutdown $vmachine : $cresu +lt \n"; } else { print "VMachine $vmachine stopped... \n"; print LOGFTP "VMachine $vmachine stopped... \n"; } } $merker2 = "vmware-cmd ".$merker1." getstate"; $cresult =`$merker2`; # expected value : getstate() = off chomp($cresult); if (!($cresult =~ m/^getstate(.*)? (off)$/)) { print "VM $vmachine stuck during shutdown, performing hard shu +tdown \n"; print LOGFTP "VM $vmachine stuck during shutdown, performing h +ard shutdown \n"; $merker2 = "vmware-cmd ".$merker1." stop hard"; system $merker2; } else { print "VM $vmachine has state off as expected \n"; } print "Uploading files to NAS; please be patient.. \n"; my @merker3 = &ftpup($vpath_sou{"$vmachine"}, $vpath_dest{"$vmachi +ne"}); $backup_counter++ if ($merker3[0] == $merker3[1]); print "$merker3[1] of $merker3[0] files have been stored... \n"; print LOGFTP "$merker3[1] of $merker3[0] files have been stored... + \n"; print "Files uploaded, starting VM $vmachine ...\n"; print LOGFTP "Files uploaded, starting VM $vmachine ...\n"; ################ PROBLEM ########################### $merker2 = "vmware-cmd ".$merker1." start"; system $merker2; $cresult = $?; ################ Script ends here after second loop ############## +# if ($cresult>0) { print "Error during startup $vmachine : $cresult \n"; print LOGFTP "Error during startup $vmachine : $cresult \n +"; } else { print "VMachine $vmachine started successfully... \n"; print LOGFTP "VMachine $vmachine started successfully... \n"; } $merker2 = "vmware-cmd ".$merker1." getstate"; $cresult =`$merker2`; # expected value : getstate() = on chomp($cresult); if (!($cresult =~ m/^getstate(.*)? (on)$/)) { print "VM $vmachine stuck during startup \n"; print LOGFTP "VM $vmachine stuck during startup \n"; } } ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime time +; $datestring = sprintf("%s ,the %02d.%02d.%04d at %02d:%02d h", $week_d +ay[$wday], $mday, $mon+1, $year+1900, $hour, $min); print LOGFTP "Job ending accross the counter at ${datestring}. \n"; print "Job ending accross the counter at ${datestring}. \n"; print LOGFTP "$backup_counter VMs have been stored successfully. Have +a nice day! \n\n"; print "$backup_counter VMs have been stored successfully. Have a nice +day! \n\n"; print LOGFTP "$backup_counter VMs have been stored successfully. Have +a nice day! \n\n"; print "$backup_counter VMs have been stored successfully. Have a nice +day! \n\n"; close LOGFTP; # # ------------------ End Main --------------------------------- #

Replies are listed 'Best First'.
Re: system command aborts without exit code
by Corion (Patriarch) on Mar 11, 2008 at 12:42 UTC

    Your post is far too long and verbose for me to read in its extension. But you have at least conveniently marked the problematic line:

    system $merker2;

    Never run system without checking its result:

    system $merker2 == 0 or die "Couldn't launch [$merker]: $!/$?";

    ... or, if you want to continue even though the external command failed/was not launched, just output a warning instead. Maybe consider putting all those system() calls into one central routine that logs the command, runs it and outputs errors:

    sub run_command { my ($cmd) = @_; warn "Running [$cmd]\n"; system($cmd) == 0 or die "Couldn't launch [$cmd]: $!/$?"; };
Re: system command aborts without exit code
by swampyankee (Parson) on Mar 11, 2008 at 14:04 UTC

    Since I'm not familiar with the command you're using, one thing to check is to see what values it returns on failure. It may not return a non-zero ("true") value on failure.


    emc

    Information about American English usage here and here. Floating point issues? Please read thisbefore posting.