Подтвердить что ты не робот

Почему мой конец stderr не заканчивается после завершения команды? И как мне это исправить?

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

EDIT: Это будет работать и с файлами. "DIR 2 > TEXT.TXT 3 > & 2" Любые ошибки после этого будут добавлены к файлу.

4b9b3361

Ответ 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 для полного лечения.