Pregunta

Estoy trabajando en un enlace posterior a la confirmación de .net para introducir datos en OnTime a través de su SDK Soap.Mi gancho funciona bien en Windows, pero en nuestro servidor de subversión RHEL4 de producción, no funcionará cuando se le llame desde un script de shell.

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

Cuando lo ejecuto con parámetros desde la línea de comando, funciona correctamente.Cuando lo ejecuto a través del script de shell, aparece el siguiente error:(parece que hay algún problema con la ejecución del proceso de SVN que uso para obtener los datos de registro para la revisión):

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]

He intentado usar mkbundle y mkbundle2 para hacer un stand solo que podría ser nombrado post-commit, pero recibo un mensaje de error 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]

¿Alguna idea de por qué podría estar fallando un script de shell o qué podría estar mal con la versión incluida?

Editar: @Herms, ya lo probé con un eco y parece correcto.En cuanto a $1/hooks/post-commit.exe, Probé el script con y sin una ruta completa al ensamblado .net con los mismos resultados.

Editar: @León, he probado ambos $1 $2 y "$@" con los mismos resultados.Es un gancho posterior a la confirmación de Subversion y requiere dos parámetros, por lo que deben pasarse al ensamblado .net.El "$@" fue lo que se recomendó en el sitio mono para llamar a un ensamblado .net desde un script de shell.El script de shell es ejecutando el ensamblado .net y con los parámetros correctos, pero genera una excepción que no se genera cuando se ejecuta directamente desde la línea de comando.

Editar: @vinko, No veo ninguna diferencia en el entorno aparte de cosas como BASH_LINENO y BASH_SOURCE

Editar: @Lucas, Lo cansé, pero eso tampoco hace ninguna diferencia.La primera vez que noté el problema fue cuando probé TortoiseSVN en mi máquina (cuando se ejecuta como un subproceso del demonio de subversión), pero también descubrí que obtengo los mismos resultados cuando ejecuto el script desde el directorio de ganchos (es decir, ./post-commit REPOS REV, dónde post-commit es el script sh anterior.Haciendo mono post-commit.exe REPOS REV funciona bien.El principal problema es que para ejecutar necesito tener algo con el nombre post-commit para que sea llamado.Pero no funciona desde un script de shell y, como se señaló anteriormente, el mkbundle no está funcionando con un problema diferente.

¿Fue útil?

Solución

Es normal que algunos procesos permanezcan inactivos por un tiempo después de cerrar su salida estándar (es decir,obtendrá una lectura de final de archivo de ellos).necesitas llamar proc.WaitForExit() después de leer todos los datos pero antes de verificar ExitCode.

Otros consejos

Sólo un pensamiento aleatorio que podría ayudar con la depuración.Intente cambiar su script de shell a:

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

Verifique y vea si la línea que imprime coincide con el comando que espera que ejecute.Es posible que el manejo de los argumentos de la línea de comando en el script de shell no esté haciendo lo que usted desea.

No sé cuál se espera que sea su entrada al script, pero el $1 antes de la ruta me parece un poco fuera de lugar.

¿Estás seguro de que quieres hacer

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

$@ se expande a TODOS los argumentos."$@" se expande a todos los argumentos unidos por espacios.Sospecho que su script de shell es incorrecto.No dijiste exactamente qué querías que hiciera el guión, por lo que eso limita nuestras posibilidades de hacer sugerencias.

Compare las variables de entorno en su shell y desde el script.

Intente poner "cd $1/hooks/" antes de la línea que se ejecuta en mono.Es posible que tenga algunos ensamblados en esa carpeta que se encuentran cuando ejecuta mono desde esa carpeta en el shell pero que no se encuentran cuando ejecuta su secuencia de comandos.

Después de haber verificado que mi código hizo Trabajé desde la línea de comando, ¡descubrí que ya no funcionaba!Busqué en mi código .net para ver si algo tenía sentido.

Esto es lo que tenía:

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

Cambié esto:

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

Parece que el proceso dura un poco más de lo que obtengo y, por lo tanto, el proc.ExitCode está arrojando un error.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top