Как найти текущее значение процесса STDOUT в Perl?

У меня есть программа POE Perl, разветвляющая детей.

Дети, которые он разветвляет, ведут журнал и интерактивные telnet-соединения с удаленными устройствами. POE использует STDOUT для возврата вывода обратно в родительский процесс, но по какой-то причине он теряется (не выходит на экран или в какие-либо файлы).

Я предполагаю, что это связано с тем, что STDOUT куда-то перенаправляется - мне нужно выяснить, куда.

Я использовал (-t STDOUT), чтобы определить, что STDOUT дочернего элемента не является TTY.

Я также сбросил STDOUT дочернего элемента, чтобы он был родителем до того, как был вызван дочерний элемент, но этот метод, похоже, избегает обработчиков событий POE и просто выводит вывод на родительский STDOUT.

Q) Как мне определить, на что указывает текущий STDOUT, чтобы я мог найти, куда идут мои данные

Спасибо

Саймон


person SimonT    schedule 06.11.2009    source источник
comment
Не могли бы вы предоставить код разветвления и вывода перенаправления?   -  person Ivan Nevostruev    schedule 06.11.2009
comment
Нам нужно больше информации. Вы используете POE::Wheel::Run? Является ли подпроцесс Perl? Выводит ли подпроцесс на STDOUT, когда он работает нормально, а не как дочерний элемент вашего приложения POE?   -  person jrockway    schedule 07.11.2009
comment
В) Используете ли вы POE::Wheel::Run? A) Да Q) Является ли подпроцесс Perl? A) Да Q) Выводит ли подпроцесс на STDOUT, когда он работает нормально, а не как дочерний элемент вашего приложения POE? A) Да/Нет, и это то, что я пытаюсь определить. Подпроцесс вызывает объект, который использует Expect.pm, а также Error.pm, и что-то там мешает STDOUT. Если бы я мог сказать, где в настоящее время находится STDOUT, у меня был бы шанс изменить его. Все, что я знаю до сих пор, это то, что после разветвления ребенка STDOUT не является TTY, но до того, как он будет создан, это TTY.   -  person SimonT    schedule 09.11.2009


Ответы (4)


Поможет ли fileno в этой ситуации? Если дочерний элемент закрывает и снова открывает STDOUT, то fileno(STDOUT) будет иметь другое значение в дочернем элементе, чем в родительском.

$ perldoc -f fileno
   fileno FILEHANDLE
           Returns the file descriptor for a filehandle, or undefined if
           the filehandle is not open.  This is mainly useful for
           constructing bitmaps for "select" and low-level POSIX tty-
           handling operations.  If FILEHANDLE is an expression, the value
           is taken as an indirect filehandle, generally its name.

           You can use this to find out whether two handles refer to the
           same underlying descriptor:

               if (fileno(THIS) == fileno(THAT)) {
                   print "THIS and THAT are dups\n";
               }

           (Filehandles connected to memory objects via new features of
           "open" may return undefined even though they are open.)
person mob    schedule 06.11.2009
comment
Предполагая, что вы используете один из поддерживаемых диалектов UNIX, вы можете попробовать объединить это с lsof (man lsof для получения дополнительной информации). - person bish; 07.11.2009
comment
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat(STDOUT) or die Нет STDOUT $!; мой $output1 = system(/usr/sbin/lsof -p $$ | grep $ino ›/tmp/jsuh$$); Команда PID пользователя FD Тип устройства Размер узла NEW_BATCH 31616 SDU 0U UNIX 0x00000100376A7380 9951954 Разъем New_Batch 31616 SDU 1U Unix 0x00000100376A7380 9951954 SOCKET NEW_BATH 31616 SDU 2U UNIX 0x0000010007774680 9951957 Гнездо, так что это говорит мне, что stdout подключен к розетке? - person SimonT; 09.11.2009
comment
Это возможно, поскольку разветвленная программа порождает сеансы telnet, поэтому ее все еще можно подключить к порту на ip на удаленном сервере через сокет, но первое, что я проверил, это то, что объект, который обрабатывает это, был уничтожен. - person SimonT; 09.11.2009
comment
Игнорируйте этот последний пост - в этот момент соединение не было создано - я смотрю на объект до того, как он создаст удаленное соединение. - person SimonT; 09.11.2009
comment
Это дает вам другой результат? мой $fd = номер_файла(STDOUT); мой $output1 = system(/usr/sbin/lsof -a -p $$ -d $fd ›/tmp/jsuh$$); - person bish; 09.11.2009
comment
С дополнительным ключом -d мы получаем список телетайпов bash 17289 sdu 1u CHR 136,0 2 /dev/pts/0 bash 17320 sdu 1u CHR 136,1 3 /dev/pts/1 bash 17363 sdu 1u CHR 136, 3 5 /dev/pts/3 bash 30667 sdu 1u CHR 136,4 6 /dev/pts/4 - person SimonT; 09.11.2009
comment
Ссылается на другие сеансы sdu (sdu — исполняющий пользователь) - person SimonT; 09.11.2009
comment
Закрыли эти сессии дауны. Запустил снова. Вывод LSOF теперь не содержит записей. Никаких изменений в общении между ребенком и родителем. - person SimonT; 09.11.2009
comment
Вы не забыли добавить переключатель -a? По умолчанию lsof будет использовать ИЛИ для параметров, которые вы ему зададите, а не И для них. Похоже, это произошло, поскольку ваши результаты содержат несколько процессов. Если это не поможет, я перестану вести тебя по этому пути, потому что мне начинает казаться, что я заставляю тебя гоняться за призраками. - person bish; 09.11.2009
comment
Я не думаю, что это поможет. Суть в том, что дочерний элемент использует соединение сокета с родителем для отправки своего STDOUT. Мой следующий вопрос заключается в том, как я могу определить, работает ли этот механизм печати сокетов. Посмотрел в Интернете и не увидел никакого механизма для просмотра активности в соединении сокета. - person SimonT; 10.11.2009
comment
Нашел проблему. Когда я использовал StdoutFilter => POE::Filter::Reference->new(), он не мог распознать вывод дочернего процесса. Когда я его снял - он подхватился. Теперь я знаю намного больше о режимах отладки POE и о том, что делают все движущиеся части. Спасибо за поддержку, пока я поднимался по кривой обучения! - person SimonT; 10.11.2009
comment
Рад, что вы смогли его найти! Приятно видеть, что это помогло вам узнать намного больше о POE. - person bish; 10.11.2009

Если ваши разветвленные дочерние элементы также являются программами Perl, вы можете «выбрать STDOUT» и установить $| чтобы пометить его как небуферизованный прямо перед тем, как произойдет какое-либо ведение журнала.

person Murali VP    schedule 07.11.2009

Это было связано с тем, что обработчик POE::Filter::Reference StdOut Handler отправлял выходные данные дочерним процессом в формате, отличном от ожидаемого.

Удалил фильтр - тогда я мог видеть, что он отправляет, и это позволило мне исправить проблему.

Проблема заключалась в том, что дочерний процесс извергал содержимое своих подпроцессов STDOUT обратно по соединению сокета с обработчиком StdOut.

Саймон

person SimonT    schedule 11.11.2009

Вы уверены, что это не проблема с буферизацией? Я не знаком с POE, поэтому я не знаю, как вы это расследуете или исправите, но я подозреваю, что это стоит проверить, по крайней мере.

person BlairHippo    schedule 06.11.2009
comment
не думаю, что все инструкции, которые я видел о POE, указывают на то, что вы отправляете что-то от ребенка через STDOUT, и если он настроен правильно, родитель получает это. - person SimonT; 07.11.2009
comment
Справедливо. Решил, что я бы предложил это, поскольку, по моему собственному опыту, ответ на вопрос «Куда, черт возьми, идет мой драгоценный результат?» иногда был буфером. Надеюсь, мимо пройдёт кто-нибудь поумнее меня. :-) Удачи! - person BlairHippo; 07.11.2009
comment
@SimonT - проверить все же стоит. Вам следует подумать о том, чтобы расставить $| = 1; в соответствующих местах вашей программы, чтобы сбросить потоки вывода и посмотреть, поможет ли это. Может и нет, но, по крайней мере, это легко проверить. - person Chris Lutz; 07.11.2009
comment
Конечно, POE будет читать STDOUT, как только он будет доступен для чтения, но нет гарантии, что print в вашем дочернем элементе помещает что-либо в канал STDOUT. Буферизация. - person jrockway; 07.11.2009
comment
Добавил $|=1 и попытался напечатать в STDOUT сразу после того, как дочерний элемент был разветвлен, прежде чем он выполняет какую-либо другую работу, но по-прежнему не видит никакого вывода. - person SimonT; 09.11.2009