Почему мой конец stderr не заканчивается после завершения команды? И как мне это исправить?
В Windows, либо в командной строке, либо в командном файле, команда "DIR 2 > NUL: 3 > & 2" (вы можете заменить "DIR" чем угодно, даже если это не файл или команда) сделает все ошибки с тех пор отсутствующими, если вы не напишете "2 > CON:" после каждой команды. Почему CMD делает это? И как вы вернетесь к нему, не начав новый CMD-процесс? "DIR 2 > CON: 3 > & 2" будет работать только для этой команды.
EDIT: Это будет работать и с файлами. "DIR 2 > TEXT.TXT 3 > & 2" Любые ошибки после этого будут добавлены к файлу.
Ответы
Ответ 1
Вот тест script, который воспроизводит проблему, которую вы видите.
@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
По-моему, я наконец понял механику перенаправления Windows CMD.EXE. У меня есть рабочая теория, которая полностью объясняет все странное поведение, в том числе и то, почему реверсирование порядка предотвращает "постоянное" перенаправление. Это также объясняет наблюдение Aacini, что дескриптор 3, по-видимому, подключен к CON: (Это не так, это undefined в соответствии с документацией Windows).
Ключевыми моментами являются:
1 - Всякий раз, когда дескриптор (поток) перенаправляется, исходное определение переносится на первый доступный дескриптор undefined. Последовательные перенаправления всегда выполняются слева направо.
2 - Когда перенаправление закончено, исходные определения обычно восстанавливаются. Но если есть цепочка перенаправления, то восстановление выполняется только на 1 уровне. Это источник "постоянного" перенаправления.
Edit 2014-12-19: По-другому, восстановление, похоже, выполняется с использованием структуры очереди (FIFO - First In First Out), когда она должна быть реализована как стек (LIFO - Last In First Out).
3 - Когда CMD.EXE выполняет перенаправление, сначала сохраняет текущее определение в дескрипторе undefined, затем перенаправляет первый дескриптор. Если первый дескриптор перенаправлен на исходный дескриптор undefined, он эффективно перенаправляется на его исходное определение! Поэтому echo hello 1>&3
выводится на консоль.
Полная теория и тестовые примеры доступны в двух последовательных сообщениях в http://www.dostips.com/forum/viewtopic.php?p=14612#p14612.
Ответ 2
Приносим извинения за сообщение в качестве ответа вместо комментария, но мой "комментарий" слишком велик...
В стандарте MS-DOS все запущенные программы открывают эти стандартные ручки: 0-STDIN (клавиатура), 1-STDOUT (экран), 2-STDERR (экран), 3-STDAUX (последовательный порт) и 4- STDPRN (принтер). Хотя документация Windows четко указывает, что дескрипторы 3-9 являются undefined, дескриптор 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, который проверяет дескриптор, указанный в его параметре, и возвращает через уровень ошибок значение 3, если дескриптор подключен к устройству CONsole или значение 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; эта функция позволяет записывать полное приложение реляционной базы данных в пакетном режиме. Эта тема подробно описана в этот пост
Ответ 3
Проблема заключается в 3>&2
. Файловый дескриптор 3 недействителен и, похоже, каким-то образом нарушает работу Windows. Оставьте это, вам это не нужно.
См. документацию по Microsoft для полного лечения.