12

Easily the most difficult problem to diagnose that I have EVER experienced. I seem to be unable to call:

exec('call git pull', $output);

The process hangs and tends to take IIS with it.

exec('call git status', $output); //works fine

Here's what I've done:

  • Generated RSA key added to github (passcode is blank)
  • Everyone has permission on mysite/.git/, and Program Files/git/bin and cmd.exe
  • Tried the ssl cert fix mentioned in other posts with 'slash' issue
  • Tried using https:// instead of SSH
  • Tried piping to stderr 2>NUL and 2>&1

Clearly, there's a permissions issue where exec calls cmd.exe which in turn calls git.exe, which in turn calls sh.exeto connect to github, which in turn makes use of git-pull and possibly git-send-packand GOD KNOWS what else.

I'm guessing 'sh.exe' determines the current user is IUSR and cannot find the RSA key to authenticate with.

If I could figure out how to ssh-keygen the IUSR account, I would have tried that.

If I could figure out how to exec git bash instead of git (via cmd.exe) I would have tried that.

Here's the question in it's simplest form:

How do I pull from my github repo via PHP's exec method?

The problem certainly seems to be with SSH, but I'm totally at the end of everything to try.

Help!

rmirabelle
  • 6,268
  • 7
  • 45
  • 42
  • Why are you using `call git pull` instead of `git pull` only? – gustavotkg Nov 14 '11 at 04:47
  • call was simply a 'recommended' approach for using exec() as a read it - I've tried both methods and see no appreciable difference – rmirabelle Nov 15 '11 at 01:49
  • I'm fairly positive you're facing problems with write permissions. If you think about the difference between git status vs git pull.. one displays information about the repository while the other one actually makes filesystem level changes. – Kevin Apr 30 '13 at 07:17
  • yes, it does seem to be a permissions issue, but as the question states, I've tried the loosest permissions I can imagine, to no avail. – rmirabelle Apr 30 '13 at 12:19

10 Answers10

15

I faced the same problem today and used Process Monitor to see what was going on and found that for some reasons sh.exe looked for the keys in C:\Windows\SysWOW64\config\systemprofile\.ssh. So I copied everything in C:\Users\Administrator\.ssh to that folder and it worked perfectly.

Iamz
  • 295
  • 2
  • 6
  • 1
    WINNER! I had to also provide explicit permissions to this directory, but it's actually working. Miracle achieved, day saved, World made a better place, bounty awarded. – rmirabelle Apr 30 '13 at 13:02
  • Although this didn't answer my question it pointed me in the right direction, I think it deserves the bounty ;-) – derickito May 01 '13 at 00:40
  • How did you find that out? – Petah Aug 12 '13 at 02:13
  • 2
    I would also like to add that you have to give IUSR read permissions to the newly created folder as well before it works :) – ZorleQ Jun 20 '14 at 19:02
  • I would add as well that you should generate your keys, pull from the server once and accept the known hosts message, then copy over all the files to the folder mentioned above and set the permission for the IUSR user on the new .ssh folder. – rosswil Jul 18 '14 at 20:42
  • Awesome!, You are my savior... :) Thanks. – reignsly Jul 12 '15 at 07:07
  • running windows server 2012, and this could not resolve my issue, I am able to do git status, but not git pull. How have you checked that sh.exe looked for the key – Tarun Gupta Feb 16 '16 at 05:36
  • I came across this today and tried every folder mentioned in this thread so far before downloading Process Monitor. Running that (and peeling through reams of output) I found that the path git was looking for on the IIS server (create from a copy of C:\Users\Administrator\.ssh) was C:\Windows\System32\config\systemprofile\.ssh Hopefully that gives some people some respite. – billythekid Jun 15 '17 at 19:29
2

I am running Windows Server 2012 and wasn't able to get Iamz's solution to work.

I searched for ".ssh" in my C:\ and noticed that there was another .ssh folder at C:\Program Files (x86)\Git\.ssh. I copied all the contents from C:\Users\Administrator\.ssh to this folder, set permissions to allow IUSR access, and everything was kosher.

Lloyd Banks
  • 35,740
  • 58
  • 156
  • 248
1

there are a number of php git libraries/tools. https://git.wiki.kernel.org/index.php/Interfaces,_frontends,_and_tools#git-php

personally i have been hacking with GLIP (git library in php) http://fimml.at/#glip

i have a source fork on github where i have added an archive function. basically i dynamically create a git command and use php's passthru method to call it. perhaps looking at my code might give you some insight. here's the commit https://github.com/fontvirus/glip/commit/89127f7f9a4dc61697929f36684533406f348ffe

xero
  • 4,077
  • 22
  • 39
1

Move your .ssh folder to userprofile dir. You can see you app profile dir in this global variable $_SERVER['USERPROFILE']. In my case it's C:\Windows\system32\config\systemprofile. Then give permissions to read/write to this folder (.ssh) for users: IIS_IUSRS, IUSR

Darkhan ZD
  • 580
  • 8
  • 14
0

You need to use proc_open and will thus see the problem which most likely is permission related.

Here's a script I use:

<?php

//error_reporting(E_ALL);
ignore_user_abort(true);

function syscall ($cmd, $cwd) {
    $descriptorspec = array(
        1 => array('pipe', 'w'), // stdout is a pipe that the child will write to
    );
    $resource = proc_open($cmd, $descriptorspec, $pipes, $cwd);
    if (is_resource($resource)) {
        $output = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        proc_close($resource);
        return $output;
    }
}

// GitHub will hit us with POST (http://help.github.com/post-receive-hooks/)
if (!empty($_POST['payload'])) {

    // pull from master
    $result = syscall('git pull', '/var/www/example.com');

    // send us the output
    mail('team@example.com', 'GitHub hook `git pull` result', $result);

    // clear APC
    if (apc_clear_cache('opcode') == false) {
        mail('root', 'Unable to apc_clear_cache()', '');
    }

}

?>
webjay
  • 5,358
  • 9
  • 45
  • 62
  • Perhaps this guide can help: http://technotes.tumblr.com/post/33867325150/php-hook-script-that-can-git-pull-apc-clear-cache – webjay Oct 19 '12 at 00:46
  • miraculously and terribly, this script fails identically to my existing code :-( – rmirabelle Apr 30 '13 at 12:47
0

I was able to get this to work partly by following a lot of what was on here. I ran a batch script which ran

ssh-agent -s
ssh-add -l

to see what keys I had. Before running these commands I set the HOME=/c/Users/Username environment variable to my user with the correct ssh keys. (I'm using unix path's because I was running it with Git Bash)

derickito
  • 695
  • 7
  • 25
0

I don't quite sure about window's environment

but the main problems is ".php file" that call exec command doesn't have permission as administrator (or root in *NIX os)

in my environment I chown that file to have privilege as root (like sudo things) another way is create new user group that have permission 777 and assign that file to own by that user's group

hope this help

0

I had this issue earlier today and solved it a different way.

My problem was that the IUSR did not have a home folder to put the ssh keys or a git credentials file into.

I created a .sh file that changed the HOME variable before calling git, put my keys in the proper place as if that was it's home folder, then used sh.exe to run the .sh

#!/bin/bash
export HOME="/c/some/location"
git pull
Sean256
  • 2,849
  • 4
  • 30
  • 39
0

Another variant on Iamz's solution is to use the directory C:\Windows\System32\config\systemprofile\.ssh

I arrived at that by running the following script on my IIS server, which immediately indicated that C:\Windows\System32\config\systemprofile\.ssh was missing (please set $path_of_git and $path_to_repo as appropriate for your machine):

<?php
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin
   1 => array("pipe", "w"),  // stdout
   2 => array("pipe", "w"),  // stderr
);
$path_of_git = 'c:\\path\\to\\git';
$path_to_repo = 'C:\\inetpub\\repo';
$process = proc_open($path_of_git.' fetch', $descriptorspec, $pipes, $path_to_repo, null);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
echo '<pre>'.htmlspecialchars($stdout).'</pre>';
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
echo '<pre style="color:red;">'.htmlspecialchars($stderr).'</pre>';
echo '<p>return value=' . proc_close($process) . '</p>';
?>

All that being said, I'm still beset by permission issues, so I've found it useful to just declare that HOME is somewhere else that IUSR can get to easily before each git command, and execute the whole thing with git sh. For example:

\pathToGit\bin\sh -c "export HOME='/c/somewhereIUSRCanGetTo/';git fetch"

Where C:\somewhereIUSRCanGetTo\.ssh\ contains the private key and allowed_hosts files

Mike Godin
  • 3,727
  • 3
  • 27
  • 29
0

You will have to give permissions directly to cmd.exe. Depending on the version of windows and the way you have your app-pool setup it could be IIS_IUSR, IUSR, and/or NETWORK SERVICE. Add the user with full permissions to cmd.exe.

I, of course, don't recommend doing that since it has direct security implications. That said, I haven't found any other way of making it happen in windows.

Seth
  • 121
  • 4