Почему перенаправление моего stderr не заканчивается после завершения команды?И как мне это исправить? - PullRequest
24 голосов
/ 26 марта 2012

В Windows, либо в командной строке, либо в командном файле, команда DIR 2>NUL: 3>&2 (вы можете заменить DIR на что угодно, даже если это не файл или команда) с тех пор сделает все ошибки отсутствующими, если только Вы пишете 2>CON: после каждой команды. Почему CMD даже делает это? И как вернуть его в нормальное состояние, не запуская новый процесс CMD? DIR 2>CON: 3>&2 будет работать только для этой команды.

РЕДАКТИРОВАТЬ: Это будет работать и с файлами. DIR 2>TEXT.TXT 3>&2 Любые ошибки после этого будут добавлены в файл.

Ответы [ 3 ]

31 голосов
/ 27 марта 2012

Вот тестовый скрипт, который воспроизводит проблему, с которой вы столкнулись.

@echo off
2>nul 3>nul (
  echo I want to see stream1
  1>&2 echo I don't want to see this stream2
  1>&3 echo I don't want to see this stream3
)
echo stream1 works fine
1>&2 echo stream2 is now "permanently" void. I don't see this.
1>&3 echo stream3 works fine

А вот вывод

I want to see stream1
stream1 works fine
stream3 works fine

stderr (поток 2) отключен "навсегда", даже для родительской оболочки CMD.EXE.

Вы можете избежать «постоянного» аспекта, осуществляя поэтапное перенаправление:

@echo off
2>nul (
  3>nul (
    echo I want to see stream1
    1>&2 echo I don't want to see this stream2
    1>&3 echo I don't want to see this stream3
  )
)
echo stream1 works fine
1>&2 echo stream2 works fine
1>&3 echo stream3 works fine

И вот требуемый вывод:

I want to see stream1
stream1 works fine
stream2 works fine
stream3 works fine

Я не очень понимаю, что происходит.Но я провел несколько интересных экспериментов.Проверьте эту тему: http://www.dostips.com/forum/viewtopic.php?f=3&t=2836&start=30

Приложение

Как Эрберт обнаружил и поделился в своем комментарии, исправить это будет еще проще, если выпросто переключите порядок перенаправления - не нужно ставить его.

@echo off
3>nul 2>nul (
  echo I want to see stream1
  1>&2 echo I don't want to see this stream2
  1>&3 echo I don't want to see this stream3
)
echo stream1 works fine
1>&2 echo stream2 works fine
1>&3 echo stream3 works fine

Обновление 2012-04-03 Мне кажется, я наконец-то понял механику WindowsCMD.EXE перенаправление.У меня есть рабочая теория, которая полностью учитывает все странное поведение, включая то, почему изменение порядка предотвращает «постоянное» перенаправление.Это также объясняет наблюдение Aacini о том, что дескриптор 3, по-видимому, связан с CON: (Это не так, он фактически не определен согласно документации Windows).

Ключевые моменты:

1 -Всякий раз, когда дескриптор (поток) перенаправляется, исходное определение переносится в первый доступный неопределенный дескриптор.Последовательные перенаправления всегда выполняются слева направо.

2 - Когда перенаправление заканчивается, исходные определения обычно восстанавливаются.Но если существует цепь перенаправлений, то восстановление выполняется только на 1 уровень.Это источник «перманентного» перенаправления.

Редактировать 2014-12-19: Другими словами, восстановление, похоже, выполняется с использованием структуры очереди (FIFO - First In FirstOut), когда он должен был быть реализован как стек (LIFO - Last In First Out).

3 - Когда CMD.EXE выполняет перенаправление, сначала сохраняет текущее определение в неопределенном дескрипторе, затемон перенаправляет первую ручку.Если первый дескриптор перенаправлен на первоначально неопределенный дескриптор, то он фактически перенаправляется на свое первоначальное определение!Вот почему echo hello 1>&3 выводит на консоль.

Полная теория и тестовые примеры доступны в двух последовательных постах на http://www.dostips.com/forum/viewtopic.php?p=14612#p14612.

4 голосов
/ 27 марта 2012

Я прошу прощения за публикацию этого в качестве ответа вместо комментария, но мой "комментарий" слишком велик ...

В стандарте MS-DOS все запущенные программы имеют следующие Стандартные дескрипторы : 0-STDIN (клавиатура), 1-STDOUT (экран), 2-STDERR (экран), 3-STDAUX ( последовательный порт) и 4-STDPRN (принтер). Хотя в документации Windows четко указано, что дескрипторы 3-9 не определены, для дескриптора 3 используется специальная обработка CMD.EXE. У меня есть три причины думать так:

1- Ручка 3 подключена к CON: устройству (клавиатура для ввода, экран для вывода); ручки 4-9 не:

C>ver

Microsoft Windows XP [Version 5.1.2600]

C>echo To handle 3 >&3
To handle 3

C>echo To handle 4 >&4
The handle could not be duplicated
during redirection of handle 1.

C>set /P var=From handle 3: <&3
From handle 3: Value entered in keyboard

C>echo %var%
Value entered in keyboard

C>set /P var=From handle 4: <&4
The handle could not be duplicated
during redirection of handle 0.

2- Странное поведение дескриптора 3, изложенное в настоящей теме, которое было решено двумя различными способами. Я обнаружил, что если маркеры 0, 1 или 2 перенаправляются с помощью маркера 3 (и, возможно, маркеров 4-9), перенаправление маркеров 0, 1 или 2 становится «постоянным»; такое поведение не происходит, если дескрипторы 0, 1 или 2 являются последними дескрипторами в списке перенаправлений, которые содержат дескриптор 3. Этой проблемы полностью избегают, если дескрипторы 0, 1 или 2 перенаправляются с помощью ручек 4-9 в любом порядке, но не ручки 3.

3- Результаты, полученные с помощью моей программы TypeOfHandle.com . Эта программа представляет собой чистый исполняемый файл MS-DOS, который проверяет дескриптор, указанный в его параметре, и возвращает через errorlevel значение 3, если дескриптор подключен к устройству консоли, или значение 128, если дескриптор перенаправлен в файл на диске. , Вот результаты:

C>typeofhandle 0

C>echo %errorlevel%
3

C>typeofhandle 0 < anyFile.txt

C>echo %errorlevel%
128

C>typeofhandle 1

C>echo %errorlevel%
3

C>typeofhandle 1 > anyFile.txt

C>echo %errorlevel%
128

C>typeofhandle 3

C>echo %errorlevel%
0

C>typeofhandle 3 <&3 anyFile.txt

C>echo %errorlevel%
0

C>typeofhandle 3 >&3 anyFile.txt

C>echo %errorlevel%
0

Ручки 3-9 ведут себя странно в другом аспекте:

Результаты, полученные с моей программой SetFilePointer.com . Хотя дескрипторы 3-9 можно использовать в пакетном файле для одновременного ввода / вывода из / в нескольких файлов, такой механизм позволяет только последовательный доступ , поскольку моя программа SetFilePointer не может перемещать указатель файла дескрипторов 3-9. Программа SetFilePointer корректно работает на дескрипторах 0, 1 и 2; эта функция позволяет написать полное приложение реляционной базы данных в пакетном режиме. Эта тема подробно описана на этом посте

0 голосов
/ 26 марта 2012

Проблема с 3>&2.Файловый дескриптор 3 недействителен, и, похоже, он каким-то образом расстраивает Windows.Оставьте это, вам это не нужно.

См. Документация Microsoft (в архиве) для полной обработки.

...