Во-первых, в показанном вами коде есть что-то подозрительное: вы получаете значение $?
перед тем, как фактически выполнить команду.Теперь я расскажу о том, что вы хотели написать:
my $command = "cd $STEPBYSTEP_HOME/collins-parser;" .
"cat models/model$model_num/events | code/parser $src models/model$model_num/grammar 10000 1 1 1 1 1> $dest 2> $parse_log";
my $ret_val = `$command`;
my $ret_code = $?;
После этого $ret_code
содержит состояние всей команды оболочки.Это, в свою очередь, состояние последней команды в списке, которая является конвейером cat ... | code/parser ...
.В зависимости от оболочки это может быть либо состояние последней команды в конвейере, т. Е. code/parser
(ksh, zsh), либо всегда 0 (большинство оболочек, включая ash, bash и pdksh).
В вашем случае есть простое исправление, которое заключается в том, чтобы избавиться от бесполезного использования cat
:
my $command = "cd $STEPBYSTEP_HOME/collins-parser &&" .
"<models/model$model_num/events code/parser $src models/model$model_num/grammar 10000 1 1 1 1 1> $dest 2> $parse_log";
my $ret_val = `$command`;
my $ret_code = $?;
Если бы у вас была полезная команда вместо cat
, лучшим вариантом будетбыть обойтись без оболочки в целом.Это также имеет другие незначительные преимущества: на один инструмент меньше освоить;проще переносить на не-unix системы;работает с именами файлов, содержащими метасимволы оболочки (это также может быть достигнуто путем систематического использования quotemeta
).Вот суть идеи (не проверено);perldoc -f open
и perldoc perlipc
могут помочь.
use File::Slurp;
if (open my $fh, "|-") {
# Parent code
my $ret_val = read_file($fh);
close($ret_code);
my $ret_code = $?;
...
} else { # Child code
chdir "$ENV{STEPBYSTEP_HOME}/collins-parser" or die $!;
open STDIN, "<", "models/model$model_num/events" or die $!;
open STDOUT, ">", $dest or die $!;
open STDERR, ">", $parse_log or die $!;
exec "code/parser", $src, "models/model$model_num/grammar", "1", "1", "1", "1", "1";
die $!;
}