Вызов Java.exe с параметрами с помощью Powershell отображает информацию как ошибку

Описание

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

Дженкинс работает на Java, поэтому мне пришлось вызвать Java.exe.

Что я пробовал

Для этого мне нужно убедиться, что при завершении сценария завершается и Java-процесс.

Я обнаружил, что использование CMD /c или Start-Process запускает новый процесс, и поэтому остановка сценария PowerShell не останавливает также java.exe. Единственное, что работало, это звонок оператора &.

Однако, как вы видите ниже, информация, возвращаемая из JAVA, рассматривается как исключение. ЭТО ЛОЖНО-ПОЛОЖИТЕЛЬНО.

Что я пробовал и что мне нужно

Мне нужно убедиться, что фактическая информация отправляется на вывод как обычно, а не скрыта.

Это исключает $ErrorActionPreference = 'SilentlyContinue'

Также пробовал 2>&1 и *>&1, но результат тот же

Любые идеи будут великолепны.

Код

& "$Java\java.exe" -jar "$JenkinsPath\agent.jar" -url "$JenkinsURL/" -secret $Secret -name $env:computername -workDir "$JenkinsPath" *>>"$JenkinsPath\agent.log"

Ошибка

java.exe : Aug 04, 2024 5:14:14 PM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir
At line:1 char:1
+ & "$Java\java.exe" -jar "$JenkinsPath\agent.jar" -url "$JenkinsURL/"  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Aug 04, 2024 5:...itializeWorkDir:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
INFO: Using D:\Jenkins\remoting as a remoting work directory
Aug 04, 2024 5:14:14 PM org.jenkinsci.remoting.engine.WorkDirManager setupLogging
INFO: Both error and output logs will be printed to D:\Jenkins\remoting
Aug 04, 2024 5:14:14 PM hudson.remoting.Launcher createEngine

Заранее спасибо.

#1 Если вы работаете с открытым исходным кодом, обязательна ли Windows? №2 обязателен ли powershell? Как вы создаете службу Windows?

JRichardsz 04.08.2024 18:11

1. Да 2. Я всегда могу вернуться к C# в Powershell 3. Пока работаю над самим EXE, служба будет использована позже.

Elior Machlev 04.08.2024 18:35

В качестве отступления: вызов jave.exe через cmd /C здесь не обязателен, но в отношении завершения процесса PowerShell, выполняющего скрипт, не должно быть никакой разницы. Напротив, процесс, запущенный aStart-Process, — это независимый процесс (а не дочерний процесс вызывающего объекта), который по умолчанию запускается асинхронно и в новом окне. Только в необычных ситуациях требуется Start-Process; прямой вызов (через & или просто по имени/пути, если оно не заключено в кавычки и не содержит переменных) почти всегда является лучшим решением.

mklement0 04.08.2024 22:14
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Краткое содержание

Напишите один или несколько сценариев, способных получить pid (идентификатор процесса) запущенного процесса или каким-либо образом запросить операционную систему, чтобы найти уникальный процесс (в вашем случае jenkins). Затем используйте pid, чтобы завершить процесс.


Передний план против фона

Если вам удастся запустить процесс в фоновом режиме, его будет легко остановить позже с помощью службы Windows или аналогичной даже на другой ОС (Mac, Linux).

Предлагаю вам почитать на эту тему. По сути, фоновый процесс — это когда вы запускается оболочкой, но оболочка не блокируется. Процесс переднего плана — это когда оболочка остается заблокированной после ее запуска. В этом случае вам нужно нажать Ctrl+C, чтобы выйти из приложения, и оболочка снова станет доступной для использования.

Более подробная информация здесь. Также он работает на окнах.

Два скрипта: старт и стоп

Независимо от операционной системы (Windows, Linux, Mac), если вам удастся создать эти сценарии, процесс будет легко запускаться и останавливаться.

В Linux мы можем получить pid недавно запущенного процесса. Используя этот pid, я могу закрыть приложение из другой оболочки или сценария. У меня нет Windows, но в основном алгоритм такой:

start.bat

стоп.бат

нссм

Несколько лет назад я использовал этот инструмент http://nssm.cc/download для создания службы Windows из файла java. Это было легко. Остановка сработала как положено (процесс Java завершился)

Если я не ошибаюсь, фоновый процесс не требовался. Я просто установил расположение bat-скриптов (start.bat/stop.bat). Запуск/остановка использования службы Windows сработала как положено.

Летучая мышь или powershell

Я писал подобные скрипты для Windows и Linux. Использование bat или powershell доставляет неудобства. Как будто они были созданы не для автоматизации задач. Простые строковые алгоритмы настолько сумасшедшие, что их трудно понять

В Linux очень легко создавать подобные скрипты.

Докер

С докером это было бы легко. Даже служба Windows не потребуется, поскольку вы можете настроить запуск контейнера при запуске компьютера. В любом случае с докером вам нужно только:

  • Докер запускает Дженкинс
  • докер стоп Дженкинс

Эти команды можно зарегистрировать в вашей службе Windows, и они будут работать без ошибок.

Ответ принят как подходящий

Ваша проблема заключается в неожиданном отображении строк stderr, которые отображаются неправильно, как если бы они были ошибками. Чтобы избежать проблемы, выполните следующие действия:

  • Примените перенаправление2>&1 непосредственно к вызову java.exe.

    • При этом вывод stderr java.exe объединяется с потоком вывода PowerShell (аналог stdout PowerShell), что позволяет обрабатывать как вывод stdout, так и вывод stderr в конвейере PowerShell.
  • Передайте результат вызову ForEach-Object, который вызывает метод .ToString() для каждого результирующего объекта (% — это встроенный псевдоним ForEach-Object).

    • Эта строковая обработка необходима, поскольку PowerShell оборачивает каждую строку stderr в экземпляр System.Management.Automation.ErrorRecord, который визуализируется так, как если бы это была ошибка PowerShell, что приводит к неожиданному результату, который вы видели. Строковизация с помощью .ToString() дает исходный текст stderr.[1]
  • Примените к последнему перенаправление в файл журнала (>>"$JenkinsPath\agent.log"); поскольку весь вывод java.exe в этот момент маршрутизируется через поток вывода успеха >>, достаточно (т. е. нет необходимости в *>> для захвата всех потоков).

# java.exe arguments omitted for brevity
& "$Java\java.exe" ... 2>&1 | % ToString >>"$JenkinsPath\agent.log"

Более простая альтернатива через Добавить контент:

# java.exe arguments omitted for brevity
& "$Java\java.exe" ... 2>&1 | Add-Content "$JenkinsPath\agent.log"
  • Add-Content, как и Set-Content, неявно преобразует в строку свои входные объекты через .ToString().

  • Предостережение относительно кодировки символов:

    • В PowerShell (Core) 7 оба решения эквивалентны и создают файлы UTF-8 без спецификации, учитывая, что эта кодировка является согласованной по умолчанию в этой версии PowerShell.

    • Напротив, в Windows PowerShell (устаревшая версия, поставляемая вместе с Windows, последняя и последняя версия которой — 5.1.x) операторы перенаправления > / >> фактически являются псевдонимами Out-File, который по умолчанию имеет значение UTF- 16LE со спецификацией («Юникод»), тогда как Add-Content/Set-Content по умолчанию используют активную устаревшую кодовую страницу ANSI системы; при необходимости используйте параметр -Encoding, но учтите, что -Encoding utf8 всегда создает файл UTF-8 со спецификацией.


[2]

[1] Specifically, it is the first stderr line output by an external program such as java.exe that is rendered this way when a 2> or *> redirection (or a >> variant) is applied to an external-program call. In the console (terminal), subsequent stderr lines render by their text only, but are printed in red too. When redirecting such output to a file, such as in your case, coloring is lost, so it is only the first, error-like representation that stands out. A simple test command:
cmd /c 'echo stderr1 >&2 & echo stdout1 & echo stderr2 >&2' 2>&1
Note that the original output order among the stdout and stderr streams isn't always maintained - see GitHub issue #5424 for a discussion.

Спасибо. Работало как шарм.

Elior Machlev 07.08.2024 01:24

Рад это слышать, @EliorMachlev.

mklement0 07.08.2024 03:29

Другие вопросы по теме