views:

463

answers:

4

Is it possible to run Perl script (vas.pl) with shell sript inside (date.sh & backlog.sh) in cron or vice versa? Thanks.

 0 19 * * * /opt/perl/bin/perl /reports/daily/scripts/vas_rpt/vasCIO.pl 2> /reports/daily/scripts/vas_rpt/vasCIO.err

Error encountered:

 date.sh: not found
 backlog.sh: not found

Perl script:

#!/opt/perl/bin/perl

system("sh date.sh");
open(FH,"/reports/daily/scripts/vas_rpt/date.txt");
@date = <FH>;

close FH;

open(FH,"/reports/daily/scripts/vas_rpt/$cat1.txt");
@array = <FH>;

system("sh backlog.sh $date[0] $array[0]");

close FH;
+2  A: 

It's possible. Just keep in mind that your working directory when running under cron may not be what you think it is - it's the value in your HOME environment variable, or that specified in the /etc/passwd file. Consider fully qualifying the path to your .shes.

Blair Conrad
Or the user and PATH
Schwern
Thanks :-) I forgot to include the path. It works!:-)
Cez
+6  A: 

cron runs your perl script in a different working directory than your current working directory. Use the full path of your script file:

# I'm assuming your shell script reside in the same
# dir as your perl script:

system("sh /reports/daily/scripts/date.sh");

Or if your're allergic to hardcoding paths like I am you can use the FindBin package from CPAN:

use FindBin qw($Bin);
system("sh $Bin/date.sh");

If your shell script also needs to start in the correct path then it's probably better to first change your working directory:

use FindBin qw($Bin);
chdir $Bin;
system("sh date.sh");
slebetman
It works already. Thanks :-)
Cez
@slebetman: What is the "home/start" directory of the shell-script being run? I guess I'm a bit paranoide but I would make sure there is a 'cd /reports/daily/scripts' in there or that the script writes to an absolute path. (and +1 from me for solution and alternatives)
lexu
@lexu: You're right. Should change the current working directory before starting the shell script to be safe. But since the OP mentioned that simply adding the full path solved his problem then in his case he doesn't need it.
slebetman
+3  A: 

You can do what you want as long as you are careful.

The first thing to remember with cron jobs is that you get almost no environment set.

The chances are, the current directory is / or perhaps $HOME. And the value of $PATH is minimal - your profile has not been run, for example.

So, your script didn't find 'date.sh' because it wasn't in the correct directory.

To get the data from the shell script into your program, you need to pipe it there - or arrange for the 'date.sh' to dump the data into the file successfully. Of course, Perl has built-in date and time handling, so you don't need to use the shell for it.

You also did not run with use warnings; or use strict; which would also help you. For example, $cat1 is not a defined variable.

Personally, I run a simple shell script from cron and let it deal with all the complexities; I don't use I/O redirection in the crontab file. That's partly a legacy of working on ancient systems - but it also leads to portable and reliable running of cron jobs.

Jonathan Leffler
Thanks for the advice! It helps a lot :-)
Cez
A: 

There are a lot of things that need care in your script, and I talk about most of them in the "Secure Programming Techniques" chapter of Mastering Perl. You can also find some of it in perlsec/

Since you are taking external data and passing them to other external programs, you should use taint checking to ensure that the data are what you expect. What if someone were able to sneak something extra into those files?

When you want to pass data to external programs, use system in the list form so the shell doesn't get a chance to interpret possible meta-characters.

Instead of relying on the PATH to find the programs that you expect to run, specify their full paths explicitly to ensure you are at least running the file you think you are (and not something someone snuck into a directory that is earlier in PATH). If you were really paranoid (like taint checking is), you might also check that those files and directories had suitable permissions (e.g., not world-writeable).

Just as a bonus note, if you only want one line from a filehandle, you can use the line-input operator in scalar context:

 my $date = <$fh>;

You probably want to chomp the data too to get rid of possible ending newlines. Even if you don't think a terminating newline should be there because another program created the file, someone looking at the file with a text editor might add it.

Good luck, :)

brian d foy