Проблема с приложением .net под Linux, не работает из сценария оболочки

StackOverflow https://stackoverflow.com/questions/54503

  •  09-06-2019
  •  | 
  •  

Вопрос

Я работаю над крючком post-commit .net для передачи данных в OnTime через их Soap SDK.Мой крючок отлично работает в Windows, но на нашем производственном сервере подрывной деятельности RHEL4 он не будет работать при вызове из сценария оболочки.

#!/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]

Есть идеи, почему может произойти сбой из сценария оболочки или что может быть не так со встроенной версией?

Редактировать: @Herms, я уже пробовал с эхом, выглядит правильно.Для $1/hooks/post-commit.exe, Я пробовал сценарий с полным путем к сборке .net и без него, результаты были одинаковыми.

Редактировать: @Леон, я пробовал оба $1 $2 и "$@" с теми же результатами.Это перехватчик после фиксации Subversion, который принимает два параметра, поэтому их необходимо передать в сборку .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 "$@"

$@ расширяется до ВСЕХ аргументов.«$@» расширяется до всех аргументов, соединенных пробелами.Я подозреваю, что ваш сценарий оболочки неверен.Вы не указали, что конкретно вы хотите от сценария, и это ограничивает наши возможности вносить предложения.

Сравните переменные среды в вашей оболочке и внутри скрипта.

Попробуйте поставить «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 выдает ошибку.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top