在perl脚本中执行unix命令的最佳方法,并检查它是否失败

jda*_*mae 1 perl

我想在perl中执行几个unix命令.最好的方法是什么?使用qx或system()更好吗?有没有一种好方法可以检查它是否失败?有人能给我一个很好的例子吗?谢谢.

my $crflag=qx('/bin/touch /tmp/flag.done');
my $chgperm=qx('chmod 755 /tmp/flag.done');
Run Code Online (Sandbox Code Playgroud)

my $crflag = '/bin/touch /tmp/flag.done';
my $chgperm ='chmod 755 /tmp/flag.done';
system ($crflag);
system ($chgperm);
Run Code Online (Sandbox Code Playgroud)

Sda*_*ons 5

您的代码存在一些问题:

  • 您似乎不想要输出,这意味着您需要system,但这些步骤非常简单,可能应该直接在Perl中完成,而不是调用shell. touch在Perl中实际上是1次调用(如果你计算关闭文件,则为2次.)
  • 存在竞争条件,因为您正在创建文件,然后分两步设置其权限.由于这看起来像一个标志文件,因此竞争条件似乎相关,因此您可能希望在一个命令中使用原子create/setperms.
  • 因为它是一个标志文件,你可能想要模式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 );
Run Code Online (Sandbox Code Playgroud)

你可以将它放在一个sub中,你想要创建一个(更多)原子创建步骤,以避免其他进程在大量shell调用之间干扰两次以创建文件然后重置其权限.(仍然存在同步问题,所以它仍然可以抢占先机,但这总体上是一个更好的解决方案.)

您可能希望使用其他标志.检查perldoc perlopentut并搜索sysopen一个小列表,或查看perldoc Fcntl平台的文档以获得更全面的列表.您可能还希望将0644权限更改为更严格的限制,并且您可能还希望使用锁定; 请参阅perldoc -f flock有关咨询锁定的信息和代码示例.