简体   繁体   English

PHP-在循环中运行脚本

[英]PHP - running script within a loop

I am trying to run a script from within a script and have the below which does not seem to work. 我试图从一个脚本中运行一个脚本,并有以下似乎无法正常工作。 I am basically getting a load of data from a database, looping through each row and running a script that will generate XML based on that data. 我基本上是从数据库中获取大量数据,遍历每一行并运行一个脚本,该脚本将基于该数据生成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');
}

Whats the best possible way to do this? 最好的方法是什么? Will the 2nd row wait until the 1st row is successfully executed or can multiple run at the same time? 第二行会等到第一行成功执行后还是可以同时运行多个? Many thanks for any advice with this. 非常感谢您的任何建议。

You need to do something like this: 您需要执行以下操作:

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

Then, in your index.php script: 然后,在您的index.php脚本中:

<?php

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

  // ... do stuff

What you have attempted to do is use a HTTP query string in a file system invoke, which will not work. 您试图做的是在文件系统调用中使用HTTP查询字符串,该字符串不起作用。 You need to pass the data as command-line arguments, like you would in a terminal. 您需要像在终端中一样将数据作为命令行参数传递。 Then, you can get the data from $argv . 然后,您可以从$argv获取数据。

You need to start the command with php otherwise the kernel will (most likely, unless you add a hashbang and set permissions) not know how to execute the script, or have permissions to do it. 您需要使用php启动命令,否则内核(很可能,除非您添加hashbang并设置权限)不知道如何执行脚本或具有执行该脚本的权限。

If you add > /dev/null 2>&1 & the commands will be run asynchronously, ie you will not have to wait for the last command to finish before you can invoke another. 如果添加> /dev/null 2>&1 &这些命令将异步运行,即,您不必等待最后一个命令完成就可以调用另一个命令。 Be carefull with this though, you could end up with many processes if your query returns many rows. 但是请小心,如果查询返回许多行,可能会导致许多过程。

To avoid this, you could do somthing like: 为了避免这种情况,您可以执行以下操作:

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

    }

  }

This would get $perBatch records from the DB at a time, and process all but the last asynchronously. 这将$perBatch从数据库获取$perBatch记录,并异步处理除最后一个记录外的所有记录。 This would result in them being processed roughly $perBatch records at a time, and help to avoid a large number of processes eating server resources. 这将导致它们一次大约处理$perBatch记录,并有助于避免大量进程$perBatch服务器资源。

As a side note, you seem to be using an odd mix of OO DB code and procedural DB code - you should stick to one or the other to avoid confusion. 附带说明一下,您似乎混合使用了OO DB代码和过程DB代码的奇怪组合-您应该坚持一个或另一个以避免混淆。

The answer by George P answers your question literally; George P的回答从字面上回答了您的问题; how to run the script as-is from the command line. 如何从命令行按原样运行脚本。 Let me in turn offer some alternatives. 接下来让我提供一些替代方案。

First of all, your shop_xml/index.php script could check to see if it is being called from command line and read arguments accordingly. 首先,您的shop_xml / index.php脚本可以检查是否从命令行调用它,并相应地读取参数。 Thus: 从而:

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'];
}

Then you would call your command as follows: 然后,您将按以下方式调用命令:

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

However, a far better solution would be to take the code in index.php which is being called from the CLI and move it to an include (like functions.php), placing it inside a function like so: 但是,更好的解决方案是将要从CLI调用的index.php中的代码拿走,然后将其移到include(如functions.php)中,然后将其放入如下函数中:

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

Now, in both index.php and in the code run from the CLI, you will include and run the code as follows: 现在,在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);
}

your script is not working becuase 您的脚本不起作用,因为

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

make it 做了

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

single quotes can't have variables inside them. 单引号内不能包含变量。

Have you tried using this: 您是否尝试过使用此功能:

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

instead of your original? 而不是原来的? The single quotes ' don't allow you to evaluate embedded variables or php objects in it. 单引号'不允许您评估其中的嵌入式变量或php对象。 You'll have to use the double quotes " --Could you try that out? 您必须使用双引号" -您能尝试一下吗?

In your exec command you need to either run the script using lynx (command line browser) or the PHP CLI. 在exec命令中,您需要使用lynx(命令行浏览器)或PHP CLI运行脚本。 You also should reference the domain, not the full path: 您还应该引用域,而不是完整路径:

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

exec() attempts to invoke a program on your server's file system, exactly as if you'd typed in the exec() parameter at a shell prompt. exec()尝试调用服务器文件系统上的程序,就像在shell提示符下键入exec()参数一样。 Shells do not know what to do with a URL, so you'll get a "no matching files" error, as the ? 外壳程序不知道如何处理URL,因此您将收到“没有匹配的文件”错误,如? in the url will be seen as a shell wildcard. 网址中的内容将被视为外壳通配符。

If you want to request a url, you'd have to at minimum do 如果您想请求网址,则至少需要

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

and PHP will do a full HTTP request for you. 并且PHP将为您执行完整的HTTP请求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM