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

Hi

I'm working with a program that uses GetOptions to process command line options. The code that does this is as follows:

if (!GetOptions( 'user=s' => \$user, 'group=s' => \$group, 'cliaddr=s' => \$cliaddr, 'cliport=s' => \$cliport, 'daemon' => \$daemon, 'diag' => \$diag, 'httpaddr=s' => \$httpaddr, 'httpport=s' => \$httpport, 'logfile=s' => \$logfile, 'audiodir=s' => \$audiodir, 'playlistdir=s' => \$playlistdir, 'cachedir=s' => \$cachedir, 'pidfile=s' => \$pidfile, 'playeraddr=s' => \$localClientNetAddr, 'priority=i' => \$priority, 'stdio' => \$stdio, 'streamaddr=s' => \$localStreamAddr, 'prefsfile=s' => \$prefsfile, 'quiet' => \$quiet, 'nosetup' => \$nosetup, 'noserver' => \$noserver, 'd_artwork' => \$d_artwork, 'd_cli' => \$d_cli, 'd_command' => \$d_command, 'd_control' => \$d_control, 'd_display' => \$d_display, 'd_factorytest' => \$d_factorytest, 'd_files' => \$d_files, 'd_firmware' => \$d_firmware, 'd_formats' => \$d_formats, 'd_graphics' => \$d_graphics, 'd_http' => \$d_http, 'd_http_verbose' => \$d_http_verbose, 'd_info' => \$d_info, 'd_ir' => \$d_ir, 'd_irtm' => \$d_irtm, 'd_itunes' => \$d_itunes, 'd_itunes_verbose' => \$d_itunes_verbose, 'd_mdns' => \$d_mdns, 'd_moodlogic' => \$d_moodlogic, 'd_musicmagic' => \$d_musicmagic, 'd_mp3' => \$d_mp3, 'd_os' => \$d_os, 'd_paths' => \$d_paths, 'd_perf' => \$d_perf, 'd_parse' => \$d_parse, 'd_playlist' => \$d_playlist, 'd_plugins' => \$d_plugins, 'd_protocol' => \$d_protocol, 'd_prefs' => \$d_prefs, 'd_remotestream' => \$d_remotestream, 'd_scan' => \$d_scan, 'd_scheduler' => \$d_scheduler, 'd_select' => \$d_select, 'd_server' => \$d_server, 'd_slimproto' => \$d_slimproto, 'd_slimproto_v' => \$d_slimproto_v, 'd_source' => \$d_source, 'd_source_v' => \$d_source_v, 'd_sql' => \$d_sql, 'd_stdio' => \$d_stdio, 'd_stream' => \$d_stream, 'd_stream_v' => \$d_stream_v, 'd_sync' => \$d_sync, 'd_sync_v' => \$d_sync_v, 'd_time' => \$d_time, 'd_ui' => \$d_ui, 'd_usage' => \$d_usage, 'd_filehandle' => \$d_filehandle, )) { showUsage(); exit(1); };
The argument I'm interested in / having problems with is --logfile. I'd like to pipe log output to an external program (multilog) and am specifying the logfile parameter as follows:

SLIMSERVER_LOG="|/usr/local/bin/multilog t s1000000 n20 /var/log/slims +erver" SLIMSERVER_ARGS="--daemon --prefsfile=$SLIMSERVER_CFG --logfile=$SLIMS +ERVER_LOG"
The program then gets called with $SLIMSERVER_ARGS on the command line, i.e. slimserver $SLIMSERVER_ARGS

This works in that output does indeed get written to the multilog program and logged in the correct directory. However, the only output I get is a usage message which I think is caused by GetOptions thinking that the tokens in the logfile name are options to the slimserver program.

Is there some way round this?

Thanks,

R.

--

Robin Bowes | http://robinbowes.com

Edit by castaway, moved node-text out of sig

Replies are listed 'Best First'.
Re: Problem with GetOptions
by Stevie-O (Friar) on Dec 22, 2004 at 03:04 UTC
    I think your problem stems from the fact that when the shell parses your string, it breaks on spaces (and there are spaces in your thing).

    Try this:

    SLIMSERVER_LOG="'|/usr/local/bin/multilog t s1000000 n20 /var/log/slim +server'"
    Note the addition of quotes, which will cause the shell to not break the string up in the arglist.
    --Stevie-O
    $"=$,,$_=q>|\p4<6 8p<M/_|<('=> .q>.<4-KI<l|2$<6%s!<qn#F<>;$, .=pack'N*',"@{[unpack'C*',$_] }"for split/</;$_=$,,y[A-Z a-z] {}cd;print lc
Re: Problem with GetOptions
by ysth (Canon) on Dec 22, 2004 at 05:24 UTC
    Put in a print join ":", @ARGV before the GetOptions, and test for yourself what it is getting. You probably want to say slimserver "$SLIMSERVER_ARGS", not slimserver $SLIMSERVER_ARGS. Trying in bash:
    $ THEORB2="|fgrep -e THE -e B2" $ perl -we'print join ":", @ARGV' $THEORB2 |fgrep:-e:THE:-e:B2 $ perl -we'print join ":", @ARGV' "$THEORB2" |fgrep -e THE -e B2
      Thanks for both suggestions.

      I used the "print join" suggestion to see what was going on and used single quotes in the string to prevent GetOptions splitting the log command.

      I then saw that the script was tring to open the log file with ">>$log", which of course failed with a pipe for a log file. I removed the ">>" and it now works as desired.

      Is there a foolproof way to only add the ">>" if the log file is a file rather than a pipe?

      Is it as simple as checking for the pipe character at the start of the string? Something like:

      $logfilename = $log; if (substr($log, 0, 1) ne "|") { $logfilename = ">>" . $log; } if (!open STDOUT, $logfilename) { die "Can't write to $logfilename: $! +";}
      Thanks,

      R.

      --

      Robin Bowes | http://robinbowes.com

        Whitespace before the | is allowed (even tabs and newlines!), so you may want to check for that also. If $log has a trailing | or leading <, removing your >> may also be not what you want, but those cases you probably ought to treat as input errors, along with |- (which also can have whitespace between the two chars).