开发者

php foreach: problem with a script

I am having a problem with the following script, it only writes in the database the first PID number but it executes both commands:

<?php
error_reporting(0);

include_once "config/mysql.php";

// the path
$path = "PATH=$PATH:/share/MD0_DATA/.qpkg/Optware/bin:";

//random number for the log file name
$random = rand(1,500000);

//initial download location
$init_loc="/share/MD0_DATA/Qdownload/plowshare";

$items = rtrim($_POST['items'],",");
$sql = mysql_query("SELECT url FROM plow WHERE id IN ($items)") or die ('Error: ' . mysql_error());
$db_r开发者_运维技巧ow = mysql_fetch_assoc($sql);
foreach ($db_row as $value) { 
  //random number for the log file name
  $random = rand(1,500000);
  //log file name
  $out_file = '/share/MD0_DATA/Qdownload/plowshare/Logs/log'.$random.'.txt';
  //command 1
  $command = exec("($path" . " nohup /opt/bin/plowdown -o '$init_loc' " . "'$value' 2> " . "'$out_file' > /dev/null &);" . "echo $$;", $out); 
  exec($command, $out);
  $query = mysql_query("UPDATE plow SET state = 'Active', pid = '$out[0]' WHERE id IN ($items)") or die ('Error: ' . mysql_error());
 }
mysql_close();

?>

$items comes from a multiselection I make in flexigrid.

LE: If I run this command thru Putty:

nohup /opt/bin/plowdown -o /share/Qdownload/plowshare http://www.megadownloadlink.com 2> /share/Qdownload/plowshare/Logs/log342342.txt > /dev/null &

I get the PID number of that process PLOWDOWN, I can see this in my process list with TOP.

so I need to a run the command for every URL that is selected and input the PID number in the database in case I want to stop the process later on.

Hope this makes sense.


mysql_fetch_assoc returns a single row at a time where the columns form an associative array. Your code, right now, appears to loop on the columns, but you're only selecting one column. Thus it would be equivalent for you to remove the foreach loop and simply say $value = $db_row['url'];. But that's still not your desired behavior.

When you run a query, you should loop over the results until there are no more results. That would be something like:

$sql = mysql_query("SELECT url FROM plow WHERE id IN ($items)")
       or die ('Error: ' . mysql_error());
while($db_row = mysql_fetch_assoc($sql)){
    // execute per result stuff, $db_row['url'] gives you the `url` column

}

This line: while($db_row = mysql_fetch_assoc($sql)) will run until $db_row holds a null value, and it will hold a null value whenever there are no more results left to process. Each time it holds a non-null value, the body of the loop will execute. Now, as for why you're only writing one PID to the database, well, it's because you're only getting one URL out of the database. You need to loop over all URLs.

Besides that, your exec calls don't match your test case, here's a call that matches your test case:

exec("{$path} nohup /opt/bin/plowdown -o {$init_loc} {$db_row['url']} 2> $out_file > /dev/null &", $out); 

Putting this all together we yield something like this:

$sql = mysql_query("SELECT url FROM plow WHERE id IN ($items)")
       or die ('Error: ' . mysql_error());
while($db_row = mysql_fetch_assoc($sql)){
    // execute per result stuff, $db_row['url'] gives you the `url` column
    $random = rand(1,500000);
    //log file name
    $out_file = '/share/MD0_DATA/Qdownload/plowshare/Logs/log'.$random.'.txt';

    exec("{$path} nohup /opt/bin/plowdown -o {$init_loc} {$db_row['url']} 2> $out_file > /dev/null &", $out);

    mysql_query("UPDATE plow SET state = 'Active', pid = '{$out[0]}' WHERE id IN ($items)") 
        or die ('Error: ' . mysql_error());
}


Since your query is using the where in items it will effect the same records no matter how many times it runs. If you wish a different pid you will want to utilize an identifier from the record you are looping over.

Also I would recommend using time() instead of your random number which will assure uniqueness.

$sql = mysql_query("SELECT url FROM plow WHERE id IN ($items)")
       or die ('Error: ' . mysql_error());
while($db_row = mysql_fetch_assoc($sql)){
    // execute per result stuff, $db_row['url'] gives you the `url` column
    $random = time();
    //log file name
    $out_file = '/share/MD0_DATA/Qdownload/plowshare/Logs/log'.$random.'.txt';
    $command = exec("($path" . " nohup /opt/bin/plowdown -o '$init_loc' " . "'$value' 2> " . "'$out_file' > /dev/null &);" . "echo $$;", $out1); 
    exec($command, $out2);

    // first exec saved output to $out1
    mysql_query("UPDATE plow SET state = 'Active', pid = '$out1[0]' WHERE id IN ($items)") 
        or die ('Error: ' . mysql_error());
    // second exec saved output to $out2
    mysql_query("UPDATE plow SET state = 'Active', pid = '$out2[0]' WHERE id = $db_row['id']") 
        or die ('Error: ' . mysql_error());
}


Should be a while loop:

while($db_row = mysql_fetch_assoc($sql))
{
    //Your Code here
}

Update: How I would write the following:

error_reporting(0);

include_once "config/mysql.php";

// the path
$path = "PATH=$PATH:/share/MD0_DATA/.qpkg/Optware/bin:";

//initial download location
$init_loc="/share/MD0_DATA/Qdownload/plowshare";

$items = mysql_real_escape_string(rtrim($_POST['items'],","));

$query = mysql_query("SELECT url FROM plow WHERE id IN (" . $items .")");
if($query)
{
    while($row = mysql_fetch_assoc($query))
    {
        $out_file = '/share/MD0_DATA/Qdownload/plowshare/Logs/log'.rand().'.txt';
        while(file_exists($out_file))
        {
            $out_file = '/share/MD0_DATA/Qdownload/plowshare/Logs/log'.rand().'.txt';
        }

        $command = "(" . $path . "  nohup /opt/bin/plowdown -o ".$init_loc." " . $value . " 2> " . $out_file . " > /dev/null &);";

       exec($command,$out);

       $update = "UPDATE plow SET state = 'Active', pid = '" . $out[0] . "' WHERE id IN ( " . $items . " )";

       if(mysql_query($update))
       {
           echo 'Updated: ' . mysql_insert_id() . "\n";
       }
    }
}
mysql_close();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜