How do I redirect the output of Perl script executed from within another perl script to a file? - perl

I am running a perl script via crontab and redircting its output to a file:
30 1 * * * /full/path/to/my_script.pl >> /full/path/to/my_log_file
Within my_script.pl, I'm executing several other perl scripts via the system() command:
#/usr/bin/env perl
system( "/full/path/to/another_script.pl" );
And within those scripts, I am using 'print' to write to STDOUT:
#/usr/bin/env perl
print "Standard output...\n";
It appears, however, that none of those child scripts' output is getting redirected to my_log_file- The only output I see there is that of the parent perl script. Am I missing something obvious? This is on a linux system.

Instead of system(), use qx:
print qx( "/full/path/to/another_script.pl" );

Hmmm, if using system() then STDOUT should end up back in your log.
Do you have an example?
My immediate thoughts go towards the system() call isn't actually running the other scripts - do you use a full path to the script? Remember cron wont have the same $PATH that your shell has, so may not find the scripts you are trying to run unless they have the full path.
You could also capture STDERR in your log:
30 1 * * * /my_script.pl 2>&1 >> my_log_file

Related

how to collect ARGV using Perl CGI?

I want to run a script from my website using CGI.pm - The script I am running is usally ran from the command line and requires several command line ARGV inputs. How do I deal with this using CGI.pm? - can I insert a system($command) into Perl CGI script? The script can be seen here - http://www.ncbi.nlm.nih.gov/IEB/ToolBox/C_DOC/lxr/source/doc/blast/web_blast.pl
how to collect ARGV using Perl CGI?
#ARGV didn't go anywhere, but CGI doesn't use command line arguments, so there are no command line arguments to collect.
can I insert a system($command) into Perl CGI script?
Yes.
You can dual-purpose the script by checking if you are connected to a terminal:
if (-t STDOUT) {
# Command LIne mode, use #ARGV;
}
else {
# CGI mode, get ARGV equivalent from CGI->param
}
You will have to adjust the output to work in CGI mode, by adding content headers before you output anything.
If you use system($foo) in a web page, make sure the logic controlling what's in $foo is secure, otherwise you might end up hacked.

Calling perl script from perl

I have a perl script which takes 2 arguments as follows and calls appropriate function depending on the argument. I call this script from bash, but i want to call it from perl, is it possible?
/opt/sbin/script.pl --group="value1" --rule="value2";
Also the script exits with a return value that I would like to read.
The Perl equivalent of sh command
/opt/sbin/script.pl --group="value1" --rule="value2"
is
system('/opt/sbin/script.pl', '--group=value1', '--rule=value2');
You could also launch the command in a shell by using the following, though I'd avoid doing so:
system(q{/opt/sbin/script.pl --group="value1" --rule="value2"});
Just like you'd have to do in sh, you'll have to follow up with some error checking (whichever approach you took). You can do so by using use autodie qw( system );. Check the docs for how to do it "manually" if you want more flexibility.
If you want to capture the output:
$foo = `/opt/sbin/script.pl --group="value1" --rule="value2"`;
If you want to capture the exit status, but send script.pl's output to stdout:
$status = system "/opt/sbin/script.pl --group=value1 --rule=value2";
If you want to read its output like from a file:
open SCRIPT, "/opt/sbin/script.pl --group=value1 --rule=value2 |" or die $!;
while (<SCRIPT>) ...
Yes. You can use system, exec, or <backticks>.
The main difference between system and exec is that exec "executes a command and never returns.
Example of system:
system("perl", "foo.pl", "arg");

How to capture STDOUT from executable (cap) executed within a perl script executed from a crontab

Whew that is a long-winded title. But it explains my issue:
I have a crontab that runs a perl script.
That perl script runs a cap task, which outputs to STDOUT some status messages.
The perl script is supposed to capture the STDOUT (currently using backticks) from cap and parse it.
Now, this works 100% fine when I run the script from a bash user. However, when I run the script from a crontab, the perl script doesn't capture any output from the cap task.
Has anyone dealt with anything like this before? Thanks.
Maybe your cap executables are died without emitting any message to stdout. Did you checking the success state of execution?
Could you tried this?
$check_result = `$cmd 2>&1`;
if ($?){
die "$cmd failed with $check_result, $!";
}

How to set a crontab job for a perl script

I have a Perl script which I want to run every 4 hours through cron. But somehow it fails to execute through cron and runs fine if I run it through command line. Following is the command which I set in crontab:
perl -q /path_to_script/script.pl > /dev/null
Also, when I run this command on command prompt, it does not execute but when I go in the leaf folder in path_to_script and execute the file, it runs fine.
Also, where will the log files of this cron job be created so that I can view them?
You should probably change the working directory to "leaf folder".
Try this in your crontab command:
cd /path_to_script; perl script.pl >/dev/null
Wrt. log files. Cron will mail you the output. But since you sent stdout to /dev/null, only stderr will be mailed to you.
If you want the output saved in a log file, then pipe the stderr/stdout output of the script into a file, like so:
cd /path_to_script; perl script.pl 2>&1 >my_log_file
Usually cron will send you mail with the output of your program. When you're figuring it out, you probably want to check the environment. It won't necessarily be the same environment as your login shell (since it's not a login shell):
foreach my $key ( keys %ENV ) {
printf "$key: $$ENV{$key}\n";
}
If you're missing something you need, set it in your crontab:
SOME_VAR=some_value
HOME=/Users/Buster
If you need to start in a particular directory, you should chdir there. The starting directory from a cron job probably isn't what you think it is. Without an argument, chdir changes to your home directory. However, sometimes those environment variables might not be set in your cron session, so it's probably better to have a default value:
chdir( $ENV{HOME} || '/Users/Buster' );
At various critical points, you should give error output. This is a good thing even in non-cron programs:
open my $fh, '<', $some_file or die "Didn't find the file I was expecting: $!";
If you redirect things to /dev/null, you lose all that information that might help you solve the problem.
looks like you may have missed the
#!/usr/bin/perl
at the start of your perl script which is why you might need perl -q to run it
once you have added that line you can run it directly from the command line using
/path_to_script/script.pl
If you use a command in your perl program, i advise you to put the full path to the command in your program.
I have try to load environment but it is not more helpful.
After a oversee with one colleague, i think it's from interaction between perl and the system environment.
Best regards,
Moustapha Kourouma

Missing output when running system command in perl/cgi file

I need to write a CGI program and it will display the output of a system command:
script.sh
echo "++++++"
VAR=$(expect -c " spawn ssh -o StrictHostKeyChecking=no $USER#$HOST $CMD match_max
100000 expect \"*?assword:*\" send -- \"$PASS\r\" send -- \"\r\" expect eof ")
echo $VAR
echo "++++++"
In CGI file:
my $command= "ksh ../cgi-bin/script.sh";
my #output= `$command`;
print #output;
Finally, when I run the CGI file in unix, the $VAR is a very long string including \n and some delimiters. However, when I run on web server, the output is
++++++
++++++
So $VAR is missing when passing in the web interface/browser.
I know maybe the problem is $VAR is very long string.
But anyway, is there anyway to solve this problem except writing the output to a file then retrieve it from browser?
Thanks if you are interested in my question.
script.sh uses several environment variables: $USER, $HOST, $CMD and $PASS. The CGI environment will have different environment variables set than a login shell. You may need to set these variables from your CGI script before calling script.sh.
Try finding where commands like expect and ssh that you are calling are on your system and adding their directory paths to the PATH used by your script.
I.e.
which expect
returns /usr/bin/expect then add the line:
PATH=$PATH:/usr/bin && export PATH
near the beginning of the ksh script. During debug you may also want to redirect stderr to a file by appending 2>/tmp/errors.txt to the end of your command since stderr is not shown in the browser.
my $command= "ksh ../cgi-bin/script.sh 2>/tmp/errors.txt";