exec() not working as expected in PHP - php

I have a PHP script in which I need to execute a shell script 'add_article.sh' which reads a parameter file and adds the news article contents to a search index (Lemur/Indri).
Executing the 'add_article.sh' script on its own (from the shell) works perfectly, but running it from within the php script I get this:
$blah = exec("./add_article.sh", $out, $ret_val);
echo $out . "<BR />";
echo $ret_val . "<BR />";
This produces
Array
255
It is in the correct directory and fails even with an absolute path. I use exactly the same format in another function in the same file that executes another script in the same directory and all is fine.
Any ideas?

Have you checked the execute permissions of your shell script? Apache runs as a user with very few permissions in most operating systems, so that may be the cause.

$out is supposed to be an array. You should probably print_r() or var_dump() it to see what's coming back from the script; it may be telling you what's going wrong.
In general, there's probably some environmental dependency that isn't being satisfied when PHP is running the script. This is especially common if it's being run from inside Apache.

Try:
$blah = exec("./add_article.sh", $out, $ret_val);
print_r($out);
echo '<br />';
echo $ret_val . "<br />";

Related

Save the console text into a txt file? (PHP)

actual I finished writing my program. Because it is only a plugin and it runs on a external server I still want to see if I get some errors or something else in the console.
I wrote every console input with echo ...;. My question now is if it is possible to get the text of the console?
Because then I could easily safe it in a .txt file and could get access to it from the web :) - Or is there another way to get the console text?
I could probably just say fwrite(...) instand of echo ...;. But this will cost a lot of time...
Greetings and Thank You!
An alternative that could be usefull on windows would be to save all the output buffer to a txt, first check your php configuration for the console app implicit_flush must be off then
<?php
ob_start(); //before any echo
/** YOUR CODE HERE **/
$output = ob_get_contents(); //this variable has all the echoes
file_put_contents('c:\whatever.txt',$output);
ob_flush(); //shows the echoes on console
?>
If your goal is to create a text file to access, then you should create a text file directly.
(do this instead of echoing to console)
$output = $consoleData . "\n";
$output .= $moreConsoleData . "\n";
(Once you've completed that, just create the file:)
$file = fopen('output.txt', 'a');
fwrite($file, $output);
fclose($file);
Of course, this is sparse - you should also check that the file exists, create it if necessary, etc.
For console (commando line interface) you can redirect the output of your script:
php yourscript.php > path-of-your-file.txt
If you haven't access to a command line interface or to edit the cronjob line, you can duplicate the starndar output at the begining of the script:
$fdout = fopen('path-to-your-script.txt', 'wb');
eio_dup2($fdout, STDOUT);
eio_event_loop();
fclose($fdout);
(eio is an pecl extension)
If you are running the script using the console (i.e. php yourscript.php), you can easily save the output my modifying your command to:
php yourscript.php > path/to/log.txt
The above command will capture all output by the script and save it to log.txt. Change the paths for your script / log as required.

Iterating through $_FILES array to perform exec()

So i've got a python script, which is being executed using the exec() command through embedded PHP. Currently, the python script takes just one file (uploaded using a standard HTML form), but I want to pass it multiple files, and have it run through them every time. I've tried the following code based on some examples I saw here on StackOverflow, but can't seem to get it to work. Does anyone know how I can do it? I just need to get the tmp_file name and the name, then pass them to the exec function, I want it to run once for each file (with the respective information for each file).
<?php
foreach ($_FILES["inputFile"]{
$dataIn = $_FILES["inputFile"]["tmp_name"];
$originalName = $_FILES["inputFile"]["name"];
exec("python /home/will/public_html/OrderAnalyser.py $dataIn $originalName 2>&1",$output);
foreach ($output as $out){
echo $out;
echo "<br />";
}
}
?>

PHP using ruby returning output (using metainspector)

I'm currently creating a php page which does a ssh call with a .rb (ruby) file.
rb file
require 'metainspector'
page = MetaInspector.new("www.hln.be")
puts page.image
When creating a php file with the following code (php):
$cmd = "ruby facescrape.rb";
$last_line = system($cmd, $retval);
echo $last_line . '
echo $retval;
this only returns value 1.
However 2 things :
When running the same command in ssh, it will print the page.image
correctly.
When i change the rb file and for instance set as last line
puts "test"
this value returns correctly with also print correctly with the aboven php code.
I don't get why printing the page.image works in ssh but won't work by using that php code.
Also tried using exec() instead of system().
Thank you in advance!
Kind regards,
Kurt Colemonts

Finding correct of PHP binary - exec()

I'm trying to execute a separate PHP script from within a PHP page. After some research, I found that it is possible using the exec() function.
I also referenced this SO solution to find the path of the php binary. So my full command looks like this:
$file_path = '192.168.1.13:8080/doSomething.php';
$cmd = PHP_BINDIR.'/php '.$file_path; // PHP_BINDIR prints /usr/local/bin
exec($cmd, $op, $er);
echo $er; // prints 127 which turns out to be invalid path/typo
doSomething.php
echo "Hi there!";
I know $file_path is a correct path because if I open its value; i.e. 192.168.1.13:8080/doSomething.php, I do get "Hi there!" printed out. This makes me assume that PHP_BINDIR.'/php' is wrong.
Should I be trying to get the path of the php binary in some other way?
The file you are requesting is accessible via a web server, not as a local PHP script. Thus you can get the result of the script simply by
$output = file_get_contents($file_path);
If you however for some reason really have to exec the file, then you must provide a full path to that file in your server directory structure instead of server URL:
$file_path = '/full/path/to/doSomething.php';
$cmd = PHP_BINDIR.'/php '.$file_path;
exec($cmd, $op, $er);

clamdscan can't read from tmp directory

I was wondering what's wrong with my code, if I use clamscan, it works fine both reading from /tmp, or manually specified the path. but if I use clamdscan, any path from /tmp will result in error (the int result is 2). This is the code.
$command = 'clamdscan ' . escapeshellarg($_FILES['file']['tmp_name']);
$out = '';
$int = -1;
exec($command, $out, $int);
echo "\n" . $command;
echo "\n" . $out;
echo "\n This is int = " . $int;
if ($int == 0) {
// all good, code goes here uploads file as normal IE move to
//echo "File path : ".$file."Return code : ".cl_pretcode($retcode);
//echo "\n";
move_uploaded_file($_FILES["file"]["tmp_name"], "filesave/" . $_FILES["file"]["name"]);
echo "Stored in: " . "filesave/" . $_FILES["file"]["name"];
} else {
echo "\n FAILED";
}
based on above code, it will failed because $int = 2. But, if I change the command to
//some file that is saved already in the directory
$command = 'clamdscan ' . '/abc/abc.txt';
It works perfectly fine.
It only failed if the command is clamdscan. if I use clamscan, temp directory is fine
any idea?
You should really just use one of the many clamd clients out there instead of relying on exec'ing a command and parsing its output, that's super fragile and will bring you nothing but headache in the future. For example:
http://torquecp.sourceforge.net/phpclamcli.html
If you are the do-it-yourself type, the clamd wire protocol is super simple (http://linux.die.net/man/8/clamd) and you could potentially write up a simple client in a couple of hours. Again, the benefit here is that it's a well defined protocol and has some nice features like a streaming call that allows you to operate the clamd service and your webapp with completely difference security credentials (heck they can even run on different boxes).
I hope this helps.
Just a quick remark on using http://torquecp.sourceforge.net/phpclamcli.html as a supposedly better alternative to a DIY cli exec. The aforementioned php script does entirely rely on the syntax of the clamav response text as well.
Old question but I've just had the same issue. clamdscan runs as user clamav which doesn't have permission to files in /tmp. There is an additional parameter --fdpass which runs the command as the user running the script.
Using $command = 'clamdscan --fdpass' . escapeshellarg($_FILES['file']['tmp_name']); should run the command as the www user which will have access to the temporary file.

Categories