How to push git from php using exec() - php

Here is my push.bat file
echo "Hello world!"
cd abhishek3/
call git add .
call git commit -m "sadf"
call heroku accounts:set abhishek84
call git push heroku master
I am able to push to my repository by running push.bat file in cmd
I want to push to my repo from php, tried following snippets but none of them worked for me.
exec("psexec -d push.bat");
Result: PHP page loads indefinitely
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("cmd /C abhishek3.bat, 0, false);
Result: Page stops loading after a while and nothing works
exec("cmd.exe /c abhishek3.bat")
Result: Page stops loading after a while and nothing works
EDIT:
Tried the following snippet but nothing worked.
exec("hstart.exe /NOCONSOLE \"cmd.exe /c \"abhishek3.bat\"\"");
The above snippet runs successfully when run from cmd but when run from php through exec() didn't worked. Download hstart (Hidden Start Binary)

check the permissions for the web users are correct (It can access the files and execute git)
check the path for git and any environment variables it may need. You may have to set those environment variables in your script and use absolute paths)
check IIS or apache (whichever you are using) is allowed to execute programs in general and bat files (for example if it is apache, you may have to configure httpd.conf or htaccess depending on your configuration)

Related

PHP shell_exec() unable to run part of shell script

I have encountered a strange problem. I have created a gitlab custom webhook. The webhook service is written in php (gitlab.php). The php script, when called with proper payload, should start an automated deployment. The deployment script is basically a shell script (deploy.sh)
Code of gitlab.php
<?php
$json = file_get_contents('php://input');
// Converts it into a PHP object
$data = json_decode($json, true);
$secret = "";
foreach (getallheaders() as $name => $value) {
if($name=='X-Gitlab-Token') {
$secret = $value;
}
}
if($secret=="mysecretcode" && $data['object_kind']=="push") {
file_put_contents("/opt/lampp/htdocs/autodeploy/autodeploy.log", "Webhook auto deployment started at ". date("Y-m-d H:i:s") . "\n". shell_exec("sh /opt/lampp/htdocs/autodeploy/deploy.sh")."\n**********************************************\n\n", FILE_APPEND);
die("Deployment success");
}
else {
die("Auth token invalid or no triggerable event found");
}
?>
Code of deploy.sh
#!/bin/bash
cd "/opt/lampp/htdocs/nodejs/myapp"
echo "Stopping application..."
forever stop index.js
cd ..
sudo rm -rf myapp
echo "Pulling latest code from gitlab..."
git clone -b "master" https://myusername%40domain.com:MyEncodedPass123#gitlab.com/myusername/myapp.git
cd myapp
echo "Installing dependencies..."
npm install
echo "Starting application..."
forever start index.js
echo "Application started on port 3000."
When I push code to gitlab, it triggers the webhook and initiates the deployment process and I see my webhook file gitlab.php returned success response to Gitlab and has written following output in autodeploy.log file
Webhook auto deployment started at 2021-10-03 13:32:07
Stopping application...
Pulling latest code from gitlab...
Installing dependencies...
Starting application...
Application started on port 3000.
**********************************************
But, the deployment actually never happens. It just runs the echo statements (and may be cd, rm etc as well) and rest of the shell commands are kind of ignored or not executed. It for sure doesn't run the git clone command, because I do not see latest code getting refreshed on my server from gitlab. Not sure though what happens to the npm and forever commands.
By the way, this is a Ubuntu VPS server with latest ApacheFriends XAMPP server installed, php v8. All the three files mentioned above reside at the same path i.e. /opt/lampp/htdocs/autodeploy and my deploy.sh script tries to deploy a separate nodejs application in /opt/lampp/htdocs/nodejs/myapp folder. Strangely enough, when I run deploy.sh directly from terminal it deploys the latest code successfully. Which means, all the statements in the script gets executed as expected. It only fails when executed from the php script using shell_exec() function.
Any clue what could be the reason?
The documentation for shell_exec doesn't state it clearly, but chances are you only get the stdout of your command, not its stderr -- the first comment certainly seems to indicate that, it would also match the "it's the same thing as backtick" decription.
If such is the case, you simply don't have the error messages in your output.
Try running :
shell_exec("sh .../deploy.sh 2>&1")
I also second #phd's suggestion (in the comments to your question) : turn set -e on, at least your script will halt when you get an error.
Chances are your current script would fail at the first line : cd "/opt/lampp/htdocs/nodejs/myapp".
I also strongly advise to drop the sudo in sudo rm -rf ....

Linux mount script runs in PHP interpreter but not in web Apache

My website is about copying files. Instead of copy the files to avoid to much time and server lagging, I decided to use overlayfs. The code mount the folder to the location specified in the terminal using the PHP interpreter. But, when I run the php script from Apache the script does not mount the overlay. And the worst is that there is no error output so I can debug what's wrong. I checked the php error log, no output about what happened.
The destination i'm mounting the overlayfs is to another user. For that I need root to execute the mount command. To be able to run the code without using root nor sudo, I took a look at this question. I created the c code, compile it and set the proper permissions (root.root, rwsr,sr...). I ran the code in a php file:
<?php
// filename over.php
print shell_exec("whoami")."\n";
print shell_exec('/var/www/vhosts/user/deployment/exec "sudo mount -t overlay overlay -o lowerdir=/var/www/vhosts/user/deployment/template5_dev,upperdir=/var/www/vhosts/user.deve/httpdocs,workdir=/var/www/vhosts/user/deployment/overlay-work /var/www/vhosts/user.deve/httpdocs"');
What the code does is print the actual user name (to make sure I have an output, to see if the code executed) then merge the folders. The file /var/www/vhosts/user/deployment/exec is the c program then I pass the code to execute as argument.
In the terminal I run: php -f "/var/www/vhosts/user/httpdocs/over.php". I check the merged folder I can see it works. And the output is user.
Then I unmount the overlay sudo umount /var/www/vhosts/user.deve/httpdocs.
I access the php script via the browser, I got the output user but the folder does not merge. I ctrl-f5 multiple times but nothing, no error, no error in log nothing.
I changed the command to shell_exec('/var/www/vhosts/user/deployment/exec "sudo mkdir /var/www/vhosts/user.deve/httpdocs/nouvo"');, the sudo created the folder from the browser.
I noticed that only the mount command does not run properly.
What could be the reason the sudo mount command does not run by apache, and even if there was an error, doesn't it print out the error?
I just take a look at /var/log/kern.log. I can see the mount command got executed from the web-browser. But the log is different from the one the ones executed in the terminal.
From the web-browser:
kernel: [ 149.465459] overlayfs: filesystem on '/var/www/vhosts/user.deve/httpdocs' not supported as upperdir
kernel: [ 151.629192] overlayfs: filesystem on '/var/www/vhosts/user.deve/httpdocs' not supported as upperdir
kernel: [ 153.453612] overlayfs: filesystem on '/var/www/vhosts/user.deve/httpdocs' not supported as upperdir
From the terminal after executing from the browser:
kernel: [ 312.858797] overlayfs: upperdir is in-use as upperdir/workdir of another mount, accessing files from both mounts will result in undefined behavior.
kernel: [ 312.858804] overlayfs: workdir is in-use as upperdir/workdir of another mount, accessing files from both mounts will result in undefined behavior.
I just don't get the log from the browser since the script is same.

Using exec() in php via web

Hello i was trying to use exec() in php via web page to execute a file in the root directory, and for some reason none of my commands work except
ls
witch even when i do
ls /root
it doesn't work seems i can only do ls in the current directory or commands like whoami which returns apache
i've tried setting user permissions for apache, and i've tried setting permissions for file or /var/www/html directory and nothing seems to work any ideas?, my basic code below
<?php
command = "ls /root";
exec($command);
?>
The exec command return only the last line of your command.
Like said in the documentation, you should add a second parameter to get the result or use the function passthru

Executing bash file via php on apache server

So I have hosted a webpage on my apache server and I'm trying to run some python and bash scripts when the user presses a button via PHP and AJAX.
Now my php file executes at python script (located in /var/www/html) which in turn executes a bash file (located in root/files).
On doing this manually in terminal, everything works perfectly fine.
But when I try to this via the webpage, the bash script isn't executed.
(I can't place the bash script in /var/www/html because it has the command to clone a git repository to the server and it gives private key shouldn't be public error when placed there)
I already tried suggestions in this answer by adding www-data to sudoers but it is still not working as expected.
Any help on this would be appreciated.
Thanks
PHP file :
if(isset($_POST['timestamp']))
{
$uid = $_POST['timestamp'];
echo "Please wait while the app is being generated".$uid;
exec("python /var/www/html/appgenserver.py $uid");
appgenserver.py
#! /usr/bin/env python
import os
import json,sys
from firebase import firebase
import requests
import subprocess
arg = sys.argv[1]
# Path to be created
path = "/root/files/"+str(arg)
print path
if not os.path.exists(path):
os.makedirs(path) #Gets executed
subprocess.call(['/root/Final/clone.sh', path) #Not getting executed
Most likeley because a bash script in its self won't be executable, it's just a plain textfile.
Your bash (and perhaps even appgenserver.py?) might be located under /root and apache probably runs as a non-priviliged user such as www-data, that user won't be able to access either your python script and in turn not the bash that the python would run.
Consider instead calling bash with the script as a parameter.
#! /usr/bin/env python
import os
import json,sys
from firebase import firebase
import requests
import subprocess
arg = sys.argv[1]
path = "/root/files/"+str(arg)
print path
if not os.path.exists(path):
os.makedirs(path)
subprocess.call(['/bin/bash', '/root/Final/clone.sh', path)
Now, this is NOT the most pretty of solutions.
But what you got before was probably a generic "Permission denied" error in the background (check your /var/log/apache/error.log).
What this does is start /bin/bash as a subprocess with the first parameter being the script you want to execute.
But you have zero error handling here and you can't interract with the process very much.
Consider doing something like this instead:
import subprocess
handle = subprocess.Popen(['/bin/bash', '/root/Final/clone.sh', 'parameter'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
while handle.poll() is None:
print(handle.stdout.read()) # There's some optimizations here to be done as well so it's not a blocking call etc.
handle.stdout.close()
handle.stdin.close()
And one last tip is not to place stuff in /root/ at all if you're integrating it into a web front-end/backend type of thing.
You're asking for trouble : )
Another way is to make use of sudo
If you modify your exec() in PHP to run exec("sudo ...") and enable your web-user to run the scripts without a password prompt it could work.
Bare in mind, it's not recommended to give www-data sudo access, rather do something like this:
# useradd -m -G www-data -s /bin/bash wwwexec
# echo "myuser ALL=NOPASSWD: /usr/bin/python" >> /etc/sudoers
and change your PHP script to have the following:
exec("sudo -u wwwexec python /var/www/html/appgenserver.py $uid");
That way at least your entire web service isn't given root access via the default username.
The way to do it
Would be to place your appgenserver.py under /var/www/cgi-bin/ instead, and create a CGI hook for .py in your apache configuration and hand over the user to the URL prividing you access to the CGI script.
That way everything should be according to best practices even tho, in theory, you could get your original solution to work.
For instance, this guide should get you started.

php shell_exec and hg pull

I have written simple php script to help me update site contents when the commit is sent to bitbucket. I have following problem with it.
<?php
$repo_dir = '/var/www/vhosts/my_full_path';
$output = shell_exec('cd '.$repo_dir.' && hg --config auth.rc.prefix=https://bitbucket.org/XXXXX --config auth.rc.username=my_username --config auth.rc.password=my_pass pull -u https://bitbucket.org/XXXXXXX &');
echo $output;
?>
When I type it to web browser it doesn't work. The output of script is:
pulling from https://bitbucket.org/XXXXXXXXXXXXXX
but when I try to execute it under console on the server it works like a charm:
php myscript.php
generates following output:
pulling from https://bitbucket.org/XXXX
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
See the oupt is full and correct! in concole I'm using root user in web browser data-www? Is there any difference in this case?
I have found the solution. I hope it helps someone.
There were two problems:
Permissions to my repo dir
Authentication for user www-data for this repo
The problem occured because web browser doesn't flush warnings and abort messages while executing command shell_exec. If you want to test your script, you have to lgoin to console by SSH (as root for example) then execute script / command as apache user:
sudo -u www-data php /path-to-your-script/script.php
In console you will see all problems which following user generates.

Categories