unable to execute python script from php - php

I want to execute Python script from PHP file. I am able to execute simple python script like:
print("Hello World")
but when I want to execute following script, nothing happens
from pydub import AudioSegment
AudioSegment.converter = "/usr/bin/ffmpeg"
sound = AudioSegment.from_file("/var/www/dev.com/public_html/track.mp3")
sound.export("/var/www/dev.com/public_html/test.mp3", format="mp3", bitrate="96k")
and same script works fine when I execute it from terminal. here is my php script:
$output = shell_exec("/usr/bin/python /var/www/dev.com/public_html/index.py");
echo $output;
I have also tried following method but no luck:
$output = array();
$output = passthru("/usr/bin/python /var/www/dev.com/public_html/index.py");
print_r($output);
please help me

PHP's passthru function does not have the elegant method for which you may be searching of passing environment variables. If you must use passthru, then export your variables directly in the command:
passthru("SOMEVAR=$yourVar PATH=$newPATH ... /path/to/executable $arg1 $arg2 ...")
If you are inclined toward shell_exec, you may appreciate putenv for the slightly cleaner interface:
putenv("SOMEVAR=$yourVar");
putenv("PATH=$newPATH");
echo shell_exec("/path/to/executable $arg1 $arg2 ...");
If you are open to a more robust (if tedious) approach, consider proc_open:
$cmd = "/path/to/executable arg1 arg2 ..."
# Files 0, 1, 2 are the standard "stdin", "stdout", and "stderr"; For details
# read the PHP docs on proc_open. The key here is to give the child process a
# pipe to write to, and from which we will read and handle the "passthru"
# ourselves
$fileDescriptors = array(
0 => ["pipe", "r"],
1 => ["pipe", "w"],
2 => ["pipe", "w"]
);
$cwd = '/tmp';
$env = [
'PATH' => $newPATH,
'SOMEVAR' => $someVar,
...
];
# "pHandle" = "Process handle". Note that $pipes is new here, and will be
# given back to us
$pHandle = proc_open($cmd, $fileDescriptors, $pipes, $cwd, $env);
# crucial: did proc_open work?
if ( is_resource( $pHandle ) ) {
# $pipes is now valid
$pstdout = $pipes[ 1 ];
# Hey, whaddya know? PHP has just what we need...
fpassthru( $pstdout );
# Whenever you proc_open, you must also proc_close. Just don't
# forget to close any open file handles
fclose( $pipes[0] );
fclose( $pipes[1] );
fclose( $pipes[2] );
proc_close( $pHandle );
}

Acc to your reply, as you want to execute the python script from PHP
I was able to execute it using the following code
$command = escapeshellcmd('/var/www/yourscript.py');
$output = shell_exec($command);
echo $output;
Please use the above PHP code with the same python script.
Try to run the python script as a GCI script first to make sure it is working and set the permissions to public directory and script as I mentioned before
===================old ans============================
From what you asked, I guess this is what you are trying to do is that you are trying to run it as a CGI script like http://localhost/yourscript.py
And why are you using PHP to execute python script when you can run it directly as a CGI script?
here is what you need to do to make it work like a web page:
enable python CGI in apache ( or in the web server you are using ).
put the script in CGI configured directory
add proper code to your script to make it work as a CGI script
#!/usr/local/bin/python
from pydub import AudioSegment
AudioSegment.converter = "/usr/local/bin/ffmpeg"
sound = AudioSegment.from_file("/var/www/dev.com/public_html/track.mp3")
sound.export("/var/www/dev.com/public_html/test.mp3", format="mp3", bitrate="96k")
print "Content-type: text/html"
print
print ""
print ""
print ""
print "Done/ you can perform some conditions and print useful info here"
print ""
Give permissions to the script and make the public directory writable
Access the script http://localhost/your-path-to-script.py
I was able to run this properly.
let me know if that's not your case if you want something else

In my case, I did this code.
<?php
chdir('/home/pythontest') ; // python code dir
$commandline="/usr/bin/python3 test.py parameter" ;
exec($commandline, $output, $error) ;
echo $output ;
?>
If you need to set some environments for python, add environment vars like this.
$commmandline="LANG=en_US.utf8 LC_ALL=en_US.utf8 /usr/bin/python3 ..." ;
and check the httpd log.

Check this:
The apache user has to be in sudoers file, better you don't give sudo to apache instead give apache (www-data) user right to run your python program
put first line in your python script: #!/usr/bin/env python so the script knows which program to open it with..
then,
change group:
chgrp www-data /path/to/python-script.py
make it executabe:
chmod +x /path/to/python-script.py
then try it:
shell_exec("/path/to/python-script.py");
I hope this will work! :)

You can also exec ffmpeg directly without python:
$output = shell_exec("/usr/bin/ffmpeg -i in.mp3 -b:a 96k out.mp3");
echo $output;
ffmpeg docs

Answered in 2022.
In php 8.0 and above the following method worked. Above answers are very useful but i am compiling few extra steps here.
PHP Code.
$output = shell_exec("python3 /var/www/python/test.py");
print_r($output);
exec('python3 --version 2>&1', $output);
var_dump($output);
Trying both shell_exe and exec
Make sure the python file has executable permission and added to www-data group (if its ubuntu/debian systems) . sudo chmod +x test.py and sudo chgrp www-data test.py
Make sure the php.ini has disabled_functions line commented or empty.
sudo vim sudo vim /etc/php/8.0/cli/php.ini
sudo vim sudo vim /etc/php/8.0/apache2/php.ini
For both.
I compiled a simple video to make sure others dont spend more time figuring out the problem. https://youtu.be/t-f6b71jyoM

Related

Executing a linux program from php

Using the following software: http://silvercoders.com/en/products/doctotext/
I got it to work on my Window's machine using this following code:
<?php
$file = 'C:\xampp\htdocs\SMF\sdsdssss.docx';
$content = exec( 'C:\xampp\htdocs\SMF\doctotext\doctotext.exe /c '. $file , $output );
var_dump( $output );
However, when I tried it on my Centos machine, using the linux x86_64 version of the software, I cannot get it to work. (Yes, my machine is x86_64 too)
I tried:
<?php
$file = '/home/***/public_html/downloads/test_doc.docx';
$content = shell_exec( '/home/***/public_html/doctotext/doctotext.sh \c '. $file , $output );
But nothing outputs. What is the equivalent execution format for those running centos.
Please advise
First of all shell_exec() does not take a second argument. I think you are confusing the function with exec() which does take more than one argument:
exec('/home/***/public_html/doctotext/doctotext.sh \c '. $file, $output, $return);
From the documentation for shell_exec():
This function can return NULL both when an error occurs or the program produces no output. It is not possible to detect execution failures using this function. exec() should be used when access to the program exit code is required.
Second, I think you first should check so the shell script has execute permissions. You can set the correct permissions using:
chmod +x /home/***/public_html/doctotext/doctotext.sh
Depending on what the script is doing you might also need to run it with root privileges:
sudo php -f myscript.php
If you are running the script through your browser you should also make sure so that the path to the shell script is readable by the webserver.
It would also be nice if you enabled error reporting and check if you get any error messages when running your script.

ROS catkin_init_workspace not found when spawned as process by PHP

Let me elaborate: I am trying to spawn the catkin_init_workspace from PHP, using the proc_open like so:
touch( "$dir/stderr.txt" );
chmod( "$dir/stderr.txt", 0755 );
$fp = fopen("$dir/stderr.txt", "w");
fclose($fp);
$descr = array(
0 => array("pipe", 'r'), // stdin
1 => array("pipe", 'w'), // stdout
2 => array("file", "$dir/stderr.txt", "w")to file
);
$pid = proc_open( "catkin_init_workspace", $descr, $pipes, $dir );
if (!is_resource( $pid) )
throw new Exception ( "`catkin_init_workspace` exec failed");
else if ( is_resource( $pid ) )
{
fclose( $pipes[1] );
$retval = proc_close( $pid );
}
The above code has worked with CMake, with GCC and other applications.
However, when I try this with catkin_init_workspace, I get:
sh: 1: catkin_init_workspace: not found
Now, as far as I understand, catkin_init_workspace is a python script at:
/opt/ros/indigo/bin/catkin_init_workspace
I tried invoking it directly by using the absolute path, but that didn't work.
As a user, everything works fine. But not when I am executing via www-data, the user/group setup for Apache2.
ROS tutorial explain that I need to setup my environment variables, by running
source /opt/ros/indigo/setup.bash
Which I also tried doing via PHP, right before I invoke the proc_open, but to no avail.
My understanding is that I need to setup the environment variables correctly.
Doing
export | grep ROS
shows:
declare -x ROSLISP_PACKAGE_DIRECTORIES="/home/alex/Projects/ros_ws/devel/share/common-lisp"
declare -x ROS_DISTRO="indigo"
declare -x ROS_ETC_DIR="/opt/ros/indigo/etc/ros"
declare -x ROS_MASTER_URI="http://localhost:11311"
declare -x ROS_PACKAGE_PATH="/home/alex/Projects/ros_ws/src:/opt/ros/indigo/share:/opt/ros/indigo/stacks"
declare -x ROS_ROOT="/opt/ros/indigo/share/ros"
declare -x ROS_TEST_RESULTS_DIR="/home/alex/Projects/ros_ws/build/test_results"
Are those the environment variables I need to setup for www-data to correctly invoke catkin?
If so, how do I pass as an env array to PHP's proc_open, those variables?
As you already figured out, source /opt/ros/indigo/setup.bash has to be called in advance, otherwise your environment is not set up to find the ROS commands.
When you did this in PHP, I guess you used something like an additional proc_open or exec call or something similar before you call proc_open("catkin_init_workspace", ...)?
By doing this, the environment is probably only set up for this single call and it is not kept until you run catkin_init_workspace in another proc_open-call.
Possible Solution
I cannot test this here right now (no PHP installed), but the following should work:
Create a simple bash script with the following content:
#!/bin/bash
source /opt/ros/indigo/setup.bash
catkin_init_workspace
In PHP, call this script instead of catkin_init_workspace

php command line exec() multiple execution and directories?

I am trying to Execute a multiple commands in php using exec() and shell_exec but i am getting a null value back which i shouldn't and nothing is happening (if i copy and paste the strings below in the command line it will work fine and accomplish the job needed) this is the commands i am using:
$command = "cd /../Desktop/FolderName;";
$command .= 'export PATH=$PATH:`pwd`;';
$command .= 'Here i execute a compiler;';
and then i use the escapeshellcmd()
$escaped_command = escapeshellcmd($command);
then
shell_exec($escaped_command);
any ideas what i am doing wrong and i also tried escapeshellarg() instead of escapeshellcmd()?
Solution: the Problem was the permission of the execution compiler for other owners is non and this was the problem.
because when you are using exec() function in php the owner of the file will be www-data so you need to give permission for the www-data either from the ACL of ubuntu or whatever linux based operating system(you can know the owner by doing this exec('whoami')), or by the files you need to execute.
(Sorry my bad English)
On Linux you can add your Commands in a Shell Script.
You can put this in any file:
#!/bin/bash
cd /../Desktop/FolderName
export PATH=$PATH:`pwd`
EXECUTE COMPILER
And save this as fille.sh
Then, add execution permissions:
chmod +x path/to/file.sh
From PHP, you can call this Script executing:
shell_exec('sh path/to/file.sh');
Hope this helps!

PHP sudo in shell_exec

I want to execute a command as root with shell_exec. Now I know this is dangerous, but believe me, you need to login with MOD_AUTH and have the right privilleges to come to this page. It's secure. How can I get this done?
You could use the latest SVN version of phpseclib, a pure PHP SSH implementation, to do this. eg.
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
$ssh->login('username', 'password');
$ssh->read('[prompt]');
$ssh->write("sudo command\n");
$ssh->read('Password:');
$ssh->write("Password\n");
echo $ssh->read('[prompt]');
?>
The problem isn't that your page is or isn't secure, the problem is that giving a php page the ability to run some sudo command would give it to all pages including any injected code on any insecure page on any site on the server.
That said, it might be best to make a wrapper script that does just the one job that needs doing, then give the http user access to just that ONE command as sudo
http ALL=(ALL) NOPASSWD:/user/local/bin/your_wrapper_script.sh
Definitley not advised. However, you will want to look into editing the sudoers file and add the user php is running as a NOPASSWD for the command you need to run. This will only allow him to sudo that one command with out entering a password.
If you need more commands add more to it. Sudoers Configuration I know that forum/post is debian based but sudo is not strictly debian and that should help you out with the sudo configuration values that you need to put it.
I just Google'd for php sudo shell_exec and this came up as the #1 match:
http://www.php.net/manual/en/function.shell-exec.php#101440
ilya at linemedia dot ru 16-Dec-2010 04:36
sudo can be executed without storing pass in a file
system('echo "PASS" | sudo -u root -S COMMAND');
$aux=echo "admin-pass" | your command;
echo $aux;
/*******************************
************Example*************
*******************************/
Run a Perl script named my_perl_script.pl:
$aux=echo "admin-pass" | sudo -u root -S perl /path-to-the-script/my-perl-script.pl;
echo $aux;
Best way to do it:
$descriptorSpec = array(
0 => STDIN,
1 => STDOUT,
2 => STDERR,
);
if (posix_getuid() === 0) {
echo "Root\n";
} else {
echo "No root\n";
$command = 'sudo ' . PHP_BINARY . ' ' . implode(' ', $_SERVER['argv']);
$pipes = [];
$process = proc_open($command, $descriptorSpec, $pipes);
if (is_resource($process)) {
proc_close($process);
}
}
It runs the same command again, with sudo prefixed.

What is linux equivalent of running a .bat file on windows from PHP using system()

I have a PHP script that runs a .bat file on my windows machine using
$result = system("cmd /C nameOfBatchFile.bat");
This sets some environmental variables and is used to call Amazon EC2 API from the command line.
How do I do the same from a Linux server? I have renamed my .bat file to a shell (.sh) and changed the script to use 'export' when setting env vars. I have tested by running the code from a putty terminal and it does what it should. So I know the commands in the script are good. How do I run this from PHP? I have tried running the same command as above with the new filename and I don't get any errors, or file not found etc but it doesn't appear to work.
Where do I start trying to solve this?
---------------------------------- UPDATE -------------------------------
Here is the PHP script that calls the shell file -
function startAmazonInstance() {
$IPaddress = "1.2.3.4"
$resultBatTemp = system("/cmd /C ec2/ec2_commands.sh");
$resultBat = (string)$resultBatTemp;
$instanceId = substr($resultBat, 9, 10);
$thefile = "ec2/allocate_address_template.txt";
// Open the text file with the text to make the new shell file file
$openedfileTemp = fopen($thefile, "r");
contents = fread($openedfileTemp, filesize($thefile));
$towrite = $contents . "ec2-associate-address -i " . $instanceId . " " . $IPaddress;
$thefileSave = "ec2/allocate_address.sh";
$openedfile = fopen($thefileSave, "w");
fwrite($openedfile, $towrite);
fclose($openedfile);
fclose($openedfileTemp);
system("cmd /C ec2/mediaplug_allocate_address_bytemark.sh");
}
And here is the .sh file - ec2_commands.sh
#!/bin/bash
export EC2_PRIVATE_KEY=$HOME/.ec2/privateKey.pem
export EC2_CERT=$HOME/.ec2/Certificate.pem
export EC2_HOME=$HOME/.ec2/ec2-api-tools-1.3-51254
export PATH=$PATH:$EC2_HOME/bin
export JAVA_HOME=$HOME/libs/java/jre1.6.0_20
ec2-run-instances -K $HOME/.ec2/privateKey.pem -C $HOME/.ec2/Certificate.pem ami-###### -f $HOME/.ec2/aws.properties
I have been able to run this file from the command line so I know that the commands work ok. When I had this working on windows there would be a delay as the instance started up and I could echo the results to the screen. Now there is no delay as if nothing is happening.
Put a hash-bang on the first line of your shell script.
#!/bin/bash
Then give it the executable flag.
$ chmod a+x yourshellscript
You can then call it from PHP with system.
$result = system("yourshellscript");
$result = system("/bin/sh /path/to/shellfile.sh");
Is script executable? If not, make it so:
$ chmod a+x script.sh # shell
system ("/path/to/script.sh"); // PHP
or launch it via interpreter:
system("sh /path/to/script.sh"); // PHP
Is interpreter specified in shell script (ie. #!/bin/sh line)?
have you tried shell_exec() ?

Categories