CC Em has asked for the wisdom of the Perl Monks concerning the following question:

I am having trouble piping all standard output into a log file. Here is what i have been trying:
my $logFile = IO::File->new("$someFile", 'w'); my $cmd = $rsh $host -l $id \"$command >> $logFile\" ";
I have also tried:
my $cmd = $rsh $host -l $id \"$command\" >> $logFile";
Can someone show me then the proper way to append output in this manner? Thanks!

Replies are listed 'Best First'.
Re: Piping output into a log file
by Tanktalus (Canon) on Apr 11, 2005 at 16:54 UTC

    To be honest, it's not entirely clear to me what you're trying to do. At the very least, you're missing some double-quotes. What are you going to do with the $cmd variable? Send it to system?

    system($cmd);

    That would work better with the ">>" outside of the command. Here we're just worried about a bit of shell scripting:

    /usr/bin/rsh somehost -l someuser "ls -l" >> /tmp/someFile
    Thus, in your perl code, you want a command something like this:
    my $cmd = qq[$rsh $host -l $id "$command" >> $someFile]; system($cmd);
    Or, if you want to be really sneaky/smart, you want to open the file at the beginning, ...
    my $output = IO::File->new("|tee $someFile"); local *STDOUT; open STDOUT, '>&', $output;
    and put all your output to it.
    my $cmd = qq[$rsh $host -l $id "$command"]; system($cmd);
    Note also how I've changed your quotes - escaping quotes is annoying, so by using one of the other quote operators, we're freed from continuous hitting of the backslash key which was annoying when I worked on OS/2, and is doubly annoying now that I work on Linux/Unix (since I'm out of the habit) :-)

    Finally, one more change:

    my @cmd = ($rsh, $host, '-l', $id, $command); print "Executing: ", join(' ', @cmd), "\n"; system(@cmd)
    Now that I've removed all your special characters (the >>), we don't need the shell anymore. This will make building up $command (which is still going to use the shell on the remote machine) much easier as there will be significantly less to interpolate. One less layer of escaping. This may mean changing your $command to remove extra backslashes, but you'll thank me when you have to come back and re-read it later :-)

    Update: changed close STDOUT to local *STDOUT. Works better now.

Re: Piping output into a log file
by gam3 (Curate) on Apr 11, 2005 at 16:40 UTC
    If you want to log on the local system, then you should try:
    my $logFile = IO::File->new("$someFile", 'a'); my $cmd = qx($rsh $host -l $id "$command"); print $logfile $cmd;
    You might also want to look at IPC::Open2 and IPC::Open3.

    -- gam3
    A picture is worth a thousand words, but takes 200K.
Re: Piping output into a log file
by Zaxo (Archbishop) on Apr 11, 2005 at 16:41 UTC

    You can simply open the file in append mode, open my $log, '>>', $someFile or die $!;

    After Compline,
    Zaxo

Re: Piping output into a log file
by Roy Johnson (Monsignor) on Apr 11, 2005 at 16:46 UTC
    Assuming you want to write more than the output of the command to the logfile, you'll want the file descriptor number of the file handle, which you should be able to get via
    my $fdes = $logFile->fileno;
    and then your $cmd would end in something like >>& $fdes

    Caution: Contents may have been coded under pressure.
Re: Piping output into a log file
by JediWizard (Deacon) on Apr 11, 2005 at 16:47 UTC

    First of all this cannot be your exact code because it doesn't even compile.That aside:

    $logFile is a file handle. when it is interoplated into a string it will become something like "GLOB(0x810388c)". What you need to do is either: make $logFile contain the name of the file to which you wish output to be directed, or execute the command using backticks (`command >> logfile`) and capture the return value and print it to your filehandle.

    my $output = `command`; print $logFile $output; # or my $logFile = "path/to/loge/file"; system("command >> $logFile");

    Does that make sense?


    A truely compassionate attitude towards other does not change, even if they behave negatively or hurt you

    —His Holiness, The Dalai Lama

Re: Piping output into a log file
by NateTut (Deacon) on Apr 11, 2005 at 19:49 UTC
    You could also try:
    system($command . ' >> ' . $someFile);
    You don't need to open $logFile thts way, unless you need $logFile further on in the program for some reason.