在非可执行环境中执行git hooks /编辑git调用钩子的方式

时间:2018-03-22 14:19:36

标签: git ssh sh githooks

问题:如何编辑git如何调用钩子?

TL; DR - 我的托管平台的安全性很奇怪,我需要弄清楚如何编辑git如何调用post-receive hook。

我尝试通过GIT设置自动部署,但人们建议您这样做的主要方式是使用后接收脚本。如果我进入钩子并做

$ sh post-receive

,它工作正常,但如果我

$ ./post-receive

,虽然它有

,但它会抱怨权限
$ chmod 777 post-receive

(您可以使用$ ls -l查看)。

这是我从支持中获得的信息: "原因是出于安全原因,SSH环境作为非可执行环境安装。这意味着您无法仅通过路径运行脚本。

例如,运行:/www/repos/webprosjekt18.git/hooks/post-receive将无效,它将给出权限错误。

运行: bash /www/repos/webprosjekt18.git/hooks/post-receive将正常工作(取决于该脚本的功能,但它至少会运行该文件)。

我们认为git默认通过调用:/www/repos/webprosjekt18.git/hooks/post-receive运行挂钩,这将失败。 "

远程脚本:

mkdir repos
cd repos
git init --bare
cat > hooks/post-receive <<END
#!/bin/sh
echo "executing post-receive hook"
END
chmod 777 hooks/post-receive
cd hooks
sh post-receive

2 个答案:

答案 0 :(得分:1)

作为sneep noted in a comment,一旦决定运行一些钩子,Git基本上只会执行fork后跟execve的钩子路径。 (有关“决定运行某些挂钩”的更多信息,请参阅下文。)这意味着由内核决定是否允许exec操作。

The specific source code involved is here.请注意ENOEXEC的测试,但不是EACCES的测试。

如果查看the Linux mount documentation,您将看到noexec选项禁止对该已安装文件系统上的任何文件执行(执行操作)。 (如果托管系统是基于BSD的,则BSD的mount有类似的选项。)此案例返回的错误是EACCES,而不是ENOEXEC。这意味着你的托管系统的分析,你完全不能这样做,是正确的。

有趣的是,如果Git会运行一个没有设置x位的钩子,那么在某些情况下上面调出的代码部分可能会得到ENOEXEC(不是这些 - 你想弄乱使用“魔术数字”来触发这个)并且在钩子上运行shell的第二个代码路径实际上可以工作。但是,the find_hook code明确要求access(path, X_OK)成功。这需要both the x bits set and the file system mounted without noexec

您可以尝试构建更改这些测试的Git变体版本并让您的托管公司将其安装为Git版本,但如果他们愿意这样做,他们可能愿意将您的存储库放在文件中允许执行的系统。

答案 1 :(得分:1)

这不是一个真正的答案,因为它很大程度上建立在@ torek建议它可能使用NOEXEC挂载选项的基础之上。那么这个解决方法怎么样:你可以添加一个钩子,它是/usr/bin/script的符号链接(其他文件系统的符号链接甚至可以用NOEXEC执行)。 script将执行bash,而bash会认为它在终端中。 (如果您只是符号链接到/bin/bash目录中的hooksbash会放弃看到它不能open /dev/tty,但script需要为我们照顾这个。)如果我们在~/.bashrc中放入一些代码来确定它是否被称为git hook,我们就会执行真实的脚本。所以我们可以把它放在/.bashrc

的顶部
pppid=$(ps -o ppid= $PPID) # determine grandparent PID
ppproc=$(ps -o comm= $pppid) # determine grandparent process name
if [ "$ppproc" == "git" ]; then # is it 'git'?
    echo running from git @ `date` # call script here
    exit
else
    echo not running from git # you might want to remove this
fi

示例:

$ touch test15
$ git add test15
$ git commit -m "Test15"
Script started, file is typescript
running from git @ Fri Mar 23 13:19:54 JST 2018
Script done, file is typescript
[master 608083b] Test15
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test15

(这会在您的Git目录中创建一个名为typescript的文件。)