Crontab fails to run my Perl module - linux

My perl module is working fine when whenever I run it without using crontab,
but when I try running the script through Crontab it's throwing some error like couldnt find other modules which have been called inside my Perl.pl file.
The line I have added in Crontab file is
* * * * * cd /usr/bin/perl | perl path_to_script/script.pl;
The error I am getting is
Can't locate module.pm in #INC (#INC contains: /home/path/lib /usr/another/path/lib /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at path_to_script/script.pl line 23
When ever I am tring to run the script through crontab file it fails to connect to the sub modules.

So many things can be different when running from crontab. Such as:
different user
different shell
Often the $PATH under crontab is not what you usually expect it to be. You may have to explicitly provide the $PERL5LIB environment variable so a Perl script knows what library folders to look in.

try this :
*/5 * * * * bash -l perl path/script.pl
# change the above to your crontab settings

Run Perl with an -I (uppercase i) option indicating where to find the missing module(s), or create a wrapper something like
#!/bin/sh
cd /usr/lib/perl
PERL5LIB=$HOME/lib/perl perl path_to_script/script.pl
... and run this script from your crontab instead.
(The value of PERL5LIB might have to be more complex than this; maybe copy/paste from its value in your interactive shell.)

Just add the PERL5LIB environment variable in /etc/crontab and include the path to the .pm module file.
Example:
PERL5LIB=/root/perl5/lib/perl5:/usr/share/perl5

Related

bash script not working as expected when executed with cron [duplicate]

I have a strange problem of being to able to run a bash script from commandline but not from the crontab entry for root. I am running Ubuntu 12.04.
* * * * 1-5 root /home/xxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/jmeter-cron-randomise.sh >> /home/xxxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/cron.log
If I run the script from the cmd line using bash, it works fine but sh fails with following error:
> jmeter-cron-randomise.sh: 7: jmeter-cron-randomise.sh: arithmetic
> expression: expecting primary: " % 1 "
Having googled the problem, it seems like standard shell doesn't have the same math operators, like % (modulus), as bash. I'm Not sure why the cron job is failing in the script? I am assuming it is because it's not using the bash shell? It's definitely being fired by the cron daemon (can see it in /var/log/syslog). Any help much appreciated.
You likely need to tell cron that the shell to use is the bash shell as it defaults to sh. You can do that for all crontab entries by putting this line in your crontab:
SHELL=/bin/bash
Note that this will cause all scripts in the crontab to be run under bash which may not be what you want. If you want to change the crontab line itself to just run bash, change it to this:
* * * * 1-5 root /bin/bash /home/xxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/jmeter-cron-randomise.sh >> /home/xxxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/cron.log 2>&1
Note that I have also caused stderr to be written to the cron.log file (2>&1) which may not be what you want but is pretty common practice. This may help you further diagnose errors from the script.
In case this helps anyone: for me this appeared to be because I had ended up with "DOS" line endings (CR-LF) instead of "unix" line endings (LF). This can be checked using od or your favourite hex dump tool, e.g.:
od -c <script_file>
... and look for \r\n instead of just \n.
It seems (and this article supports it) that the CR character stops the "shebang" from working because it's interpreted as part of the shell executable's filename.
(The line endings themselves appeared because the file came from a git repository and was transferred via a Windows machine).
I also encountered this problem trying to schedule a database backup as root and it made me pull my hair out! I was working on a CentOS 7 box.
Whenever I would check /var/spool/mail/root I would see a log:
sh: root: command not found, yet the command would run perfectly in the terminal.
This is what worked for me:
I created the crontab entry using crontab -e while logged in as root.
Using the command above as an example:
* * * * 1-5 root /home/xxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/jmeter-cron-randomise.sh >> /home/xxxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/cron.log
I deleted the root user entry like:
* * * * 1-5 /home/xxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/jmeter-cron-randomise.sh >> /home/xxxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/cron.log
That solved my problem.

crontab output nothing when calling a .sh that contains an output

I have the following test.sh file in /home/me folder
#!/bin/sh
_now=$(date +"%Y_%m_%d")
_file="/home/me/$_now.txt"
speedtest-cli --simple > $_file
Where speedtest-cli is a python script that gives internet up and dll speed infos : https://github.com/sivel/speedtest-cli.
Calling test.sh from /home/me works very good: I get my yyy_mm_dd.txt output with all infos (dll speed up speed, etc.).
But when I try to call the test.sh from a crontab I get a empty yyy_mm_dd.txt file (nothing inside).
Inside crontab-e
20 20 * * * /home/me/test.sh
Did I do something wrong?
I suspect a PATH problem, so
pick one of :
add PATH=/usr/local/bin:/bin:/usr/bin in the top of your script
add in the top of crontab -e : PATH=/usr/local/bin:/bin:/usr/bin on his own line
source ~/.bashrc in the top of your script
add full path to each commands in your script
Your PATH is probably different for your interactive shell than the context your cronjob runs in, so you should specify the full path of speedtest-cli in your crontab entry.

Crontab absolute path not working

I have a script to backup my database at /home/<user>/bin/dbbackup. The script is executable by all users, and owned by me. The files /etc/cron.allow and /etc/cron.deny do not exist.
In my crontab I have the following lines (including a new blank line after the last line of code):
#reboot /home/<user>/.dropbox-dist/dropboxd
30 2 * * * bash /home/<user>/bin/dbbackup
However, cron is not running my dbbackup script. When I run a manual test of the script it works. When I run this test on the command line: * * * * * /bin/echo "cron works" >> ~/file I get the following error:
No command 'dbbackup' found, did you mean:
Command 'dvbackup' from package 'dvbackup' (universe)
Command 'tdbbackup' from package 'tdb-tools' (main)
dbbackup: command not found
My server is running Ubuntu Trusty. Any help please?
As the comments noted, it appears that amiga_os needed remove the reference to bash in the line.
30 2 * * * bash /home/<user>/bin/dbbackup
Should be.
30 2 * * * /home/<user>/bin/dbbackup
I usually just call scripts from their path and use "#!/bin/bash" (or wherever your bash lives) as the first line of the script. It appears the amiga_os had already done this, which is good. I don't like putting sentences into cron because it makes me nervous.
I think it was a path issue as cron executes as the user but does not read the bash profile and therefore does not work exactly like it would under your shell as it might not have access to your $PATH.

Crontab running issue

I have 500 php files i want to make a crontab to run them automatically (they store XML data in my database) my problem is :
when I make a crontab for each php file it works fine. the command like this:
* * * * * php /home/username/public_html/codes/php0.php
But when I want to run a shell script including all my php files like this :
* * * * * bash /home/username/public_html/codes/php.sh
it does not run.
php.sh:
#!/bin/sh
php php0.php
echo php0
php php1.php
echo php1
php php2.php
echo php2
.
.
.
Is it possible to wrap php files with bash script? and if yes why does not work am I miss something?
You are probably not running in the directory you believe you are.
So replace temporarily #!/bin/sh with #!/bin/sh -vx
and add a
pwd
at the beginning of your script (that is, the 2nd line)
Then perhaps add a
cd /home/username/public_html/codes
or maybe define a variable and use it:
mycodedir=/home/username/public_html/codes
php $mycodedir/php0.php
echo php0
etc...
I suggest to read the advanced bash scripting guide (even if it does have weaknesses).
At the moment, you have relative paths in your php.sh. The following line
php php0.php
means that php will look for the php0.php file in the current working directory. In a cron job, the working directory is usually /, i.e. the file system root. To check what the working directory really is, you can use the pwd command.
So your php.sh script looks for a file php0.php in your file system root, but the file is in /home/username/public_html/codes/.
If you use absolute paths in your php.sh, the current working directory does not matter. So simply add absolute paths in your php.sh. The file will look like this:
#!/bin/sh
php /home/username/public_html/codes/php0.php
echo php0
php /home/username/public_html/codes/php1.php
echo php1
php /home/username/public_html/codes/php2.php
echo php2
.
.
.

perl + perl script location under /etc/rc3.d with diff results

I need advice about the following:
option 1
I run the script /usr/local/bbp/api/bbpinstaller.pl from /var/tmp directory in my Linux machine and there are no problem
option 2
I create new script - script.pl under /var/tmp
and then I create link from /var/tmp/script.pl to /etc/rc3.d/S99script.pl ( by ln -s )
so S99script.pl is link to /var/tmp/script.pl
and script.pl execute the /usr/local/bbp/api/bbpinstaller.pl
more /etc/rc3.d/script.pl
#!/bin/bash
/usr/local/bbp/api/bbpinstaller.pl
.
.
.
my problem :
when the script bbpinstaller.pl run after reboot from /etc/rc3.d/S99script.pl then I get the following errors ( /usr/local/bbp/api/bbpinstaller.pl run from S99script.pl )
Can't locate Term/ReadKey.pm in #INC (#INC contains: /etc/bbp/shared /usr/perl5/5.8.4/lib/sun4-solaris- 64int /usr/perl5/5.8.4/lib /usr/perl5/site_perl/5.8.4/sun4-
solaris- 64int /usr/perl5/site_perl/5.8.4 /usr/perl5/site_perl /usr/perl5/vendor_perl/5.8.4/sun4- solaris-64int /usr/perl5/vendor_perl/5.8.4 /usr/perl5/vendor_perl
. ) at /usr/local/bbp/api/bbpinstaller.pl line 25.
BEGIN failed--compilation aborted at /usr/local/bbp/api/bbpinstaller.pl line 25.
in /usr/local/bbp/api/bbpinstaller.pl script , I have the following perl modules:
#################################
# Modules imported
#################################
use Config;
use Getopt::Long;
use File::Find;
use English;
use Sys::Hostname;
$File::Find::dont_use_nlink=1;
use lib "/etc/bbp/shared";
use Term::ReadKey qw(GetTerminalSize);
use Cwd 'abs_path';
require "bbp_globals.pl";
require "bbp_functions.pl";
the PATH of the file ReadKey.pm
/usr/local/lib/perl5/site_perl/5.8.7/sun4-solaris-thread-multi/Term/ReadKey.pm
please help me to understand . what the problem here ??? ( I not have allot experience with Perl )
/usr/local/ is used by local installs (i.e. it wasn't provided by the OS vendor). Then your shell is setup to run ($PATH) /usr/local/bin/perl (5.8.7) rather than /usr/local/bin/perl (5.8.4).
However the init scripts don't run with your shell settings - they use the system settings, which won't have /usr/local/bin in them - so they will use the OS provided perl - /usr/bin/perl which doesn't have this library (Term::ReadKey) installed.
(The .pl extension is normally for perl programs - I'd use .sh for bash/shell scripts)
When you run a script directly (that is, not specifying an interpreter first on the command-line), the kernel uses the hash-bang line (the first line) to work out which program to execute to interpret the script.
e.g. your shell script /etc/rc3.d/script.pl has a hash bang line of "#!/bin/bash", telling it to execute with /bin/bash.
/usr/local/bbp/api/bbpinstaller.pl will have a hash-bang line at its start, possibly something like: #!/usr/bin/env perl
This tells the kernel/shell to look at the PATH variable to find an interpreter; the same way it would find perl if you typed it on the command-line.
In order to fix your problem, either:
Install Term/ReadKey into the system perl.
Set your PATH in you shell script as MichaelN suggests.
Call the explicit perl instead of letting the kernel decide, as MichaelN also suggests.
Recode /usr/local/bbp/api/bbpinstaller.pl to not need Term/ReadKey
By default the os perl is /usr/bin/perl which has all its modules in /usr/perl5/site_perl/5.8.4 /usr/perl5/site_perl. Since running the script via rc3 uses root's standard path and standard lib, it won't find your custom perl in /usr/local/bin and thus won't find your site-lib in /usr/local/lib. So you need to modify your calling script "/etc/rc3.d/script.pl" which is a bash script (should probably be call script.sh but that's symantics) to include /usr/local/bin in the path, ie: export PATH=/usr/local/bin:${PATH}. That'll pre-append the /usr/local/bin to the front of the PATH and then your perl in /usr/local/bin will be called instead of /usr/bin/perl. So change the script.pl to:
#!/bin/bash
export PATH=/usr/local/bin:${PATH}
/usr/local/bbp/api/bbpinstaller.pl
or call your script with your perl.
#!/bin/bash
/usr/local/bin/perl /usr/local/bbp/api/bbpinstaller.pl
I'm totally keying off the work Douglas did in analyzing your issue, in order to provide the fix you asked for.
I would either:
In the RC shell script, set your PATH to run the right version of perl, and then call your Perl script.
Change the "shebang" line in your Perl script to use the right version of Perl.
Hope one of those helps!

Resources