Problem with a crontab job (debian 4)

Discussion in 'Server Operation' started by Reptile, May 12, 2008.

  1. Reptile

    Reptile New Member

    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.
     
  2. topdog

    topdog Active Member HowtoForge Supporter

    How can we help if we dont know what is commands are being run in the script ?
     
  3. Reptile

    Reptile New Member

    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.
     
  4. Reptile

    Reptile New Member

    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) = @_;
    
    	[email protected] = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
    	[email protected] = 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;
    
    
     
  5. topdog

    topdog Active Member HowtoForge Supporter

    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.
     
  6. Reptile

    Reptile New Member

    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! :mad:

    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.
     
  7. topdog

    topdog Active Member HowtoForge Supporter

    cron.daily is run by run-parts check your /etc/crontab for the time at which it will run.
     
  8. Reptile

    Reptile New Member

    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.
     
    Last edited: May 13, 2008
  9. topdog

    topdog Active Member HowtoForge Supporter

    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.
     
  10. Reptile

    Reptile New Member

    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 :eek:

    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 :confused: 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.
     
  11. topdog

    topdog Active Member HowtoForge Supporter

    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;
     
  12. Reptile

    Reptile New Member

    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.
     
    Last edited: May 13, 2008
  13. Reptile

    Reptile New Member

    Physically changing my bash script to change directory appears to be the solution.
     

Share This Page