PHP exec() not working properly - php

I am having difficulty with the PHP exec() function. It seems to not be calling certain functions. For instance, the code echo exec('ls'); produces no output whatsoever (it should, there are files in the directory). That main reason this is a problem for me is that I'm trying execute a .jar from a PHP exec() call.
As far as I know I'm calling the java program properly, but I'm not getting any of the output. The .jar can be executed from the command line on the server. (For the record, it's an apache server).
My php for the .jar execute looks like this:
$output = array();
exec('java -jar testJava.jar', $output);
print_r($output);
All I get for output from this exec() call is Array().
I have had success with exec() executing 'whoami' and 'pwd'. I can't figure out why some functions are working and some aren't. I'm not the most experienced person with PHP either, so I'm not too sure how to diagnose the issue. Any and all help would be appreciated.

The reason why you are not able to execute ls is because of permissions.
If you are running the web server as user A , then you can only ls only those directories which have permissions for user A.
You can either change the permission of the directory or you can change the user under which the server is running by changing the httpd.conf file(i am assuming that you are using apache).
If you are changing the permissions of the directory, then make sure that you change permissions of parent directories also.
To change the web server user, follow following steps:
Open the following file:
vi /etc/httpd/conf/httpd.conf
Search for
User apache
Group apache
Change the user and group name. After changing the user and group, restart the server using following command.
/sbin/service httpd restart
Then you will be able to execute all commands which can be run by that user.
EDIT:
The 'User' should be a non-root user in httpd.conf. Apache by default doesnot serve pages when run as root. You have to set user as a non-root user or else you will get error.
If you want to force apache to run as root, then you have to set a environment variable as below:
env CFLAGS=-DBIG_SECURITY_HOLE
Then you have to rebuild apache before you can run it as root.

I have found the issue - SELinux was blocking PHP from accessing certain functions. Putting SELinux into permissive mode has fixed the issues (although, I'd rather not have to leave SELinux in permissive mode; I'd rather find a way of allowing certain functions if I can).

I have a solution:
command runs from console, but not from php via exec/system/passthru.
The issue is the path to command. It works with the absolute path to command
So that:
wkhtmltopdf "htm1Eufn7.htm" "pdfIZrNcb.pdf"
becomes:
/usr/local/bin/wkhtmltopdf "htm1Eufn7.htm" "pdfIZrNcb.pdf"
And now, it's works from php via exec
Where command binary you can see via whereis wkhtmltopdf

Tore my hair out trying to work out why PHP exec works from command line but not from Apache. At the end, I found the following permissions:
***getsebool -a | grep httpd*** ---->
**httpd_setrlimit --> off
httpd_ssi_exec --> off
httpd_sys_script_anon_write --> off**
USE: setsebool -P httpd_ssi_exec 1
SEE: https://linux.die.net/man/8/httpd_selinux

Your problem is not an execution issue but the syntax of the exec command. The second argument is always returned as an array and contains a single line of the output in each index. The return value of the exec function will contain the final line of the commands output. To show the output you can use:
foreach($output as $line) echo "$line\n";
See http://php.net/manual/en/function.exec.php for details. You can also get the command's exit value with a third argument.

Related

Can't execute yolo/darknet from php exec - predictions.png never appears?

YOLO: https://github.com/pjreddie/darknet
I'm trying to run this from within a php script, but predictions.png never appears. I assume this is a general problem with my understanding of how exec works, rather than how YOLO works.
I've changed the permissions and users on all relevant folders and directories to nginx/777. I know that's not ideal but it's a troubleshooting step!
What happens when calling darknet from the terminal:
Logging output appears on the screen, and at the end of the process a file called predictions.php should be created in the /darknet directory. When running this from PHP in the browser I don't care about the logging output, I just want the png file to be created.
Works:
/darknet/darknet detect /darknet/cfg/yolo.cfg /darknet/yolo.weights /path/to/photo.jpg
Works:
sudo -u nginx php71 -r 'exec("/darknet/darknet detect /darknet/cfg/yolo.cfg /darknet/yolo.weights /path/to/photo.jpg");'
Works from commandline (php71 myfile.php), but not in the browser:
<?php
exec("/darknet/darknet detect /darknet/cfg/yolo.cfg /darknet/yolo.weights /path/to/photo.jpg");
What am I doing wrong?

Is it possible to pass the parameter in php execution?

Hi I am trying to run a C binary program in a php script.
The name of the binary program is prog and it takes one or two parameters. In terminal this binary program runs fine with this command:
prog param1
In a php sript, I am trying to run the above command. But I am not sure if this syntax is correct. I have the following:
exec('../permission/prog param1', $output, $return);
I am not seeing expected behavior after executing the php file. Is it possible to pass the parameter like this in php?
Thanks!
I think you will need to do couple of things and check again:
Your function params uses is fine but try using the full script path.
If still it does not function from with in your php script. You will need to check and see if the apache group:user has the ownership of running the permission/prog script or not. If not try giving the ownership to apache group:user. The apache group:user may apache:apache. You will need to exactly check for what group and user is there in your server for apache.
PHP usually runs executables from the user and group of www-data
This will likely be different to the user you are using in the terminal. Check that www-data has permission to execute the binary

Running shell script from webserver

I have a shell script named brew.sh as follows:
#!/bin/bash
brew doctor > test.txt
Which works fine when I run it from the command line. It outputs as expected the output of brew doctor to the test.txt file. However, when I call it from a php webpage as below it creates the test.txt file but the file is empty.
<?php
$output = shell_exec("./brew.sh");
echo $output;
?>
I suspected it was a permissions/ownership issue so I used chown to change ownership from username:staff to _www:_www on the parent directory,where it would then create the test.txt file but not write the output to it. I've even tried changing permissions to 777 temporarily on the test.txt and even that didn't work. Ultimately I would like to view the output of brew doctor and brew update on a webpage on my local development machine. Surely it shouldn't be that difficult?
Elias is going to be right I suspect - your environment on the cmd line is not going to be like the environment the script finds itself in within the webserver, assuming the webserver user is even allowed to run a proper shell...
You'll need a path. Check what your path value is, and put it in.
Also doesn't hurt to always include the full path for your binary, i.e. brew.
#!/bin/bash
PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
/usr/local/bin/brew doctor > /var/www/whatever/test.txt
.... personally.. This isn't the approach I would use. If this is for brew doctor and brew update I would just use cron jobs that redirect output to a file on the webserver since I wouldn't want the webserver invoking brew commands... someone could DoS the server pretty easily just by requesting those pages a lot. The cron solution is pretty bulletproof though - and in any case with cron I can run it as a more appropriate user where the permissions/environment for brew are likely to work more correctly in any case.
Also - the other guys point about checking errors is a good one. stderr is probably ending up in your web logs at the moment when you get empty output. 2>&1 can make it go into that file instead, probably.
[ Note that it has to be 2>&1 !! I think chris had a typo when he wrote >2&1 which does something very different. 2 is the stderr filehandle which we want to redirect to 1. >2 will redirect 1 (stdout) to a file called 2.
If you add 2>&1 to your shell command, you should get STDERR and STDOUT returned which will at least help you determine what is going on:
<?php
$output = shell_exec("./brew.sh >2&1");
echo $output;
?>

PHP exec() with Pygments for PHP

I'm currently using the Pygments for PHP plugin that is located here: http://derek.simkowiak.net/pygments-for-php/.
The line that actually calls Pygments from that code is an exec() passed: pygmentize -f html $extra_opts -l $language $temp_name as the command. This all works fine, and I get back the output and it is formatted by the plugin.
What I would like to happen at the same time is for Pygments to create an image of it, so I pass exec() a similar command: pygmentize -f png $extra_opts -l $language -o $full_image_path/$output_file.png $temp_name This is where I run into a problem. The image never shows up in the expected folder.
However, if I var_dump() that command string before I exec() it and take it and run it straight from the command line, it works fine.
I have tried echoing exec('whoami') which tells me that the PHP user is www-data. I've tried giving permissions to www-data and changing ownership to www-data on the folder where I store the images. I've also tried changing permissions to 777 just to see what would happen, and the answer is nothing.
Is there something I'm missing? I'm running out of ideas to try. Thank you!
Edit: Another thing that I've checked is the output from the exec command, and the return value. It outputs an empty array, and it returns 1 as the return value.
Edit 2: After seeing that that directory should be writeable/readable for the PHP user, is it possible that pygments doesn't have permission to write it as a specific user? I'm not sure this makes sense, as when I run it myself it works fine, and in fact, when PHP runs it with the HTML lexer, it is able to run. I'm not very experienced in Python, so I don't know if this is a potential issue.
I guess you cannot do it like this.
$output_file.png
Try
$file = $output_file.".png"
and substitute in the exec
Ended up being an issue with the font that was installed for use by the www-root user. Apparently the one that is used by default for Pygments was installed only for the user that I was running as when I use the command line.
The way I was able to figure this out, was running
exec("$command 2>&1", $out, $code);.
The extra 2>&1 redirects stderr into the output for me to see the issue.
The $out parameter showed the FontNotFound error that pygments was throwing.
I changed the font that Pygments used via the command line using: full,style=manni,cssclass=pygmentize_kbOKBd,font_name='DejaVu Sans Mono' -l php -o /srv/www/path/to/images/uploads/2513732976ad4b7.02729290.png /tmp/pygmentize_kbOKBd after finding which fonts I had available to me.
To see which fonts I had available to me as the user running the script, I just ran fc-list in an exec() command for Ubuntu, and checked the output of that for the list of available fonts.

Why cannot PHP execute a command from web browser?

This is really simple but I cannot get it to work at all. Spent many hours and I've always give up. I created php script called copy.php and it should call a python script called copy.py.
I want to execute a command line like this
<?php exec('/var/www/html/copy.py'); ?>
Really simple.
Why cannot I get the python script executed from php exec()? The function inside python script is to get a copy of error_log from a different directory (outside of Apache) into html directory.
If I run that from a terminal
> php copy.php
It did execute the function and made a copy. Why is that the web browser isn't doing it?
Let me simplify this:
why cannot exec("cp /var/log/httpd/error_log /var/www/html/path/to/php/script") work?
it works fine if I type it in terminal but not when run in a browser.
As others have alluded to, the difference is probably permissions. When you run a command from the command line, you're generally not the same users as your apache script is running as.
Put another way, if from the command line you type whoami, you'll probably get whatever name your user account is.
The echo exec('whoami'); from within php shows who the script is running as, which is Apache.
So, whatever command you're trying to run from your web server isn't available to run as the Apache user. You mentioned you've been able to have exec("python /usr/diskpurge/script.py") work, but not to have exec('/var/www/html/copy.py') doesn't. This is due to in one instance you're running python, in the other you're trying to execute your copy.py script. If copy.py doesn't have execute permissions for the Apache user, you're not going to be able to run it from the browser.
Perhaps different settings apply for the Apache environment versus the command line.
Use error_reporting(E_ALL); and ini_set('display_errors', true) to see what errosr may come up.
It is possible that the Apache environment is prohibited from using exec or the fact that Apache runs under a different user that does not have execute rights on the python script.
sounds like a permission error. Check if your server is running with sufficient rights.
echo exec('whoami');
Set your error reporting to report all:
ini_set('display_errors', true);
error_reporting(E_ALL);
and check for errors..
If your whoami returns a user which is not a member of the SU family (linux) or administration (windows) then resite your permissions..
Linux:
Assign the user returned by whoami correct permissions to run python scripts.. Do not allow the resulted username to run as root with total administration powers.. This is a big no no
The only reason its not working is because you didn't set the write permissions!
Do:
sudo nano /etc/sudoers
And then put the following:
www-data ALL=(root) NOPASSWD:ALL

Categories