Perl program to run a Shell script issues...

Hi all,

I have the following Perl script which is intended to run a Shell script and generate some logging for the purposes of tracking weather or not the script ran.

I get an error, of course, since I don't know what I'm doing really.

Here is the code:

#!/opt/perl/bin/perl -w  

# Using recommended pragmas 
use strict; 
use warnings;  

use File::Basename;  

my $Directory = "/directory/script"; 
my $LogFile   = $Directory . "/logs/" . basename($0, ".pl") . ".log"; my $RunFile   = $Directory . "/logs/" . basename($0, ".pl") . ".run"; my $RunScript = $Directory . "/directory/script/script.sh";  


my $OutfileH; #Output File Handle 
print $OutfileH;  

# Make sure another instance isn't already running my $pp = Proc::Pidfile->new (pidfile => $RunFile) or die "Unable to create pidfile: $RunFile\n";  

open( $OutfileH, '>>', $LogFile); 
print $OutfileH &nicetime . ":Running script - " . $RunScript . "\n"; close($OutFileH);  

#Run the shell script through perl program system( $RunScript, ">>/directory/script/logs/script.log  2>&1" ) == 0 or print $OutFileH &nicetime "Script FAILED\n"  or exit(1);  exit(0);  

#Functions 
########################################################################## 

sub nicetime {    
my ( $sec, $min, $hour, $mday, $mon, $year, $yday, $isdst ) = localtime(time);    
my $timestr = sprintf "%4d-%02d-%02d %02d:%02d:%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec;    
return $timestr; };

The errors I get are:

String found where operator expected at script.pl line 25, near "&nicetime "Script FAILED\n""         (Missing operator before  "Script FAILED\n"?) 
Global symbol "$OutFileH" requires explicit package name at scrit.pl line 22. 
Global symbol "$OutFileH" requires explicit package name at talend.pl line 25. 
syntax error at script.pl line 25, near "&nicetime "Script FAILED\n"" 
Execution of script.pl aborted due to compilation errors.

after quick look,
seems you have not declared

$OutFileH
my $OutfileH; #Output File Handle

Oh right I noticed that. Is it just the misspelling, or that it's not declared?

---------- Post updated at 03:29 PM ---------- Previous update was at 03:24 PM ----------

Ok fixed that, but now I still have this issue:

root@comp:/directory/script# perl script.pl 
String found where operator expected at script.pl line 25, near "&nicetime "Script FAILED\n""         
          (Missing operator before  "Script FAILED\n"?) syntax error at script.pl line 25, near "&nicetime "Script FAILED\n"" 
Execution of script.pl aborted due to compilation errors. 

Yes, just a typo.

Yeah I'm still getting the following error:

root@comp:/directory/script# perl script.pl  
String found where operator expected at script.pl line 25, near "&nicetime "Script FAILED\n""                    
          (Missing operator before  "Script FAILED\n"?) syntax error at script.pl line 25, near "&nicetime "Script FAILED\n""  
Execution of script.pl aborted due to compilation errors.

I apologize.

remove the last ; which is not needed for subroutine.
};
try running

perl -c <your_file_name>

# for compilation errors.

Thank you for clarifying about the ; after the operand.

Almost the same output still though.

root@comp:/directory/script# perl -c script.pl
String found where operator expected at script.pl line 25, near "&nicetime "Script FAILED\n""         
           (Missing operator before  "Script FAILED\n"?) syntax error at script.pl line 25, near "&nicetime "Script FAILED\n"" 
script.pl had compilation errors.
# Using recommended pragmas 
use strict; 
use warnings;

use File::Basename;

my $Directory = "/directory/script";
my $LogFile   = $Directory . "/logs/" . basename($0, ".pl") . ".log"; my $RunFile   = $Directory . "/logs/" . 
basename($0, ".pl") . ".run"; my $RunScript = $Directory . "/directory/script/script.sh";


my $OutfileH; #Output File Handle 
print $OutfileH;

# Make sure another instance isn't already running 
my $pp = Proc::Pidfile->new (pidfile => $RunFile) or die "Unable to create pidfile: $RunFile\n";

open( $OutfileH, '>>', $LogFile);
print $OutfileH &nicetime . ":Running script - " . $RunScript . "\n"; close($OutfileH);

#Run the shell script through perl program 
system( $RunScript, ">>/directory/script/logs/script.log  2>&1" ) == 0 or print $OutfileH &nicetime ."Script FAILED\n"  or exit(1);  exit(0);

#Functions 
########################################################################## 

sub nicetime {
my ( $sec, $min, $hour, $mday, $mon, $year, $yday, $isdst ) = localtime(time);
my $timestr = sprintf "%4d-%02d-%02d %02d:%02d:%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec;
return $timestr; };
user@Imperfecto_:~/test$ perl -c run.pl 
run.pl syntax OK

--ahamed

Ok,

And now it complains about this test if there is another instance of the Pidfile running:

root@comp:/directory/script# perl script.pl Can't locate object method "new" via package "Proc::Pidfile" (perhaps you forgot to load "Proc::Pidfile"?) at script.pl line 18. 

---------- Post updated at 02:39 PM ---------- Previous update was at 09:57 AM ----------

So I added at Line 7:

use Proc::Pidfile;

...but now I get a different error. Wow I am really new at this...

root@comp:/directory/script# perl script.pl 
Can't locate Proc/Pidfile.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at script.pl line 7. 
BEGIN failed--compilation aborted at script.pl line 7.

---------- Post updated at 02:47 PM ---------- Previous update was at 02:39 PM ----------

Does this mean that something is not installed correctly in my perl distro (using Ubuntu Server 12.04 LTS)?

---------- Post updated 08-16-13 at 10:11 AM ---------- Previous update was 08-15-13 at 02:47 PM ----------

Ok nevermind,
Seems that I was using an HP-UX native Perl library on Ubuntu.

Corrected:

#must install libproc-pid-file-perl package 
use Proc::PID::File;

my $pp = Proc::PID::File->new (pidfile => $RunFile) or die "Unable to create pidfile: $RunFile\n";

instead of:

use Proc::Pidfile; 

#my $pp = Proc::Pidfile->new (pidfile => $RunFile) or die "Pidfile exists or can't be created: $!\n"; 

---------- Post updated at 01:57 PM ---------- Previous update was at 10:11 AM ----------

I am still not getting the desired output I guess. When the script runs, I am being told that my supervisor that the script will not create the file handle $OutfileH:

And I guess that is correct because I have to Ctrl-C out of it to get the following error:

root@comp:/directory/script# perl script.pl 
^C print() on closed filehandle $OutfileH at script.pl line 28.

Line 28 being the following:

#Run the shell script through perl program 
system( $RunScript, ">>/directory/logs/script.log 2>&1" ) == 0 or print $OutfileH &nicetime ."Script FAILED\n" or exit(1);  

??

(1) But why do you Ctrl-C in the first place?
(2) Do you encounter that error because you press Ctrl-C? Or do you encounter it anyway?
(3) What happens if you let the script run its course? What do you see? Does it do what it is expected to do?

Because the Script never seems to end.

Yes I press Ctrl-C because the script doesn't seem to finish.

Well I don't really see why it would take that long. I left it alone for a couple of hours and it was doing nothing.
I see that it creates the log entry and says that the script is being run. However it never exits.

---------- Post updated at 02:39 PM ---------- Previous update was at 02:33 PM ----------

Seems that by the time my script reaches Line 28, it doesn't open $OutfileH even though I am doing:

open( $OutfileH, '>>', $LogFile)or die "Can't open $OutfileH: $!\n"; print $OutfileH &nicetime . ":Running script - " . $RunScript . "\n"; close($OutfileH); 

and I have declared $OutfileH before that:

my $OutfileH; #Output Handle

Interesting. I haven't seen your entire script and the "die" should've said something, but in any case:

  • Print the value of $LogFile right before that "open" statement.
  • Check that the path till the directory of the log file exists in your system.
  • Check that you have the permission to create a file in that path.

Here is my script as it stands now:

#!/opt/perl/bin/perl -w  

# Using recommended pragmas 
use strict; 
use warnings;  

#must install libproc-pid-file-perl package 
use Proc::PID::File; 
use File::Basename;  

my $Directory = "/Directory"; 
my $LogFile   = $Directory . "/logs/" . basename($0, ".pl") . ".log"; 
my $RunFile   = $Directory . "/logs/" . basename($0, ".pl") . ".run"; 
my $RunScript = $Directory . "/script/script.sh";  

my $OutfileH; #Output Handle  

# Make sure another instance isn't already running 
my $pp = Proc::PID::File->new (pidfile => $RunFile) or die "Unable to create pidfile: $RunFile\n";  
print $LogFile 
open( $OutfileH, '>>', $LogFile)or die "Can't open $OutfileH: $!\n"; 
print $OutfileH &nicetime . ":Running script - " . $RunScript . "\n"; 
close($OutfileH); 

#Run the shell script through perl program 
system( $RunScript, ">>/Directory/logs/script.log 2>&1" ) == 0 or print $OutfileH &nicetime ."Script FAILED\n" or exit(1);  exit(0);  

#Functions 
########################################################################## 
sub nicetime {    
my ( $sec, $min, $hour, $mday, $mon, $year, $yday, $isdst ) = localtime(time);    
my $timestr = sprintf "%4d-%02d-%02d %02d:%02d:%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec;    
return $timestr; 
}

---------- Post updated at 04:10 PM ---------- Previous update was at 04:05 PM ----------

The path to the Log files is definitely there as i can see the log file logging a script start:

Ok, much better.
I haven't used Proc::PID::File, so I can't say much about it.
However, consider the following lines in your code:

You close $OutfileH and then try to print to it if the shell script ($RunScript) fails. That will not work as Perl cannot write to a closed filehandle.

Also, assuming your Perl program is called "script.pl", the value of $LogFile would be "/Directory/logs/script.log", which is where you apparently want to redirect your shell script output. So, instead of hard-coding the log file name in the "system" command, use $LogFile.

Change the code to something like this:

open( $OutfileH, '>>', $LogFile)or die "Can't open $OutfileH: $!\n";
print $OutfileH &nicetime . ":Running script - " . $RunScript . "\n";
#Run the shell script through Perl program
system( $RunScript, ">>${LogFile} 2>&1" ) == 0 or print $OutfileH &nicetime ."Script FAILED\n";
close($OutfileH);

Finally, if you see the line containing "Running script" in your log file but nothing after it, then most likely your shell script is taking up a long time to run.

Try it out on its own first by executing the following command on the shell prompt:

/Directory/script/script.sh

You can also time it using the (surprise!) "time" command:

time /Directory/script/script.sh

See if the shell script's the bottleneck.

I think you have managed to break through my silliness. I got a "script failed" in my logs. But thats because I think it was already running. So I actually had output saying it failed. Yay!

:smiley:

Thanks you guys so much for your assistance. There is a lot I have to learn with Perl, that's for sure!