0

I am running Ubuntu 14.04 with a locally hosted webpage running on Apache2. I can access index.php fine through my browser, but I want that page to display a graph that is prepared in a python script called graph.py. graph.py will execute fully when the I execute index.php from the terminal, and it will PARTIALLY execute when I access it from the browser. commands from pyplot, used within the graph.py file will not execute when called from the browser.

I have simplified the contents of the files for this question.

Contents of index.php:

<?php
echo exec('whoami');
echo "</br>";
$r = `python graph.py`;
echo($r);
?>

Contents of graph.py:

#!/usr/bin/python2.7

import cgi
import matplotlib.pyplot as plt

print("Initial file parsing successful")

plt.plot([1,2,3,4])

print("File completed operation using pyplot")

The output of index.php from the terminal has what I would expect:

MYUSERNAME</br>Initial file parsing successful
File completed operation using pyplot

The browser never completed the PyPlot operation as shown by its output:

www-data
Initial file parsing successful 

After scouring the internet for answers, this post appears to be the most similar to my issue:

Why cannot PHP execute a command from web browser?

As suggested in the responses, it makes sense that I may be dealing with a permissions issue. I used "updatedb" and "locate pyplot" to find every instance the pyplot module appears. On my machine, there are three files in two directories:

/usr/lib/pymodules/python2.7/matplotlib/pyplot.py
/usr/lib/pymodules/python2.7/matplotlib/pyplot.pyc
/usr/share/pyshared/matplotlib/pyplot.py

Since pyplot has other dependencies in the matplotlib directory, I set permissions for every file in both of these directories with "chmod 777." I know I will have to restore these for security reasons once I find where I can scale permissions back, but even allowing that level of access, the php file will not execute when accessed from the browser. Does anyone have any ideas what could be catching this?

Community
  • 1
  • 1
Jeff12
  • 35
  • 5
  • Were I doing this I'd get PHP to emit an `` tag for the graph, the `src` attribute of which points to your Python script, and modify the python script to emit its graph as a PNG (or JPG) file directly. There's no need to execute your Python script from PHP at all. –  Jun 07 '15 at 03:22
  • Thank you I may decide to circle back to that later on. I did try that approach, but the python script will need to execute each time the homepage is accessed. There may be a way to get it to work but for the time being, I only get the alternate text when I try that. – Jeff12 Jun 07 '15 at 03:48
  • The fact that your brower shows the text "Initial file parsing successful" proves that your webserver executes the python script, it just doesn't finis. PHP receives only normal output from executed scripts, no errors, so you need to redirect the error output to normal output. You can do that by adding `2>&1` to your command: `exec("python graph.py 2>&1");` – Gerald Schneider Jun 07 '15 at 04:24
  • my guess would be that the user the webserver is running under is missing some environment variables, e.g. the correct include path – Gerald Schneider Jun 07 '15 at 04:26
  • I have been trying to echo exec("python graph.py 2>&1"); and I have tried to place it inside a img tag with echo "&1") . ">" and echo "&1'>". I'm getting an empty image. – Jeff12 Jun 07 '15 at 04:41
  • Why would the webserver be missing some correct include paths? Shouldn't it pull that from the same paths the shell uses? And if this is the case, where can I go to change these paths? – Jeff12 Jun 07 '15 at 04:52

3 Answers3

1

AFAIK, when you execute python from the browser the user is www-data. Thus you should change the python script's permissions to a+x. You don't need cgi unless you run PHP in cgi that is unusual. Just put 'graph.py' into the same folder where you keep your index.php. Save your plot into am image and open it in your browser via PHP. That's it.

Python script

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
plt.savefig('img.png')

PHP code

<?php
$r = '/usr/bin/python ./graph.py';
exec($r);

$im = imagecreatefrompng("img.png");
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
?>

Output:

img

Alex Ivanov
  • 695
  • 4
  • 6
  • The browser can't display the image "because it has errors." I tried running in the terminal and received the errors below. graph.py is in the same directory as index.php. sh: 1: graph.py: not found PHP Warning: imagecreatefrompng(img.png): failed to open stream: No such file or directory in /var/www/html/index.php on line 5 PHP Warning: imagepng() expects parameter 1 to be resource, boolean given in /var/www/html/index.php on line 7 PHP Warning: imagedestroy() expects parameter 1 to be resource, boolean given in /var/www/html/index.php on line 8 – Jeff12 Jun 07 '15 at 05:21
  • I needed to specify "python graph.py" in the exec function and it would create img.png when executed from the terminal, but it still wont execute when index.php is loaded to the browser. – Jeff12 Jun 07 '15 at 05:32
  • Well, I didn't test it since I have neither PHP nor matplotlib on my computer. I described the basic principle. You can test it with something simpler first like writing a text file via PHP from the browser to make sure that exec works. The error can occur, for example, if the directory is unwritable, or www-data can't find the executable or python's modules. How can I know what's going on there? I just showed you the direction to go. – Alex Ivanov Jun 07 '15 at 06:06
  • I think the error happened because apach doesn't know where to find python's modules. If you execute graph.py from bash Python Environment is set in bash. You need to teach apach where to find modules first or bring the whole Python installation to html folder. – Alex Ivanov Jun 07 '15 at 06:28
  • +)Thank you very much. This solves my problem. – xpaul Apr 07 '21 at 14:09
0

As per my understanding you will need to configure your webserver to work with python compiler. Any of the web server will by default will not be able to use any compiler installed on your system. Your webserver should understand for a particular file extension which program should be used to run it. Below is the link where you can find information for it here: [How do you set up Python scripts to work in Apache 2.0?

But in your case you may need just to run python scripts from php. You can find information about it here : Running a Python script from PHP

Community
  • 1
  • 1
Luke P. Issac
  • 1,471
  • 15
  • 32
  • Try this way as well of getting the python scripts executed using PHP itself here : http://stackoverflow.com/questions/19735250/running-a-python-script-from-php – Luke P. Issac Jun 07 '15 at 04:01
  • Thanks, found that one a while ago, but didn't overcome my obstacles. I'm still working on your first recommendation, but I am actually running in Apache 2.4 which means the httpd.conf file no longer exists, and I am trying to figure out where the ScriptAlias line needs to be placed, and what exactly the paths should be pointing to. – Jeff12 Jun 07 '15 at 04:20
  • After putting a bunch of hours into this, I think this was on the right track. I tried running a terminal with user account "www-data" and came across the same issues. By modifying the sudoers file, I was able to run the program successfully in the terminal with no sudo prompts. unfortunately, it is still not working when initialized from the browser. Any other ideas? – Jeff12 Jun 07 '15 at 17:47
0

I was able to make a plot with Python in cgi. No problems. http://wiki.scipy.org/Cookbook/Matplotlib/Using_MatPlotLib_in_a_CGI_script

PHP

<?php
header('Location: cgi-bin/graph.py'); 
?>

PYTHON

#!/usr/bin/python

import os,sys
import cgi
import cgitb; cgitb.enable()

os.environ[ 'HOME' ] = '/tmp/'

import matplotlib
matplotlib.use( 'Agg' )
import pylab
form = cgi.FieldStorage()
pylab.plot([1,2,3])

print "Content-Type: image/png\n"
pylab.savefig( sys.stdout, format='png')

And here's without cgi. Since PHP is pretty much executable, we don't actually need cgi. I moved the graph.py from cgi-bin to html folder and deleted all the cgi modules from it and even os.environ[ 'HOME' ] = '/tmp/'.

PHP

<?php
$r = '/usr/bin/python ./graph.py';
exec($r);

$im = imagecreatefrompng("img.png");
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
?>

PYTHON

#!/usr/bin/python

import matplotlib
matplotlib.use( 'Agg' )
import pylab

pylab.plot([1,2,3])
pylab.savefig('img.png')

AS you see the difference is

matplotlib.use( 'Agg' )

I have no idea what it means. Something important, maybe. Without this opting the script doesn't run.

Alex Ivanov
  • 695
  • 4
  • 6