簡體   English   中英

PHP-在循環中運行腳本

[英]PHP - running script within a loop

我試圖從一個腳本中運行一個腳本,並有以下似乎無法正常工作。 我基本上是從數據庫中獲取大量數據,遍歷每一行並運行一個腳本,該腳本將基於該數據生成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');
}

最好的方法是什么? 第二行會等到第一行成功執行后還是可以同時運行多個? 非常感謝您的任何建議。

您需要執行以下操作:

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啟動命令,否則內核(很可能,除非您添加hashbang並設置權限)不知道如何執行腳本或具有執行該腳本的權限。

如果添加> /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記錄,並異步處理除最后一個記錄外的所有記錄。 這將導致它們一次大約處理$perBatch記錄,並有助於避免大量進程$perBatch服務器資源。

附帶說明一下,您似乎混合使用了OO DB代碼和過程DB代碼的奇怪組合-您應該堅持一個或另一個以避免混淆。

George P的回答從字面上回答了您的問題; 如何從命令行按原樣運行腳本。 接下來讓我提供一些替代方案。

首先,您的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" );

但是,更好的解決方案是將要從CLI調用的index.php中的代碼拿走,然后將其移到include(如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);
}

您的腳本不起作用,因為

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");

單引號內不能包含變量。

您是否嘗試過使用此功能:

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

而不是原來的? 單引號'不允許您評估其中的嵌入式變量或php對象。 您必須使用雙引號" -您能嘗試一下嗎?

在exec命令中,您需要使用lynx(命令行瀏覽器)或PHP CLI運行腳本。 您還應該引用域,而不是完整路徑:

exec("php http://domain.com/index.php?shopKeeper=$row[SKID]&shop=1");

exec()嘗試調用服務器文件系統上的程序,就像在shell提示符下鍵入exec()參數一樣。 外殼程序不知道如何處理URL,因此您將收到“沒有匹配的文件”錯誤,如? 網址中的內容將被視為外殼通配符。

如果您想請求網址,則至少需要

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

並且PHP將為您執行完整的HTTP請求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM