Linux 下的 .net 应用程序存在问题,无法从 shell 脚本中工作

Problem with .net app under linux, doesn't work from shell script

提问人:crashmstr 提问时间:9/10/2008 最后编辑:Communitycrashmstr 更新时间:1/26/2015 访问量:1682

问:

我正在开发一个 .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]

我尝试使用并制作一个可以命名的独立文件,但我收到不同的错误消息:mkbundlemkbundle2post-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,我已经用回声尝试过了,看起来不错。至于 ,我已经尝试了带有和没有 .net 程序集的完整路径的脚本,结果相同。$1/hooks/post-commit.exe

编辑:@Leon,我都尝试过,结果相同。它是一个 Subversion 提交后钩子,它需要两个参数,因此需要将这些参数传递给 .net 程序集。这是在 mono 站点上推荐的从 shell 脚本调用 .net 程序集的内容。shell 脚本正在执行 .net 程序集并使用正确的参数,但它抛出的异常在直接从命令行运行时不会引发。$1 $2"$@""$@"

编辑:@Vinko,除了 和BASH_LINENOBASH_SOURCE

编辑:@Luke,我累了,但这也没有区别。我首先注意到这个问题是在我的机器上从 TortoiseSVN 进行测试时(当它作为 subversion 守护进程的子进程运行时),但也发现我从 hooks 目录执行脚本时得到了相同的结果(即 ,上面的 sh 脚本在哪里。做得很好。主要问题是要执行,我需要有一些名称,以便调用它。但它不能从 shell 脚本中工作,并且如上所述,它不适用于其他问题。./post-commit REPOS REVpost-commitmono post-commit.exe REPOS REVpost-commitmkbundle

.NET Linux SVN 单声道

评论


答:

0赞 Herms 9/11/2008 #1

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

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

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

我不知道你对脚本的输入应该是多少,但路径之前的 1 美元对我来说看起来有点不合适。

0赞 Leon Timmermans 9/11/2008 #2

你确定要做吗

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

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

0赞 Vinko Vrsalovic 9/11/2008 #3

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

0赞 Luke 9/11/2008 #4

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

0赞 crashmstr 9/11/2008 #5

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

2赞 apenwarr 9/16/2008 #6

某些进程在关闭其 stdout 后会徘徊一段时间是正常的(即,您从它们那里获得文件末尾读数)。您需要在读取所有数据后但在检查 ExitCode 之前调用。proc.WaitForExit()