您可以将数据作为命令行参数传递给使用 CLI 运行的 PHP 脚本。该数据将可用于$argv
数组中的子脚本。
输入.php:
$arg = "Data!";
exec("/usr/bin/php /path/to/data.php ".escapeshellarg($arg)." > /dev/null 2>&1 &");
数据.php
$fp = fopen('data.txt', 'w');
fwrite($fp, $argv[1]);
fclose($fp);
几点注意事项:
- 传递每个参数 以确保用户无法将命令注入到您的 shell 中,这一点很重要。这也将阻止参数中的特殊 shell 字符破坏您的脚本。
escapeshellarg()
$argv
是一个全局变量,而不是像and这样的超全局变量。它仅在全局范围内可用。如果需要在函数范围内访问它,可以使用. 这是我认为使用可接受的唯一情况,尽管最好在启动时处理全局范围内的参数,并将它们作为参数传递给范围。$_GET
$_POST
$GLOBALS['argv']
$GLOBALS
$argv
是一个 0 索引数组,但第一个“参数”在$argv[1]
. $argv[0]
总是包含当前正在执行的脚本的路径,因为$argv
它实际上代表了传递给 PHP 二进制文件的参数,其中脚本的路径是第一个。
- 命令行参数的值始终具有字符串类型。PHP 的输入非常混乱,因此对于标量值这无关紧要,但您(很明显)不能通过命令行传递向量类型(对象、数组、资源)。
serialize()
可以通过使用例如或编码来传递对象和数组json_encode()
。无法通过命令行传递资源。
编辑在传递我更喜欢使用的向量类型时,serialize()
因为它带有有关对象所属类的信息。
这是一个例子:
输入.php:
$arg = array(
'I\'m',
'a',
'vector',
'type'
);
exec("/usr/bin/php /path/to/data.php ".escapeshellarg(serialize($arg))." > /dev/null 2>&1 &");
数据.php
$arg = unserialize($argv[1]);
$fp = fopen('data.txt', 'w');
foreach ($arg as $val) {
fwrite($fp, "$val\n");
}
fclose($fp);
以下是我用来简化此过程的剪辑集合中的几个函数:
// In the parent script call this to start the child
// This function returns the PID of the forked process as an integer
function exec_php_async ($scriptPath, $args = array()) {
$cmd = "php ".escapeshellarg($scriptPath);
foreach ($args as $arg) {
$cmd .= ' '.escapeshellarg(serialize($arg));
}
$cmd .= ' > /dev/null 2>&1 & echo $$';
return (int) trim(exec($cmd));
}
// At the top of the child script call this function to parse the arguments
// Returns an array of parsed arguments converted to their correct types
function parse_serialized_argv ($argv) {
$temp = array($argv[0]);
for ($i = 1; isset($argv[$i]); $i++) {
$temp[$i] = unserialize($argv[$i]);
}
return $temp;
}
If you need to pass a large amount of data (larger than the output of getconf ARG_MAX
bytes) you should dump the serialized data to a file and pass the path to the file as a command line argument.