php执行shell命令,cmd命令(命令管道)

2021-03-10

执行命令方法1

// 返回一个command命令的指针资源,$mode为读写模式(r/w)
$fp = popen('dir', $mode);

// 循环读取命令执行结果,直到feof返回true,表示读取完毕
while (!feof($fp)) {
    // 读取$length字节的数据
    // $data1 = fread($fp, $length);
    
    // 读取一行(碰到换行符或EOF)或$length(默认1K)字节的数据
    $data2 = fgets($fp, $length);

    // 读取一行(碰到换行符或EOF)或$length(默认1K)字节的数据,去掉数据中的HTML和PHP标记($allowable_tags指定不需要去除的标记)
    // $data3 = fgets($fp, $length, $allowable_tags);
}

// 关闭命令的指针,发生错误时返回1
pclose($fp);

执行命令方法2

执行命令并直接输出结果

$descriptorspec = [STDIN, STDOUT, STDOUT];
// 命令在windows下必须在最外层加双引号,否则会执行失败
$cmd = '""findstr" "search" "filename.txt""';
$proc = proc_open($cmd, $descriptorspec, $pipes);
proc_close($proc);

使用命令管道执行命令

// 数组的键表示描述符,数组元素值表示PHP如何将这些描述符传送至子进程。 0表示标准输入(stdin),1表示标准输出(stdout),2 表示标准错误(stderr)。文件描述符的值不限于 0,1 和 2,可以使用任何有效的文件描述符 并将其传送至子进程。这使得你的脚本可以和其他脚本交互操作。
// 数组元素可以是
//      1、包含了要传送至进程的管道的描述信息。第一个元素为描述符类型,第二个元素是针对该描述符的选项。有效的类型有:pipe(第二个元素可以是: r向进程传送该管道的读取端,w向进程传送该管道的写入端),以及 file(第二个元素为文件名)。
//      2、表达一个真实文件描述符的流资源类型 (例如:已打开的文件,一个 socket 端口,STDIN)
$descriptorspec = array(
    0 => array('pipe', 'r'),  // 标准输入,子进程从此管道中读取数据
    1 => array('pipe', 'w'),  // 标准输出,子进程向此管道中写入数据
    2 => array('file', 'C:\Users\Administrator\Desktop\error.txt', 'a') // 标准错误,写入到一个文件
);

$cmd   = 'F:\phpstudy_pro\Extensions\php\php7.3.4nts1\php'; // 以 string 形式执行的命令行。特殊字符必须经过转义,并且使用正确的引号
$cwd   = 'C:\Users\Administrator\Desktop'; // 执行命令的初始工作目录,必须是绝对路径;此参数设置为null表示使用默认值(当前PHP进程的工作目录)
$env   = array('some_option' => 'aeiou'); // 命令所使用的环境变量;此参数设置为null表示使用和当前PHP进程相同的环境变量
$pipes = []; // 索引数组,元素是被执行程序创建的管道对应到PHP这一端的文件指针
// $other_options:指定一些附加选项(使用时参数应为array),包括:
//      suppress_errors(仅用于 Windows 平台):设置为true时抑制本函数产生的错误
//      bypass_shell(仅用于 Windows 平台):设置为true表示绕过cmd.exe shell。
//      blocking_pipes(仅用于 Windows 平台):设置为true表示强制堵塞管道。
//      create_process_group(仅用于 Windows 平台):设置为true表示允许子进程处理 CTRL 事件。
//      create_new_console(仅用于 Windows 平台):表示新进程有一个新的控制台,用于代替父进程的控制台。
$other_options = null; 


// 执行一个命令,失败返回false,成功返回资源
$process = proc_open($cmd, $descriptorspec, $pipes, $cwd, $env, $other_options);

if (is_resource($process)) {

    // $pipes[0]是可以向子进程标准输入写入的句柄
    fwrite($pipes[0], '<?php print_r(123321); ?>');
    fclose($pipes[0]);

    // $pipes[1]可以从子进程标准输出读取的句柄
    var_dump(stream_get_contents($pipes[1]));
    fclose($pipes[1]);

    // var_dump($process);

    // 关闭命令,关闭前需要将所有管道关闭(此例中的$pipes[0]和$pipes[1])
    proc_close($process);
};

执行命令方法3

// 执行$command命令;
// 指定$output时将命令输出记录到$output中(一行输出一个元素),指定$return_var时将命令执行后的状态记录到$return_var中;$return_var可以不指定
exec($command, $output, $return_var);

执行命令方法4

// 通过shell环境执行$cmd命令,返回命令输出;发生错误或没有输出返回null
shell_exec($cmd);

执行命令方法5

// 执行外部程序$command,返回命令输出,如果指定了$return_var,则将状态写入$return_var中
system($command, $return_var);

shell命令参数转码

// 给字符串增加单引号并且转码已经存在单引号(确保安全)
escapeshellarg($arg);

 

{/if}