我正在开发一个 .net post-commit 挂钩,通过他们的 Soap SDK 将数据输入到 OnTime 中。我的钩子在 Windows 上工作得很好,但在我们的生产 RHEL4 subversion 服务器上,当从 shell 脚本调用时它不会工作。

#!/bin/sh
/usr/bin/mono $1/hooks/post-commit.exe "$@"

当我使用命令行参数执行它时,它可以正常工作。当通过 shell 脚本执行时,出现以下错误:(看起来我用来获取修订日志数据的 SVN 的流程执行存在一些问题):

Unhandled Exception: System.InvalidOperationException: The process must exit before getting the requested information.
  at System.Diagnostics.Process.get_ExitCode () [0x0003f] in /tmp/monobuild/build/BUILD/mono-1.9.1/mcs/class/System/System.Diagnostics/Process.cs:149
  at (wrapper remoting-invoke-with-check) System.Diagnostics.Process:get_ExitCode ()
  at SVNLib.SVN.Execute (System.String sCMD, System.String sParams, System.String sComment, System.String sUserPwd, SVNLib.SVNCallback callback) [0x00000]
  at SVNLib.SVN.Log (System.String sUrl, Int32 nRevLow, Int32 nRevHigh, SVNLib.SVNCallback callback) [0x00000]
  at SVNLib.SVN.LogAsString (System.String sUrl, Int32 nRevLow, Int32 nRevHigh) [0x00000]
  at SVNCommit2OnTime.Program.Main (System.String[] args) [0x00000]

我尝试过使用 mkbundlemkbundle2 建立一个可以被命名的独立体 post-commit, ,但我收到不同的错误消息:

Unhandled Exception: System.ArgumentNullException: Argument cannot be null.
Parameter name: Value cannot be null.
  at System.Guid.CheckNull (System.Object o) [0x00000]
  at System.Guid..ctor (System.String g) [0x00000]
  at SVNCommit2OnTime.Program.Main (System.String[] args) [0x00000]

任何想法为什么它可能会因 shell 脚本而失败或者捆绑版本可能有什么问题?

编辑: @爱马仕, ,我已经用 echo 试过了,看起来不错。至于 $1/hooks/post-commit.exe, ,我尝试了带有和不带有 .net 程序集完整路径的脚本,结果相同。

编辑: @莱昂, ,我都尝试过 $1 $2"$@" 具有相同的结果。它是一个颠覆后提交挂钩,它需要两个参数,因此需要将它们传递给 .net 程序集。这 "$@" 这是 mono 站点推荐的从 shell 脚本调用 .net 程序集的方法。外壳脚本 执行 .net 程序集并使用正确的参数,但它引发了直接从命令行运行时不会引发的异常。

编辑: @温科, ,除了类似的事情之外,我没有看到环境有任何差异 BASH_LINENOBASH_SOURCE

编辑: @卢克, ,我厌倦了,但这也没有什么区别。我第一次注意到这个问题是在我的机器上从 TortoiseSVN 进行测试时(当它作为 subversion 守护进程的子进程运行时),但也发现从 hooks 目录执行脚本时得到了相同的结果(即 ./post-commit REPOS REV, , 在哪里 post-commit 就是上面的sh脚本。正在做 mono post-commit.exe REPOS REV 工作正常。主要问题是要执行,我需要有一些名称 post-commit 以便它被调用。但它不能在 shell 脚本中工作,并且如上所述, mkbundle 没有解决不同的问题。

有帮助吗?

解决方案

某些进程在关闭标准输出后停留一段时间是正常的(即你会从它们那里得到文件结尾的读数)。你需要打电话 proc.WaitForExit() 读取所有数据之后但在检查 ExitCode 之前。

其他提示

只是一个可能有助于调试的随机想法。尝试将您的 shell 脚本更改为:

#!/bin/sh
echo /usr/bin/mono $1/hooks/post-commit.exe "$@"

检查并查看它打印的行是否与您期望它运行的命令匹配。shell 脚本中的命令行参数处理可能没有执行您想要的操作。

我不知道您对脚本的输入预期是什么,但路径之前的 $1 对我来说看起来有点不合适。

你确定要这样做吗

/usr/bin/mono $1/hooks/post-commit.exe "$@"

$@ 扩展到所有参数。“$@”扩展到所有由空格连接的参数。我怀疑你的shell脚本不正确。您没有准确说明您希望脚本执行的操作,因此这确实限制了我们提出建议的可能性。

比较 shell 中和脚本中的环境变量。

尝试将“cd $1/hooks/”放在运行单声道的行之前。该文件夹中可能有一些程序集,当您从 shell 中的该文件夹运行 mono 时可以找到这些程序集,但在运行脚本时却找不到这些程序集。

验证我的代码后 做过 从命令行工作,我发现它不再工作了!我查看了我的 .net 代码,看看是否有任何意义。

这是我所拥有的:

        static public int Execute(string sCMD, string sParams, string sComment,
                                  string sUserPwd, SVNCallback callback)
        {
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.EnableRaisingEvents = false;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.Verb = "open";
            proc.StartInfo.FileName = "svn";
            proc.StartInfo.Arguments = Cmd(sCMD, sParams, sComment, UserPass());
            proc.Start();
            int nLine = 0;
            string sLine = "";
            while ((sLine = proc.StandardOutput.ReadLine()) != null)
            {
                ++nLine;
                if (callback != null)
                {
                    callback.Invoke(nLine, sLine);
                }
            }
            int errorCode = proc.ExitCode;
            proc.Close();
            return errorCode;
        }

我改变了这个:

            while (!proc.HasExited)
            {
                sLine = proc.StandardOutput.ReadLine();
                if (sLine != null)
                {
                    ++nLine;
                    if (callback != null)
                    {
                        callback.Invoke(nLine, sLine);
                    }
                }
            }
            int errorCode = proc.ExitCode;

看起来该进程的停留时间比我获得输出的时间要长一些,因此 proc.ExitCode 正在抛出一个错误。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top