使用会话数据从另一个脚本运行脚本

use*_*465 3 php session exec

我正在尝试让脚本启动另一个脚本并将其数据放入会话变量中以供另一个脚本使用。问题是当第二个脚本 data.php 运行时,它似乎无法访问会话变量。它们是空白的,没有任何内容写入 data.txt。如果我自己运行 data.php,它会写入$_SESSION["data"]正确设置的最后一个值,但不会在它与 exec 一起运行时写入。我不确定问题是什么。有任何想法吗?

输入.php:

session_start();
$_SESSION["data"] = "Data!";
exec("/usr/bin/php /path/to/data.php > /dev/null 2>&1 &");
Run Code Online (Sandbox Code Playgroud)

数据.php:

session_start();
$fp = fopen('data.txt', 'w');
fwrite($fp, $_SESSION["data"]);
fclose($fp);
Run Code Online (Sandbox Code Playgroud)

编辑:我试图从 input.php 内部启动 data.php 并在 data.php 中访问 input.php 中的变量。

Dav*_*dom 5

您可以将数据作为命令行参数传递给使用 CLI 运行的 PHP 脚本。此数据将可用于$argv数组中的子脚本。

输入.php:

$arg = "Data!";
exec("/usr/bin/php /path/to/data.php ".escapeshellarg($arg)." > /dev/null 2>&1 &");
Run Code Online (Sandbox Code Playgroud)

数据.php

$fp = fopen('data.txt', 'w');
fwrite($fp, $argv[1]);
fclose($fp);
Run Code Online (Sandbox Code Playgroud)

一些注意事项:

  • 传递每个参数 以确保用户无法将命令注入您的 shell 非常重要。这也将阻止参数中的特殊 shell 字符破坏您的脚本。escapeshellarg()
  • $argv是一个全局变量,而不是像and那样的全局变量。它仅在全局范围内可用。如果需要在函数范围内访问它,可以使用. 这是我认为使用可接受的唯一情况,尽管最好在启动时处理全局范围内的参数,并将它们作为参数传递给范围。$_GET$_POST$GLOBALS['argv']$GLOBALS
  • $argv是一个索引为 0 的数组,但第一个“参数”在$argv[1]. $argv[0]始终包含当前正在执行的脚本的路径,因为$argv实际上表示传递给 PHP 二进制文件的参数,其中脚本的路径是第一个。
  • 来自命令行参数的值始终具有字符串类型。PHP 的类型非常混乱,因此对于标量值这无关紧要,但是您(相当明显)无法通过命令行传递向量类型(对象、数组、资源)。可以通过使用 egserialize()或对对象和数组进行编码来传递对象和数组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 &");
Run Code Online (Sandbox Code Playgroud)

数据.php

$arg = unserialize($argv[1]);
$fp = fopen('data.txt', 'w');
foreach ($arg as $val) {
  fwrite($fp, "$val\n");
}
fclose($fp);
Run Code Online (Sandbox Code Playgroud)

以下是我用来简化此过程的剪辑集合中的几个函数:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

如果您需要传递大量数据(大于getconf ARG_MAX字节输出),您应该将序列化数据转储到文件中,并将文件路径作为命令行参数传递。