Monday, October 15, 2018

'commit' changes on webserver to Github repo using PHP not working

Leave a Comment

I'm trying to write a little PHP script that can spot all the changes to a local git repo on my web server and push them up to my (private) Github repo. Pushing and pulling from the Github repo using Atom works perfectly, pushing changes to the web server using a webhook works perfectly, pushing and pulling updates on the web server via the command line works perfectly, my problem is trying to commit and push updates on the web server to my Github repo using PHP. How do you do this?

If I have to change, add or even delete an entire template on the server manually I can commit those changes and push them up to Github using the command line like this no problem:

git add --all git commit -m "from server" git push -u origin master 

But when I try to do this using a PHP script it never works and I get no error message (I even try with pauses):

$output = `git add --all`; echo $output; sleep(1);  $output = `git commit -m "from server"`; echo $output; sleep(3);  $output = `git push -u origin master`; echo $output; sleep(3); 

If I run something simple like 'git --version', 'git config --list' or 'git status' it works perfectly from these scripts, so I'm at a loss.

4 Answers

Answers 1

When you run a script with php it is run by a user www-data(by default). When you connect to git repository you need to do auth. Most likely it will be done using ssh key. So you need authorize user www-data with the ssh key to allow him accessing the remote repository.

So the steps.

  1. Generate key
  2. Add the key to the remote repository
  3. Add the key to ssh agent locally for user www-data
  4. Check the enviroment where you run the command
  5. Enjoy

Useful link: https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/

There's also an option to use authentication via https with skipping putting credentials. You can see more here

Moreover, there's the library that does such things you may check it as well

Answers 2

You says:

But when I try to do this using a PHP script it never works and I get no error message (I even try with pauses):

$output = `git add --all`; echo $output; sleep(1);  $output = `git commit -m "from server"`; echo $output; sleep(3);  $output = `git push -u origin master`; echo $output; sleep(3); 

If I run something simple like 'git --version', 'git config --list' or 'git status' it works perfectly from these scripts, so I'm at a loss.

It seems like you have no write permission here.

You can easily run following commands to check permission for git repo, login user and owner of web server.

Run command whoami or id to identify login user.

$ whoami gasolwu $ id uid=501(gasolwu) gid=20(staff) groups=20(staff),501(access_bpf),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),33(_appstore),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh),701(com.apple.sharepoint.group.1) 

List directory to check owner and permissions for given path (git repo)

$ ls -al /path/to/repo total 16 drwxr-xr-x   5 gasolwu  staff  160 Oct 15 21:50 ./ drwxr-xr-x   5 gasolwu  staff  160 Oct 15 21:48 ../ drwxr-xr-x  13 gasolwu  staff  416 Oct 15 21:53 .git/ -rw-r--r--   1 gasolwu  staff  196 Oct 15 21:50 git.php* -rw-r--r--   1 gasolwu  staff   79 Oct 15 21:49 git.sh* 

Show process status to check user whom runs web server

$ ps auxwww | grep 'httpd\|nginx\|apache' _www              1139   0.0  0.0  4342760   3692   ??  S     9:51PM   0:00.01 /usr/sbin/httpd -D FOREGROUND _www              1138   0.0  0.0  4351976   3692   ??  S     9:51PM   0:00.02 /usr/sbin/httpd -D FOREGROUND _www              1137   0.0  0.0  4317160   1988   ??  S     9:51PM   0:00.01 /usr/sbin/httpd -D FOREGROUND _www              1129   0.0  0.0  4334568   2300   ??  S     9:51PM   0:00.01 /usr/sbin/httpd -D FOREGROUND root              1119   0.0  0.1  4316156  11772   ??  Ss    9:51PM   0:00.51 /usr/sbin/httpd -D FOREGROUND gasolwu           1465   0.0  0.0  4268036    824 s000  S+   10:19PM   0:00.00 grep --color=auto -d skip httpd\|nginx\|apache 

or check user of php-fpm if you run web sever with PHP-FPM

$ ps auxwww | grep php-fpm gasolwu           1761   0.0  0.0  4268036    812 s000  S+   10:33PM   0:00.00 grep --color=auto -d skip php-fpm nobody            1737   0.0  0.0  4323216    724   ??  S    10:33PM   0:00.00 php-fpm nobody            1736   0.0  0.0  4323216    732   ??  S    10:33PM   0:00.00 php-fpm root              1735   0.0  0.0  4323216    920   ??  Ss   10:33PM   0:00.00 php-fpm 

As you can see, It also has permission problem here, The .git directory can only be written by user gasolwu, not web user _www. So when you run git operation via php script through web server. .It can't do git operation (add/commit) without write permission.

The shell_exec (is identical to the backtick operator) function only returns stdout, It's empty here when error occurs, The stderr will be redirected to error log base on your environment, You will get similar error message log in Apache or PHP.

$ cat /var/log/apache2/error_log Mon Oct 15 21:51:06.734474 2018] [mpm_prefork:notice] [pid 1119] AH00163: Apache/2.4.34 (Unix) PHP/7.1.19 configured -- resuming normal operations [Mon Oct 15 21:51:06.734572 2018] [core:notice] [pid 1119] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND' fatal: Unable to create '/path/to/repo/.git/index.lock': Permission denied fatal: Unable to create '/path/to/repo/.git/index.lock': Permission denied error: could not lock config file .git/config: Permission denied error: Unable to write upstream branch configuration hint: hint: After fixing the error cause you may try to fix up hint: the remote tracking information by invoking hint: "git branch --set-upstream-to=origin/master". error: update_ref failed for ref 'refs/remotes/origin/master': cannot lock ref 'refs/remotes/origin/master': Unable to create '/path/to/repo/.git/refs/remotes/origin/master.lock': Permission denied Everything up-to-date error: remote unpack failed: unable to create temporary object directory To /tmp/git  ! [remote rejected] master -> master (unpacker error) error: failed to push some refs to '/tmp/git' 

Let's fix it by given write permission to right user (_www here).

chown -R _www /path/to/repo 

After that, you can send request to http://example.com/git.php to add files, commit with message "from server" then push them to GitHub.

CAVEAT: There is some security concern for this methodology without authentication.

Answers 3

The problem is with the authentication. The first solution is to do like Robert said. But I think that no need to Reinvent the wheel, try to see this package :

https://github.com/kbjr/Git.php

Everything is already there.

Answers 4

You are literally just echoing strings, not running them.

Instead of echo(), you can use exec(), shell_exec():

http://php.net/manual/en/function.exec.php

http://php.net/manual/en/function.shell-exec.php

Here are the PHP commands that allow you to execute programs on the server:

http://php.net/manual/en/ref.exec.php

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment