2

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_row = 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.

6
  • 1
    not 100% sure whats going on here but why the double exec()? Commented Nov 9, 2010 at 12:28
  • don't quite understand the problem, but: you define $out_file and use $out Commented Nov 9, 2010 at 12:29
  • 1
    error_reporting(0); is the root of all your problem. Should be at least E_ALL, not zero. Commented Nov 9, 2010 at 12:34
  • @Brady, that part of the code is been give to me by someone on stackoverflow as well and I tried it with only one but doesn't output anything. so not sure what the say on that one. Thx. Commented Nov 9, 2010 at 12:53
  • @Col. Shrapnel I'll look into that, newbie here. The script that I am trying to put together is well above my knowledge of php and javascript but I am confident that with some help I'll manage to finish it. Thx. Commented Nov 9, 2010 at 12:55

3 Answers 3

2

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());
}
Sign up to request clarification or add additional context in comments.

5 Comments

I already tried "while" but couldn't get it to work so thought I might give a shot to "foreach" but same thing.
I tried the updated code but it returns 0 as the PID number for the selected items. Thanks.
My initial logic was: get the selected items with POST, get from the database the URL addresses, run the command and get the PID number so I can use it, if I would like to stop the process later on. The double exec are needed because if I try with only one, it doesn't output anything.
@Chris19: you actively suppress the first command's output by sending it to /dev/null. Your second exec literally runs something like 0 as a command -- I can't imagine how this is what you actually want to do. Why don't you show us the real commands you want to run without any PHP code, and then show us the output of those commands in the terminal (at least the first line) -- and show those things by editing the question rather than in a comment.
I tried it with the new code Mark, same thing. the PID value in the databse for that specific item is 0.
0

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());
}

1 Comment

can you please give me an example on how to use that identifier? Thx.
0

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

9 Comments

I tried with "while" already and does the same thing, so I though I should try foreach, but that's not working either, so I am bit lost.
@Chris19 before trying anything you should realize what you want to get. Then compare expected result with actual one.
As I said below, this is what I am trying to accomplish: "My initial logic was: get the selected items with POST, get from the database the URL addresses, run the command and get the PID number so I can use it, if I would like to stop the process later on. The double exec are needed because if I try with only one, it doesn't output anything" Thanks.
Updated with how i would write it, cleaned the code etc. see if that works.
I think there is a problem with the code, because it doesn't even get executed, 500 internal server error.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.