I have a small script I tested on the command line using php test.php.
test.php
<?php
exec('ps -acux | grep test', $testvar);
print_r($testvar);
?>
This works fine. I am able to run the script and get the desired result. However, when I add the code to a file being run by my PHP server, the result is empty.
My OS is FreeBSD. Looking at the man page for ps the only restriction I see is on the -a option. It states:
If the security.bsd.see_other_uids sysctl is set to zero, this option
is honored only if the UID of the user is 0.
My security.bsd.see_other_uids is set to 1.
$ sysctl security.bsd.see_other_uids
security.bsd.see_other_uids: 1
The only thing I can think of is that the command is being run by my user when I run it via the command line whereas when run by PHP, it's being run by www. I'm not seeing anything in the manual of ps that indicates www shouldn't be able to run the command.
As per the comments you need to redirect stderr to stdout. This is achieved by 2>&1 to the end of your command. So an example of the PHP exec() is as follows:
exec('ps -acux | grep test 2>&1', $testvar);
This allows you to see potential errors. In my case there was no error and likely a bug of some sorts. However this is useful in all cases where you execute a command. If any error were to occur you can retrieve it to see what is happening with your command.
Related
EDIT - Adding new info at the top for visibility. The www-data user can't use the exec() command. All attempts return a 127 error.
I setup a simple script that is just this
<?php
$res = exec("echo EXEC", $res1, $res2);
var_dump($res);
var_dump($res1);
var_dump($res2);
?>
When executed via the application (which of course runs as www-data) this returns the 127 error code.
When executed via this command it runs flawlessly sudo -u root php testExec.php
When executed via this command it again returns the 127 error code sudo -u www-data php testExec.php
Original Question
I can only seem to get the error code 127 back when trying to use the exec command in php. I'm trying to use the https://github.com/rialto-php/puphpeteer package to generate pdfs and it was working flawlessly but I can't find what changed that is causing it to fail now.
I've been using /usr/local/.nvm/versions/node/v14.2.0/bin/node as the path to node but I also tried copying it here /node/v16.14.2/bin so I could give the entire directory structure execute permissions. In either/both places node is owned by www-data (the user that php runs as) and has execute permissions (755).
Running '/node/v16.14.2/bin/node' '/var/www/html/vendor/nesk/puphpeteer/src/get-puppeteer-version.js' (the initial command that puphpeteer generates) from the command line works just fine and returns the expected result "5.5.0" so node is there and executable and the get-puppeteer-version script exists.
After troubleshooting that I decided to just test exec and discovered that that doesn't work for any commands. I've tried just running exec("date"); and exec("echo EXEC") and these also return the same exit code 127.
The disable_functions ini setting is empty (confirmed via empty result from ini_get('disable_functions')). Safe mode is not enabled (confirmed via false result from ini_get('safe_mode')).
If anyone has any insight into why exec won't work at all would be great!
Environment:
Ubuntu 18.04.4
PHP 8.1
So after further investigation.. I found that this was indeed a permissions issue. I had double checked that node and everything in the /bin folder had appropriate execute permissions..
What I had missed (and am not sure how it got changed) was that the /bin folder itself didn't have the appropriate execute permissions. Adding those immediately fixed my issue.
I'm trying to use PHP to trigger a bash script that should never stop running. It's not just that the command needs to run and I don't need to wait for output, it needs to continue running after PHP is finished. This has worked other times (and the question has been asked already), the difference seems to be my bash script has a trap for when it's closed.
Here is my bash script:
#!/bin/bash
set -e
WAIT=5
FILE_LOCK="$1"
echo "Daemon started (PID $$)..."
echo "$$" > "$FILE_LOCK"
trap cleanup 0 1 2 3 6 15
cleanup()
{
echo "Caught signal..."
rm -rf "$FILE_LOCK"
exit 1
}
while true; do
# do things
sleep "$WAIT"
done
And here is my PHP:
$command = '/path/to/script.sh /tmp/script.lock >> /tmp/script.log 2>&1 &';
$lastLine = exec($command, $output, $returnVal);
I see the script run, the lock file get created, then it exits, and the trap removes the lock file. In my /tmp/script.log I see:
Daemon started (PID 55963)...
Caught signal...
What's odd is that this only happens when running the PHP via Apache. From command line it keeps running as expected.
The signal on the trap that's being caught is 0.
I've tried wrapping my command in a bash environment, like $command = '/bin/bash -c "' . addslashes($command) . '"';, also tried adding nohup to the beginning. Nothing seems to be working. Is this possible to do for a never ending script?
Found the problem thanks to #lxg.
My # do things command was giving errors, which was causing the script to exit. For some reason they were suppressed.
When removing set -e from the beginning of my bash script I started seeing the errors output to my log file. Not sure why they didn't show up before.
The issue was in my bash loop it was running PHP commands. Even though my bash user and Apache user are the same, for some reason they had different $PATHs. This meant that when running on command line I was using a PHP7 binary, but when Apache trigged bash commands it was using a PHP5 binary (even though Apache itself is configured to use PHP7). So the application errored out and that is what caused the script to die.
The solution was to explicitly set the PHP binary path in my bash loop.
I was doing this with
BIN_PHP=$(which php)
But on true command line it would return one value (/path/to/php7/bin/php) vs command line initiated by Apache (/path/to/php5/bin/php). Despite Apache being the same as a my command line user, it didn't load the ~/.bashrc which specified my correct PHP path.
I'm trying to execute a command through PHP with shell_exec. The PHP file is hosted by Apache on my Ubuntu server.
When I run this:
echo shell_exec("ps ax | grep nginx");
Then I get to see data. But when I run another command, for example:
echo shell_exec("cat /usr/local/nginx/config/nginx.config");
Then it's not showing anything at all. But when I copy that command and paste it in my terminal, then it executes fine.
My Apache server is running as user www-data. So I edited sudoers and added this line:
www-data ALL=(ALL:ALL) ALL
I know this is a security risk, but I wanted to make sure (for now) that www-data is able to execute all commands. But, for some reason I'm still not able to execute all commands with my PHP script.
Anyone any idea what to do?
have you read http://php.net/manual/en/function.shell-exec.php
There is quite a discussion in comments section. Top comment is:
If you're trying to run a command such as "gunzip -t" in shell_exec and getting an empty result, you might need to add 2>&1 to the end of the command, eg:
Won't always work:
echo shell_exec("gunzip -c -t $path_to_backup_file");
Should work:
echo shell_exec("gunzip -c -t $path_to_backup_file 2>&1");
In the above example, a line break at the beginning of the gunzip output seemed to prevent shell_exec printing anything else. Hope this saves someone else an hour or two.
echo shell_exec("sudo cat /usr/local/nginx/config/nginx.config");
Try that.
I have been trying to execute a script using shell_exec() function in php:
I've written the following lines of code:
$command = "bash /path/to/my/script/ funciton_name() 2>&1";
echo shell_exec($command);
Inside the shell script I'm doing:
sudo rsync -avvc /source/path /destination/path
On executing this on the browser, I get the following error message:
sudo: no tty present and no askpass program specified
When I execute the same shell script on my server, it executes fine.
When I went through similar questions posted on this forum, I realised that I had to add the NOPASSWD line on my server which I found out has already been added in the following format:
User_Alias NOBODY=nobody,apache
NOBODY ALL=(ALL) NOPASSWD : /path/to/my/script
Also when I do:
echo shell_exec("whois");
I get the output as:
apache
Any assistance in overcoming this problem would be of great help.
sudo will require a TTY, even if you have set up it up to be passwordless, unless you explicitly do not require it. But as #Cfreak pointed out, it would be much better (simpler and safer) to avoid sudo by setting correct access rights (read it before continuing) in the first place.
rsync itself will not require root permissions on a sanely configured *nix install. To verify this, you can check that type -a rsync doesn't print anything weird like rsync is aliased to `sudo rsync' and that ls -l $(which rsync) prints sensible permissions (at least rx for everyone).
I actually try to laucnh a gnome-term with a php script, seems i have some problems with the users www-data;
my script make only a ls -l command in a directory (is just for a test) and i run it with a php page in my local-web site.
here the gnome-terminal command in my bash script (he run perfectly when i double-click on him) :
gnome-terminal --working-directory=/opt/cuckoo -x bash -c "ls -l"
and here is the call on the php-page :
system("/my/path/to/the/script/script.sh");
i have some echo in my script and i see them in the php page after i try to run the script with the php.page.
i think www-data don't have the right to do so i give the ownership of the script with the chown command, and at last a try the sudo visudo command and make the script execute like the user www-data is root (with NO PASSWD arg)
But i can't open the terminal and make a ls at last, i try with exec too, and show the result with $ouput butthe result is the same as well.
At last my question is : Php can really run a terminal or maybe a fool myself^^? Thanks for taking time to rescure me ;)
PHP can run everything, but depends who spawns it. Forget just running X apps from a web server - you'll need more than just executing them (permissions, DISPLAY and Xauth settings). Read more about the X clients and architecture.
Probably the right place to ask this is at SuperUser, since the problem is not in the coding itself.