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

时间:2012-08-01 07:51:50

标签: php session exec

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

input.php:

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

data.php:

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

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

2 个答案:

答案 0 :(得分:3)

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

input.php:

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

data.php

$fp = fopen('data.txt', 'w');
fwrite($fp, $argv[1]);
fclose($fp);

几点说明:

  • 通过 escapeshellarg() 传递每个参数非常重要,以确保用户无法将命令注入您的shell 。这也将阻止参数中的特殊shell字符破坏您的脚本。
  • $argv全局变量,而非超全局,如$_GET$_POST。它仅适用于全球范围。如果需要在函数范围内访问它,可以使用$GLOBALS['argv']。这是我考虑使用$GLOBALS可接受的唯一情况,尽管在启动时处理全局范围中的参数仍然更好,并将它们作为参数传递给作用域。
  • $argv是一个0索引数组,但第一个“参数”在$argv[1]中。 $argv[0]始终包含当前正在执行的脚本的路径,因为$argv实际上表示传递给PHP二进制文件的参数,其中脚本的路径是第一个。
  • 命令行参数中的值始终具有字符串类型。 PHP的输入非常混杂,所以标量值无关紧要,但你(很明显)不能通过命令行传递矢量类型(对象,数组,资源)。可以通过用例如对象和数组进行编码来传递对象和数组。 serialize()json_encode()。无法通过命令行传递资源。

编辑当传递矢量类型时,我更喜欢使用serialize(),因为它带有关于对象所属的类的信息。

以下是一个例子:

input.php:

$arg = array(
  'I\'m',
  'a',
  'vector',
  'type'
);
exec("/usr/bin/php /path/to/data.php ".escapeshellarg(serialize($arg))." > /dev/null 2>&1 &");

data.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字节的输出),则应将序列化数据转储到文件中,并将路径作为命令行参数传递给文件。

答案 1 :(得分:0)

您可以尝试对$ _SESSION [“data”]进行urlencode并将其作为参数传递给CLI脚本:

脚本1

$URLENCODED = urlencode($_SESSION["data"]);
exec("/usr/bin/php /path/to/data.php " . $URLENCODED . " > /dev/null 2>&1 &")

脚本2

$args = urldecode($argv[1]);   // thanks for the reminder daverandom ..forgot to do this :)

fwrite($fp, $args);
相关问题