1

Fairly new to Perl. I have a Perl script on a Linux machine, which has own logfile. Logfile name can change, dependent on data the script is working on (date, filename, datatype, etc.)

The script at some pionts is calling a native executable with system() call, which gives some information out to STDOUT and STDERR - few tens to few hundreds lines over many minutes. After the executable is done, the script continues and logs some other info to the logfile.

Until now the script only logged its own output, without the native executables output, which I want to log in same files as the Perl script logs to. Tried it with following two methods:

#!/usr/bin/perl
#some other code
@array_executable_and_parameters = qw/echo foo/ ;
open $log_fh, '>>', 'log/logfile1.txt';
*STDOUT = $log_fh;
*STDERR = $log_fh;
print "log_fh=$log_fh\n";
system( @array_executable_and_parameters);

$logfilename='log/logfile2.txt';
open(LOGFILEHANDLE, ">>$logfilename" );
*STDOUT = LOGFILEHANDLE;
*STDERR = LOGFILEHANDLE;
print LOGFILEHANDLE "Somethinglogged\n";
system( @array_executable_and_parameters);

It works when I run the script manually, but not when run from cron.

I know it is possible to redirect in the crontab by Linux means, but then I have to know the filename to log to, which only will be known when some data arrives, so seems to me not feasible. I also would like to have as much as possible inside the script, without many dependencies on the Linux etc. I have also no possibility to install any extra modules, libraries for Perl to use, suppose it is bare minimum install.

How do I get STDOUT and STDERR redirected to a specific file from inside the Perl script?

And if possible, how do I detect filename the STDOUT currently goes to?

9
  • How is this Perl script invoked, and how exactly are you calling system()? Commented Dec 21, 2017 at 13:07
  • From crontab: * * * * * /home/username/perl/myscript.pl Manually: ./home/username/perl/myscript.pl Executable is called from inside the script like: system( @array_executable_and_parameters); Commented Dec 21, 2017 at 13:11
  • Your interactive example has a dot before /home so those are not equivalent unless you are in the root directory; but I assume that's a spurious detail. Can you edit your question with a simple system() call in the demo script which fails to do what you expect? Commented Dec 21, 2017 at 13:15
  • For your second question, stackoverflow.com/questions/2813092/… Commented Dec 21, 2017 at 13:17
  • Thanks for the edit, We'd still need a good example of what's in the array in order to make this a proper minimal reproducible example. Commented Dec 21, 2017 at 13:19

1 Answer 1

4

Reassigning *STDOUT is only affecting the Perl-internal STDOUT scalar's binding. The proper way to redirect standard output on the system level is something like

open (STDOUT, '>&', $log_fh) or die "$0: could not: $!";

You should similarly report errors from your other system calls which could fail (and use strict and etc).

cron runs your job in your home directory, so if the path $HOME/log does not exist, the script will fail to open the log file handle (silently, because you are not logging open errors!)

Sign up to request clarification or add additional context in comments.

11 Comments

What about select?
Haven't tested that specifically but yeah, TMTOWTDI.
@simbabque, select won't affect system either. Only open (STDOUT, '>&', $log_fh) and open (STDOUT, '>', "...") will change fd 1
Adding open (STDOUT, '>>', "$logfilename"); after open(LOGFILEHANDLE, ">>$logfilename" ); works same way - all good when run manually, but outputs everything to mail file when run from cron. I can not use strict, as the script is failry old and big beast, which needs some improvements many places. I probably am completely unaware of some more missed stuff, thanks for your patience with a Perl beginner here :)
So, repeat; are you running it from cron in a directory where the log directory exists, and are you sure that you were successfully able to open the log file?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.