Perl-进程管理2

1. 环境变量

可以在一个特定的工作目录下启动进程,然后它会从父进程继承这个工作目录。

在unix类系统上,PATH是以冒号分隔的目录列表,其元素是可执行文件的搜索路径。当输入rm fred这样的命令时,系统会在目录列表中依次寻找rm命令

在perl中,环境变量可通过特殊的%ENV哈希取得。在程序运行时,%ENV会保留父进程(通常为shell)继承而来的设定值,修改%ENV这个哈希就可以改变环境变量,它会被perl调用的子进程继承

$ENV{'PATH'} = "/home/rootbeer/bin:$ENV{'PATH'}";
delete $ENV{'IFS'};
my $make_result = system 'make';
use Config;
$ENV{'PATH'} = join $Config{'path_sep'},
	'/home/rootbeer/bin', $ENV{'PATH'};

2. exec函数

目前为止,之前介绍的system函数的所有语法也适用于exec函数。不过有一个重要例外,system函数会创建子进程,子进程会在perl睡眠期间执行任务,而exec函数会使当前的perl进程自己去执行任务,有点像“goto”语句执行到一半跑去做别的事,而不是就地调用子程序处理

chdir '/tmp' or die "Cannot chdir /tmp: $!";
exec 'bedrock', '-o', 'args1', @ARGV;

当我们运行到exec时,perl会找到bedrock并且跳进去执行,此后,就没有perl进程了,只有那个执行的bedrock命令的进程。这样在bedrock执行结束时,没有perl进程在等待

这个perl程序的主要功能是为另一个程序的运行设定运行环境。可以预先修改环境变量,修改当前工作目录,修改默认的文件句柄等

$ENV{PATH} = '/bin:/usr/bin';
$ENV{DEBUG} = 1;
$ENV{ROCK = 'granite';

chdir '/Users/fred';

open STDOUT, '>', '/tmp/granite.out';

exec 'bedrock';

如果使用system而不是exec,perl程序就必须傻傻的等另一个程序运行完毕才能跟着收工

不过我们一般很少用到exec,一般都是将exec和fork一起使用
如果不知道该用system还是exec,那就用system好啦

一旦启动了要执行的程序,perl就放手退出,无法再控制它,因此再exec调用之后写的任何代码都无法运行,不过如果启动过程出现错误,那么后续的捕获语句还是可以继续执行的

exec 'date';
die "date couldn't run: $!";

3. 用反引号捕获输出结果

无论用system还是exec,所执行命令的输出都会被重定向到perl的标准输出,不过有时候会想把输出结果捕获成字符串

my $now = `date`; # 捕获date命令的输出
print "The time is now $now"; # 换行符已经包含在捕获内容中

这个像是unix shell的反引号一样,不过shell还会做额外的处理,它会将最后一个换行符移除

chomp(my $no_newline_now = `date`);
print "A moment ago, it was $no_newline_now, I think.\n";

反引号里面的内容就相当于单个参数形式的system函数调用,并且按照双引号内的字符串进行解释

my @functions = qw{ int rand sleep length hex eof not exit sqrt umask };
my %about;
foreach (@functions){
	$about{$_} = `perldoc -t -f $_`;
}

除了反引号,还可以使用更为一般化的引起操作符qx(),它所完成的工作和反引号是一样的

foreach (@functions){
	$about{$_} = qx(perldoc -t -f $_);
}

和其它一般化的引起操作符类似,选用这种写法可以避免频繁转义带来的干扰。使用引起操作符的另外一个好处是,如果选用单引号作为分隔符的话,可以禁止变量内插

my $output = qx'echo $$';

如果不需要捕获输出内容,就不要使用反引号

print "Starting the frobnitzigator:\n";
`frobnitz -enable`; # 如果要忽略输出结果就没必要这么做
print "Done!\n";

以反引号执行的命令会继承perl当前的标准错误流,如果这个命令将错误信息送到标准错误,就可能会显示在终端上,从而使用户迷糊。
如果想要一起捕获标准输出和标准错误,可以使用shell规范“将标注错误合并至标准输出”,一般在linux中写成 2>&1

my $output_with_errors = `frobnitz -enable 2>&1`;

不过这回让标准错误与标准输出的信息交织在一起。如果需要分别捕获标准输出和标准错误,可以使用模块IPC::Open3

不要用会读取标准输入的命令,如果不太确定这个命令是不是会从标注能输入读取数据,可以将标准输入重定向为从/dev/null读取数据

my $result = `some_questionable_command arg arg argh </dev/null`; # linux
my $result = `some_questionable_command arg arg argh < NUL`; # windows

Capture::Tiny模块和IPC::System::Simple模块可以封装不同操作系统的特定细节,帮助捕获输出数据

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值