linux下的.net应用程序问题,无法从shell脚本运行

时间:2008-09-10 15:56:33

标签: .net linux svn mono

我正在研究一个.net post-commit钩子,通过他们的Soap SDK将数据提供给OnTime。我的钩子可以在Windows上正常工作,但是在我们的RHEL4生产版本​​的服务器上,从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脚本失败或捆绑版本可能出错?的任何想法?

编辑: @Herms,我已经用回声尝试了它,看起来是正确的。对于$1/hooks/post-commit.exe,我尝试使用和没有.net程序集的完整路径的脚本,但结果相同。

修改: @Leon,我尝试了$1 $2"$@"同样的结果。它是一个subversion post commit钩子,它需要两个参数,所以需要将它们传递给.net程序集。 "$@"是mono网站上推荐用于从shell脚本调用.net程序集的内容。 shell脚本执行.net程序集并使用正确的参数,但它抛出的异常在直接从命令行运行时不会被抛出。

修改: @Vinko,除了BASH_LINENOBASH_SOURCE

之外,我认为环境没有任何差异

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

6 个答案:

答案 0 :(得分:2)

某些进程在关闭stdout后暂停一段时间是正常的(即,从文件中获取文件结尾读取)。您需要在读取所有数据之后但在检查ExitCode之前调用proc.WaitForExit()

答案 1 :(得分:0)

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

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

检查并查看它打印的行是否与您期望它运行的命令相匹配。 shell脚本中的命令行参数处理可能没有按照您的意愿执行。

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

答案 2 :(得分:0)

你确定要做吗

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

在从命令行验证我的代码 工作后,我发现它已不再有效了!我去查看我的.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;

看起来Process比我输出的时间要长一些,因此proc.ExitCode会抛出错误。