当您运行钩子时,STDOUT(通常由echo
语句)被禁用。这意味着您的脚本无法使用 STDOUT 打印任何内容,即使它已被重定向到文件。
相反,您需要打开另一个文件描述符而不是使用1
(标准输出)。您可以使用exec
命令打开另一个文件描述符,然后将其通过管道传输到文件中:
exec 4> $my_file #Opening my_file for writing
echo "This is going to $my_file" >&4
STDERR 也是重定向。 STDERR 的输出被收集并发回调用客户端,但前提是挂钩返回非零退出代码。这为您提供了一种与客户端沟通挂钩失败原因的方法。
您还必须小心,因为钩子运行的环境会被擦洗。甚至$PATH
一片空白。
这些是为什么钩子脚本可以从命令行正常运行,但在作为钩子执行时却不能正常运行的一些原因。
如果您不相信某个钩子正在工作,只需对其进行设置,使其以非零退出代码退出。如果您从 Subversion 收到事务失败的消息,您就知道执行了挂钩脚本。
我还建议您至少使用svnserve
充当 Subversion 服务器——即使您是唯一使用该存储库的人。我从不使用file://
即使我是唯一使用该存储库的人。这svnserve
该过程使用起来非常简单,而且相当轻量。
另外,切勿使用svn
在钩子脚本中。使用svnlook
反而。
Addendum
我想对此说得非常非常清楚。我们需要就一些定义达成一致:
- SERVER 是运行 Subversion 存储库的计算机。你使用了命令
svnadmin create foo
创建一个foo
将充当存储库本身的目录。
- REPOSITORY DIRECTORY 是服务器上由
svnadmin create
命令。这是存储库的服务器端。你会not在这里查看您已签入 Subversion 的所有文件。相反,您会看到一个hooks
目录和一个db
目录。这是服务器用来跟踪其更改的内容。
- 工作目录是你已经完成的目录
svn checkout
查看项目的特定修订版。
- REPOSITORY 是您使用各种库时获得的 REPOSITORY DIRECTORY 的虚拟视图
svn
命令如svn ls
or svn log
or svn co
。这不是存储库目录,而是存储库的视图。
好的,现在我们已经解决了:
Hook 脚本存储在 REPOSITORY DIRECTORY 下hooks
目录。当您创建存储库目录时,已经有一个名为的子目录hooks
以及一些钩子脚本的模板。这些将有一个*.tmpl
后缀。要创建挂钩,您需要将这些脚本之一替换为您的挂钩脚本,然后将其删除*.tmpl
后缀。挂钩脚本必须具有可执行权限,并且由运行 Subversion SERVER 进程的用户拥有。 (用户运行httpd
or the svnserve
服务器上的命令)。
挂钩适用于整个存储库。您不能告诉钩子仅在特定分支受到影响时才触发。但是,您的挂钩脚本可以查看文件所在的位置并据此采取操作。我有一个预提交钩子 https://github.com/qazwart/SVN-Precommit-Kitchen-Sink-Hook就是这么做的。它使用控制文件来根据文件的位置确定需要采取的操作。但是,每次提交发生时,即使不需要执行任何操作,该钩子也会触发。
我希望这回答了你的问题。