开发者

best way to execute unix commands within a perl script and to check if it failed

开发者 https://www.devze.com 2023-02-15 05:50 出处:网络
I want to execute a couple of unix commands within perl. What\'s the best way to do so? Is it better to use qx or system()? Is there a good way to check if it fails? Can someone show me a good example

I want to execute a couple of unix commands within perl. What's the best way to do so? Is it better to use qx or system()? Is there a good way to check if it fails? Can someone show me a good example? Thanks.

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

vs.

开发者_如何学Python
my $crflag = '/bin/touch /tmp/flag.done';
my $chgperm ='chmod 755 /tmp/flag.done';
system ($crflag);
system ($chgperm);


There are a couple of problems with your code:

  • You don't seem to want the output, meaning you'd want system, but these are very simple steps and should probably be done directly in Perl, instead of calling out to the shell. touch is literally 1 call in Perl (2 if you count closing the file.)
  • There is a race condition, since you're creating the file, and then setting its permissions in two steps. Since this looks like a flag file, a race condition seems relevant, and thus you probably want an atomic create/setperms in one command.
  • Since it's a flag file, you probably want mode 0644 instead of 0755.

In Perl, you can solve all of the above with something like this:

#!/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 );

You can place this into a sub with whatever arguments you want to create a (much more) atomic creation step to avoid other processes interfering between the large number of calls to shell out twice to create the file and then reset its permissions. (There's still concerns with synchronization, so it could still be pre-empted, but this is overall a far better solution.)

There are other flags you may wish to use. Check perldoc perlopentut and search for sysopen for a small list, or check perldoc Fcntl and your platform's documentation for a more comprehensive list. You may also wish to change the 0644 permissions to something more and less restrictive, and you may further wish to use locking; see perldoc -f flock for information and code samples on advisory locking.


Besides the fact that both operations can be done trivially using builtins utime and chmod, IPC::System::Simple provides error checking.

use IPC::System::Simple qw( system );
system('/bin/touch /tmp/flag.done');
system('chmod 755 /tmp/flag.done');


Use system along with $?. Try to avoid using qx when the output is not required.

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

system 'chmod 755 /tmp/flag.done';
my $chmod_status = $? >> 8;
0

精彩评论

暂无评论...
验证码 换一张
取 消