Технологический процесс Waitforexit

Класс .NET Process в Linux.

В этой статье мы рассмотрим класс .NET Process. Мы рассмотрим основы того, как и когда его использовать, затем рассмотрим различия в использовании между Windows и Linux и укажем на несколько предостережений. В этой статье рассматривается поведение в .NET Core 3.0..

Основы.

Класс Process представляет собой экземпляр запущенного процесса. Вы можете использовать его для запуска новых процессов с помощью Process.Start или запуска процессов с помощью статических методов GetProcessById, GetProcesses, GetProcessesByName..

При запуске нового процесса вся информация для запуска процесса устанавливается в экземпляре ProcessStartInfo (PSI). PSI имеет такие свойства, как FileName и Arguments, для установки программы и ее аргументов. UseShellExecute позволяет открывать документы. RedirectStandard позволяет писать / читать стандартные потоки ввода-вывода. Environment / EnvironmentVariables и WorkingDirectory позволяют управлять переменными среды и рабочим каталогом..

.NET Core 2.1 (/ netstandard 2.1) добавлено свойство ArgumentList. Свойство Arguments представляет собой строку и требует, чтобы пользователь использовал правила экранирования командной строки Windows (например, использование двойных кавычек для разделения аргументов). Свойство ArgumentsList представляет собой коллекцию, содержащую отдельные аргументы. Process.Start позаботится о передаче их базовой платформе. При ориентации на .NET Core 2.1 + / netstandard2.1 рекомендуется использовать список аргументов вместо аргументов.+.

В следующем примере показан запуск приложения echo с одним аргументом hello world, а затем ожидание завершения процесса..

Не поддерживается в Linux.

Следующие свойства ProcessStartInfo не поддерживаются в Linux и вызывают исключение PlatformNotSupportedException: PasswordInClearText, Domain, LoadUserProfile, Password. .

Получение процессов с удаленного компьютера с помощью перегрузки MachineName GetProcessById, GetProcesses, GetProcessesByName также не поддерживается..

В Процессе не поддерживается установка ограничений рабочего набора (MinWorkingSet, MaxWorkingSet). В ProcessThread (полученном через Process.Threads) нельзя установить PriorityLevel / ProcessorAffinity.

Технологический процесс Waitforexit waitforexit

Процессы убийства.

Процессы можно остановить, вызвав Process.Kill. В Linux это реализуется путем отправки сигнала SIGKILL, который сообщает ядру о немедленном завершении приложения. Невозможно отправить сигнал SIGTERM, который запрашивает у приложения корректное завершение работы..

Начиная с .NET Core 3.0, Process.Kill больше не генерирует Win32Exception / InvalidOperationException, если процесс завершается или уже был завершен. Если вы ориентируетесь на более ранние версии .NET Core (или .NET Framework), вам следует добавить блок try / catch для обработки этих исключений..

.NET Core 3,0 добавляет перегрузку к методу Process.Kill, который принимает логическое целоеProcessTree. Если установлено значение true, потомки процесса также будут убиты..

UseShellExecute.

Свойство ProcessStartInfo.UseShellExecute можно использовать для открытия документов. Оболочка относится к графической оболочке пользователя, а не к оболочке командной строки, такой как bash. Установка этого значения в значение true означает, что вы будете вести себя так, как если бы пользователь дважды щелкнул файл. Когда ProcessStartInfo.FileName ссылается на исполняемый файл, он будет выполнен. Когда он ссылается на документ, он будет открыт с помощью программы по умолчанию. Например, файл .ods откроется с помощью LibreOffice Calc. Вы можете установить для FileName значение http-uri (например, https://redhatloves.net), чтобы открыть браузер и показать веб-сайт..

Сценарии оболочки Unix считаются настоящими исполняемыми файлами операционной системы (ОС). Это означает, что устанавливать UseShellExecute не требуется. Этот подход отличается от файлов .bat Windows, которым требуется оболочка Windows для поиска интерпретатора..

В Windows UseShellExecute позволяет выполнять альтернативные действия с документом (например, печать), задав для параметра ProcessStartInfo.Verb. В других ОС это свойство игнорируется..

Разрешение FileName.

При установке относительного имени файла в Process.FileName файл будет разрешен. Шаги разрешения зависят от того, установлен ли UseShellExecute. Разрешение на платформах, отличных от Windows, реализовано так, чтобы вести себя аналогично Windows..

Когда UseShellExecute имеет значение false:

Найдите файл в каталоге собственного приложения. Найдите файл в рабочем каталоге процесса. Найдите файл в PATH.

Собственный каталог приложения — это каталог установки dotnet при запуске dotnet. При использовании собственного хоста приложения это каталог хоста приложения..

Когда UseShellExecute имеет значение true:

Найдите исполняемый файл в ProcessStartInfo.WorkingDirectory. Если он не установлен, используется рабочий каталог процесса. Найдите исполняемый файл в PATH. Используйте программу открытия оболочки и передайте ей относительный путь.

Важно знать, что в обоих случаях производится поиск в каталогах, которые могут быть небезопасными (исполняемый каталог, рабочий каталог). Вы можете реализовать собственное разрешение и всегда устанавливать для FileName абсолютный путь.

Перенаправленные потоки.

Когда UseShellExecute имеет значение false, вы можете перенаправить стандартный ввод, вывод и ошибку с помощью ProcessStartInfo.RedirectStandard. Соответствующие свойства кодирования (например, StandardOutputEncoding) позволяют вам устанавливать кодировку для потоков..

Если вы не запускаете или не запускаете интерактивное приложение (например, запускаете vi), вам следует перенаправить потоки и обработать их..

Обратите внимание, что асинхронные методы, такие как Process.StandardOutput.ReadAsync и Process.BeginOutputReadLine, используют ThreadPool для асинхронного чтения, что означает, что они блокируют поток ThreadPool при ожидании вывода приложения. Такой подход может привести к нехватке ThreadPool, если у вас много процессов, которые мало выводят. Это проблема и в Windows.

Если вы используете Begin ReadLine и вызываете WaitForExit, этот метод будет ждать, пока не будет прочитан весь стандартный вывод / ошибка (и не будут сгенерированы соответствующие события DataReceived). Этот подход может привести к блокировке вызова для процесса, который завершился, когда есть потомки, которые сохраняют перенаправленные потоки открытыми..

Имя процесса.

В Linux при выполнении сценария оболочки Process.ProcessName содержит имя сценария. Точно так же Process.GetProcessesByName будет соответствовать именам скриптов. Эта возможность полезна для идентификации процессов независимо от того, являются ли они собственными исполняемыми файлами, сценариями или сценариями, обертывающими собственные исполняемые файлы..

Выход из процесса.

Процессы занимают некоторые ресурсы в ядре. В Windows эта информация подсчитывается по ссылкам, что позволяет нескольким пользователям поддерживать информацию в актуальном состоянии с помощью дескриптора процесса. В Unix есть единственный владелец этой информации. Во-первых, это родительский процесс, а когда родитель умирает, это процесс init (pid 1) (или процесс, который взял на себя эту ответственность, используя PR_SET_CHILD_SUBREAPER). Процесс владения — это процесс, отвечающий за очистку ресурсов ядра (также известный как получение дочернего элемента). .NET Core перехватывает дочерние процессы, как только они завершаются.

Когда ресурсы очищены, информация о процессе больше не может быть получена. Свойства, возвращающие информацию о времени выполнения, в этот момент вызывают исключение InvalidOperationException. В Windows вы можете получить StartTime, ProcessorTime после выхода из процесса. В Linux эти свойства также вызывают исключение InvalidOperationException..

В Linux Process.ExitCode действителен только для прямых потомков. Для других процессов он возвращает 0 или выдает исключение InvalidOperationException в зависимости от состояния процесса. .

Если вы работаете в контейнере, часто процесс инициализации отсутствует. Это означает, что никто не пожинает детей-сирот. Такие дочерние процессы будут продолжать использовать ресурсы ядра, и .NET Core никогда не будет считать их завершенными. Эта проблема возникает, когда у приложения есть потомки, которые живут дольше своих родителей. В этом случае вам следует добавить процесс инициализации в свой контейнер. При использовании docker / podman run вы можете добавить его с помощью флага —init.

Заключение.

В этой статье мы объяснили поведение .NET-класса Process в Linux. Мы рассмотрели базовое использование, неподдерживаемое поведение, различия с Windows и другие вещи, о которых следует знать..

Похожие статьи