Trouble with Named Pipes - php

I am new to using php and python but I have a task that I am trying to complete and the test code I have does not seem to work. Basically I am trying to get data from an html form (using php) to a python script for processing. After looking at some really useful stuff from other posts I have decided to use pipes. To test the process I have used the following code.
php code:
<?php
$pipe = fopen('Testpipe','r+');
fwrite($pipe, 'Test');
fclose($pipe);
?>
Python code:
#!/usr/bin/env python
import os
pipeName = 'Testpipe'
try:
os.unlink(pipeName)
except:
pass
os.mkfifo(pipeName)
pipe = open(pipeName, 'r')
while True:
data = pipe.readline()
if data != '':
print repr(data)
When I run the Python code I can see the pipe being created in the directory using ls -l but when I use my browser to run the php script (I am running a webserver on a raspberry pi) nothing happens. It has got me a little confused as most of the posts I read state how simple pipes are to get going. I assume on opening the browser (php script through the server) I should see the text come up in the python shell?
Any help would be appreciated.
Ok further to my original post I have modified my original code thanks to alot of trawling through the net and some really useful Python tutorials. I now have something that proves the principal of pipes although I still have to resolve the php side of things but I feel as though I'm getting there now. Revised code is below:
import os,sys
pipe_name = 'testpipe'
def child():
pipeout = os.open(pipe_name, os.O_WRONLY)
while True:
time.sleep(1)
os.write(pipeout, 'Test\n')
def parent():
pipein = open(pipe_name, 'r')
while True:
line = pipein.readline()[:-1]
print 'Parent %d got "%s"' %(os.getpid(),line)
if not os.path.exists(pipe_name):
os.mkfifo(pipe_name)
pid = os.fork()
if pid != 0:
parent()
else:
child()
This has got me on the path to where I want to go so hopefully it may be of use to someone having similar questions.

try to provide an absolute path ("/tmp/TestPipe") to be sure that both are looking to the same file.

Related

Better way to run python & display python errors from PHP

I am running a webserver for my laboratory that basically has a bunch of scripts I wrote in python for processing and analyzing tabular data.
I have a DigitalOcean droplet with a Laravel application deployed on it. When I want to run a script, I have the user upload some data file, and then from the PHP controller run:
shell_exec(python my_script.py arg1 arg2 etc);
The problem is, there are differences in dependencies and libraries between my development environment and 'production' environment. As such, when I try to run the script from the webserver and there is a python error, the object returned by shell_exec is just null. When the PHP blade template tries to parse/get data from this object, I get an error like so:
In this case, 'matchCount' is just a variable stored within a python list like this:
#Label peptides we found experimentally but do not have an in silico match for... as to predict contaminants
output = {
'sequence': protSeq,
'peptides': pepList,
'observablePeptideCount': str(len(pepList)),
'possibleObserved': possibleObserved,
'matchCount': matchCount,
'coverage': matchSumAA/protSeqAALength*100,
'massList': massList,
'tolerances': tolerances,
}
output = json.dumps(output)
The problem is, I understand the python script failed somewhere, but the error log does not give any indication of why or where. Is there some way I can have the webpage output the python error so I can correct it in the production environment?
Is there a better way to be doing all of this? Thank you for any help.
I won't recommend you print things out in production, but if it's a last resort you can try this:
<?php
$output = '';
$result = '';
exec('python my_script.py arg1 arg2 etc 2>&1', $output, $result);
var_dump($output); // all the output is here
var_dump($result); // gives an exit code, might be 1 if it's error

How can I send "user input" to python script from another python script (or php execute)?

I'm creating a website using php and XAMPP. This website accepts a python file from the user, then it needs to run that python file and receive all output from that file. I've been able to accomplish this by using shell_exec() in the php file.
The problem is getting user input for the python files. The files use both the input() and sys.stdin.readline() functions. I need to be able to automatically send the python file "user input" (sometimes several inputs). I know exactly what and how many "user inputs" I will need to send so this doesn't require my intervention.
I think one way to do this is by changing the way the submitted python files get input. If I could do this then I would have each input stored in a list that would be iterated through. Unfortunately, I cannot edit the actual input commands in the submitted files so this would have to be done at the top of the submitted python file.
Here is how the php file executes the python files.
$command = "python python_script.py";
$output = shell_exec($command);
echo nl2br($output);
I tried using the echo function (with the && for multiple inputs), but the only problem with this is the fact that the echo function can't press enter after each echo. This did however successfully match the inputs to the input prompts. Below is an example.
python_script.py should take input then print it, but the cmd displayed this:
C:\>(echo 2 && echo 3) | python python_script.py
number one: 2
number two: 3
C:\>
Now I'm trying to use the subprocess functions in a separate python file. Again the problem is "user input"; I don't know how to send inputs. The solutions to like problems have not been able to work for me, but I'm certain that this is due to my lack of understanding of the subprocess functions.
I think that subprocess is my best bet, but I would also appreciate any suggestions utilizing php. I would also prefer to not have to create a batch file for this problem.
I found a solution to this problem.
To send inputs from one python file to another (python version 3.7), I used three files.
File for running the subprocess
File for outputs (very simple)
File that needs the inputs
Here are the three files in the same order as above.
You don't need to print out the output, but I'll include the terminal output below the file examples.
The subprocess file:
from subprocess import Popen,PIPE
p1 = Popen(["python","output_file.py"], stdout=PIPE)
p2 = Popen(["python", "input_file.py"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()
output = p2.communicate()[0]
print(output)
The output file is very simple and there may be a way to work around it. Nevertheless, here is my version:
print(1)
print(2)
print('My String')
The input file requires type casting for numbers.
i = input('Enter a number: ')
j = input('Enter another: ')
k = int(i) + int(j)
print(k)
l = input('Tell me something. ')
print(l)
Here is the terminal output:
b'Enter a number: Enter another: 3\r\nTell me something. My String!\r\n'

Open Linux terminal command in PHP

I have a server running on Linux that execute commands to 12 nodes (12 computers with Linux running in them). I recently downloaded PHP on the server to create web pages that can execute commands by opening a specific PHP file.
I used exec(), passthru(), shell_​exec(), and system(). system() is the only one that returns a part of my code. I would like PHP to act like open termainal command in linux and I cannot figure out how to do it!
Here is an example of what is happening now (Linux directly vs PHP):
When using linux open terminal command directly:
user#wizard:/home/hyperwall/Desktop> /usr/local/bin/chbg -mt
I get an output:
The following settings will be used:
option = mtsu COLOR = IMAGE = imagehereyouknow!
NODES = LOCAL
and additional code to send it to 12 nodes.
Now with PHP:
switch($_REQUEST['do'])
{ case 'test':
echo system('/usr/local/bin/chbg -mt');
break;
}
Output:
The following settings will be used:
option = mtsu COLOR = IMAGE = imagehereyouknow!
NODES = LOCAL
And stops! Anyone has an explanation of what is happening? And how to fix it? Only system displays part of the code the other functions display nothing!
My First thought is it can be something about std and output error. Some softwares dump some informations on std out and some in std error. When you are not redirecting std error to std out, most of the system calls only returns the stdout part. It sounds thats why you see the whole output in terminal and can't in the system calls.
So try with
/usr/local/bin/chbg -mt 2>&1
Edit:
Also for a temporary work through, you can try some other things. For example redirect the output to file next to the script and read its contents after executing the command, This way you can use the exec:
exec("usr/local/bin/chbg -mt 2>&1 > chbg_out");
//Then start reading chbg_out and see is it work
Edit2
Also it does not make sense why others not working for you.
For example this piece of code written in c, dumps a string in stderr and there is other in stdout.
#include <stdio.h>
#include<stdlib.h>
int main()
{
fputs("\nerr\nrro\nrrr\n",stderr);
fputs("\nou\nuu\nuttt\n",stdout);
return 0;
}
and this php script, tries to run that via exec:
<?php
exec("/tmp/ctest",&$result);
foreach ( $result as $v )
{
echo $v;
}
#output ouuuuttt
?>
See it still dumps out the stdout. But it did not receive the stderr.
Now consider this:
<?php
exec("/tmp/ctest 2>&1",&$result);
foreach ( $result as $v )
{
echo $v;
}
//output: errrrorrrouuuuttt
?>
See, this time we got the whole outputs.
This time the system:
<?php
echo system("/tmp/ctest 2>&1");
//output: err rro rrr ou uu uttt uttt
?>
and so on ...
Maybe your chbg -mt writes additional code to stderr instead of stdout? Try to execute your script inside php like this:
/usr/local/bin/chbg -mt 2>&1
The other responses are good for generic advice. But in this specific case, it appears you are trying to change your background on your desktop. This requires many special considerations because of 'user context':
First, your web server is probably running as a different user, and therefore would not have permissions to change your desktop.
Second, the program probably requires some environmental variables from your user context. For example, X programs need a DISPLAY variable, ssh-agent needs SSH_AGENT_PID and SSH_AUTH_SOCK, etc. I don't know much about changing backgrounds, but I'm guessing it involves D-Bus, which probably requires things like DBUS_SESSION_BUS_ADDRESS, KONSOLE_DBUS_SERVICE, KONSOLE_DBUS_SESSION, and KONSOLE_DBUS_WINDOW. There may be many others. Note that some of these vars change every time you log in, so you can't hard-code them on the PHP side.
For testing, it might be simpler to start your own webserver right from your user session. (i.e. Don't use the system one, it has to run as you. You will need to run it on an alternate port, like 8080). The web server you start manually will have all the 'context' it needs. I'll mention websocketd because it just came out and looks neat.
For "production", you may need to run a daemon in your user context all the time, and have the web server talk to that daemon to 'get stuff done' inside your user context.
PHP's system only returns the last line of execution:
Return Value: Returns the last line of the command output on success, and FALSE on failure.
You will most likely want to use either exec or passthru. exec has an optional parameter to put the output into an array. You could implode the output and use that to echo it.
switch($_REQUEST['do'])
{ case 'test':
exec('/usr/local/bin/chbg -mt', $output);
echo implode('\n', $output); // Could use <br /> if HTML output is desired
break;
}
I think that the result of execution, can changes between users.
First, try to run your PHP script directly into your terminal php yourScript.php
If it runs as expected, go to your Apache service and update it to run with your own credentials
You are trying to change the backgrounds for currently logged in users... While they are using the desktop. Like while I'm typing this message. I minimize my browser and 'ooh my desktop background is different'. Hopefully this is for something important like it turns red when the reactor or overheating.
Anyway to my answer:
Instead of trying to remotely connect and run items as the individual users. Setup each user to run a bash script (in their own account, in their own shell) on a repeating timer. Say every 10 minutes. Have it select the SAME file.. from a network location
/somenetworkshare/backgrounds/images/current.png
Then you can update ALL nodes (1 to a million) just by changing the image itself in /somenetworkshare/backgrounds/images/current.png
I wrote something a while ago that does just this -- you can run a command interpreter (/bin/sh), send it commands, read back responses, send more commands, etc. It uses proc_open() to open a child process and talk to it.
It's at http://github.com/andrasq/quicklib, Quick/Proc/Process.php
Using it would look something like (easier if you have a flexible autoloader; I wrote one of those too in Quicklib):
include 'lib/Quick/Proc/Exception.php';
include 'lib/Quick/Proc/Exists.php';
include 'lib/Quick/Proc/Process.php';
$proc = new Quick_Proc_Process("/bin/sh");
$proc->putInput("pwd\n");
$lines = $proc->getOutputLines($nlines = 10, $timeoutSec = 0.2);
echo $lines[0];
$proc->putInput("date\n");
$lines = $proc->getOutputLines(1, 0.2);
echo $lines[0];
Outputs
/home/andras/quicklib
Sat Feb 21 01:50:39 EST 2015
The unit of communication between php and the process is newline terminated lines. All commands must be newline terminated, and all responses are retrieved in units of lines. Don't forget the newlines, they're hard to identify afterward.
I am working on a project that uses Terminal A on machine A to output to Terminal B on Machine B, both using linux for now. I didnt see it mentioned, but perhaps you can use redirection, something like this in your webserver:
switch($_REQUEST['do'])
{ case 'test':
#process ID on the target (12345, 12346 etc)
echo system('/usr/local/bin/chbg -mt > /proc/<processID>/fd/1');
#OR
#device file on the target (pts/0,tty0, etc)
echo system('/usr/local/bin/chbg -mt > /dev/<TTY-TYPE>/<TTYNUM>');
break;
}
Definitely the permissions need to be set correctly for this to work. The command "mesg y" in a terminal may also assist...Hope that helps.

retrieve R output in PHP

Here's the issue:
I am using R to run some statistical analysis. The results of which will eventually be sent to a an embedded swf on the user's client machine.
To do this, I have PHP execute a shell script to run the R program, and I want to retrieve the results of that program so I can parse them in PHP and respond with the appropriate data.
So, it's simply:
$output = shell_exec("R CMD BATCH /home/bitnami/r_script.R");
echo $output;
But, I receive nothing of course, because R CMD BATCH writes to a file. I've tried redirecting the output in a manner similar to this question which changes my script to
$output = shell_exec('R CMD BATCH /home/bitnami/raschPL.R /dev/tty');
echo $output;
But what I get on the console is a huge spillout of the source code, and nothing is echoed.
I've also tried this question's solution in my R script.
tl;dr; I need to retrieve the results of an R script in PHP.
Cheers!
If it writes to file perhaps you could use file_get_contents to read it?
http://php.net/manual/en/function.file-get-contents.php
Found it, the answer is through Rscript. Rscript should be included in the latest install of R.
Using my code as an example, I would enter this at the very top of r_script.R
#!/usr/bin/Rscript --options-you-need
This should be the path to your Rscript executable. This can be found easily by typing
which Rscript
in the terminal. Where I have --options-you-need, place the options you would normally have when doing the CMD BATCH, such as --slave to remove extraneous output.
You should now be able to run your script like so:
./r_script.R arg1 arg2
Important! If you get the error
Error in `contrasts<-`(`*tmp*`, value = "contr.treatment") :
could not find function "is"
You need to include the "methods" package, like so:
require("methods");
Perhaps,a much simpler workaround, would be:
$output = shell_exec('R CMD BATCH /home/bitnami/raschPL.R > /dev/tty 2>&1');
echo $output;
Redirects both STDOUT and STDERR, since R outputs to STDERR, by default.

Calling Python in PHP

I have a Python script I recently wrote that I call using the command line with some options. I now want a very thin web interface to call this script locally on my Mac.
I don't want to go through the minor trouble of installing mod_python or mod_wsgi on my Mac, so I was just going to do a system() or popen() from PHP to call the Python script.
Any better ideas?
Depending on what you are doing, system() or popen() may be perfect. Use system() if the Python script has no output, or if you want the Python script's output to go directly to the browser. Use popen() if you want to write data to the Python script's standard input, or read data from the Python script's standard output in php. popen() will only let you read or write, but not both. If you want both, check out proc_open(), but with two way communication between programs you need to be careful to avoid deadlocks, where each program is waiting for the other to do something.
If you want to pass user supplied data to the Python script, then the big thing to be careful about is command injection. If you aren't careful, your user could send you data like "; evilcommand ;" and make your program execute arbitrary commands against your will.
escapeshellarg() and escapeshellcmd() can help with this, but personally I like to remove everything that isn't a known good character, using something like
preg_replace('/[^a-zA-Z0-9]/', '', $str)
The shell_exec() operator will also allow you to run python scripts using similar syntax to above
In a python file called python.py:
hello = "hello"
world = "world"
print hello + " " + world
In a php file called python.php:
$python = shell_exec(python python.py);
echo $python;
You can run a python script via php, and outputs on browser.
Basically you have to call the python script this way:
$command = "python /path/to/python_script.py 2>&1";
$pid = popen( $command,"r");
while( !feof( $pid ) )
{
echo fread($pid, 256);
flush();
ob_flush();
usleep(100000);
}
pclose($pid);
Note: if you run any time.sleep() in you python code, it will not outputs the results on browser.
For full codes working, visit How to execute python script from php and show output on browser
I do this kind of thing all the time for quick-and-dirty scripts. It's quite common to have a CGI or PHP script that just uses system/popen to call some external program.
Just be extra careful if your web server is open to the internet at large. Be sure to sanitize your GET/POST input in this case so as to not allow attackers to run arbitrary commands on your machine.
Your call_python_file.php should look like this:
<?php
$item='Everything is awesome!!';
$tmp = exec("py.py $item");
echo $tmp;
?>
This executes the python script and outputs the result to the browser.
While in your python script the (sys.argv[1:]) variable will bring in all your arguments. To display the argv as a string for wherever your php is pulling from so if you want to do a text area:
import sys
list1 = ' '.join(sys.argv[1:])
def main():
print list1
if __name__ == '__main__':
main()
The above methods seems to be complex. Use my method as a reference.
I have this two files
run.php
mkdir.py
Here, I've created a html page which contains GO button. Whenever you press this button a new folder will be created in directory whose path you have mentioned.
run.php
<html>
<body>
<head>
<title>
run
</title>
</head>
<form method="post">
<input type="submit" value="GO" name="GO">
</form>
</body>
</html>
<?php
if(isset($_POST['GO']))
{
shell_exec("python /var/www/html/lab/mkdir.py");
echo"success";
}
?>
mkdir.py
#!/usr/bin/env python
import os
os.makedirs("thisfolder");
Note that if you are using a virtual environment (as in shared hosting) then you must adjust your path to python, e.g: /home/user/mypython/bin/python ./cgi-bin/test.py
is so easy 😁
You can use [phpy - library for php][1]
php file
<?php
require_once "vendor/autoload.php";
use app\core\App;
$app = new App();
$python = $app->python;
$output = $python->set(your python path)->send(data..)->gen();
var_dump($ouput);
python file:
import include.library.phpy as phpy
print(phpy.get_data(number of data , first = 1 , two =2 ...))
you can see also example in github page
[1]: https://github.com/Raeen123/phpy
If you want to execute your Python script in PHP, it's necessary to do this command in your php script:
exec('your script python.py')

Categories