致命:无法执行 'hooks/update':使用 Git 时权限被拒绝
fatal: cannot exec 'hooks/update': Permission denied when using Git
我们校园里有一个 Solaris 服务器,每个学生和教职工都有一个帐户。我想托管一个裸 Git 存储库,并且只允许某些用户访问它。
现在,因为我不管理服务器,所以我不能乱搞组和用户帐户。我知道我可以使用 Giotlite 并为我的用户创建 public 密钥,但这看起来很愚蠢,因为他们已经在服务器上拥有自己的用户帐户。所以我正在做的是使用 FACL 为特定用户提供访问权限。
以下是我使用 cs101
帐户在其主目录(这是课程帐户)上设置回购所做的工作:
- 我为 repo 创建了一个目录:
mkdir cs101.git
设置 FACL 权限以授予对我的用户帐户的访问权限
setfacl -m d:u::rwx,d:g::---,d:o:---,d:m:rwx cs101.git
setfacl -m d:u:cs101:rwx,u:cs101:rwx,d:u:welcomb:rwx,u:welcomb:rwx cs101.git
然后最后初始化Git
cd cs101.git
git init --bare --shared
目录列表显示
total 88
drwx--S---+ 7 cs101 cs101 4096 Aug 3 14:33 .
drwx-----x 6 cs101 cs101 4096 Aug 5 15:02 ..
drwxrws---+ 2 cs101 cs101 4096 Aug 3 14:33 branches
-rw-rw----+ 1 cs101 cs101 126 Aug 3 14:33 config
-rw-rw----+ 1 cs101 cs101 73 Aug 3 14:33 description
-rw-rw----+ 1 cs101 cs101 23 Aug 3 14:33 HEAD
drwxrws---+ 2 cs101 cs101 4096 Aug 3 14:33 hooks
drwxrws---+ 2 cs101 cs101 4096 Aug 3 14:33 info
drwxrws---+ 33 cs101 cs101 4096 Aug 5 15:10 objects
drwxrws---+ 4 cs101 cs101 4096 Aug 3 14:33 refs
目录权限似乎正确
# file: hooks/
# owner: cs101
# group: cs101
user::rwx
user:cs101:rwx #effective:rwx
user:welcomb:rwx #effective:rwx
group::rwx #effective:rwx
mask:rwx
other:---
default:user::rwx
default:user:cs101:rwx
default:user:welcomb:rwx
default:group::---
default:mask:rwx
default:other:---
仍在使用课程帐户cs101
,我将一些文件推送到存储库中。
现在,我注销课程帐户并使用我自己的用户帐户登录,我可以克隆存储库 welcomb@solaris$ git clone ~cs101/cs101.git
到目前为止还不错,一切都很好。
现在的问题是我无法使用我自己的用户帐户将新提交推回回购协议:
welcomb@solaris$ GIT_TRACE=1 git push
trace: built-in: git 'push'
trace: run_command: 'git-receive-pack '\''/home/course/cs101'\'''
trace: exec: '/bin/bash' '-c' 'git-receive-pack '\''/home/course/cs101'\''' 'git-receive-pack '\''/home/course/cs101'\'''
trace: built-in: git 'receive-pack' '/home/course/cs101'
trace: run_command: 'pack-objects' '--all-progress-implied' '--revs' '--stdout' '--thin' '--delta-base-offset' '-q'
trace: exec: 'git' 'pack-objects' '--all-progress-implied' '--revs' '--stdout' '--thin' '--delta-base-offset' '-q'
trace: built-in: git 'pack-objects' '--all-progress-implied' '--revs' '--stdout' '--thin' '--delta-base-offset' '-q'
trace: run_command: 'unpack-objects' '--pack_header=2,3' '-q'
remote: trace: exec: 'git' 'unpack-objects' '--pack_header=2,3' '-q'
remote: trace: built-in: git 'unpack-objects' '--pack_header=2,3' '-q'
trace: run_command: 'rev-list' '--objects' '--stdin' '--not' '--all'
trace: exec: 'git' 'rev-list' '--objects' '--stdin' '--not' '--all'
trace: built-in: git 'rev-list' '--objects' '--stdin' '--not' '--all'
trace: run_command: 'hooks/update' 'refs/heads/master' '629b5b1f0122de95bd4e7b50a7968e64aaef6e65' 'b2072da84ee7d3fde6c6daf2cae61dbae6b0a5d9'
fatal: cannot exec 'hooks/update': Permission denied
remote: error: hook declined to update refs/heads/master
trace: run_command: 'gc' '--auto' '--quiet'
trace: exec: 'git' 'gc' '--auto' '--quiet'
trace: built-in: git 'gc' '--auto' '--quiet'
To /home/course/cs101
! [remote rejected] master -> master (hook declined)
error: failed to push some refs to '/home/course/cs101'
好像无法执行hooks/update
.
fatal: cannot exec 'hooks/update': Permission denied
但是 hooks/update
执行位是
甚至没有设置,这意味着 Git 应该忽略 运行 它。
/home/course/cs101/cs101.git/hooks$ getfacl update
# file: update
# owner: cs101
# group: cs101
user::rw-
user:cs101:rwx #effective:rwx
user:welcomb:rwx #effective:rwx
group::rw- #effective:rw-
mask:rwx
other:---
/home/course/cs101/cs101.git/hooks$ ls -al update
-rw-rw---- 1 cs101 cs101 2910 Aug 4 10:50 update
我可以访问目录中的文件,甚至可以使用我的帐户执行 update.sample
/home/course/cs101/cs101.git/hooks$ ./update.sample
Don't run this script from the command line.
(if you want, you could supply GIT_DIR then run
./update.sample <ref> <oldrev> <newrev>)
所以我不明白为什么 Git 推送无法更新存储库。
getfacl
输出包括以下行:
user:cs101:rwx #effective:rwx
user:welcomb:rwx #effective:rwx
这意味着 C 库 access(path, X_OK)
函数可能声明文件 可以 执行(运行 通过 execve
系统调用或类似),至少对于用户 cs101
和 welcomb
。这就是 Git 确定钩子是否可执行的方式。
(请注意,任何 other 用户调用 access
都会得到答案:不,此文件不可执行。这是使 ACL 如此复杂的部分原因。)
然而,当 OS 实际尝试执行它时,出现了其他问题。还不完全清楚什么 出错了,但是execve
系统调用失败并出现"permission denied" 错误。 Git 然后决定挂钩失败,而不是挂钩实际上不可执行(Git 假设 access
会说 no 而不是 是 对于这些情况)。
鉴于文件很小(2910 字节,来自 ls -al update
输出),update
挂钩似乎不太可能是 shell 脚本以外的任何东西。如果它 是 一个 shell 脚本,它需要一个正确的 #!
解释器行才能执行,并且该解释器行必须指向一个本身具有执行权限的文件.
如果您确实希望挂钩 运行,则必须追查实际失败的根源。如果您不想要挂钩运行,并且不希望Git想挂钩应该 运行,从 ACL 的各个元素中删除执行位,或者完全删除 ACL(ACL 和 "Unix style" 权限通常是底层系统中的独立实体,虽然这里的 ZFS 不同)。
我们校园里有一个 Solaris 服务器,每个学生和教职工都有一个帐户。我想托管一个裸 Git 存储库,并且只允许某些用户访问它。
现在,因为我不管理服务器,所以我不能乱搞组和用户帐户。我知道我可以使用 Giotlite 并为我的用户创建 public 密钥,但这看起来很愚蠢,因为他们已经在服务器上拥有自己的用户帐户。所以我正在做的是使用 FACL 为特定用户提供访问权限。
以下是我使用 cs101
帐户在其主目录(这是课程帐户)上设置回购所做的工作:
- 我为 repo 创建了一个目录:
mkdir cs101.git
设置 FACL 权限以授予对我的用户帐户的访问权限
setfacl -m d:u::rwx,d:g::---,d:o:---,d:m:rwx cs101.git setfacl -m d:u:cs101:rwx,u:cs101:rwx,d:u:welcomb:rwx,u:welcomb:rwx cs101.git
然后最后初始化Git
cd cs101.git git init --bare --shared
目录列表显示
total 88
drwx--S---+ 7 cs101 cs101 4096 Aug 3 14:33 .
drwx-----x 6 cs101 cs101 4096 Aug 5 15:02 ..
drwxrws---+ 2 cs101 cs101 4096 Aug 3 14:33 branches
-rw-rw----+ 1 cs101 cs101 126 Aug 3 14:33 config
-rw-rw----+ 1 cs101 cs101 73 Aug 3 14:33 description
-rw-rw----+ 1 cs101 cs101 23 Aug 3 14:33 HEAD
drwxrws---+ 2 cs101 cs101 4096 Aug 3 14:33 hooks
drwxrws---+ 2 cs101 cs101 4096 Aug 3 14:33 info
drwxrws---+ 33 cs101 cs101 4096 Aug 5 15:10 objects
drwxrws---+ 4 cs101 cs101 4096 Aug 3 14:33 refs
目录权限似乎正确
# file: hooks/
# owner: cs101
# group: cs101
user::rwx
user:cs101:rwx #effective:rwx
user:welcomb:rwx #effective:rwx
group::rwx #effective:rwx
mask:rwx
other:---
default:user::rwx
default:user:cs101:rwx
default:user:welcomb:rwx
default:group::---
default:mask:rwx
default:other:---
仍在使用课程帐户cs101
,我将一些文件推送到存储库中。
现在,我注销课程帐户并使用我自己的用户帐户登录,我可以克隆存储库 welcomb@solaris$ git clone ~cs101/cs101.git
到目前为止还不错,一切都很好。
现在的问题是我无法使用我自己的用户帐户将新提交推回回购协议:
welcomb@solaris$ GIT_TRACE=1 git push
trace: built-in: git 'push'
trace: run_command: 'git-receive-pack '\''/home/course/cs101'\'''
trace: exec: '/bin/bash' '-c' 'git-receive-pack '\''/home/course/cs101'\''' 'git-receive-pack '\''/home/course/cs101'\'''
trace: built-in: git 'receive-pack' '/home/course/cs101'
trace: run_command: 'pack-objects' '--all-progress-implied' '--revs' '--stdout' '--thin' '--delta-base-offset' '-q'
trace: exec: 'git' 'pack-objects' '--all-progress-implied' '--revs' '--stdout' '--thin' '--delta-base-offset' '-q'
trace: built-in: git 'pack-objects' '--all-progress-implied' '--revs' '--stdout' '--thin' '--delta-base-offset' '-q'
trace: run_command: 'unpack-objects' '--pack_header=2,3' '-q'
remote: trace: exec: 'git' 'unpack-objects' '--pack_header=2,3' '-q'
remote: trace: built-in: git 'unpack-objects' '--pack_header=2,3' '-q'
trace: run_command: 'rev-list' '--objects' '--stdin' '--not' '--all'
trace: exec: 'git' 'rev-list' '--objects' '--stdin' '--not' '--all'
trace: built-in: git 'rev-list' '--objects' '--stdin' '--not' '--all'
trace: run_command: 'hooks/update' 'refs/heads/master' '629b5b1f0122de95bd4e7b50a7968e64aaef6e65' 'b2072da84ee7d3fde6c6daf2cae61dbae6b0a5d9'
fatal: cannot exec 'hooks/update': Permission denied
remote: error: hook declined to update refs/heads/master
trace: run_command: 'gc' '--auto' '--quiet'
trace: exec: 'git' 'gc' '--auto' '--quiet'
trace: built-in: git 'gc' '--auto' '--quiet'
To /home/course/cs101
! [remote rejected] master -> master (hook declined)
error: failed to push some refs to '/home/course/cs101'
好像无法执行hooks/update
.
fatal: cannot exec 'hooks/update': Permission denied
但是 hooks/update
执行位是
甚至没有设置,这意味着 Git 应该忽略 运行 它。
/home/course/cs101/cs101.git/hooks$ getfacl update
# file: update
# owner: cs101
# group: cs101
user::rw-
user:cs101:rwx #effective:rwx
user:welcomb:rwx #effective:rwx
group::rw- #effective:rw-
mask:rwx
other:---
/home/course/cs101/cs101.git/hooks$ ls -al update
-rw-rw---- 1 cs101 cs101 2910 Aug 4 10:50 update
我可以访问目录中的文件,甚至可以使用我的帐户执行 update.sample
/home/course/cs101/cs101.git/hooks$ ./update.sample
Don't run this script from the command line.
(if you want, you could supply GIT_DIR then run
./update.sample <ref> <oldrev> <newrev>)
所以我不明白为什么 Git 推送无法更新存储库。
getfacl
输出包括以下行:
user:cs101:rwx #effective:rwx
user:welcomb:rwx #effective:rwx
这意味着 C 库 access(path, X_OK)
函数可能声明文件 可以 执行(运行 通过 execve
系统调用或类似),至少对于用户 cs101
和 welcomb
。这就是 Git 确定钩子是否可执行的方式。
(请注意,任何 other 用户调用 access
都会得到答案:不,此文件不可执行。这是使 ACL 如此复杂的部分原因。)
然而,当 OS 实际尝试执行它时,出现了其他问题。还不完全清楚什么 出错了,但是execve
系统调用失败并出现"permission denied" 错误。 Git 然后决定挂钩失败,而不是挂钩实际上不可执行(Git 假设 access
会说 no 而不是 是 对于这些情况)。
鉴于文件很小(2910 字节,来自 ls -al update
输出),update
挂钩似乎不太可能是 shell 脚本以外的任何东西。如果它 是 一个 shell 脚本,它需要一个正确的 #!
解释器行才能执行,并且该解释器行必须指向一个本身具有执行权限的文件.
如果您确实希望挂钩 运行,则必须追查实际失败的根源。如果您不想要挂钩运行,并且不希望Git想挂钩应该 运行,从 ACL 的各个元素中删除执行位,或者完全删除 ACL(ACL 和 "Unix style" 权限通常是底层系统中的独立实体,虽然这里的 ZFS 不同)。