设为首页 收藏本站
查看: 660|回复: 0

[经验分享] [Perl]管道、进程及其他

[复制链接]

尚未签到

发表于 2015-12-28 08:18:10 | 显示全部楼层 |阅读模式
版权声明:可以任意转载,但转载时必须标明原作者charlee、原始链接http://tech.idv2.com/2008/09/04/perl-pipe-process-etc/以及本声明。



    昨天一个同事问我关于Perl中的 -| 描述符的问题。他的程序大概是这样的:

unless (open FH, "-|") {
exec "foo bar";        # 用exec执行另一个程序
exit;
}
while (<FH>) {
...
}
close FH;
$ret = $? >> 8;
if ($ret == 1) {
...
}
  那么这里的 open FH, "-|" 是什么意思?$? >> 8 又是什么意思?
  关于管道和子进程
  首先看看 perldoc -f open,有这样一段话:
  If you open a pipe on the command '-', i.e., either '|-' or '-|' with 2-arguments (or 1-argument) form of open(), then there is an implicit fork done, and the return value of open is the pid of the child within the parent process, and 0 within the child process. (Use "defined($pid)" to determine whether the open was successful.) The filehandle behaves normally for the parent, but i/o to that filehandle is piped from/to the STDOUT/STDIN of the child process. In the child process the filehandle isn't opened--i/o happens from/to the new STDOUT or STDIN.
  这段话的意思是:如果在'-'上打开一个管道,即通过'|-'或者'-|'并带有两个参数(或一个参数)的形式执行open(),那么就会隐含地执行fork。在父进程中,open的返回值是子进程的pid,而在子进程中open的返回值是0.(使用"defined($pid)"来判断执行是否成功。)对于父进程来说,文件句柄就是普通的文件句柄,但这个文件句柄的输入输出被连接到子进程的STDOUT/STDIN上。在子进程中并不会打开这个文件句柄,输入输出只能在STDOUT或STDIN上发生。
  可见,open FH, "-|"一行产生了两个进程。在子进程中open的返回值为0,因此执行下面的 exec "foo bar"语句。注意exec函数执行外部命令后不会返回,而是直接结束进程,所以子进程就到exit之前为止。不过子进程的STDIN/STDOUT被连接到了文件句柄FH上,因此foo bar命令的输出可以在父进程中通过FH来读取。
  unless块之后的语句是父进程执行的,通过<FH>读取子进程产生的输出内容。
  关于退出状态
  那么 $? >> 8 又是什么意思?这个就说来话长了。首先看看 perldoc -f close :
  Closing a pipe also waits for the process executing on the pipe to complete, in case you want to look at the output of the pipe afterwards, and implicitly puts the exit status value of that command into $?.
  大意是说:关闭管道会等待管道另一端的进程执行结束,并隐含地将这个命令结束时的状态值保存到 $? 中。而现在,FH的另一端是子进程,所以close它会隐含地执行wait,然后将子进程的结束状态保存到 $? 中。 perldoc -f wait中的一句话可以验证这一点:
  The status is returned in $?.
  那么,$?中保存的&#8220;状态&#8221;到底是什么呢?我们知道Perl中的wait函数其实是调用系统的 wait() 或waitpid()函数。来看看wait()的文档,man 2 wait:

pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
  可以推测,$? 中保存的值就是这里的 status 值。继续往下看:
  If status is not NULL, wait() and waitpid() store status information in the int to which it points. This integer can be inspected with the following macros.
  WEXITSTATUS(status): returns the exit status of the child.
  如果status不为NULL,wait()和waitpid()将把状态信息保存到status指针指向的整数。该整数可以用下面的宏来查看:
  WEXITSTATUS(status):返回子进程的退出状态。
  可见,对status(在Perl中就是 $?)使用 WEXITSTATUS宏,才能得到子进程真正的退出状态(即子进程中通过exit()函数或在main()中return时设置的返回值)。
  而这个WEXITSTATUS在 /usr/include/bits/waitstatus.h 中有定义:

/* If WIFEXITED(STATUS), the low-order 8 bits of the status.  */
#define __WEXITSTATUS(status)   (((status) & 0xff00) >> 8)
  /usr/include/stdlib.h 中再次封装:

# define WEXITSTATUS(status)    __WEXITSTATUS(__WAIT_INT(status))
  可见,WEXITSTATUS宏正是在取 status 值的高8位。
  到此可以得知, $? >> 8 其实是在获取子进程的退出状态。
  总结
  可见,上面这个例子是在Perl中执行外部程序,并获取其输出内容的一个好办法。基本的结构再次重复一下:

unless (open FH, "-|") {
# 这里是子进程的部分
exec "command";     # 通过exec命令执行外部程序
exit;               # 保证子进程退出
}
while (<FH>) ...      # 读取子进程命令的输出结果
close FH;
$ret = $? >> 8;       # 取得子进程的返回值

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-157220-1-1.html 上篇帖子: perl学习之:read 下篇帖子: Perl 测Strut2漏洞
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表