简体   繁体   中英

perl script running on command line but not in crontab

It is very strange, i have many script like following and all running in crontab but following script running on command (./load.pl) line but not inside crontab

crontab:

0-59/5 * * * * /home/spatel/rrd/load.pl >> /tmp/load.out

Notes: I also tried following method

0-59/5 * * * * /usr/bin/perl /home/spatel/rrd/load.pl >> /tmp/load.out
0-59/5 * * * * root /usr/bin/perl /home/spatel/rrd/load.pl >> /tmp/load.out

Somewhere i read cron ignore newline end of the script so i look care of that too

I have put print in script and redirect to /tmp/load.out i can see that output in load.out when cron execute but somehow it is not updating data in side load.rrd file.

If i run script on command like ./load.pl it works! but not inside crontab.

I have set crontab PATH whatever root use has. I tried all possible way to debug but it is not running inside cron. Here is the place where i get this script, all other script working file in crontab only following one has issue :( https://github.com/mmitch/rrd

Script:

#!/usr/bin/env perl
#
# RRD script to display system load
# 2003,2011 (c) by Christian Garbs <mitch@cgarbs.de>
# Licensed under GNU GPL.
#
# This script should be run every 5 minutes.
#
# *ADDITIONALLY* data aquisition is done externally every minute:
# rrdtool update $datafile N:$( PROCS=`echo /proc/[0-9]*|wc -w|tr -d ' '`; read L1 L2 L3 DUMMY < /proc/loadavg ; echo ${L1}:${L2}:${L3}:${PROCS} )
#
use strict;
use warnings;
#use 5.010;
use RRDs;

# parse configuration file
my %conf;
eval(`/bin/cat /home/spatel/rrd/rrd-conf.pl`);
die $@ if $@;

# set variables
my $datafile = "/home/spatel/rrd/db/load.rrd";
my $picbase  = "/var/www/mrtg/rrd/load-";

# global error variable
my $ERR;

# whoami?
my $hostname = `/bin/hostname`;
chomp $hostname;

# generate database if absent
if ( ! -e $datafile ) {
    # max 70000 for all values
    RRDs::create($datafile,
         "--step=60",
         "DS:load1:GAUGE:120:0:70000",
         "DS:load2:GAUGE:120:0:70000",
         "DS:load3:GAUGE:120:0:70000",
         "DS:procs:GAUGE:120:0:70000",
             "RRA:AVERAGE:0.5:1:120",
         "RRA:AVERAGE:0.5:5:600",
         "RRA:AVERAGE:0.5:30:700",
         "RRA:AVERAGE:0.5:120:775",
         "RRA:AVERAGE:0.5:1440:797",
         "RRA:MAX:0.5:1:120",
         "RRA:MAX:0.5:5:600",
         "RRA:MAX:0.5:6:700",
         "RRA:MAX:0.5:120:775",
         "RRA:MAX:0.5:1440:797",
         "RRA:MIN:0.5:1:120",
         "RRA:MIN:0.5:5:600",
         "RRA:MIN:0.5:6:700",
         "RRA:MIN:0.5:120:775",
         "RRA:MIN:0.5:1440:797"
         );
      $ERR=RRDs::error;
      die "ERROR while creating $datafile: $ERR\n" if $ERR;
      print "created $datafile\n";
  }

# data aquisition is done externally every minute:
my @procs = glob '/proc/[0-9]*';

my $file = '/proc/loadavg';
open my $fh, '<', $file or die "Failed to open '$file': $!";

my $load = <$fh>;

my $p = (scalar @procs);
my $l = (join ':', (split ' ', $load)[0..2]);
print "${l}:${p}";

# update rrd
RRDs::update($datafile,
            "N:${l}:${p}"
            );
$ERR=RRDs::error;
die "ERROR while updating $datafile: $ERR\n" if $ERR;

# draw pictures
foreach ( [3600, "hour"], [86400, "day"], [604800, "week"], [31536000, "year"] ) {
    my ($time, $scale) = @{$_};
    RRDs::graph($picbase . $scale . ".png",
        "--start=-${time}",
        '--lazy',
        '--imgformat=PNG',
        "--title=${hostname} system load (last $scale)",
        "--width=$conf{GRAPH_WIDTH}",
        "--height=$conf{GRAPH_HEIGHT}",
        '--slope-mode',
        '--alt-autoscale',

        "DEF:load1=${datafile}:load1:AVERAGE",
        "DEF:load2=${datafile}:load2:AVERAGE",
        "DEF:load3=${datafile}:load3:AVERAGE",
        "DEF:procsx=${datafile}:procs:AVERAGE",
        "DEF:procminx=${datafile}:procs:MIN",
        "DEF:procmaxx=${datafile}:procs:MAX",

        'CDEF:procs=procsx,100,/',
        'CDEF:procmin=procminx,100,/',
        'CDEF:procrange=procmaxx,procminx,-,100,/',

        'AREA:procmin',
        'STACK:procrange#E0E0E0',
        'AREA:load3#000099:loadavg3',
        'LINE2:load2#0000FF:loadavg2',
        'LINE1:load1#9999FF:loadavg1',
        'COMMENT:\n',
        'LINE1:procs#000000:processes/100',
        );
    $ERR=RRDs::error;
    die "ERROR while drawing $datafile $time: $ERR\n" if $ERR;
}

Update:

Here is the output of script:

[root@spatel tmp]# pwd
/tmp
[root@spatel tmp]# /home/spatel/rrd/load.pl 
0.15:0.06:0.01:664

Its most likely an environment problem.

A "cron" scripts starts of with the default system environment (Default PATH, LANG etc.) your .profile, .rc are NOT executed.

So you need to provide all the environment variables PATHs etc. your program requires in the script. This is a bit of a pain for a pure perl script so its probably better to wrap it in a shell script which sets whatever your ".profile" script sets.

Solved:

You won't believe how problem got resolved, I use perl instead of /usr/bin/perl in crontab , I though its best practice to use full PATH in crontab but it prove wrong, Still i don't know why and How?

0-59/5 * * * * perl /home/spatel/rrd/load.pl

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM