代码之家  ›  专栏  ›  技术社区  ›  crashmstr

Linux下的.NET应用程序有问题,无法从shell脚本运行

  •  1
  • crashmstr  · 技术社区  · 16 年前

    我正在开发一个.NET提交后挂钩,通过他们的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]
    

    我试过用 mkbundle mkbundle2 使一个可以命名的独立 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脚本而失败,或者捆绑版本有什么问题吗?

    编辑: @Herms ,我已经用回声测试过了,看起来不错。至于 $1/hooks/post-commit.exe ,我尝试了使用和不使用具有相同结果的.NET程序集完整路径的脚本。

    编辑: @Leon 我都试过了 $1 $2 "$@" 结果相同。它是一个subversion post commit hook,它需要两个参数,因此这些参数需要传递到.NET程序集。这个 “$@” 是Mono站点建议从shell脚本调用.NET程序集的内容。shell脚本 执行.NET程序集并使用正确的参数,但它引发的异常在直接从命令行运行时不会引发。

    编辑: @Vinko 我看不出环境有什么不同,除了 BASH_LINENO BASH_SOURCE

    编辑: @Luke 我累了,但也没什么区别。在我的机器上从tortoissesvn进行测试时(当它作为subversion守护进程的子进程运行时),我首先注意到了这个问题,但是在从hooks目录(即 ./post-commit REPOS REV 在哪里 后提交 是上面的sh脚本。做 mono post-commit.exe REPOS REV 工作良好。主要的问题是要执行,我需要有一个名字 后提交 所以它会被称为。但它不适用于shell脚本,如上所述, Mk捆 没有处理其他问题。

    6 回复  |  直到 10 年前
        1
  •  2
  •   Arnab Nandy    10 年前

    有些进程在关闭stdout后会挂起一段时间是正常的(即,从中读取文件结束)。你需要打电话 proc.WaitForExit() 在读取所有数据之后,但在检查exitcode之前。

        2
  •  0
  •   Herms    16 年前

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

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

    检查并查看它打印的行是否与您期望它运行的命令匹配。shell脚本中的命令行参数处理可能没有按您希望的方式进行。

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

        3
  •  0
  •   Leon Timmermans    16 年前

    你确定要这样做吗

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

    $@扩展到所有参数。“$@“扩展到所有由空格连接的参数。我怀疑你的shell脚本不正确。你没有明确说明你想要脚本做什么,所以这限制了我们提出建议的可能性。

        4
  •  0
  •   Vinko Vrsalovic    16 年前

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

        5
  •  0
  •   Luke    16 年前

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

        6
  •  0
  •   crashmstr    16 年前

    在验证了我的代码之后 从命令行开始工作,我发现它不再工作了!我查看了我的.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 正在引发错误。