exec( $cmd.' > /dev/null &')
exec — 执行一个外部程序
语法基础
命令
string exec ( string $command [, array &$output [, int &$return_var ]] )
exec() 执行 command 参数所指定的命令
参数
command:要执行的命令。
output:如果提供了 output 参数, 那么会用命令执行的输出填充此数组, 每行输出填充数组中的一个元素。 数组中的数据不包含行尾的空白字符,例如 \n 字符。 请注意,如果数组中已经包含了部分元素,exec() 函数会在数组末尾追加内容。如果你不想在数组末尾进行追加, 请在传入 exec() 函数之前 对数组使用 unset() 函数进行重置。
return_var:如果同时提供 output 和 return_var 参数, 命令执行后的返回状态会被写入到此变量。命令执行结果的最后一行内容。 如果你需要获取未经处理的全部输出数据, 请使用 passthru() 函数。如果想要获取命令的输出内容, 请确保使用 output 参数。
参考
system() - 执行外部程序,并且显示输出
passthru() - 执行外部程序并且显示原始输出
示例
<?php
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
?>
分析
$cmd = ROOT_PATH .'/script/file.php';
exec( $cmd.' > /dev/null &');
⚠️后台运行的脚本需要使用绝对路径
缺点
这个进程放在shell后台执行了。但这是一个很危险的操作,没人去监管它,可能会造成服务器最后死掉
改进
建议使用popen和pclose代替exec
popen和pclose
语法
popen() 函数打开进程文件指针
说明
popen() 创建一个管道,通过fork或者invoke一个子进程,然后执行command。返回值在标准IO流中,由于是在管道之中,因此数据流是单向的,command只能产生stdout或者读取stdin,因此type只有两个值:‘w’或‘r’。r表示command从管道中读取数据流,而w表示command的stdout输出到管道中。command无法同时读取和输出。popen返回该FIFO数据流的指针
<?php
$file = popen("/bin/ls","r");
//一些要执行的代码
pclose($file);
?>
⚠️popen()必须由pclose()函数关闭,必须由pclose()函数关闭,必须由pclose()函数关闭,而不是fclose()函数(若使用fclose则会产生僵尸进程)。pclose()函数关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态。如果shell不能被执行,则pclose()返回的终止状态与shell已执行exit一样。
参数
type参数只能是读或者写中的一种,得到的返回值(标准I/O流)也具有和type相应的只读或只写类型。如果type是"r"则文件指针连接到command的标准输出;如果type是"w"则文件指针连接到command的标准输入。
command参数是一个指向以NULL结束的shell命令字符串的指针。这行命令将被传到bin/sh并使用-c标志,shell将执行这个命令。
popen()的返回值是个标准I/O流,必须由pclose来终止。前面提到这个流是单向的(只能用于读或写)。向这个流写内容相当于写入该命令的标准输入,命令的标准输出和调用popen()的进程相同;与之相反的,从流中读数据相当于读取命令的标准输出,命令的标准输入和调用popen()的进程相同。
返回值
如果调用fork()或pipe()失败,或者不能分配内存将返回NULL,否则返回标准I/O流。popen()没有为内存分配失败设置errno值。如果调用fork()或pipe()时出现错误,errno被设为相应的错误类型。如果type参数不合法,errno将返回EINVAL。
缺点
使用popen的不好影响是,针对每个popen调用,不仅要启动一个被请求的程序,还要启动一个shell,即每个popen调用将多启动两个进程。