The Apache’s user www-data need to be granted privileges to execute certain applications using sudo.
- Run the command
sudo visudo. Actually we want to edit the file inetc/sudoers.To do that, by usingsudo visudoin terminal ,it duplicate(temp)sudoersfile to edit. - At the end of the file, add the following ex:-if we want to use command for
restartsmokeping andphpcommand for another action in your question,
www-data ALL=NOPASSWD: /etc/init.d/smokeping/restart, usr/bin/php
(This is assuming that you wish to run restart and php commands using super user
(root) privileges.And you use php command in usr/bin/ path )
However, if you wish to run every application using
super user privileges, then add the following instead of what’s above.You might not want to do that, not for ALL commands, very dangerous.
www-data ALL=NOPASSWD: ALL
3.After edit the sudoers file(by visudo we edit the temp file of sudoers so save and quit temp file(visudo) to write in sudoers file.(wq!)
4.That’s it, now use exec() or shell_exec in the following manner inside your xxx.phpscript.keep remember to use sudo before the command use in the php script.
ex:-
exec ("sudo /etc/init.d/smokeping restart 2>&1");
or
shell_exec("sudo php -v");
So in your problem,add the commands that you wish to use in to the step no (2.) as I add and change your php script as what you want.
here is the same problem as yours https://stackoverflow.com/a/22953339/1862107
Answer from Thusitha Sumanadasa on Stack ExchangeThe Apache’s user www-data need to be granted privileges to execute certain applications using sudo.
- Run the command
sudo visudo. Actually we want to edit the file inetc/sudoers.To do that, by usingsudo visudoin terminal ,it duplicate(temp)sudoersfile to edit. - At the end of the file, add the following ex:-if we want to use command for
restartsmokeping andphpcommand for another action in your question,
www-data ALL=NOPASSWD: /etc/init.d/smokeping/restart, usr/bin/php
(This is assuming that you wish to run restart and php commands using super user
(root) privileges.And you use php command in usr/bin/ path )
However, if you wish to run every application using
super user privileges, then add the following instead of what’s above.You might not want to do that, not for ALL commands, very dangerous.
www-data ALL=NOPASSWD: ALL
3.After edit the sudoers file(by visudo we edit the temp file of sudoers so save and quit temp file(visudo) to write in sudoers file.(wq!)
4.That’s it, now use exec() or shell_exec in the following manner inside your xxx.phpscript.keep remember to use sudo before the command use in the php script.
ex:-
exec ("sudo /etc/init.d/smokeping restart 2>&1");
or
shell_exec("sudo php -v");
So in your problem,add the commands that you wish to use in to the step no (2.) as I add and change your php script as what you want.
here is the same problem as yours https://stackoverflow.com/a/22953339/1862107
Try specifying the entire path to the php binary.. Eg, /usr/bin/php
If you don't know it, find it using: which php
If you say it works on the terminal and not on apache then apache's php.ini file may be disabling the use of shell_exec().
See http://www.php.net/manual/en/ini.core.php#ini.disable-functions
Your apache's php.ini file may look something like
disable_functions=exec,passthru,shell_exec,system,proc_open,popen
Remove shell_exec from this list and restart the web server, although this is a security risk and I don't recommend it.
shell_exec might not know what directory to look in for your executable's location directory. What solved it for me was this before the shell_exec:
putenv('PATH=/usr/local/bin');
Then the terminal can find the executable. Also check permissions on every part of the command to make sure apache user has read and execute permissions.
PHP exec() not working | php.ini is fine
Shell_exec is not working
linux - PHP shell_exec() doesn't work but commands work from console - Stack Overflow
Executing a shell command from PHP with shell_exec - Unix & Linux Stack Exchange
Videos
The question is a bit old, but for those who experience this problem can try to set the environment variables of direct on the server. PHP uses the putenv () function.
Example:// Set Variable Enviromental
$JAVA_HOME = "/usr/lib/jvm/java-8-oracle"; $ANDROID_HOME = "/opt/android-sdk-linux"; $PATH="$JAVA_HOME/bin:/usr/local/bin:/usr/bin:/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$ANDROID_HOME/build-tools/24.0.0-preview"; putenv ("JAVA_HOME = $JAVA_HOME"); putenv ("PATH = $PATH");
Most likely, your $PATH is set incorrectly. Specify the full path to android, or set your path via something like this:
<?php
putenv(
implode(PATH_SEPARATOR, array('/dir/containing/android', getenv('PATH')))
);
$fname = $_POST['fname'];
$fpack = $_POST['fpack'];
$email = $_POST['email'];
// Create a new Android project
var_dump(shell_exec("android create project --target 8 --name $fname --path ./$fname --activity MainActivity --package $fpack 2>&1"));
There's multiple problems here.
- Do people even read the error messages they get?
- Don't use shell commands to read a file to a variable! Use
fopen. - Don't do globbing. Globs are expanded by the shell, but PHP is not a shell, so it doesn't do globbing. It hands your exact command off to the shell, and asks the shell to execute it. And yes,
*-releaseis a valid filename.
[~]$ ls -la /tmp/\*-releases
-rw-r--r-- 1 vidarlo users 0 Jun 23 10:16 /tmp/*-releases
[~]$
- Globbing potentially opens you to attacks. If you glob, you have no control over what files you end up reading. That's a potential security issue. Probably not in this case, as you're reading from
/etc, but... - You lack a basic understanding about your environment, when you expect that modifying a path parameter will change anything - the problem is not that
catcommand is not found, it's that the file you give as parameter is not found... A general understanding of the platform is a good starting point for programming. putenv('/etc');is not howputenvworks. Environment variables are generallykey=value-pairs.- Don't post it on serverfault. It's not about managing IT, it's purely about programming. Additionally, you should probably spend some time to learn the platform you're working on.
The problem was that PHP was setup to run in chroot jail. I had exhausted all other possibilities. I only even discovered it thanks to @vidarlo's comment.
I was able to resolve the issue in WHM via the CageFS plugin. The Linux user that PHP uses was set to execute and I removed it from the association.
On the php manual for shell_exec, it shows that the function returns the output as a string. If you expect output from the program you launch, you need to capture this like so:
$execQuery = "echo -n test_command";
$output = shell_exec($execQuery);
echo $output;
Your question doesn't show trying to capture any data. If you also make sure to connect stdout and stderr when you run your command, you should get a better idea is what is going on. To use your example:
$output = shell_exec("/usr/bin/oneuser create test10 test10 2>&1");
var_dump($output);
That should help you see what is going on. As Shadur suggests, it seems likely that these programs expect an interactive terminal that can enter passwords in order to run. Even if don't need input, they might expect interactive shells. And he's right that su doesn't play nice in this context. There is, however, a correct tool for the job.
You can setup sudo to such that your http user can execute your program as username without a password but NOT be able to do anything else by running visudo or whatever you use to edit your sudoers file and adding this line:
http ALL=(username) /usr/bin/oneadmin
Then in php your command would look something like this:
$execQuery = "sudo -u username /usr/bin/oneadmin postgres -c '/usr/bin/oneuser create test10 test10'";
$out = shell_exec ("$execQuery 2>&1");
echo $out
Try passthru($cmd);
It will allow user's I/O on the Terminal screen.
Hello,
I have a php script that execute a Shell. It is supposed to execute a .ps1 when i request the page.
It was working fine but a coworker had to reboot the IIS VM running php 8 with CGI. The script is not working anymore and is giving me a blank page when i request it.
<?php echo Shell_exec ('Powershell.exe -ExecutionPolicy Bypass -NoProfile -File ".\dev.ps1"'); ?>What i did so far :
Checking the php.ini file to make sure Shell_exec wasn't in Disable_functions="".
Changing the FastCGI Protocol configuration from "Named pipe" to "TCP"
Rebooting, of course
Thanks,
1) Check the security setup
Can shell_exec() be run or not? If it can't then it's because
you are having some security settings enabled.
The problem is that shell_exec() and exec() can be disabled
for security reasons. This can be changed by editing
PHP's disable_functions option.
INI settings are usually stored in specific *.ini files under the
/etc/php/* directories. So you have to look for some settings
in there. You’ll find several INI settings, depending on how PHP is
run. To find them :
find /etc/php/ -iname 'php.ini'
This could output something like this :
/etc/php/8.2/fpm/php.ini
/etc/php/8.2/apache2/php.ini
/etc/php/8.2/cli/php.ini
/etc/php/8.2/cgi/php.ini
To see the settings and which INI file is loaded, add this at the beginning of your script and call it via your web server :
phpinfo();
die();
You'll see all the loaded INI files and what is set on the
disable_functions option.
/etc/php/8.2/cli/php.ini is probably setting disable_functions
to an empty string, meaning that in command line there's no
restriction. But for the other INI files, this option might contain
a list of functions that you won't be able to run. Edit this option
if needed. But be always aware that giving your server the ability
to run some binaries can lead to some security issues if your app
is taking some user input to build the command.
Apache configuration can also set some
PHP settings,
just for a specific Virtual Host. So have a look at them if you can't
find something in the php.ini files.
Depending on your PHP setup, you may also have to check safe_mode and suhosin.executor.* if you have the Suhosin hardening module installed.
2) Verify that you can run shell_exec
There are several ways to run a binary.
shell_exec
is equivalent to the built-in
backtick operator.
So if shell_exec is listed in the disable_functions option then
you won't be able to use the backtick operator.
If you get an error 500 then it's typically because you cannot run
shell_exec. If you check /var/log/nginx/error.log or
/var/log/apache2/error.log with this command :
sudo tail -f /var/log/{apache2,nginx}/error.log
It will print both logs until you press CTRL+C. You may see this error :
PHP Fatal error: Uncaught Error: Call to undefined function shell_exec()
PHP also offers
exec(),
passthru(),
system(),
and the
proc_*()
functions. So you've got several possibilities to try and run your
command.
Have a try with a simple PHP code :
<?php
header('Content-Type: text/plain; charset=utf-8');
echo 'PHP user given with the "id" command: ' . `id`; // equivalent to shell_exec('id');
echo 'System date is ' . `date --iso-8601=seconds`;
This should output RAW text in your browser with :
PHP user given with the "id" command: uid=33(www-data) gid=33(www-data) groups=33(www-data)
System date is 2023-09-29T11:50:28+00:00
3) Use a full path to the binary
When shell_exec() is run from the web server, it's rather common
that the binary isn't found in the PATH.
Usually, the www-data user running PHP won't even have a shell.
But this user can normally run some binaries, except if some settings
at point 1 is blocking it.
To find the full path to a binary, use the which command :
which wkhtmltopdf
This should output the full path to the binary. Certainly something
such as /usr/bin/wkhtmltopdf.
Now replace your PHP code with the full path to the binary:
header('Content-Type: text/plain; charset=utf-8');
echo shell_exec('/usr/bin/wkhtmltopdf --version');
Does it print wkhtmltopdf 0.12.6 like expected?
If no, then we have to investigate more at the next point.
4) Get the execution output and find errors
This can be done with the help of exec(), passthru() or system()
as they all return the execution status code.
With the proposition of Volkerschulz, we'll also redirect the standard error stream to the standard output stream so that we can see some details that may have only be printed to the error stream.
This is done by redirecting stderr (2) into stdout (1) by adding 2>&1 after your command.
Just as info, stdin is 0.
In PHP, this becomes :
<?php
header('Content-Type: text/plain; charset=utf-8');
$command = '/usr/bin/wkhtmltopdf --wrong-option 2>&1';
$last_line = exec(
$command, // The command to execute.
$output, // A variable that will be filled with an array of all the lines returned.
$result_code // The return status of the executed command.
);
var_export([
'$command' => $command,
'$output' => $output,
'$last_line' => $last_line,
'$result_code' => $result_code,
]);
This outputs :
array (
'$command' => '/usr/bin/wkhtmltopdf --wrong-option 2>&1',
'$output' =>
array (
0 => 'Unknown long argument --wrong-option',
1 => '',
2 => 'Name:',
3 => ' wkhtmltopdf 0.12.6',
...
...
95 => '',
),
'$last_line' => '',
'$result_code' => 1,
)
Now I'm able to see that I got a $result_code of 1 instead of 0.
In case the executable is having other errors, you'll see them in
the $output array as the stderr stream should be visible. This
should help you find how to fix the issue. Probably some other
security problems due to the fact the www-data user might be
missing some rights, paths or whatever.
PS: On my Vagrant box of Ubuntu 22.04, I managed to run wkhtmltopdf without errors on both Apache and NGINX.
Don't forget also that your www-data user should have write
access to the destination folder where you are producing the PDF file.
5) Try re-installing wkhtmltopdf and/or use a PHP wrapper
You might have to re-install wkhtmltopdf if it's not properly working :
sudo apt remove wkhtmltopdf
sudo apt autoremove
sudo apt install wkhtmltopdf
You can also try using a PHP wrapper library for wkhtmltopdf called Snappy. It might be useful.
6) Switch to an alternative in pure PHP if necessary
Perhaps you won't manage to make wkhtmltopdf work that easily.
It's a pity as it's effectively a fast and reliable solution.
But to create a PDF from HTML you could also use the Dompdf PHP library. I've used it in the past and was happy with it.
Instead of
shell_exec($wkhtmltopdfCommand);
try
$result = passthru($wkhtmltopdfCommand . ' 2>&1');
var_dump($result);
and it should tell you what's wrong.
Hi all I'm trying to SvtAv1EncApp tools via web interface, I try to us both exec() shell_exec() with no success , BTW I print the command and run it into the shell directly and it's works perfectly fine.
$cmd2="/usr/local/bin/ffmpeg -loglevel -8 -i "$mp4" -s 960x540 -strict -1 -f yuv4mpegpipe - | /usr/local/bin/SvtAv1EncApp --no-progress -i stdin --rc 0 -q 38 --preset 8 -b stdout 2>/var/www/vl/ffmpeg.log | /usr/local/bin/ffmpeg -loglevel -8 -y -i - -i "$mp4" -map 0:v -map 1:a:0 -c:v copy $a '".$mpa."_.mkv' & ";
shell_exec( $cmd2 ) ;
Here is the text of echo $cmd2 output
/usr/local/bin/ffmpeg -loglevel -8 -i "FHD.mp4" -s 960x540 -strict -1 -f yuv4mpegpipe - | /usr/local/bin/SvtAv1EncApp --no-progress -i stdin --rc 0 -q 38 --preset 8 -b stdout 2>/var/www/vl/ffmpeg.log | /usr/local/bin/ffmpeg -loglevel -8 -y -i - -i "FHD.mp4" -map 0:v -map 1:a:0 -c:v copy -strict -2 -c:a libopus -b:a 64k 'FHD_.mkv' &
=Update=
I kinda solve it , I don't know why but exec() successfully executed the script , I created new bash script from command line thanks to @xisonc suggesting nano /usr/local/sbin/av1c with this value
!/bin/sh
touch /var/www/vl/ffmpeg.log /usr/local/bin/ffmpeg -loglevel -8 -i "$1" -s 960x540 -strict -1 -f yuv4mpegpipe -
| /usr/local/bin/SvtAv1EncApp --no-progress -i stdin --rc 0 -q 38 --preset 8 -b stdout 2>/var/www/vl/ffmpeg.log
| /usr/local/bin/ffmpeg -loglevel -8 -y -i - -i "$1" -map 0:v -map 1:a:0 -c:v copy -strict -2 -c:a libopus -b:a 64k "$2"
On the php script i had this
$cmd2="/usr/local/sbin/av1c '$mp4' '$mpa"."_.mkv' 2>/dev/null >/dev/null & " ; exec( $cmd2 , $pid, $r ) ; var_dump( $r ) ;
var_dump returns 0 , and since the bash script are silent I don't need to see the output , now I want to change it to wok on the background it's running on background now after adding 2>/dev/null >/dev/null & at the end of the command .