Perl进程——exec system qx//

来源:互联网 发布:nba球队数据 编辑:程序博客网 时间:2024/04/29 13:18

在perl中启动子进程执行外部程序有多种方式,主要有exec system qx//qx//也就是通常说的反引号``。这几种方式有或多或少的区别。

本文想从是否返回进程 返回值是什么 什么时候返回 是否使用shell几个方面对这三个命令加以解析说明。

exec

## 语法exec PATHNAME LISTexec LIST

exec函数会终止当前进程,并执行一个外部命令,而且不会返回进程
exec不会创建子进程,而是直接使用Perl的进程去执行exec任务。通常是使用Perl为一个程序设置运行环境,然后用exec去运行。
只有当命令不存在,并且是直接执行命令而不是通过系统Shell执行,exec才会失败并返回false。命令出错不会返回。

exec函数执行时会出现三种情况
exec的参数不同时,exec执行的实际执行过程不一样。

  • 使用系统shell执行

    • 当exec只有一个标量参数,会检查这个参数是否有shell元字符。如果找到shell元字符(见文章末尾),整个标量会传到系统标准命令解释权去执行。如果没有shell元字符,参数被分解为单词,并直接执

      {exec 'ls;touch file.pl;ls' } ## 分号是shell元字符,所以使用shell运行{exec 'ls touch file.pl ls' } ## 没有shell元字符,分解为单词且直接执行,由于执行的是ls命令,所有会报错,没有xxxx文件或目录
    • 当exec的参数是LIST,但是LIST中只有一个元素,这会和只有一个标量参数做同样的解析。同上

      {exec ('ls; touch file.pl; ls')} ## 列表中只有一个元素,且其中有shell元字符,使用shell执行{exec ('ls touch file.pl ls')} ## 执行ls且会报错
  • 直接执行—–LIST参数
    当exec的参数是LIST,且LIST不只有一个元素。第一个元素作为命令,后面的参数作为参数,并直接执行。当命令不存在时,执行失败返回false

    {exec ('ls', '-a', '-l')} ## 执行'ls'命令,参数是'-a' '-l'## 这样避免使用shell的用法,更安全,因为它只执行'ls'命令## eg:执行失败返回{exec ('ls touch file.pl ls', '-a', '-l')} ## 这会执行命令'ls touch file.pl ls',由于没有这个命令,所以失败并且会返回。print STDERR "exec err: $!\n"; ## 错误存储在'$!'变量中## do sth
  • 直接执行—–PATHNAME LIST参数
    要求操作系统在现有的进程中执行一个新程序时,需要告诉系统执行的程序的位置(通过PATHNAME),并且还要告诉这个新程序(通过LIST的第一个参数)将以什么名字来调用。

    { exec {'/usr/bin/vi'} 'view' }  ## 执行vi,使用vi的view启动{ exec {'/usr/bin/vi'} 'vi' }    ## 执行vi,使用vi的vi启动

    针对LIST只有一个元素的情况,exec会做出错误的解析,可以用PATHNAME语法避免不安全的调用。

    @args = ('echo surprise');exec {$args[0]} @args || print "can't exec : $!\n";   

system

system LISTsystem PATHNAME LIST

system命令会根据当前的Perl进程创建一个子进程,同时继承父进程的标准输入、标准输出、标准错误,创建子进程后立即切换并运行外部命令。
system执行外部进程时,Perl进程会等待直到自己成结束并返回。
如果system使用shell执行,可以通过&把子进程切换到后台运行,Perl无需等待进程结束。

system返回值有-1,0和其他错误码;执行失败(命令错误)返回-1,执行成功返回0,执行出错(参数错误等)返回错误码。

对于参数处理,system和exec一样,是否通过shell执行,是否使用PATHNAME指定程序名都与参数形式相关,详细见exec。

qx//

system和exec执行的命令,其执行输出都是输出到Perl进程的标准输出。
qx//是反引号执行,能捕获执行结果,也就是其返回值

## 在标量上下文中调用my $date = `date`;   ## 捕获date的输出,存入标量变量$dateprint "date: $date"; ## 2017年xxxxxx## 在列表上下文中调用my $pwd = `cat /etc/passwd`; ## 所有的输出作为一行文本存入$pwd变量my @pwd = `cat /etc/passwd`; ## 所有的输出以换行符拆分存入@pwd

对于执行结果的返回码,存入到变量$?中,和system的返回值一样,执行失败(命令错误)返回-1,执行成功返回0,执行出错(参数错误等)返回错误码。

反引号执行时,最好将命令的标准错误重定向,避免输出都Perl进程的标准输出,使用户困惑。
如果不需要捕获执行结果,最好使用system,因为反引号执行总会捕获结果。

其他

shell元字符

这里写图片描述

0 0
原创粉丝点击