PHP - запуск скрипта внутри цикла - PullRequest
0 голосов
/ 14 ноября 2011

Я пытаюсь запустить скрипт изнутри скрипта и получить нижеприведенное сообщение, которое, похоже, не работает. Я в основном получаю данные из базы данных, перебираю каждую строку и запускаю скрипт, который будет генерировать XML на основе этих данных.

set_time_limit(0);

//connect to database
$msSqlDB = new mySqlConnect('store');

$select = "SELECT * FROM FStores"; 

$run = mysql_query($select);
while($row = mysql_fetch_array($run)){
    exec('/var/www/web/shop_xml/index.php?shopKeeper=$row[SKID]&shop=1');
}

Каков наилучший способ сделать это? Будет ли 2-й ряд ждать, пока 1-й ряд не будет успешно выполнен, или может быть запущен одновременно несколько раз? Большое спасибо за любые советы с этим.

Ответы [ 6 ]

4 голосов
/ 14 ноября 2011

Вам нужно сделать что-то вроде этого:

exec('php /var/www/web/shop_xml/index.php "'.escapeshellarg($row['SKID']).'" "1" > /dev/null 2>&1 &');

Затем в вашем index.php скрипте:

<?php

  $shopKeeper = $argv[1];
  $shop = $argv[2];

  // ... do stuff

То, что вы пытались сделать, это использовать строку HTTP-запросав файловой системе вызвать, который не будет работать.Вам необходимо передать данные в качестве аргументов командной строки, как в терминале.Затем вы можете получить данные из $argv.

. Вам нужно запустить команду с php, иначе ядро ​​(скорее всего, если вы не добавите хэш-банг и не установите разрешения) не будет знать, как выполнитьсценария или у вас есть права на это.

Если вы добавите > /dev/null 2>&1 &, команды будут выполняться асинхронно, то есть вам не придется ждать завершения последней команды, прежде чем вы сможете вызвать другую.Будьте осторожны с этим, однако, вы можете получить много процессов, если ваш запрос возвращает много строк.

Чтобы избежать этого, вы можете сделать что-то вроде:

<?php

  // Number of records to process at a time
  $perBatch = 5;

  set_time_limit(0);

  //connect to database
  $msSqlDB = new mySqlConnect('Freewebstore');

  // Get the number of records in the table
  $query = "SELECT count(*) FROM FacebookStores";
  $result = mysql_fetch_row(mysql_query($select));
  $count = $result[0];

  for ($i = 0; $i < $count; $i += $perBatch) {

    // Get $perBatch records from the DB
    $query = "SELECT * FROM FacebookStores LIMIT $i,$perBatch";
    $result = mysql_query($select);

    for ($j = 1; $row = mysql_fetch_array($result); $j++) {

      // Base command
      $command = 'php /var/www/web/shop_xml/index.php "'.escapeshellarg($row['SKID']).'" "1"';

      // Run all except the last asynchronously
      if ($j < $perBatch) {
        $command .= ' > /dev/null 2>&1 &';
      }

      exec($command);

    }

  }

Это получит $perBatch Записывает данные из БД одновременно и обрабатывает все, кроме последнего, асинхронно.Это приведет к тому, что они будут обрабатывать примерно $perBatch записей за один раз, и поможет избежать большого количества процессов, потребляющих ресурсы сервера.

В качестве дополнительного примечания вы, кажется, используете нечетное сочетание OOКод БД и процедурный код БД - вам следует придерживаться одного или другого, чтобы избежать путаницы.

2 голосов
/ 14 ноября 2011

Ответ Джорджа Р отвечает на ваш вопрос буквально; как запустить скрипт как есть из командной строки. Позвольте мне, в свою очередь, предложить несколько альтернатив.

Прежде всего, ваш скрипт shop_xml / index.php может проверить, вызывается ли он из командной строки, и соответственно прочитать аргументы. Таким образом:

if( php_sapi_name() == 'cli' ) {
   // you would, of course, want to escape these for malicious code!
   $shopKeeper = $argv[1];
   $shop = $argv[2];
}
else {
   $shopKeeper = $_GET['shopKeeper'];
   $shop = $_GET['shop'];
}

Тогда вы бы назвали свою команду следующим образом:

$arg = escapeshellarg($row['SKID']);
exec( "/var/www/web/shop_xml/index.php \"$arg\" 1" );

Однако гораздо лучшим решением было бы взять код в index.php, который вызывается из CLI, и переместить его во включаемый файл (например, functions.php), поместив его внутри функции, например:

function processShopRow($showKeeper, $shop) {
   // stuff that used to be in index.php goes here
}

Теперь и в index.php, и в коде, запускаемом из CLI, вы включите и выполните код следующим образом:

include('functions.php');
set_time_limit(0);

//connect to database
$msSqlDB = new mySqlConnect('Freewebstore');

$select = "SELECT * FROM FacebookStores"; 

$run = mysql_query($select);
while($row = mysql_fetch_array($run)){
    processShopRow($row['SKID'], 1);
}
1 голос
/ 14 ноября 2011

Вы пробовали использовать это:

exec("/var/www/web/shop_xml/index.php?shopKeeper=$row[SKID]&shop=1");

вместо твоего оригинала? Одинарные кавычки ' не позволяют вам оценивать встроенные переменные или объекты php в нем. Вам придется использовать двойные кавычки " - Можете ли вы попробовать это?

1 голос
/ 14 ноября 2011

ваш скрипт не работает, потому что

exec('/var/www/web/shop_xml/index.php?shopKeeper=$row[SKID]&shop=1');

сделать его

exec("/var/www/web/shop_xml/index.php?shopKeeper=$row[SKID]&shop=1");

одинарные кавычки не могут содержать переменные внутри.

0 голосов
/ 14 ноября 2011

exec () пытается вызвать программу в файловой системе вашего сервера, точно так же, как если бы вы вводили параметр exec () в командной строке. Оболочки не знают, что делать с URL-адресом, поэтому вы получите сообщение об ошибке «Нет подходящих файлов», так как ? в URL будет рассматриваться как подстановочный знак оболочки.

Если вы хотите запросить URL, вам нужно как минимум сделать

$output = file_get_contents("/var/www/etc....");

и PHP выполнит полный HTTP-запрос для вас.

0 голосов
/ 14 ноября 2011

В вашей команде exec вам нужно либо запустить скрипт, используя lynx (браузер командной строки) или PHP CLI. Вы также должны ссылаться на домен, а не на полный путь:

exec("php http://domain.com/index.php?shopKeeper=$row[SKID]&shop=1");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...