Linux での .net アプリの問題、シェル スクリプトから動作しない
質問
私は、Soap SDK 経由で OnTime にデータをフィードするための .net コミット後のフックに取り組んでいます。私のフックは Windows では正常に動作しますが、運用環境の RHEL4 Subversion サーバーでは、シェル スクリプトから呼び出すと動作しません。
#!/bin/sh /usr/bin/mono $1/hooks/post-commit.exe "$@"
コマンドラインからパラメータを指定して実行すると、正常に動作します。シェルスクリプト経由で実行すると、次のエラーが発生します。(リビジョンのログ データを取得するために使用する 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]
シェルスクリプトが原因で失敗する理由、またはバンドルされたバージョンに問題がある可能性がある理由はありますか?
編集: @ヘルムス, すでにエコーで試してみましたが、問題ないようです。については、 $1/hooks/post-commit.exe
, .net アセンブリへのフルパスを指定した場合と指定しない場合でスクリプトを試してみましたが、同じ結果でした。
編集: @レオン, 両方試してみました $1 $2
そして "$@"
同じ結果になります。これは Subversion のコミット後のフックであり、2 つのパラメーターを取るため、それらを .net アセンブリに渡す必要があります。の "$@"
これは、モノラル サイトでシェル スクリプトから .net アセンブリを呼び出すために推奨されていたものでした。シェルスクリプト は 正しいパラメーターを使用して .net アセンブリを実行すると、コマンド ラインから直接実行した場合にはスローされない例外がスローされます。
編集: @ヴィンコ, といったこと以外に環境の違いは見当たりません。 BASH_LINENO
そして BASH_SOURCE
編集: @ルーク, 疲れましたが、それも問題ありません。私が最初にこの問題に気づいたのは、自分のマシンで TortoiseSVN をテストしたとき (Subversion デーモンのサブプロセスとして実行したとき) でしたが、フック ディレクトリからスクリプトを実行したときにも同じ結果が得られることもわかりました (つまり、 ./post-commit REPOS REV
, 、 どこ post-commit
は上記の sh スクリプトです。やってる mono post-commit.exe REPOS REV
正常に動作します。主な問題は、実行するには、次のような名前が必要であることです。 post-commit
そう呼ばれるようになります。ただし、シェル スクリプトからは機能しません。また、上で述べたように、 mkbundle
別の問題で動作しません。
解決
一部のプロセスが標準出力を閉じた後、しばらくハングアップするのは正常です。ファイルの終わりを読み取ることができます)。電話する必要があります proc.WaitForExit()
すべてのデータを読み取った後、ExitCode をチェックする前。
他のヒント
デバッグに役立つかもしれない単なる考えです。シェル スクリプトを次のように変更してみてください。
#!/bin/sh
echo /usr/bin/mono $1/hooks/post-commit.exe "$@"
出力される行が、実行する予定のコマンドと一致するかどうかを確認してください。シェル スクリプトでのコマンド ライン引数の処理が意図したとおりに動作していない可能性があります。
スクリプトへの入力がどのようなものになると予想されるのかわかりませんが、パスの前の $1 は少し場違いに思えます。
本当に実行してもよろしいですか
/usr/bin/mono $1/hooks/post-commit.exe "$@"
$@ はすべての引数に展開されます。「$@」は、スペースで結合されたすべての引数に展開されます。シェルスクリプトが間違っているのではないかと思います。スクリプトで何をさせたいのかを正確に述べていないため、私たちが提案できる可能性は限られています。
シェル内の環境変数とスクリプト内の環境変数を比較します。
mono を実行する行の前に「cd $1/hooks/」を入れてみてください。そのフォルダー内には、シェルでそのフォルダーから 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
エラーがスローされています。