Use PHP to run a shell script - php

Now I know this question has been asked a few times, but I've followed everyone's suggestions and I'm still stumped.
I have a shell script (/var/www/scripts/test.sh):
ssh_con="ssh-user#x.x.x.x"
key="/home/user/.ssh/key"
echo "export start"
ssh -i $key $ssh_con "php /file/location/ service:batch:job export --env=prod"
echo "export complete"
the script has the following permissions:
-rwxrwxrwx 1 www-data www-data 1792 Jun 3 10:44 bash_script.sh*
the code im running in php is:
try {
$outbuf=shell_exec("sh /var/www/scripts/test.sh");
echo "<pre>".$outbuf."</pre>";
}catch (Exception $e) { //while an error has occured
echo "==> Error: ".$e->getMessage();
exit();
}
When I view this from a web browser I get:
export start
export complete
However, ssh does not run.
I can confirm that php.ini allows exec and shell_exec.
I feel like I'm missing something obvious.

Since your script is already executable, you should call it directly. Just put a shebang on top and you've removed one layer of complication.
Next, redirect standard error from ssh to standard output so that PHP can show you any error messages.
I'd be willing to bet that you'll find ssh is complaining about the key. You'll need to put that key file somewhere else. An SSH key in a user directory typically has 600 permissions.
Finally, shell_exec() won't throw anything you can catch. If you want to know if the process succeeded, you can use a different function. In that case it might be a good idea to pass on the exit status that matters.
So, to sum up:
#!/bin/sh
ssh_con="ssh-user#x.x.x.x"
key="/home/user/.ssh/key"
echo "export start"
ssh -i "$key" "$ssh_con" "php /file/location/ service:batch:job export --env=prod" 2>&1
ssh_result=$?
echo "export complete"
exit ssh_result
And then:
<?php
exec("/var/www/scripts/test.sh", $outbuf, $result);
$outbuf = htmlspecialchars(implode("\n", $outbuf));
echo "Exited with code $result.";
echo "<pre>$outbuf</pre>";

More than likely, the script isn't executing properly because environment variables that are present in your terminal session may not be when run via PHP. So calling ssh or php without them being present in $PATH will not work.
Try running this immediately before your call to shell_exec():
putenv("PATH", "/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin");

Related

Trigger script on html form submit [duplicate]

I'm trying to run a Python script from PHP using the following command:
exec('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');
However, PHP simply doesn't produce any output. Error reporting is set to E_ALL and display_errors is on.
Here's what I've tried:
I used python2, /usr/bin/python2 and python2.7 instead of /usr/bin/python2.7
I also used a relative path instead of an absolute path which didn't change anything either.
I tried using the commands exec, shell_exec, system.
However, if I run
if (exec('echo TEST') == 'TEST')
{
echo 'exec works!';
}
it works perfectly fine while shutdown now doesn't do anything.
PHP has the permissions to access and execute the file.
EDIT: Thanks to Alejandro, I was able to fix the problem. If you have the same problem, don't forget that your webserver probably/hopefully doesn't run as root. Try logging in as your webserver's user or a user with similar permissions and try to run the commands yourself.
Tested on Ubuntu Server 10.04. I hope it helps you also on Arch Linux.
In PHP use shell_exec function:
Execute command via shell and return the complete output as a string.
It returns the output from the executed command or NULL if an error
occurred or the command produces no output.
<?php
$command = escapeshellcmd('/usr/custom/test.py');
$output = shell_exec($command);
echo $output;
?>
Into Python file test.py, verify this text in first line: (see shebang explain):
#!/usr/bin/env python
If you have several versions of Python installed, /usr/bin/env will
ensure the interpreter used is the first one on your environment's
$PATH. The alternative would be to hardcode something like
#!/usr/bin/python; that's ok, but less flexible.
In Unix, an executable file that's meant to be interpreted can indicate
what interpreter to use by having a #! at the start of the first line,
followed by the interpreter (and any flags it may need).
If you're talking about other platforms, of course, this rule does not
apply (but that "shebang line" does no harm, and will help if you ever
copy that script to a platform with a Unix base, such as Linux,
Mac, etc).
This applies when you run it in Unix by making it executable
(chmod +x myscript.py) and then running it directly: ./myscript.py,
rather than just python myscript.py
To make executable a file on unix-type platforms:
chmod +x myscript.py
Also Python file must have correct privileges (execution for user www-data / apache if PHP script runs in browser or curl)
and/or must be "executable". Also all commands into .py file must have correct privileges.
Taken from php manual:
Just a quick reminder for those trying to use shell_exec on a
unix-type platform and can't seem to get it to work. PHP executes as
the web user on the system (generally www for Apache), so you need to
make sure that the web user has rights to whatever files or
directories that you are trying to use in the shell_exec command.
Other wise, it won't appear to be doing anything.
I recommend using passthru and handling the output buffer directly:
ob_start();
passthru('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');
$output = ob_get_clean();
If you want to know the return status of the command and get the entire stdout output you can actually use exec:
$command = 'ls';
exec($command, $out, $status);
$out is an array of all lines. $status is the return status. Very useful for debugging.
If you also want to see the stderr output you can either play with proc_open or simply add 2>&1 to your $command. The latter is often sufficient to get things working and way faster to "implement".
To clarify which command to use based on the situation
exec() - Execute an external program
system() - Execute an external program and display the output
passthru() - Execute an external program and display raw output
Source: http://php.net/manual/en/function.exec.php
Alejandro nailed it, adding clarification to the exception (Ubuntu or Debian) - I don't have the rep to add to the answer itself:
sudoers file:
sudo visudo
exception added:
www-data ALL=(ALL) NOPASSWD: ALL
In my case I needed to create a new folder in the www directory called scripts. Within scripts I added a new file called test.py.
I then used sudo chown www-data:root scripts and sudo chown www-data:root test.py.
Then I went to the new scripts directory and used sudo chmod +x test.py.
My test.py file it looks like this. Note the different Python version:
#!/usr/bin/env python3.5
print("Hello World!")
From php I now do this:
$message = exec("/var/www/scripts/test.py 2>&1");
print_r($message);
And you should see: Hello World!
The above methods seem to be complex. Use my method as a reference.
I have these two files:
run.php
mkdir.py
Here, I've created an HTML page which contains a 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");
This is so trivial, but just wanted to help anyone who already followed along Alejandro's suggestion but encountered this error:
sh: blabla.py: command not found
If anyone encountered that error, then a little change needs to be made to the php file by Alejandro:
$command = escapeshellcmd('python blabla.py');
All the options above create new system process. Which is a performance nightmare.
For this purpose I stitched together PHP module with "transparent" calls to Python.
https://github.com/kirmorozov/runpy
It may be tricky to compile, but will save system processes and will let you keep Python runtime between PHP calls.
Inspired by Alejandro Quiroz:
<?php
$command = escapeshellcmd('python test.py');
$output = shell_exec($command);
echo $output;
?>
Need to add Python, and don't need the path.

Problems while calling python in PHP [duplicate]

I'm trying to run a Python script from PHP using the following command:
exec('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');
However, PHP simply doesn't produce any output. Error reporting is set to E_ALL and display_errors is on.
Here's what I've tried:
I used python2, /usr/bin/python2 and python2.7 instead of /usr/bin/python2.7
I also used a relative path instead of an absolute path which didn't change anything either.
I tried using the commands exec, shell_exec, system.
However, if I run
if (exec('echo TEST') == 'TEST')
{
echo 'exec works!';
}
it works perfectly fine while shutdown now doesn't do anything.
PHP has the permissions to access and execute the file.
EDIT: Thanks to Alejandro, I was able to fix the problem. If you have the same problem, don't forget that your webserver probably/hopefully doesn't run as root. Try logging in as your webserver's user or a user with similar permissions and try to run the commands yourself.
Tested on Ubuntu Server 10.04. I hope it helps you also on Arch Linux.
In PHP use shell_exec function:
Execute command via shell and return the complete output as a string.
It returns the output from the executed command or NULL if an error
occurred or the command produces no output.
<?php
$command = escapeshellcmd('/usr/custom/test.py');
$output = shell_exec($command);
echo $output;
?>
Into Python file test.py, verify this text in first line: (see shebang explain):
#!/usr/bin/env python
If you have several versions of Python installed, /usr/bin/env will
ensure the interpreter used is the first one on your environment's
$PATH. The alternative would be to hardcode something like
#!/usr/bin/python; that's ok, but less flexible.
In Unix, an executable file that's meant to be interpreted can indicate
what interpreter to use by having a #! at the start of the first line,
followed by the interpreter (and any flags it may need).
If you're talking about other platforms, of course, this rule does not
apply (but that "shebang line" does no harm, and will help if you ever
copy that script to a platform with a Unix base, such as Linux,
Mac, etc).
This applies when you run it in Unix by making it executable
(chmod +x myscript.py) and then running it directly: ./myscript.py,
rather than just python myscript.py
To make executable a file on unix-type platforms:
chmod +x myscript.py
Also Python file must have correct privileges (execution for user www-data / apache if PHP script runs in browser or curl)
and/or must be "executable". Also all commands into .py file must have correct privileges.
Taken from php manual:
Just a quick reminder for those trying to use shell_exec on a
unix-type platform and can't seem to get it to work. PHP executes as
the web user on the system (generally www for Apache), so you need to
make sure that the web user has rights to whatever files or
directories that you are trying to use in the shell_exec command.
Other wise, it won't appear to be doing anything.
I recommend using passthru and handling the output buffer directly:
ob_start();
passthru('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');
$output = ob_get_clean();
If you want to know the return status of the command and get the entire stdout output you can actually use exec:
$command = 'ls';
exec($command, $out, $status);
$out is an array of all lines. $status is the return status. Very useful for debugging.
If you also want to see the stderr output you can either play with proc_open or simply add 2>&1 to your $command. The latter is often sufficient to get things working and way faster to "implement".
To clarify which command to use based on the situation
exec() - Execute an external program
system() - Execute an external program and display the output
passthru() - Execute an external program and display raw output
Source: http://php.net/manual/en/function.exec.php
Alejandro nailed it, adding clarification to the exception (Ubuntu or Debian) - I don't have the rep to add to the answer itself:
sudoers file:
sudo visudo
exception added:
www-data ALL=(ALL) NOPASSWD: ALL
In my case I needed to create a new folder in the www directory called scripts. Within scripts I added a new file called test.py.
I then used sudo chown www-data:root scripts and sudo chown www-data:root test.py.
Then I went to the new scripts directory and used sudo chmod +x test.py.
My test.py file it looks like this. Note the different Python version:
#!/usr/bin/env python3.5
print("Hello World!")
From php I now do this:
$message = exec("/var/www/scripts/test.py 2>&1");
print_r($message);
And you should see: Hello World!
The above methods seem to be complex. Use my method as a reference.
I have these two files:
run.php
mkdir.py
Here, I've created an HTML page which contains a 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");
This is so trivial, but just wanted to help anyone who already followed along Alejandro's suggestion but encountered this error:
sh: blabla.py: command not found
If anyone encountered that error, then a little change needs to be made to the php file by Alejandro:
$command = escapeshellcmd('python blabla.py');
All the options above create new system process. Which is a performance nightmare.
For this purpose I stitched together PHP module with "transparent" calls to Python.
https://github.com/kirmorozov/runpy
It may be tricky to compile, but will save system processes and will let you keep Python runtime between PHP calls.
Inspired by Alejandro Quiroz:
<?php
$command = escapeshellcmd('python test.py');
$output = shell_exec($command);
echo $output;
?>
Need to add Python, and don't need the path.

PHP/Ubuntu - QxcbConnection: Could not connect to display aborted

I am using a php script on my apache/ubuntu server to call a bash script that triggers an application taking a python script as an argument (IDAPro).
PHP Code
chdir('/var/www/dashboard/team/static/sql');
$output = exec('sudo -u rohan ./start.sh');
Now, the above code works fine if I run the PHP file from the terminal - but only if I run it as the root user. Needless to say, if I execute the bash file directly it runs too.
But when I run the PHP file on the browser, it doesn't work and I get the following error in the apache error log:
QXcbConnection: Could not connect to display
Aborted
I understand that Apache/php runs as 'www-data' user (used the 'whoami' to verify), and that is why I have the sudo in my exec. I have tweaked and tinkered the permissions for both users to no avail. When I run the php file from the terminal as the 'www-data' user, it throws no error but does not do anything except display the random echo tags I at the start and end of the script to debug it.
I am a linux novice, so any help is greatly appreciated.
Okay, I finally managed to solve it.
The issue is not with the permissions, but it is with the environment variables.
I had to include the following line in my bash script
export DISPLAY=':0.0'
Note that setting the variable in the terminal and running the script does not work. The line needs to be inside the script.
I assume this is because the DISPLAY variable is not set if you run the script as any user other than root, which is what happens in case of Apache/PHP where the script is executed as the 'www-data' user.
perhaps you could use something like the following at the top of your script:
if [ "$(id -un)" != "rohan" ]; then
exec sudo -u rohan $0 "$#"
fi
export XAUTHORITY=/home/rohan/.Xauthority
export DISPLAY=:0

php Why can't I run a batch file?

I have tried to run a batch file using PHP:
$script = "\\\MAFINFWWWPV02\D$\WebContent\\engsys.corp.ftr.com\BatchFiles\CopyFiles.bat";
exec($script,$ReturnArray,$ReturnValue);
//shell_exec($script);
//system('cmd /c $script');
//system($script,$ReturnValue);
None of these work! I've tried
var_dump($ReturnValue); echo "<br>";
var_dump($ReturnArray); echo "<br>";
to try and see what is going on, but I get what appears to be normal output like this:
int(1)
array(0) { }
But the files that I'm trying to copy with my bat file, which works fine when run manually, don't get copied!
Edit additional question
Do the \ need to be escaped in the file address?
EDIT 2
Here's what I get from running icacls:
CopyFiles.bat NT AUTHORITY\IUSR:(I)(RX)
NT AUTHORITY\SYSTEM:(I)(F)
NT AUTHORITY\NETWORK:(I)(RX)
CORP\ibb601:(I)(F)
CORP\taw330:(I)(F)
CORP\mmm976:(I)(F)
BUILTIN\Administrators:(I)(F)
BUILTIN\Users:(I)(RX,W)
I have full control and everybody else has at least read/execute.
EDIT 3
I have narrowed it down. It's not that the commands are not working it's that permission is denied to the files. Which I don't understand since everyone has write and read/execute access to the entire folder.
EDIT 4
I am running the commands from above trying to get it to work. I am using a function (var_export(my_exec("shell_exec($script)"));) to print what the errors are to my screen. I keep getting something like this:
'\'shell_exec\' is not recognized as an internal or external command, operable program or batch file.
I get a different one for each shell_exec, system, and exec. It just keeps saying that the command is not recognized. This is being executed on a Windows Server 2012 R2 Standard 64-bit. Is there something that I'm doing wrong with the commands?
Function that I'm using to print errors (I found it on another post):
function my_exec($cmd, $input='')
{
$proc=proc_open($cmd, array(0=>array('pipe', 'r'), 1=>array('pipe', 'w'), 2=>array('pipe', 'w')), $pipes);
fwrite($pipes[0], $input);fclose($pipes[0]);
$stdout=stream_get_contents($pipes[1]);fclose($pipes[1]);
$stderr=stream_get_contents($pipes[2]);fclose($pipes[2]);
$rtn=proc_close($proc);
return array('stdout'=>$stdout,'stderr'=>$stderr,'return'=>$rtn);
}
I finally got it to work. Here's what I ended up with:
$script = chr(92) . chr(92) . 'MAFINFWWWPV02\D$\WebContent\engsys.corp.ftr.com\BatchFiles\CopyFiles.bat';
if (!file_exists($script))
{
var_dump($script); echo " Script<br>";
echo "Script doesn't exist!<br>";
var_dump(!file_exists($script));
}
else
{
system('cmd /c ' . $script); echo " <br>";
}
Sometimes I still get the Script doesn't exist! message, but that is usually when I'm connected to the #1 server and not the #2 server. The .nat looks like this:
echo off
SET source2="\\MAFINFWWWPV02\engsys.corp.ftr.com"
START /wait NET USE L: "\\MAFINFWWWPV01\engsys.corp.ftr.com" Password /user:UserName
xcopy %source2% L: /E /Y /Q
NET USE L: /DELETE
You don't need to escape \ when inside single quotes.
If you want to run a script, make sure is exists and is executable:
$script = '\\MAFINFWWWPV02\engsys.corp.ftr.com\CopyFiles.bat';
if (!file_exists($script) || !is_executable($script)) {
// Im' sorry dave
}
// carry on...
If the script is run through a webserver, make sure the user running the service has execute rights, not your own user! is_executable only checks if the file is an executable, not if the user running the script has executable rights
Since your return code is 1, you probably have some permission issue. A successful execution has return code 0
Also consider the following note from the docs:
Note: When safe mode is enabled, you can only execute files within the safe_mode_exec_dir. For practical reasons, it is currently not allowed to have .. components in the path to the executable.
To have a OS agnostic method of running exernal processes, have a look at the Symfony Process component
after many hours. you should try
c:\\a\\b\\c
instead of
c:\a\b\c

run shell script from php

I am attempting to create a php script that can connect thru ssh to my Qnap TS219 server and run a command on it.
My script so far connects fine to the server but when I run the command I get an error message and I can't figure it out.
exec.sh
#!/bin/bash
cp /share/MD0_DATA/Qdownload/rapidshare/admin/script.txt /share/MD0_DATA/Qdownload/rapidshare/admin/script.sh
chmod 755 /share/MD0_DATA/Qdownload/rapidshare/admin/script.sh
nohup sh /share/MD0_DATA/Qdownload/rapidshare/admin/script.sh &
exit 0
script.sh
#!/bin/bash
/opt/bin/plowdown -o /share/MD0_DATA/Qdownload/rapidshare /share/MD0_DATA/Qdownload/rapidshare/admin/down.txt 2>/share/MD0_DATA/Qdownload/rapidshare/admin/output.txt
the command that I am currently running thru ssh after I submit the form:
echo $ssh->exec('sh /share/MD0_DATA/Qdownload/rapidshare/admin/exec.sh');
Right now generates the code below but only after I kill 2 bash processes (the page keeps loading indefinetly and the processor activity is at 100% if I don't kill the 2 bash processes):
/share/MD0_DATA/.qpkg/Optware/share/plowshare/lib.sh: line 261: getopt: command not found start download (rapidshare): http://rapidshare.com/files/312885386/Free_Stuff-Your_Internet_eBay_Business_Free_Startup_Resources.rar /share/MD0_DATA/.qpkg/Optware/share/plowshare/lib.sh: line 261: getopt: command not found /share/MD0_DATA/.qpkg/Optware/share/plowshare/lib.sh: line 46: --insecure: command not found Error: failed inside rapidshare_download()
This script will be used in my local network, no access from outside, so I am not worry about security, I know the code looks very basic, primitive but I have no experience with php, shell script, so if someone can make any sense on this and help me out will be greatly appreciated.
Edit1. I also tried the shell_exec command still no joy and if I run the script thru putty works beautifully.
Edit2. I think we are on to something.
I added the code you suggested and I got the following message.
sh: /share/MD0_DATA/.qpkg/Optware/share/plowshare: is a directory /usr/bin:/bin:/usr/sbin:/sbin
I think at the moment the PATH is usr/bin:/bin:usr/sbin:/sbin and I think it should be /opt/bin /opt/sbin because there are the "executables". Any ideeas?
Thanks,
Chris.
Run this
echo $ssh->exec('pwd');
Does it list your path correctly? If so then your problem is NOT PHP, if it doesn't list or still gives an error then PHP is your problem and we can continue from there.
From the error you've listed, my first guess would be that PATH isn't set, so lib.sh can't find what it's looking for.
Remember you're logging in with a custom shell (PHP ssh), quite often things aren't set as they should be, so your scripts might not find requirements like paths and variables.
Edit:
Since it's giving /root, we at least know it's going through, why not also set the PATH etc...
echo $ssh->exec('PATH=$PATH;/share/MD0_DATA/.qpkg/Optware/share/plowshare; sh /share/MD0_DATA/Qdownload/rapidshare/admin/exec.sh');
Remember you can also use this to see what is and isn't being set.
echo $ssh->exec('ECHO $PATH');
I think I got it:
Following viper_sb logic, I changed the code to:
echo $ssh->exec('PATH=$PATH:/share/MD0_DATA/.qpkg/Optware/bin; sh /share/MD0_DATA/Qdownload/rapidshare/admin/exec.sh');
echo $ssh->exec('echo $PATH');
and magic, it worked ... I'll test it further, when I get home, but I think it worked, a file was downloaded in the /Qdownload/rapidshare folder ... hooray.

Categories