Pergunta

Estou trabalhando em um gancho pós-commit .net para alimentar dados no OnTime por meio do Soap SDK.Meu gancho funciona bem no Windows, mas em nosso servidor subversion RHEL4 de produção, ele não funciona quando chamado a partir de um script de shell.

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

Quando executo com parâmetros da linha de comando, ele funciona corretamente.Quando executado através do shell script, recebo o seguinte erro:(parece que há algum problema com a execução do processo do SVN que utilizo para obter os dados de log da revisão):

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]

Eu tentei usar mkbundle e mkbundle2 para fazer um stand sozinho que poderia ser nomeado post-commit, mas recebo uma mensagem de erro diferente:

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]

Alguma idéia de por que pode estar falhando em um script de shell ou o que pode estar errado com a versão incluída?

Editar: @Herms, já tentei com um eco e parece certo.Quanto ao $1/hooks/post-commit.exe, tentei o script com e sem um caminho completo para o assembly .net com os mesmos resultados.

Editar: @Leão, eu tentei os dois $1 $2 e "$@" com os mesmos resultados.É um gancho de pós-commit do Subversion e leva dois parâmetros, portanto, eles precisam ser passados ​​​​para o assembly .net.O "$@" foi o que foi recomendado no site mono para chamar um assembly .net a partir de um script de shell.O script de shell é executando o assembly .net e com os parâmetros corretos, mas está lançando uma exceção que não é lançada quando executada diretamente da linha de comando.

Editar: @Vinko, não vejo nenhuma diferença no ambiente além de coisas como BASH_LINENO e BASH_SOURCE

Editar: @Lucas, cansei, mas isso também não faz diferença.Notei o problema pela primeira vez ao testar o TortoiseSVN na minha máquina (quando ele é executado como um subprocesso do daemon do subversion), mas também descobri que obtenho os mesmos resultados ao executar o script no diretório hooks (ou seja, ./post-commit REPOS REV, onde post-commit é o script sh acima.Fazendo mono post-commit.exe REPOS REV funciona bem.O principal problema é que para executar preciso ter algo com o nome post-commit para que seja chamado.Mas não funciona a partir de um script de shell e, como observado acima, o mkbundle não está trabalhando com um problema diferente.

Foi útil?

Solução

É normal que alguns processos fiquem parados por um tempo depois de fecharem seu stdout (ou seja,você obtém uma leitura de final de arquivo deles).Você precisa ligar proc.WaitForExit() depois de ler todos os dados, mas antes de verificar o ExitCode.

Outras dicas

Apenas um pensamento aleatório que pode ajudar na depuração.Tente alterar seu script de shell para:

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

Verifique e veja se a linha impressa corresponde ao comando que você espera que seja executado.É possível que o tratamento de argumentos da linha de comando no script Shell não esteja fazendo o que você deseja.

Não sei qual será a sua entrada no script, mas $1 antes do caminho parece um pouco deslocado para mim.

Tem certeza que deseja fazer

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

$@ expande para TODOS os argumentos."$@" expande para todos os argumentos unidos por espaços.Suspeito que seu script de shell esteja incorreto.Você não declarou exatamente o que queria que o roteiro fizesse, o que limita nossas possibilidades de fazer sugestões.

Compare as variáveis ​​de ambiente no seu shell e no script.

Tente colocar "cd $1/hooks/" antes da linha que executa mono.Você pode ter alguns assemblies nessa pasta que são encontrados quando você executa mono a partir dessa pasta no shell, mas não são encontrados quando você executa seu script.

Depois de ter verificado que meu código fez trabalhar na linha de comando, descobri que não estava mais funcionando!Analisei meu código .net para ver se alguma coisa fazia sentido.

Aqui está o que eu tinha:

        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;
        }

Eu mudei isso:

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

Parece que o processo está demorando um pouco mais do que estou obtendo a saída e, portanto, o proc.ExitCode está gerando um erro.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top