Почему мой системный вызов Perl не работает с точкой? - PullRequest
2 голосов
/ 18 марта 2010

Я новичок в Perl, и у меня возникли проблемы с использованием "системного" вызова. Вот небольшой фрагмент кода, в котором я пытаюсь выполнить 2 команды оболочки:

# First command is :
# dot -Tpng $dottmpfile > $pngfile
# Second command is :
# rm $dottmpfile

if (!($pngfile eq "")) {
  my @args = ("dot", "-Tpng", $dottmpfile, " > ", $pngfile);
  system (join (' ' , @args ))
    or die "system @args failed : $!";

  unlink $dottmpfile;
}

РЕДАКТИРОВАТЬ: Вот мой код сейчас, и я все еще получаю ошибку:

system dot -Tpng toto.dot  >  toto.png failed : Inappropriate ioctl for device at /home/claferri/bin/fractal.pl line 79.

Я использовал system для создания этого куска кода.

Ответы [ 4 ]

3 голосов
/ 18 марта 2010

Просмотр системы perldoc -f , примечание:

Если в LIST имеется более одного аргумента или если LIST является массивом с более чем одним значением, запускается программа, заданная первым элементом списка, с аргументами, заданными остальной частью списка. Если есть только один скалярный аргумент, этот аргумент проверяется на наличие метасимволов оболочки, и, если они есть, весь аргумент передается командной оболочке системы для анализа

Вы вызываете system LIST, поэтому > заканчивается передачей dot вместо интерпретации оболочкой.

Я бы порекомендовал вам продолжать использовать system LIST, потому что это немного безопаснее, чем пропускать все через оболочку. Согласно документации, вы можете указать выходной файл, используя опцию -o для dot, так что сделайте это.

Если вы действительно хотите поставить точки i s и пересечь ваши t s (каламбур не предназначен), то вы можете использовать:

if ( defined $pngfile and $pngfile ne '') {
    my @args = (dot => '-Tpng', $dottmpfile, "-o$pngfile");
    if ( system @args ) {
        warn "'system @args' failed\n";
        my $reason = $?;
        if ( $reason == -1 ) {
            die "Failed to execute: $!";
        }
        elsif ( $reason & 0x7f ) {
            die sprintf(
                'child died with signal %d, %s coredump',
                ($reason & 0x7f),  
                ($reason & 0x80) ? 'with' : 'without'
            );
        }
        else {
            die sprintf('child exited with value %d', $reason >> 8);
        }
    }
    warn "'system @args' executed successfully\n";
    unlink $dottmpfile;
}
3 голосов
/ 18 марта 2010

Вы используете >, чтобы указать оболочке перенаправить вывод в файл, но с помощью вызова system LIST вы обходите оболочку. Поэтому вы можете использовать:

system ( join (' ' , @args ) ); 

или

system "@args";
1 голос
/ 18 марта 2010

system возвращает 0 в случае успеха и ненулевое значение в случае «отказа». Это противоречит тому, как выглядит большинство этих идиом, и немного нелогично, но при вызовах system вы должны использовать выражение вроде:

system($command) and warn "system $command: failed $?\n";   # and not or

или

if (system($command) != 0) { ... handle error ... }
0 голосов
/ 18 марта 2010

Выполняется ли "точка" в PATH? Есть ли у него права на выполнение? Какую конкретную ошибку вы получаете с этим кодом?

Кажется, что это правильно согласно perldoc -f system .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...