I made a perl script which is run from a regular bash script command. I made the script executable and can it manually without a problem if I type /root/jobs/myjob/job.sh It creates 2 output files, one to send via ftp and a log file. I was sure to use the full path in the perl files to create and access them. When i schedule it in crontab nothing happens. I know crontab is working because the automysqlbackup is running just fine. Code: 31 13 * * * /root/jobs/myjob/out/out.sh > /home/ac/snus.log 20 13 * * * /root/jobs/automysqlbackup.sh > /home/ac/mysql.log Both the "log" files are created but are totally empty. I suspect, but am not sure, that the files that are created in the first job are not being created or found. I can't seem to debug cron to see what's going on so i am totally stumped.
Well for starters I thought maybe someone could suggest how errors might be reported or to write some line in my script that would be logged that works 100% to prove the script actually begins running. Running the top line manually does exactly what it is supposed to, so why does running things in cron change that? That's what I am asking, is it likely that creating simple text files is a problem when running under the scheduler? I have to change a lot in my scripts because they contain sensitive information, which i really want to avoid doing if I am missing something simple that people have experience with.
I have removed all the mysql and sensitive code. here is my bash script Code: #!/bin/bash perl main.pm 0 The 0 is a param indicating testmode on or off. The bash works perfectly. here is main.pm Code: #!/usr/bin/perl package main; use Net::SMTP; use DBI; use Orders; $thisOrder = Orders->new(); $thisOrder->processOrders(); And here is the Order.pm Code: #!/usr/bin/perl package Orders; use lib '../classes'; use datetime; use dbconn; use Switch; use ftp; use sms; use email; use File::Copy; use encoding 'utf8'; use Encode; sub new { my $self = {}; bless($self); # but see below return $self; } sub processOrders { #stop orders being transferred and sms being sent if set to 1 my $testmode = $ARGV[0]; $thisDate = datetime->new(); my $conn = dbconn->new(); my $dbname = $conn->dbname; my $dbhost = $conn->dbhost; #find all unprocessed order information my $SQL = 'edited'; my $DB = DBI->connect("DBI:mysql:$dbname:$dbhost" , $conn->dbuser, $conn->dbpass, {'RaiseError' => 1, 'PrintError' => 0} ) or die "Failed to Connect to $conn->dbname on $conn->dbhost:\n\t$DBI::errstr\n"; my $sth = $DB->prepare($SQL) or die "Couldn't prepare statement: " . DBI->errstr; $sth->execute() ; #Write Header of the FTP file and other info my $date = $thisDate->GetCurrentDateTime(); my $dateTime = $thisDate->GetCurrentDateTimeWithTime(":"); #create the IFT file my $file = "/root/jobs/myjob/out/sent/".$thisDate->GetCurrentDateTimeWithTime("-")."-orders"; open DAT, ">:encoding(iso-8859-1)", $file || die("Cannot Open File"); #create the LOG file my $filelog = "/root/jobs/myjob/out/log/".$thisDate->GetCurrentDateTimeWithTime("-")."-log"; open LOG, ">:utf8", $filelog || die("Cannot Open File"); if($testmode==1){ print LOG "Testmode = on\n\n"; } my $ref_num = "46813"; close(DAT); #if there are no orders... if(@orderList[0] eq ""){ if($testmode==0){ } #Delete the transfer file unlink($file); print LOG "No orders to send!\n"; print LOG "File ".$file." has been removed.\n"; close(LOG); #if there are no orders then exit the program exit; } $update="false"; #transfer ftp if not in testmode if($testmode ==0){ print LOG "Sending FTP file\n"; my $ftp = ftp->new(); $result = $ftp->transfer($file); }else{ print LOG "Testmode - Sending FTP file\n"; $result = "ok"; } switch($result){ case "ok" { print LOG "Transfer successful!\n"; $update="true"; } else { print LOG $result."\n" } } #traverse the order number list and update them in the database if($testmode==0) { if($update eq "true") { print LOG "Orders prepared for sending"."\n"; print LOG "Orders status set to processing"."\n"; @orderList = (); }else{ } } close(LOG); return 1; } sub GetCurrentDateTime{ my($getHour) = @_; #@months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); #@weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun); @months = qw(01 02 03 04 05 06 07 08 09 10 11 12); ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime(); $year = 1900 + $yearOffset; if($getHour eq "hour"){ $theTime = "$hour"; return $theTime; }else{ if($dayOfMonth < 10){ $dayOfMonth = "0".$dayOfMonth; } $theTime = "$year$months[$month]$dayOfMonth"; return $theTime; } } sub GetCurrentDateTimeWithTime{ my($del) = @_; @months = qw(01 02 03 04 05 06 07 08 09 10 11 12); ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime(); $year = 1900 + $yearOffset; if($dayOfMonth < 10){ $dayOfMonth = "0".$dayOfMonth; } if($minute < 10){ $minute = "0".$minute; } $theTime = "$year$months[$month]$dayOfMonth".$del."$hour$minute"; return $theTime; } return 1;
I have a suggestion, is it not possible to run the perl script directly from cron instead of wrapping it in a bash script, try that and see what happens, i am assuming that this script with be running as root ? if so then all is well. From the way the script is coded the only way you will know where it fails is if cron is configured to mail the output of its jobs due to the fact that when an error is encountered it die's with an error message. I suspect it dies before or on trying to write to the log file.
I wrapped up the perl line in the bash because it wasn't working on it's own either. The automysql runs just fine but creates no log file either. I can't believe this is so much trouble! I've created a new entry in cron.daily and will see what happens. How do i find out what time this will run? And everything is running as root.
Ok , i figured it out, it is the working paths of the classes in my scripts. If I hard code the libraries and class locations it runs ok otherwise it doesn't find them. Do you know how to set the working directory of the program so I can technically run it from any location? these lines package Orders; use lib '../classes'; cause the trouble because it doesn't see that the directory the script is located in is the working directory, so neither lines work.
You can find the paths that perl is going to search for modules using the command Code: perl -V The @INC variable holds the paths that are searched. Put your modules in the appropriate path.
Is it possible to define my own paths in @INC? I like my programs to be totally self contained otherwise it means whenever I go to a new server or platform I have to remember to copy all my modules into these paths. Doesn't seem sensible to me. Why aren't the scripts being executed from the directory they reside in in the first place when being triggered from a different directory? There has to be some way to fix this so I don't need to copy my modules/classes into global directories Hardcoding everything seems very old fashioned to me, there must be some solution to this to allow me to use relative paths to search for my modules and created output files The real problem is that the relative path is different from the execution path and I should be able to somehow set this in my perl code.
if you have a "." in the variable it means the pwd is included, so you can place the modules in the same directory as the script. Or you can use Code: use lib '/yourpath/libdir/'; use YourMod;
Yes writing the full path works, I've established that but I can't write a relative path. The problem is that the execution path is not the same as the "working path" that I want it to be. The working path becomes wherever the first script is executed from. I guess in my bash i can add "cd /root/jobs/myjob" and that might fix it but it seems awkward that things work like this.