如何在Perl中捕获完整的命令行?

时间:2011-05-27 19:19:51

标签: perl command-line

假设电话是

/usr/local/bin/perl verify.pl 1 3 de# > result.log

verify.pl内部我想捕获上面的整个调用并将其附加到日志文件中以进行跟踪。

如何捕捉整个电话?

6 个答案:

答案 0 :(得分:10)

有办法(至少在unix系统上)获得整个命令行:

my $cmdline = `ps -o args -C perl | grep verify.pl`;
print $cmdline, "\n";

e:使用PID的清洁方式(由Nathan Fellman提供):

print qx/ps -o args $$/;

答案 1 :(得分:8)

$0具有脚本名称,@ARGV具有参数,因此整个命令行为:

$commandline = $0 . " ". (join " ", @ARGV);

或更优雅(感谢FMc):

$commandline = join " ", $0, @ARGV;

但我不知道如何捕获重定向(> result.log

答案 2 :(得分:2)

$commandline = join " ", $0, @ARGV;不处理命令行有引号的情况,例如./xxx.pl --love "dad and mom"

快速解决方案:

my $script_command = $0;
foreach (@ARGV) {
$script_command .= /\s/ ?   " \'" . $_ . "\'"
                :           " "   . $_;
}

尝试将以下代码保存为xxx.pl并运行./xxx.pl --love "dad and mom"

#!/usr/bin/env perl -w
use strict;
use feature qw ( say );
say "A: " . join( " ", $0, @ARGV );
my $script_command = $0;
foreach (@ARGV) {
    $script_command .= /\s/ ?   " \'" . $_ . "\'"
                    :           " "   . $_;
}
say "B: " . $script_command;

答案 3 :(得分:1)

这里几乎只有Linux版本(当然,在shell干预后):

纯perl

BEGIN {
    my @cmd = ( );
    if (open(my $h, "<:raw", "/proc/$$/cmdline")) {
        # precisely, buffer size must be at least `getconf ARG_MAX`
        read($h, my $buf, 1048576); close($h);
        @cmd = split(/\0/s, $buf);
    };
    print join("\n\t", @cmd), "\n";
};

使用File :: Slurp:

BEGIN {
    use File::Slurp;
    my @cmd = split(/\0/s, File::Slurp::read_file("/proc/$$/cmdline", {binmode => ":raw"}));
    print join("\n\t", @cmd), "\n";
};

答案 4 :(得分:0)

答案 5 :(得分:0)

处理更多特殊情况(且无需添加自己的名称)并使用GetOpt处理行的示例:

#!perl
use strict;
use warnings;
use Getopt::Long qw(GetOptionsFromString);
use feature qw ( say );

# Note: $0 is own name

my $sScriptCommandLine;
my @asArgs = ();

my $iRet;

my $sFile = '';
my $iN = -1;
my $iVerbose = 0;

# ============================================================================
my %OptionsHash = (
    "f=s"               => \$sFile,
    "n=i"               => \$iN,
    "v:+"               => \$iVerbose);



$sScriptCommandLine = join( ' ', @ARGV );  # useless for argument with spaces
say 'A: ' . $sScriptCommandLine;

$sScriptCommandLine = '"' . join( '" "', @ARGV ) . '"'; # all arguments in "", but not suitable for arguments with '"' (given as '\"')
say 'B: ' . $sScriptCommandLine;

$sScriptCommandLine = '';
foreach (@ARGV) {
  $sScriptCommandLine .= ' ' if ($sScriptCommandLine);
  $_ =~ s/\\/\\\\/g; # needed for GetOptionsFromString
  $_ =~ s/\"/\\\"/g;
  if (/\s/) {
    $sScriptCommandLine .= '"'.$_.'"';
  }
  else {
    $sScriptCommandLine .= $_;
  }
}
say 'C: ' . $sScriptCommandLine;


my ($iRet,$paArgs);
($iRet,$paArgs) = GetOptionsFromString($sScriptCommandLine,%OptionsHash);
# remaining parameters in $$paArgs[0] etc. 
if (!$iRet) {
  # error message already printed from GetOptionsFromString
  print "Invalid parameter(s) in: \"$sScriptCommandLine\"\n";
}

say 'D: ' . '<<' . join( '>>  <<', @{$paArgs} ) . '>>';
say 'f=s: "'.$sFile.'"'; 
say 'n=i: '.$iN; 
say 'v:+: '.$iVerbose; 

# eof