Лучший способ выполнить команды Unix в Perl-скрипте и проверить, не удалось ли это - PullRequest
1 голос
/ 08 марта 2011

Я хочу выполнить пару команд Unix в Perl.Какой лучший способ сделать это?Лучше использовать qx или system ()?Есть ли хороший способ проверить, не удается ли это?Может кто-нибудь показать мне хороший пример?Спасибо.

my $crflag=qx('/bin/touch /tmp/flag.done');
my $chgperm=qx('chmod 755 /tmp/flag.done');

против

my $crflag = '/bin/touch /tmp/flag.done';
my $chgperm ='chmod 755 /tmp/flag.done';
system ($crflag);
system ($chgperm);

Ответы [ 3 ]

5 голосов
/ 08 марта 2011

Есть несколько проблем с вашим кодом:

  • Похоже, вы не хотите вывод, то есть вы хотите system, но это очень простые шаги и, вероятно, должныбыть сделано непосредственно в Perl, вместо вызова оболочки.touch буквально 1 вызов в Perl (2, если вы считаете закрытие файла.)
  • Существует условие гонки, поскольку вы создаете файл, а затем задаете его разрешения в два этапа.Так как это выглядит как файл флага, условие гонки кажется релевантным, и, таким образом, вы, вероятно, захотите атомарный create / setperms в одной команде.
  • Поскольку это флаг file , вам, вероятно, нужен режим0644 вместо 0755.

В Perl все вышеперечисленное можно решить примерно так:

#!/usr/bin/perl

use Fcntl qw( :DEFAULT );   # Core module, for O_CREAT, etc. constants
use strict;
use warnings;

# You probably want 0644, as a flag file probably shouldn't be executable..?
sysopen( my $fh, '/tmp/flag.done', O_CREAT|O_EXCL|O_RDWR, 0644 )
# Sysopen returns a undef if unsuccessful, with an error message stored in $!
    or die "$!";
# write to it here, if you need to.
close( $fh );

Вы можете поместить это в подпрограмму с помощьюкакими бы аргументами вы ни хотели создать (намного больше) атомарный шаг создания, чтобы избежать вмешательства других процессов между большим количеством вызовов, которые нужно дважды выложить для создания файла, а затем сбросить его разрешения.(Все еще есть проблемы с синхронизацией, поэтому ее все еще можно заменить, но в целом это гораздо лучшее решение.)

Есть и другие флаги, которые вы, возможно, захотите использовать.Проверьте perldoc perlopentut и найдите sysopen для небольшого списка, или проверьте perldoc Fcntl и документацию вашей платформы для более полного списка.Возможно, вы также захотите изменить разрешения 0644 на что-то более и менее ограничительное, и вы также можете захотеть использовать блокировку;см. perldoc -f flock для получения информации и примеров кода по консультативной блокировке.

4 голосов
/ 08 марта 2011

Помимо того, что обе операции можно выполнить тривиально с помощью встроенных utime и chmod, IPC :: System :: Simple обеспечивает проверку ошибок.

use IPC::System::Simple qw( system );
system('/bin/touch /tmp/flag.done');
system('chmod 755 /tmp/flag.done');
2 голосов
/ 08 марта 2011

Используйте system вместе с $?. Старайтесь избегать использования qx, когда вывод не требуется.

system '/bin/touch /tmp/flag.done';
my $touch_status = $? >> 8;

system 'chmod 755 /tmp/flag.done';
my $chmod_status = $? >> 8;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...