Могу ли я перехватывать вызовы оболочки из Perl? - PullRequest
3 голосов
/ 02 августа 2011

У меня есть Perl-скрипт, который вызывает другие программы, то есть он вызывает system и / или exec и / или open с каналом и / или использует оператор обратного ключа.

Могу ли я запустить этот скрипт таким образом, чтобы он выводил аргументы для каждого из вышеперечисленных, чтобы я мог видеть, к чему он обращается?

Например, такая программа , которую я не могу изменить

#!/usr/bin/perl
sub get_arg {return "argument$_[0]";}
system "./foo", get_arg(1), get_arg(2);
print `./foo abc def`;

Вызвал что-то вроде этого

perl --shell-trace-on ./myscript.pl

Который в этом случае выдаст

./foo argument1 argument2
./foo abc def

Допустимо отбрасывать нормальный вывод myscript.pl или смешивать его с этим следом.

Большое спасибо.

Ответы [ 2 ]

5 голосов
/ 02 августа 2011

Это считается расширенным Perl, но вы можете определить подпрограммы в пространстве имен CORE::GLOBAL во время компиляции и перехватить встроенные функции Perl. Вызов функций в пространстве имен CORE вызовет оригинальные встроенные функции.

BEGIN {
    # have to use a BEGIN block so these functions are defined before
    # run time
    *CORE::GLOBAL::system = sub {
        print STDERR "about to invoke system @_\n";
        return CORE::system(@_);
    };
    *CORE::GLOBAL::qx = sub {
        print STDERR "about to invoke qx/backticks @_\n";
        return CORE::qx(@_);
    };
    *CORE::GLOBAL::exec = sub { ... };
};
system("sleep 5");
print `ls`;
1;

Чтобы применить эту функцию к произвольному автономному сценарию, вы можете поместить этот код в простой модуль (скажем, ShellTrace.pm), а затем вызвать perl с переключателем -MShellTrace. (HT: perlman):

package ShellTrace;
BEGIN {
    *CORE::GLOBAL::system = sub { ... };
    *CORE::GLOBAL::qx = sub { ... };
    *CORE::GLOBAL::exec = sub { ... };
    *CORE::GLOBAL::open = sub { ... };
}
1;

$ perl -MShellTrace ./myscript.pl
about to invoke system ./foo argument1 argument2 
about to invoke qx/backticks ./foo abc def
...
1 голос
/ 02 августа 2011

Нет, системная команда не помещает свою выполненную команду в какие-либо специальные переменные.

#!/usr/bin/perl
sub get_arg {return "argument$_[0]";}
my $command = './foo ' . join(' ', get_arg(1), get_arg(2));
print "$command\n";
my $resp = `$command`; # or system($command);
print `ls *bar*`;
...