git pull via PHP exec IIS

2019-06-15 13:49发布

问题:

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!

回答1:

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.



回答2:

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



回答3:

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.



回答4:

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.



回答5:

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()', '');
    }

}

?>


回答6:

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)



回答7:

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



回答8:

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


回答9:

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



回答10:

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



标签: php git ssh exec pull