php - 使用 session 数据从另一个脚本运行脚本

标签 php session exec

我正在尝试让一个脚本启动另一个脚本并将其数据放入一个 session 变量中以供另一个脚本使用。问题是当第二个脚本 data.php 运行时,它似乎无法访问 session 变量。它们是空白的,没有任何内容写入 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 &");

数据.php:

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

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

最佳答案

您可以将数据作为命令行参数传递给使用 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);

一些注意事项:

  • 传递每个参数很重要 escapeshellarg() 确保用户无法将命令注入(inject)您的 shell。这也将阻止参数中的特殊 shell 字符破坏您的脚本。
  • $argv 是一个全局变量,而不是像$_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;
}

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

关于php - 使用 session 数据从另一个脚本运行脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11754846/

相关文章:

python - 为什么使用 timeit 或 exec 函数时,不会在提供的全局命名空间中搜索函数内的变量?

javascript - 尝试创建二叉树,但我的下线顺序不正确

php - 表单未填写表格并返回空白页

PHP: session.auto_start

使用 pgrep 时 Node.js 命令出现错误

go - 如何清除在 Golang 的 exec.Command 中设置为 StdOut 的 bytes.Buffer(b.Reset 不起作用)

PHP 数组效率与 mySQL 查询

php - 如何显示表中的列

php - 为什么我必须取消所有 session 变量?

php - 在 $_SESSION 中存储 Doctrine 对象