Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Is it possible to determine last executed command line?

by bdimych (Monk)
on Dec 03, 2007 at 09:47 UTC ( [id://654530]=perlquestion: print w/replies, xml ) Need Help??

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

$? is exit status of last executed `backticks` or "system". But is there a way to determine last executed command line itself, so that I could write something like this
if ($? == -1) { die "failed to execute command $????? by reason $!" }
without defining additional variables

Replies are listed 'Best First'.
Re: Is it possible to determine last executed command line?
by moritz (Cardinal) on Dec 03, 2007 at 09:52 UTC
    How do you want to execute a command without calling system, backticks or the like?

    Or are you referring to Perl statements?

    If yes, you can often use something like that:

    open($handle, '<', $file) or die "Can't open '$file' for reading: $!";

    The or checks the return value of open, the last Perl statement.

      In brief

      I have separate sub inside my project

      sub retcode_full_test { # code taken from perldoc -f system if ($? == -1) { G::abend("failed to execute: $!"); } elsif ($? & 127) { G::abend(sprintf("child died with signal %d, %s coredump", ($? + & 127), ($? & 128) ? 'with' : 'without')); } else { return $? >> 8; } }
      I've thought, that it would be better and it may be possible
      sub retcode_full_test { # code taken from perldoc -f system if ($? == -1) { G::abend("failed to execute $?????: $!"); } elsif ($? & 127) { G::abend(sprintf("$????? died with signal %d, %s coredump", ($ +? & 127), ($? & 128) ? 'with' : 'without')); } else { return $? >> 8; } }
        Rather than calling
        system( "....." ); retcode_full_text();
        you might consider modifying retcode_full_text to take the last command as an argument, and using

        my_system( "....." );

        with
        sub my_system { my ( $cmd ) = @_; system( $cmd ); retcode_full_text( $cmd ); }
Re: Is it possible to determine last executed command line?
by cdarke (Prior) on Dec 03, 2007 at 10:26 UTC
    Depends what you mean. An example of the kind of 'command' you wish to test would help.
    I am assuming you are running a child process using backticks or system. The problem with the return code $? with these is that they might invoke a shell, and it will be the return code from the shell you might pickup, not that of the shell command. Is it this that bothers you?
    If so, your best bet is to execute the external program without invoking a shell. Avoid shell meta-characters like redirection, pipes, globbing, and so on. It is not that difficult to do all that from Perl before invoking the external program.
    Alternatively execute the program using fork and exec (unless you are on Windows).
      >Is it this that bothers you?

      No it is not. There are several places over my project where retcode_full_test() is called. So I just thought about minimize changes.

      After that, I'd thought, if global $? exists, why could not exist $"last_command_line"

      That's all, in general

        There is not much Perl can do about this. If you insist on invoking a shell then all that Perl can do is report what the shell returned. Anything further is outside its control.
Re: Is it possible to determine last executed command line?
by tcf03 (Deacon) on Dec 03, 2007 at 18:50 UTC
    This may be a bit overkill, and definitely defines additional variables, but you could use a hash to store the command and any errors.
    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; use Digest::MD5; use IPC::Run qw( run timeout ) ; my %syscalls; runsyscall('/usr/bin/ls'); runsyscall('/bin/ls'); runsyscall('vipw'); print Dumper %syscalls; sub runsyscall { my @cmd = @_; my $digest = digestit(@cmd); my ( $in, $out, $err ); $syscalls{$digest}{'cmd'} = qq|@cmd|; eval { run \@cmd, \$in, \$out, \$err, timeout 10 }; if ($@) { $syscalls{$digest}{'exit'} = $@; } chomp ($err) if $err; # chomp ($out) if $out; $syscalls{$digest}{'err'} = $err || undef; # $syscalls{$digest}{'out'} = $out || undef; } sub digestit { my @cmd = @_; my $sysdigest = Digest::MD5->new; $sysdigest->add(@cmd); return $sysdigest->hexdigest; }


    Ted
    --
    "That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
      --Ralph Waldo Emerson

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://654530]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (7)
As of 2024-04-19 16:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found