, perl .
, , , .
my $foopath = "/usr/bin/foo";
die "$0: $foopath is not executable" unless -x $foopath;
my $output = `$foopath 2>&1`;
die "$0: $foopath exited $?" if $?;
, Unix. .
Unix
perl.
perl -e 'print "hi\n"; warn "bye\n"'
hi
bye
, print STDOUT, warn STDERR . , .
$ perl -e 'print "hi\n"; warn "bye\n"' >/dev/null
bye
/dev/null , "" .
$ perl -e 'print "hi\n"; warn "bye\n"' 1>/dev/null
bye
1 STDOUT. "",
$ perl -e 'print "hi\n"; warn "bye\n"' 2>/dev/null
hi
, 2 STDERR. ( STDIN 0.)
STDOUT STDERR 2>&1. " 2s , 1s".
$ perl -e 'print "hi\n"; warn "bye\n"' 2>&1
hi
bye
, , . ,
$ perl -e 'print "hi\n"; warn "bye\n"' >/dev/null 2>&1
, ,
$ perl -e 'print "hi\n"; warn "bye\n"' 2>&1 >/dev/null
bye
. 2>&1, STDERR , STDOUT, : ! >/dev/null STDOUT .
, dup2, fcntl.
, .
$ perl -e 'print "hi\n"; warn "bye\n"' | sed -e 's/^/got: /'
bye
got: hi
, , STDERR STDOUT - . , "" . , STDOUT.
$ perl -e 'print "hi\n"; warn "bye\n"' 2>&1 | sed -e 's/^/got: /'
got: bye
got: hi
, fork, dup2 exec .
- shell:
fork sed - shell:
sed waitpid- sed:
pipe perl - sed:
fork perl - sed:
dup2, STDIN - sed:
exec sed - sed:
STDIN- perl:
dup2 STDOUT 3 - perl:
dup2 STDERR STDOUT s - perl:
exec perl - perl:
exit
- sed:
- sed:
- sed: reap
perl s waitpid - sed:
exit
- shell:
$? waitpid
, . , Bourne .
" "
Perl .
use strict;
use warnings;
my $pid = open my $fh, "-|";
die "$0: fork: $!" unless defined $pid;
if ($pid) {
while (<$fh>) {
s/^/got: /;
print;
}
}
else {
open STDERR, ">&=", \*STDOUT or print "$0: dup: $!";
exec "perl", "-e", q[print "hi\n"; warn "bye\n"]
or die "$0: exec: $!";
}
open , perlfunc open:
, MODE "|-", , , MODE "-|", , , ( ) tash ("-") . . open IPC perlipc .
$ ./simple-pipeline
got: bye
got: hi
hardcodes STDOUT, .
$ ./simple-pipeline >/dev/null
backticks
, perl , pp_backtick ( pp_sys.c), Perl_my_popen ( util.c) (fork, pipe, dup2). Perl_do_exec3 ( doio.c), , . :
2>&1, STDOUT , .
if (*s == '>' && s[1] == '&' && s[2] == '1'
&& s > cmd + 1 && s[-1] == '2' && isSPACE(s[-2])
&& (!s[3] || isSPACE(s[3])))
{
const char *t = s + 3;
while (*t && isSPACE(*t))
++t;
if (!*t && (PerlLIO_dup2(1,2) != -1)) {
s[-2] = '\0';
break;
}
}
PerlProc_execl(PL_sh_path, "sh", "-c", cmd, (char *)NULL);
PERL_FPU_POST_EXEC
S_exec_failed(aTHX_ PL_sh_path, fd, do_report);
S_exec_failed
if (ckWARN(WARN_EXEC))
Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't exec \"%s\": %s",
cmd, Strerror(e));
, .
, perl .
$ perl -e 'use strict; use warnings; my $out=`DNE`; print $out'
Can't exec "DNE": No such file or directory at -e line 1.
Use of uninitialized value in print at -e line 1.
.
. , 2>&1 , , :
if (*s != ' ' && !isALPHA(*s) &&
strchr("$&*(){}[]'\";\\|?<>~`\n",*s)) {
. backticks , perl . , perl exec , fork .
DNE , perl . exec , , warnings. perlop , backticks qx// undef , , undefined $out.
$ perl -e 'use strict; use warnings; my $out=`DNE 2>&1`; print $out'
Use of uninitialized value in print at -e line 1.
exec?
, :
- .
fork .dup2 STDOUT .exec, .- .
, perl . DNE 2>&1, perl STDERR STDOUT, .
if (!*t && (PerlLIO_dup2(1,2) != -1)) {
s[-2] = '\0';
break;
}
2>&1 , dup2 - , perl . , , DNE 2>&1 DNE! , , perl : "", exec .
exec , DNE . exec STDERR. - dup2, STDERR , STDOUT: .
, , undef.
$ perl -e 'use strict; use warnings; my $out=`echo 123; DNE 2>&1`; print $out'
123
sh: DNE: command not found
DNE, . ;, perl . echo , DNE , STDOUT STDERR . perl s , .
warnings -a !, exec. , perldiag W exec.
.
$ perl -Mstrict -Mwarnings -e 'my $out=`DNE`; print $out'
Can't exec "DNE": No such file or directory at -e line 1.
Use of uninitialized value $out in print at -e line 1.
$ perl -Mstrict -Mwarnings -M-warnings=exec -e 'my $out=`DNE`; print $out'
Use of uninitialized value $out in print at -e line 1.
use strict;
use warnings;
no warnings 'exec';
my $out = `DNE`;
print defined($out) ? $out : "command failed\n";
, - exec, pipe open . , exec, , , .