为什么会出现此错误:提交后挂钩失败(退出代码 255),没有输出

发布于 2024-11-05 13:31:33 字数 4259 浏览 3 评论 0原文

当我提交到存储库时,我收到以下错误:

post-commit hook failed (exit code 255) with no output.

提交后代码如下:

@echo off

setlocal enableextensions

set REPOS=%1
set REV=%2
set TEMPFILE=C:\TEMP\%REV%.txt
set LOGFILE=D:\svn\logs\mysite\post_commit.log

set MANTIS_PATH="D:\home\mantis"

"C:\Program Files\SlikSvn\bin\svnlook" author %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt
"C:\Program Files\SlikSvn\bin\svnlook" date %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt
"C:\Program Files\SlikSvn\bin\svnlook" changed %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt
echo revision:[%REV%] >> %TEMPFILE% 2>>C:\TEMP\err.txt
"C:\Program Files\SlikSvn\bin\svnlook" log %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt

date /T >> %LOGFILE% 2>>C:\TEMP\err.txt
time /T >> %LOGFILE% 2>>C:\TEMP\err.txt
D:\wamp\bin\php\php5.3.0\php.exe %MANTIS_PATH%\scripts\checkin.php < %TEMPFILE% >> %LOGFILE% 2>>C:\TEMP\err.txt
  • 如您所见,有大量错误日志记录,但错误日志永远不会被填充(除非我输入了明显的错误,例如丢失的路径) )
  • 开发环境和实时环境都是 Windows
  • 似乎出现错误的行是最后一行 - 调用 PHP 的地方。当我把它拿出来时,提交工作没有问题
  • 当我在命令行上手动运行它时,它工作并且不显示任何(明显的)错误。 Afaik svn 默认用户在 SYSTEM 下运行,该用户具有足够高的权限,不必担心

正如您可能已经发现的那样,这是将我的 SVN 签入与 Mantis 错误跟踪器连接起来。有趣的是,PHP 脚本正在执行,即注释被添加到错误中,并且问题的自动关闭功能正在运行。它似乎只是由于某种原因而出错。

我正在使用 TortoiseSVN 进行提交,但是使用命令行(SlikSVN)我得到相同的输出:

svn ci -m "this is a test" test.txt
Sending        test.txt
Transmitting file data .
Committed revision 1337.

Warning: post-commit hook failed (exit code 255) with no output.

Mantis 的 checkin.php 看起来像这样(为了可读性删除了一些一般注释):

#!/usr/bin/php -q
<?php

global $g_bypass_headers;
$g_bypass_headers = 1;
require_once( dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'core.php' );

# Make sure this script doesn't run via the webserver
if( php_sapi_name() != 'cli' ) {
    echo "checkin.php is not allowed to run through the webserver.\n";
    exit( 1 );
}

# Check that the username is set and exists
$t_username = config_get( 'source_control_account' );
if( is_blank( $t_username ) || ( user_get_id_by_name( $t_username ) === false ) ) {
    echo "Invalid source control account ('$t_username').\n";
    exit( 1 );
}

if( !defined( "STDIN" ) ) {
    define( "STDIN", fopen( 'php://stdin', 'r' ) );
}

# Detect references to issues + concat all lines to have the comment log.
$t_commit_regexp = config_get( 'source_control_regexp' );
$t_commit_fixed_regexp = config_get( 'source_control_fixed_regexp' );

$t_comment = '';
$t_issues = array();
$t_fixed_issues = array();
while(( $t_line = fgets( STDIN, 1024 ) ) ) {
    $t_comment .= $t_line;
    if( preg_match_all( $t_commit_regexp, $t_line, $t_matches ) ) {
        $t_count = count( $t_matches[0] );
        for( $i = 0;$i < $t_count;++$i ) {
            $t_issues[] = $t_matches[1][$i];
        }
    }

    if( preg_match_all( $t_commit_fixed_regexp, $t_line, $t_matches ) ) {
        $t_count = count( $t_matches[0] );
        for( $i = 0;$i < $t_count;++$i ) {
            $t_fixed_issues[] = $t_matches[1][$i];
        }
    }
}

# If no issues found, then no work to do.
if(( count( $t_issues ) == 0 ) && ( count( $t_fixed_issues ) == 0 ) ) {
    echo "Comment does not reference any issues.\n";
    exit( 0 );
}

# Login as source control user
if( !auth_attempt_script_login( $t_username ) ) {
    echo "Unable to login\n";
    exit( 1 );
}

# history parameters are reserved for future use.
$t_history_old_value = '';
$t_history_new_value = '';

# add note to each bug only once
$t_issues = array_unique( $t_issues );
$t_fixed_issues = array_unique( $t_fixed_issues );

# Call the custom function to register the checkin on each issue.

foreach( $t_issues as $t_issue_id ) {
    if( !in_array( $t_issue_id, $t_fixed_issues ) ) {
        helper_call_custom_function( 'checkin', array( $t_issue_id, $t_comment, $t_history_old_value, $t_history_new_value, false ) );
    }
}

foreach( $t_fixed_issues as $t_issue_id ) {
    helper_call_custom_function( 'checkin', array( $t_issue_id, $t_comment, $t_history_old_value, $t_history_new_value, true ) );
}

exit( 0 );

I am getting the following error when I commit to a repository:

post-commit hook failed (exit code 255) with no output.

The post commit code is as follows:

@echo off

setlocal enableextensions

set REPOS=%1
set REV=%2
set TEMPFILE=C:\TEMP\%REV%.txt
set LOGFILE=D:\svn\logs\mysite\post_commit.log

set MANTIS_PATH="D:\home\mantis"

"C:\Program Files\SlikSvn\bin\svnlook" author %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt
"C:\Program Files\SlikSvn\bin\svnlook" date %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt
"C:\Program Files\SlikSvn\bin\svnlook" changed %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt
echo revision:[%REV%] >> %TEMPFILE% 2>>C:\TEMP\err.txt
"C:\Program Files\SlikSvn\bin\svnlook" log %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt

date /T >> %LOGFILE% 2>>C:\TEMP\err.txt
time /T >> %LOGFILE% 2>>C:\TEMP\err.txt
D:\wamp\bin\php\php5.3.0\php.exe %MANTIS_PATH%\scripts\checkin.php < %TEMPFILE% >> %LOGFILE% 2>>C:\TEMP\err.txt
  • As you can see there is extensive error logging, but the error log never gets populated (unless I put in an obvious error like a missing path)
  • Both dev and live environments are Windows
  • The line that seems to case the error is the final one - where PHP is called. When I take this out the commit works without issue
  • When I run this manually on the command line it works and doesn't show any (obvious) errors. Afaik svn runs under SYSTEM by default user which is high enough privilleges to not have to worry

As you've probably made out, this is hooking up my SVN checkins with Mantis bug tracker. The interesting thing is that the PHP script is being executed, i.e. the notes are being added to bugs and the auto-closing of issues is working. It just seems to erroring for some reason.

I am using TortoiseSVN to commit, but using command line (SlikSVN) I get the same output:

svn ci -m "this is a test" test.txt
Sending        test.txt
Transmitting file data .
Committed revision 1337.

Warning: post-commit hook failed (exit code 255) with no output.

Mantis' checkin.php looks like this (some general comments removed for readability):

#!/usr/bin/php -q
<?php

global $g_bypass_headers;
$g_bypass_headers = 1;
require_once( dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'core.php' );

# Make sure this script doesn't run via the webserver
if( php_sapi_name() != 'cli' ) {
    echo "checkin.php is not allowed to run through the webserver.\n";
    exit( 1 );
}

# Check that the username is set and exists
$t_username = config_get( 'source_control_account' );
if( is_blank( $t_username ) || ( user_get_id_by_name( $t_username ) === false ) ) {
    echo "Invalid source control account ('$t_username').\n";
    exit( 1 );
}

if( !defined( "STDIN" ) ) {
    define( "STDIN", fopen( 'php://stdin', 'r' ) );
}

# Detect references to issues + concat all lines to have the comment log.
$t_commit_regexp = config_get( 'source_control_regexp' );
$t_commit_fixed_regexp = config_get( 'source_control_fixed_regexp' );

$t_comment = '';
$t_issues = array();
$t_fixed_issues = array();
while(( $t_line = fgets( STDIN, 1024 ) ) ) {
    $t_comment .= $t_line;
    if( preg_match_all( $t_commit_regexp, $t_line, $t_matches ) ) {
        $t_count = count( $t_matches[0] );
        for( $i = 0;$i < $t_count;++$i ) {
            $t_issues[] = $t_matches[1][$i];
        }
    }

    if( preg_match_all( $t_commit_fixed_regexp, $t_line, $t_matches ) ) {
        $t_count = count( $t_matches[0] );
        for( $i = 0;$i < $t_count;++$i ) {
            $t_fixed_issues[] = $t_matches[1][$i];
        }
    }
}

# If no issues found, then no work to do.
if(( count( $t_issues ) == 0 ) && ( count( $t_fixed_issues ) == 0 ) ) {
    echo "Comment does not reference any issues.\n";
    exit( 0 );
}

# Login as source control user
if( !auth_attempt_script_login( $t_username ) ) {
    echo "Unable to login\n";
    exit( 1 );
}

# history parameters are reserved for future use.
$t_history_old_value = '';
$t_history_new_value = '';

# add note to each bug only once
$t_issues = array_unique( $t_issues );
$t_fixed_issues = array_unique( $t_fixed_issues );

# Call the custom function to register the checkin on each issue.

foreach( $t_issues as $t_issue_id ) {
    if( !in_array( $t_issue_id, $t_fixed_issues ) ) {
        helper_call_custom_function( 'checkin', array( $t_issue_id, $t_comment, $t_history_old_value, $t_history_new_value, false ) );
    }
}

foreach( $t_fixed_issues as $t_issue_id ) {
    helper_call_custom_function( 'checkin', array( $t_issue_id, $t_comment, $t_history_old_value, $t_history_new_value, true ) );
}

exit( 0 );

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

趁年轻赶紧闹 2024-11-12 13:31:33

我通常建议不要对 Subversion 挂钩使用批处理脚本。有大量免费、开源的脚本语言,它们功能更强大、更易于使用。哎呀,我什至不使用 BASH 来编写钩子脚本。

尤其如此,因为钩子脚本只需在服务器上运行,而无需在其他地方运行。这意味着您只需让它在单一平台上运行即可。


话虽这么说,您需要进行一些调试。您的钩子脚本通过 svn commit 命令行失败。这意味着这不是与乌龟相关的问题。这是一个钩子脚本问题。由于这是一个后挂钩脚本,请尝试从命令行运行脚本本身,并从命令行将存储库和修订传递给它:

C> post-commit C:\repos\my_repo 2323

这有效吗?

问题是您没有在 STDERR 上打印任何内容,因此 Subversion 没有任何内容可以打印。您正在文件中捕获 STDERR。删除2>>C:\TEMP\err.txt,这样您就可以看到错误输出。在 Python、BASH 和 Perl 中,我可以捕获 STDERR,并且仍然将其打印出来,但我不确定如何在批处理脚本中执行此操作。

这将允许您查看错误输出,并可能帮助您确定脚本失败的位置。它在调用 PHP 脚本之前是否失败了?你的 PHP 脚本中有什么问题吗?您所做的假设是否不一定有效?

另外,不要仅仅在 PHP 挂钩中 echo 内容。无论挂钩成功还是失败,Subversion 都不会在 STDOUT 上打印任何内容。使用 fputs(STDERR, 'My Error Message'); 而不是 echoprint。这会将您的错误消息发送到 STDERR,如果您的钩子脚本失败,Subversion 会将其打印出来。

希望这有帮助。

I usually recommend not using batch scripts for Subversion hooks. There are a ton of free, open source, scripting languages that are more powerful and easier to work with. Heck, I don't even use BASH for hook scripts.

This is especially true since hook scripts only have to run on the server and no where else. That means you only have to get it working on a single platform.


That being said, you'll need to do some debugging. Your hook script fails via the svn commit command line. That means it's not a Tortoise related issue. It's a hook script issue. Since this is a post hook script, try running the script itself from the command line and pass to it the repository and revision from the command line:

C> post-commit C:\repos\my_repo 2323

Does that work?

The problem is that you're not printing anything on STDERR, so there's nothing for Subversion to print. You're capturing STDERR in a file. Remove the 2>>C:\TEMP\err.txt, so you can see the error output. In Python, BASH, and Perl, I could capture STDERR, and still print it out, but I'm not sure how to do this in Batch script.

This would allow you to see the error output, and maybe help you determine where your script is failing. Is it failing before it calls your PHP script? Is something going on in your PHP script? Are there assumptions you're making which aren't necessarily valid?

Also, don't merely echo stuff in your PHP hook. Subversion doesn't print anything on STDOUT no matter if the hook succeeds or fails. Use fputs(STDERR, 'My Error Message'); instead of echo or print. This will send your error message to STDERR and Subversion will print it out if your hook script fails.

Hope this helps.

旧故 2024-11-12 13:31:33

我也遇到了这个问题。确保您的脚本文件权限设置为可执行。

I was running in to this as well. Make sure your script file permissions are set to Executable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文