Отмена перехвата консоли дочернего процесса
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.01.26 12:03
Оценка:
Коллеги, всем привет. Случайно возник вот такой вот архитектурно-философский вопрос.
Сценарий: консольная программа А использует в работе консольную программу Б.
При этом есть два под-сценария:
1. К моменту старта А программа Б уже запущена. Тогда она торчит на каком-то порту 127.0.0.1, программа А подключается туда и делает всё необходимое.
1. К моменту старта А программы Б нет. Тогда А должна сначала запустить Б, и уже потом подключиться.
Нюанс — в том, что после окончания работы А программа Б должна продолжить свою работу ещё какое-то время.
И при этом нам бы хотелось помочь пользователю диагностировать неполадки запуска программы Б.
Сама Б пишет всё, что с ней происходит, в консоль и в лог-файл.
Так что если бы пользователь сам запускал Б, то он бы увидел вывод Б в консоль, и если ей что-то мешает запуститься — там была бы диагностика.

Ок, А в случае если запускает Б, то перехватывает её stout/stderr, и транслирует их пользователю.
И вот мне ИИ на эту тему говорит: постой, но когда А выйдет, а Б останется работать, то попытки Б писать в консоль могут приводить к E_PIPE.
На вопрос "и чо делать", ИИ предлагает перестать читать консоль Б, а вместо этого tail-ить лог-файл Б.
Но юмор в том, что одна из возможных причин неудачи старта Б — отсутствие прав на запись в дефолтный каталог лога

В связи с чем, собственно, вопрос — есть ли кросс-платформенный способ аккуратно отключиться от stdout дочернего процесса?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Отмена перехвата консоли дочернего процесса
От: Pavel Dvorkin Россия  
Дата: 18.01.26 12:30
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>В связи с чем, собственно, вопрос — есть ли кросс-платформенный способ аккуратно отключиться от stdout дочернего процесса?


Каким способом A перехватывает stdout дочернего B ?

ИИ на эту тему высказывается довольно длинно

https://www.google.com/search?sa=N&sca_esv=651164c6481fa95a&sxsrf=ANbL-n6UoW_48VMyPVILeecHjxYYt7B9ZQ:1768739201642&q=freopen+%D0%B4%D0%BB%D1%8F+stdout+%22%D0%B4%D0%BE%D1%87%D0%B5%D1%80%D0%BD%D0%B5%D0%B3%D0%BE%22+%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%B0&ved=2ahUKEwjSp8H-ipWSAxVj8LsIHTI0Axw4ChDm3gJ6BAgmEAE&biw=1920&bih=929&dpr=1&aic=0
With best regards
Pavel Dvorkin
Re[2]: Отмена перехвата консоли дочернего процесса
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.01.26 14:12
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Каким способом A перехватывает stdout дочернего B ?

Платформенно-специфичным.

На винде, к примеру, у CreateProcess есть специальные параметры для хэндлов stdin, stdout, stderr.
В линуксе используется комбинация из pipe(), fork(), и exec().

PD>ИИ на эту тему высказывается довольно длинно


Там смущает сама формулировка вопроса — она как будто бы уже подразумевает некоторое решение, а не поиск вариантов.

Из того, что я понял в рассуждениях ИИ, дочерний процесс должен как-то отловить момент окончания родительского, и переоткрыть stdout для продолжения работы.
По идее, если у него есть способ узнать, что выход закрыт, то он может просто больше ничего не писать в stdout.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Отмена перехвата консоли дочернего процесса
От: · Великобритания  
Дата: 18.01.26 14:29
Оценка: 80 (1)
Здравствуйте, Sinclair, Вы писали:

S>Ок, А в случае если запускает Б, то перехватывает её stout/stderr, и транслирует их пользователю.

Пусть лучше А перенаправляет консоль Б в файл в своём месте для логов.
В этом случае можно будет продолжить исследовать логи Б, даже если А грохнется.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 18.01.2026 14:30 · . Предыдущая версия .
Re[3]: Отмена перехвата консоли дочернего процесса
От: Pavel Dvorkin Россия  
Дата: 18.01.26 14:40
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Из того, что я понял в рассуждениях ИИ, дочерний процесс должен как-то отловить момент окончания родительского, и переоткрыть stdout для продолжения работы.


Ну это технически в Windows не так сложно. При запуске чайлда можно передать ему ID родителя(ну хотя бы через командную строку, кстати, отсутствие его в командной строке будет тем самым означать, что что чайлд запущен не этим родителем, а как-то иначе ), а чайлд по нему получит hParentProcess в контексте чайлда и будет в потоке WaitForSingleObject.

Наверняка в Linux есть аналогичное, а может, в нынешней C++ есть и кроссплатформенное решение.

>По идее, если у него есть способ узнать, что выход закрыт, то он может просто больше ничего не писать в stdout.


Может, дождавшись, больше и не писать. Может с помощью freopen на свой stdout перенаправить его куда-то еще.
With best regards
Pavel Dvorkin
Отредактировано 18.01.2026 14:47 Pavel Dvorkin . Предыдущая версия .
Re: Отмена перехвата консоли дочернего процесса
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 18.01.26 15:25
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Нюанс — в том, что после окончания работы А программа Б должна продолжить свою работу ещё какое-то время.


А почему А надо завершать? Пусть бы работала, чисто висела, ждала Б. Ну или прокси какой-то С, который будет жить, пока живёт Б
Маньяк Робокряк колесит по городу
Re: Отмена перехвата консоли дочернего процесса
От: Pzz Россия https://github.com/alexpevzner
Дата: 18.01.26 18:15
Оценка: 120 (1)
Здравствуйте, Sinclair, Вы писали:

S>В связи с чем, собственно, вопрос — есть ли кросс-платформенный способ аккуратно отключиться от stdout дочернего процесса?


Нет.
Re[4]: Отмена перехвата консоли дочернего процесса
От: Pzz Россия https://github.com/alexpevzner
Дата: 18.01.26 18:20
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Ну это технически в Windows не так сложно. При запуске чайлда можно передать ему ID родителя(ну хотя бы через командную строку, кстати, отсутствие его в командной строке будет тем самым означать, что что чайлд запущен не этим родителем, а как-то иначе ), а чайлд по нему получит hParentProcess в контексте чайлда и будет в потоке WaitForSingleObject.


PD>Наверняка в Linux есть аналогичное, а может, в нынешней C++ есть и кроссплатформенное решение.


Если и есть, то на уровне какого-то очень advanced API. Не проще ли разбираться с проблемой там, где она возникает — если в pipe не получается писать, то как-то разумно на это реагировать?

PD>Может, дождавшись, больше и не писать. Может с помощью freopen на свой stdout перенаправить его куда-то еще.


freopen работает с FILE*, на которую ссылается глобальная переменная stdout. Реально надо переоткрывать handle, а не трогать структуру, на которую ссылается stdout. Например потому, что не все для записи на консоль используют именно stdio.
Re[4]: Отмена перехвата консоли дочернего процесса
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.01.26 01:00
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Ну это технически в Windows не так сложно. При запуске чайлда можно передать ему ID родителя(ну хотя бы через командную строку, кстати, отсутствие его в командной строке будет тем самым означать, что что чайлд запущен не этим родителем, а как-то иначе ), а чайлд по нему получит hParentProcess в контексте чайлда и будет в потоке WaitForSingleObject.


А если у нас нет возможности переписать Б?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Отмена перехвата консоли дочернего процесса
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.01.26 01:05
Оценка:
Здравствуйте, Marty, Вы писали:
M>А почему А надо завершать? Пусть бы работала, чисто висела, ждала Б.
Потому что не дело блокировать пользовательский терминал после того, как задача завершилась. Б вообще может в разумное время не завершиться.
А скриптам, которые могут вызывать А, нужно получать от неё exit code и продолжать выполнение.
M>Ну или прокси какой-то С, который будет жить, пока живёт Б
Я об этом думал. Но ведь тогда у нас тот же самый вопрос по отношению к взаимодействия А и С.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Отмена перехвата консоли дочернего процесса
От: Pavel Dvorkin Россия  
Дата: 19.01.26 02:54
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>А если у нас нет возможности переписать Б?


Тогда не совсем понятно, чего Вы хотите

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

По идее, если у него есть способ узнать, что выход закрыт, то он может просто больше ничего не писать в stdout.

Дочерний процесс должен отловить, но его нельзя переписать, а в текущем его состоянии такого функционала нет.

В Windows в принципе можно ему такой функционал добавить, не переписывая его

Внедряем ему новый поток

https://learn.microsoft.com/ru-ru/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread

и в нем делаем эту функциональность.

Но я об этом знаю лишь теоретически, сам никогда не делал, и какие тут подводные камни — не знаю. Хотя, думаю, в Интернете на этот счет найти можно.

К тому же ИИ говорит

Malware Association: Because it is a staple of process injection, it is highly monitored by security software (AV/EDR).


В Линуксе — понятия не имею.
With best regards
Pavel Dvorkin
Re[5]: Отмена перехвата консоли дочернего процесса
От: Pavel Dvorkin Россия  
Дата: 19.01.26 03:00
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>freopen работает с FILE*, на которую ссылается глобальная переменная stdout. Реально надо переоткрывать handle, а не трогать структуру, на которую ссылается stdout. Например потому, что не все для записи на консоль используют именно stdio.


А черт его знает. Если все же используется stdio, то не уверен, что ему будет хорошо, если его хендл перенаправят без его ведома.

Можно поэкспериментировать.

1. fopen на какой-то файл
2. перенаправляем его хендл на другой файл
3. fwrite

и посмотреть, что получится.
With best regards
Pavel Dvorkin
Re[6]: Отмена перехвата консоли дочернего процесса
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.01.26 05:07
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:


PD>Тогда не совсем понятно, чего Вы хотите

Хотим запустить Б, помониторить, что он нам пишет в stdout/stderr, и если всё в порядке — "отключиться" от него, чтобы он продолжал себе работать.

PD>По идее, если у него есть способ узнать, что выход закрыт, то он может просто больше ничего не писать в stdout.

Я пока не встречал программ, которые бы как-то разумно себя вели в случае, если запись в stdout заканчивается неудачей.
PD>В Линуксе — понятия не имею.
Вот то-то и оно. Но вот вроде рабочий вариант мне уже предложили
Автор: ·
Дата: 18.01 17:29
.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Отмена перехвата консоли дочернего процесса
От: Pavel Dvorkin Россия  
Дата: 19.01.26 08:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вот то-то и оно. Но вот вроде рабочий вариант мне уже предложили
Автор: ·
Дата: 18.01 17:29
.


Да, вроде логично. Если перенаправление производится у самого B, то по логике вещей какова потом судьба A — не важно.
With best regards
Pavel Dvorkin
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.