PHP在linux上执行外部命令的方法


Posted in PHP onFebruary 06, 2017

目录:

一、PHP中调用外部命令介绍
二、关于安全问题
三、关于超时问题
四、关于PHP运行linux环境中命令出现的问题

一、PHP中调用外部命令介绍

在PHP中调用外部命令,可以用,1>调用专门函数、2>反引号、3>popen()函数打开进程,三种方法来实现:

方法一:用PHP提供的专门函数(四个):

PHP提供4个专门的执行外部命令的函数:exec(), system(), passthru(), shell_exec()

1)exec()

原型: string exec ( string $command [, array &$output [, int &$return_var ] )

说明: exec执行系统外部命令时不会输出结果,而是返回结果的最后一行。如果想得到结果,可以使用第二个参数,让其输出到指定的数组。此数组一个记录代表输出的一行。即如果输出结果有20行,则这个数组就有20条记录,所以如果需要反复输出调用不同系统外部命令的结果,最好在输出每一条系统外部命令结果时清空这个数组unset($output),以防混乱。第三个参数用来取得命令执行的状态码,通常执行成功都是返回0。

<?php
  exec("dir",$output);
  print_r($output);
?>

2)system()

原型: string system ( string $command [, int &$return_var ] )

说明: system和exec的区别在于,system在执行系统外部命令时,它执行给定的命令,输出和返回结果。第二个参数是可选的,用来得到命令执行后的状态码。

<?php
system("pwd",$result);
print $result;//输出命令的结果状态码
?>

关于第二个参数结果状态码的简单介绍:

如果返回0是运行成功,

在Bash中,当错误发生在致命信号时,bash会返回128+signal number做为返回值。

如果找不到命令,将会返回127。

如果命令找到了,但该命令是不可执行的,将返回126。

除此以外,Bash本身会返回最後一个指令的返回值。

若是执行中发生错误,将会返回一个非零的值。

Fatal Signal : 128 + signo
Can't not find command : 127
Can't not execute : 126
Shell script successfully executed : return the last command exit status
Fatal during execution : return non-zero

3)passthru()

原型: void passthru ( string $command [, int &$return_var ] )

说明: passthru与system的区别,passthru直接将结果输出到游览器,不返回任何值,且其可以输出二进制,比如图像数据。第二个参数可选,是状态码。

<?php
header("Content-type:image/gif");
passthru("/usr/bin/ppm2tiff /usr/share/tk8.4/demos/images/teapot.ppm");
?>

4)shell_exec()

原型: string shell_exec ( string $cmd )

说明: 直接执行命令$cmd

<?php
$output = shell_exec('ls -lart');
echo "<pre>$output</pre>";
?>

方法二:反撇号

原型: 反撇号`(和~在同一个键)执行系统外部命令

说明: 在使用这种方法执行系统外部命令时,要确保shell_exec函数可用,否则是无法使用这种反撇号执行系统外部命令的。

<?php
  echo `dir`;
?>

方法三:用popen()函数打开进程

原型: resource popen ( string $command , string $mode )

说明: 能够和命令进行交互。之前介绍的方法只能简单地执行命令,却不能与命令交互。有时须向命令输入一些东西,如在增加系统用户时,要调用su来把当前用户换到root用户,而su命令必须要在命令行上输入root的密码。这种情况下,用之前提到的方法显然是不行的。

popen( )函数打开一个进程管道来执行给定的命令,返回一个文件句柄,可以对它读和写。返回值和fopen()函数一样,返回一个文件指针。除非使用的是单一的模式打开(读or写),否则必须使用pclose()函数关闭。该指针可以被fgets(),fgetss(),fwrite()调用。出错时,返回FALSE。

<?php
error_reporting(E_ALL);
 
/* Add redirection so we can get stderr. */
$handle = popen('/path/to/executable 2>&1', 'r');
echo "'$handle'; " . gettype($handle) . "\n";
$read = fread($handle, 2096);
echo $read;
pclose($handle);
?>

二、关于安全问题:

由于PHP基本是用于WEB程序开发的,所以安全性成了人们考虑的一个重要方面。

于是PHP的设计者们给PHP加了一个门:安全模式。

在php.ini中的设置safe_mode = On

如果运行在安全模式下,那么PHP脚本中将受到如下四个方面的限制:

执行外部命令
在打开文件时有些限制
连接MySQL数据库
基于HTTP的认证

在安全模式下,只有在特定目录中的外部程序才可以被执行,对其它程序的调用将被拒绝。这个目录可以在php.ini文件中用safe_mode_exec_dir指令,或在编译PHP 是加上?with-exec-dir选项来指定,默认是/usr/local/php/bin。

当你使用这些函数来执行系统命令时,可以使用escapeshellcmd()和escapeshellarg()函数阻止用户恶意在系统上执行命令,escapeshellcmd()针对的是执行的系统命令,而escapeshellarg()针对的是执行系统命令的参数。这两个参数有点类似addslashes()的功能。

三、关于超时问题

当执行命令的返回结果非常庞大时,可以需要考虑将返回结果输出至其他文件,再另行读取文件,这样可以显著提高程序执行的效率。

如果要执行的命令要花费很长的时间,那么应该把这个命令放到系统的后台去运行。但在默认情况下,象system()等函数要等到这个命令运行完才返回(实际上是在等命令的输出结果),这肯定会引起PHP脚本的超时。解决的办法是把命令的输出重定向到另外一个文件或流中,如:

<?php
system("/usr/local/bin/order_proc > /tmp/abc ");
?>

但我调用的DOS命令需要几分钟的时间,而且为了批处理不能简单的把结果写入文件了事,要顺序执行以下的程序

PHP设置了调用系统命令的时间限制,如果调用命令超时,虽然这个命令还是会被执行完,但PHP没有得到返回值,被终止了(最可恨的是,不显示任何错误)

修改php.ini并重启Apache以允许系统命令运行更长的时间

max_execution_time = 600

四、关于PHP运行linux环境中命令出现的问题

php一般是以apache用户身份去执行的,也可能是www用户,把apache加入到存储你文件的父文件夹属组里去,然后改该父文件夹权限为775,这样属组成员就有写的权限,而apache属于这个组就可以改写该目录下所有文件的权限。

例如:chown www:www dirName

这样dirName目录才能被php所控制

注意:改apache/php的运行用户方法不安全

另外即使文件或目录已经是www,php的安全设置也都照顾到,一些自己安装linux的命令仍然可能无法运行,例如我曾经安装的ffmpeg软件,原因就是linux的运行权限问题,即使ffmpeg有www权限设置,但由于ffmpeg所依赖的库文件是不允许www用户运行,所以php运行此程序仍然会报127或126错误,通过 ldd 命令可以查看ffmpeg命令依赖的库情况。

这个时候就必须对ffmpeg的依赖库经行设置。具体方法属于linux管理中的话题,这里不就讨论了。

以上这篇PHP在linux上执行外部命令的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
php输出xml格式字符串(用的这个)
Jul 12 PHP
完美解决令人抓狂的zend studio 7代码提示(content Assist)速度慢的问题
Jun 20 PHP
析构函数与php的垃圾回收机制详解
Oct 28 PHP
php获取从百度搜索进入网站的关键词的详细代码
Jan 08 PHP
ThinkPHP框架实现session跨域问题的解决方法
Jul 01 PHP
PHP中使用Imagick读取pdf并生成png缩略图实例
Jan 21 PHP
thinkphp利用模型通用数据编辑添加和删除的实例代码
Nov 20 PHP
PHP mongodb操作类定义与用法示例【适合mongodb2.x和mongodb3.x】
Jun 16 PHP
PHP实现浏览器格式化显示XML的方法示例
Jan 22 PHP
PHP封装的mysqli数据库操作类示例
Feb 16 PHP
Laravel 中使用简单的方法跟踪用户是否在线(推荐)
Oct 30 PHP
php设计模式之观察者模式实例详解【星际争霸游戏案例】
Mar 30 PHP
php获取指定数量随机字符串的方法
Feb 06 #PHP
PHP严重致命错误处理:php Fatal error: Cannot redeclare class or function
Feb 05 #PHP
PHP中使用OpenSSL生成证书及加密解密
Feb 05 #PHP
PHP的中使用非缓冲模式查询数据库的方法
Feb 05 #PHP
php+redis在实际项目中HTTP 500: Internal Server Error故障排除
Feb 05 #PHP
php实现给二维数组中所有一维数组添加值的方法
Feb 04 #PHP
PHP进制转换实例分析(2,8,16,36,64进制至10进制相互转换)
Feb 04 #PHP
You might like
PHP新手上路(十)
2006/10/09 PHP
学习php分页代码实例
2013/10/24 PHP
php中OR与|| AND与&amp;&amp;的区别总结
2013/10/26 PHP
PHP之密码加密的几种方式
2015/07/29 PHP
用javascript实现的图片马赛克后显示并切换加文字功能
2007/04/21 Javascript
Pro JavaScript Techniques学习笔记
2010/12/28 Javascript
关于JavaScript中原型继承中的一点思考
2012/07/25 Javascript
jQuery实现的一个tab切换效果内部还嵌有切换
2014/08/10 Javascript
AngularJS的表单使用详解
2015/06/17 Javascript
Bootstrap开发实战之第一次接触Bootstrap
2016/06/02 Javascript
JS判断是否在微信浏览器打开的简单实例(推荐)
2016/08/24 Javascript
jQuery异步提交表单实例
2017/05/30 jQuery
ionic2屏幕适配实现适配手机、平板等设备的示例代码
2017/08/11 Javascript
微信小程序实现传参数的几种方法示例
2018/01/10 Javascript
Vue2.X 通过AJAX动态更新数据
2018/07/17 Javascript
JavaScript中this关键字用法实例分析
2018/08/24 Javascript
微信小程序自定义支持图片的弹窗
2020/12/21 Javascript
Nodejs 数组的队列以及forEach的应用详解
2021/02/25 NodeJs
Python对两个有序列表进行合并和排序的例子
2014/06/13 Python
实例探究Python以并发方式编写高性能端口扫描器的方法
2016/06/14 Python
Go/Python/Erlang编程语言对比分析及示例代码
2018/04/23 Python
通过实例解析python描述符原理作用
2020/01/22 Python
Shopee印度尼西亚:东南亚与台湾市场最大电商平台
2018/06/17 全球购物
司法所长先进事迹
2014/06/02 职场文书
大学生学习计划书
2014/09/15 职场文书
房屋所有权证明
2014/10/20 职场文书
领导干部“四风”查摆问题个人整改措施
2014/10/28 职场文书
硕士毕业论文导师评语
2014/12/31 职场文书
老员工辞职信范文
2015/05/12 职场文书
推广普通话的宣传语
2015/07/13 职场文书
校长新学期致辞
2015/07/30 职场文书
结婚喜宴迎宾词
2015/08/10 职场文书
班主任班级管理心得体会
2016/01/07 职场文书
Pandas||过滤缺失数据||pd.dropna()函数的用法说明
2021/05/14 Python
浏览器常用基本操作之python3+selenium4自动化测试(基础篇3)
2021/05/21 Python
【海涛dota解说】DCG联赛第一周 LGD VS DH
2022/04/01 DOTA