📄 cmd.pm
字号:
package IPC::Cmd;use strict;BEGIN { use constant IS_VMS => $^O eq 'VMS' ? 1 : 0; use constant IS_WIN32 => $^O eq 'MSWin32' ? 1 : 0; use constant IS_WIN98 => (IS_WIN32 and !Win32::IsWinNT()) ? 1 : 0; use Exporter (); use vars qw[ @ISA $VERSION @EXPORT_OK $VERBOSE $DEBUG $USE_IPC_RUN $USE_IPC_OPEN3 $WARN ]; $VERSION = '0.40_1'; $VERBOSE = 0; $DEBUG = 0; $WARN = 1; $USE_IPC_RUN = IS_WIN32 && !IS_WIN98; $USE_IPC_OPEN3 = not IS_VMS; @ISA = qw[Exporter]; @EXPORT_OK = qw[can_run run];}require Carp;use File::Spec;use Params::Check qw[check];use Module::Load::Conditional qw[can_load];use Locale::Maketext::Simple Style => 'gettext';=pod=head1 NAMEIPC::Cmd - finding and running system commands made easy=head1 SYNOPSIS use IPC::Cmd qw[can_run run]; my $full_path = can_run('wget') or warn 'wget is not installed!'; ### commands can be arrayrefs or strings ### my $cmd = "$full_path -b theregister.co.uk"; my $cmd = [$full_path, '-b', 'theregister.co.uk']; ### in scalar context ### my $buffer; if( scalar run( command => $cmd, verbose => 0, buffer => \$buffer ) ) { print "fetched webpage successfully: $buffer\n"; } ### in list context ### my( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = run( command => $cmd, verbose => 0 ); if( $success ) { print "this is what the command printed:\n"; print join "", @$full_buf; } ### check for features print "IPC::Open3 available: " . IPC::Cmd->can_use_ipc_open3; print "IPC::Run available: " . IPC::Cmd->can_use_ipc_run; print "Can capture buffer: " . IPC::Cmd->can_capture_buffer; ### don't have IPC::Cmd be verbose, ie don't print to stdout or ### stderr when running commands -- default is '0' $IPC::Cmd::VERBOSE = 0;=head1 DESCRIPTIONIPC::Cmd allows you to run commands, interactively if desired,platform independent but have them still work.The C<can_run> function can tell you if a certain binary is installedand if so where, whereas the C<run> function can actually execute anyof the commands you give it and give you a clear return value, as wellas adhere to your verbosity settings.=head1 CLASS METHODS =head2 $bool = IPC::Cmd->can_use_ipc_run( [VERBOSE] )Utility function that tells you if C<IPC::Run> is available. If the verbose flag is passed, it will print diagnostic messagesif C<IPC::Run> can not be found or loaded.=cutsub can_use_ipc_run { my $self = shift; my $verbose = shift || 0; ### ipc::run doesn't run on win98 return if IS_WIN98; ### if we dont have ipc::run, we obviously can't use it. return unless can_load( modules => { 'IPC::Run' => '0.55' }, verbose => ($WARN && $verbose), ); ### otherwise, we're good to go return 1; }=head2 $bool = IPC::Cmd->can_use_ipc_open3( [VERBOSE] )Utility function that tells you if C<IPC::Open3> is available. If the verbose flag is passed, it will print diagnostic messagesif C<IPC::Open3> can not be found or loaded.=cutsub can_use_ipc_open3 { my $self = shift; my $verbose = shift || 0; ### ipc::open3 is not working on VMS becasue of a lack of fork. ### todo, win32 also does not have fork, so need to do more research. return 0 if IS_VMS; ### ipc::open3 works on every platform, but it can't capture buffers ### on win32 :( return unless can_load( modules => { map {$_ => '0.0'} qw|IPC::Open3 IO::Select Symbol| }, verbose => ($WARN && $verbose), ); return 1;}=head2 $bool = IPC::Cmd->can_capture_bufferUtility function that tells you if C<IPC::Cmd> is capable ofcapturing buffers in it's current configuration.=cutsub can_capture_buffer { my $self = shift; return 1 if $USE_IPC_RUN && $self->can_use_ipc_run; return 1 if $USE_IPC_OPEN3 && $self->can_use_ipc_open3 && !IS_WIN32; return;}=head1 FUNCTIONS=head2 $path = can_run( PROGRAM );C<can_run> takes but a single argument: the name of a binary you wishto locate. C<can_run> works much like the unix binary C<which> or the bashcommand C<type>, which scans through your path, looking for the requestedbinary .Unlike C<which> and C<type>, this function is platform independent andwill also work on, for example, Win32.It will return the full path to the binary you asked for if it wasfound, or C<undef> if it was not.=cutsub can_run { my $command = shift; # a lot of VMS executables have a symbol defined # check those first if ( $^O eq 'VMS' ) { require VMS::DCLsym; my $syms = VMS::DCLsym->new; return $command if scalar $syms->getsym( uc $command ); } require Config; require File::Spec; require ExtUtils::MakeMaker; if( File::Spec->file_name_is_absolute($command) ) { return MM->maybe_command($command); } else { for my $dir ( (split /\Q$Config::Config{path_sep}\E/, $ENV{PATH}), File::Spec->curdir ) { my $abs = File::Spec->catfile($dir, $command); return $abs if $abs = MM->maybe_command($abs); } }}=head2 $ok | ($ok, $err, $full_buf, $stdout_buff, $stderr_buff) = run( command => COMMAND, [verbose => BOOL, buffer => \$SCALAR] );C<run> takes 3 arguments:=over 4=item commandThis is the command to execute. It may be either a string or an arrayreference.This is a required argument.See L<CAVEATS> for remarks on how commands are parsed and theirlimitations.=item verboseThis controls whether all output of a command should also be printedto STDOUT/STDERR or should only be trapped in buffers (NOTE: buffersrequire C<IPC::Run> to be installed or your system able to work withC<IPC::Open3>).It will default to the global setting of C<$IPC::Cmd::VERBOSE>,which by default is 0.=item bufferThis will hold all the output of a command. It needs to be a referenceto a scalar.Note that this will hold both the STDOUT and STDERR messages, and youhave no way of telling which is which.If you require this distinction, run the C<run> command in list contextand inspect the individual buffers.Of course, this requires that the underlying call supports buffers. Seethe note on buffers right above.=backC<run> will return a simple C<true> or C<false> when called in scalarcontext.In list context, you will be returned a list of the following items:=over 4=item successA simple boolean indicating if the command executed without errors ornot.=item errorcodeIf the first element of the return value (success) was 0, then someerror occurred. This second element is the error code the commandyou requested exited with, if available.=item full_bufferThis is an arrayreference containing all the output the commandgenerated.Note that buffers are only available if you have C<IPC::Run> installed,or if your system is able to work with C<IPC::Open3> -- See below).This element will be C<undef> if this is not the case.=item out_bufferThis is an arrayreference containing all the output sent to STDOUT thecommand generated.Note that buffers are only available if you have C<IPC::Run> installed,or if your system is able to work with C<IPC::Open3> -- See below).This element will be C<undef> if this is not the case.=item error_bufferThis is an arrayreference containing all the output sent to STDERR thecommand generated.Note that buffers are only available if you have C<IPC::Run> installed,or if your system is able to work with C<IPC::Open3> -- See below).This element will be C<undef> if this is not the case.=backSee the C<HOW IT WORKS> Section below to see how C<IPC::Cmd> decideswhat modules or function calls to use when issuing a command.=cutsub run { my %hash = @_; ### if the user didn't provide a buffer, we'll store it here. my $def_buf = ''; my($verbose,$cmd,$buffer); my $tmpl = { verbose => { default => $VERBOSE, store => \$verbose }, buffer => { default => \$def_buf, store => \$buffer }, command => { required => 1, store => \$cmd, allow => sub { !ref($_[0]) or ref($_[0]) eq 'ARRAY' } }, }; unless( check( $tmpl, \%hash, $VERBOSE ) ) { Carp::carp(loc("Could not validate input: %1", Params::Check->last_error)); return; }; print loc("Running [%1]...\n", (ref $cmd ? "@$cmd" : $cmd)) if $verbose; ### did the user pass us a buffer to fill or not? if so, set this ### flag so we know what is expected of us ### XXX this is now being ignored. in the future, we could add diagnostic ### messages based on this logic #my $user_provided_buffer = $buffer == \$def_buf ? 0 : 1; ### buffers that are to be captured my( @buffer, @buff_err, @buff_out ); ### capture STDOUT my $_out_handler = sub { my $buf = shift; return unless defined $buf; print STDOUT $buf if $verbose; push @buffer, $buf; push @buff_out, $buf; }; ### capture STDERR my $_err_handler = sub { my $buf = shift; return unless defined $buf; print STDERR $buf if $verbose; push @buffer, $buf; push @buff_err, $buf; }; ### flag to indicate we have a buffer captured my $have_buffer = __PACKAGE__->can_capture_buffer ? 1 : 0; ### flag indicating if the subcall went ok my $ok; ### IPC::Run is first choice if $USE_IPC_RUN is set. if( $USE_IPC_RUN and __PACKAGE__->can_use_ipc_run( 1 ) ) { ### ipc::run handlers needs the command as a string or an array ref __PACKAGE__->_debug( "# Using IPC::Run. Have buffer: $have_buffer" ) if $DEBUG; $ok = __PACKAGE__->_ipc_run( $cmd, $_out_handler, $_err_handler ); ### since IPC::Open3 works on all platforms, and just fails on ### win32 for capturing buffers, do that ideally } elsif ( $USE_IPC_OPEN3 and __PACKAGE__->can_use_ipc_open3( 1 ) ) { __PACKAGE__->_debug( "# Using IPC::Open3. Have buffer: $have_buffer" ) if $DEBUG; ### in case there are pipes in there; ### IPC::Open3 will call exec and exec will do the right thing $ok = __PACKAGE__->_open3_run( ( ref $cmd ? "@$cmd" : $cmd ), $_out_handler, $_err_handler, $verbose ); ### if we are allowed to run verbose, just dispatch the system command } else { __PACKAGE__->_debug( "# Using system(). Have buffer: $have_buffer" ) if $DEBUG; $ok = __PACKAGE__->_system_run( (ref $cmd ? "@$cmd" : $cmd), $verbose ); } ### fill the buffer; $$buffer = join '', @buffer if @buffer; ### return a list of flags and buffers (if available) in list ### context, or just a simple 'ok' in scalar return wantarray ? $have_buffer ? ($ok, $?, \@buffer, \@buff_out, \@buff_err) : ($ok, $? ) : $ok }sub _open3_run { my $self = shift; my $cmd = shift; my $_out_handler = shift; my $_err_handler = shift; my $verbose = shift || 0; ### Following code are adapted from Friar 'abstracts' in the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -