3

スクリプトで別のスクリプトを開始し、そのデータを他のスクリプトが使用できるようにセッション変数に入れようとしています。問題は、2 番目のスクリプト 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 &");

data.php:

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

編集:私はinput.php内からdata.phpを開始しようとしており、data.phpでinput.phpの変数にアクセスできるようにしています。

4

2 に答える 2

4

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()
  • $argvグローバル変数であり、やのようなスーパーグローバルではありません。グローバルスコープでのみ使用できます。関数スコープでアクセスする必要がある場合は、を使用できます。これは、私が許容できるものの使用を検討する唯一の状況ですが、起動時にグローバルスコープで引数を処理し、それらを引数としてスコープに渡す方がよいでしょう。$_GET$_POST$GLOBALS['argv']$GLOBALS
  • $argvは0インデックスの配列ですが、最初の「引数」はにあり$argv[1]ます。実際にはPHPバイナリに渡される引数を表し、スクリプトへのパスが最初である$argv[0]ため、常に現在実行中のスクリプトへのパスが含まれます。$argv
  • コマンドライン引数の値は常に文字列型です。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バイトの出力よりも大きい)を渡す必要がある場合は、シリアル化されたデータをファイルにダンプし、コマンドライン引数としてファイルへのパスを渡す必要があります。

于 2012-08-01T08:10:41.223 に答える
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);
于 2012-08-01T07:59:00.183 に答える