После использования `exec 1›file`, как я могу остановить это перенаправление STDOUT в файл и восстановить нормальную работу STDOUT?

Я новичок в написании сценариев оболочки и использую Ubuntu-11.10. В терминале после использования команды exec 1>file, какие бы команды я ни отдавал терминалу, его вывод не отображается в терминале. Я знаю, что STDOUT перенаправляется в файл, вывод этих команд перенаправляется в файл.

Мои вопросы здесь

  1. Когда я использую exec 1>file, как я могу избавиться от этого? т.е. как остановить перенаправление STDOUT в файл и восстановить нормальную работу STDOUT (т.е. перенаправление на терминал, а не в файл)?

    Я пытался использовать exec 1>&-, но это не сработало, так как это закрывает файловый дескриптор STDOUT.

  2. Пожалуйста, пролейте свет на всю эту операцию exec 1>file и exec 1>&-.

  3. Что произойдет, если мы закроем стандартные файловые дескрипторы 0, 1, 2 с помощью exec 0>&- exec 1>&- exec 2>&-?


person pawan vinayak    schedule 24.08.2014    source источник
comment
Я немного смущен. Когда вы говорите остановить перенаправление STDOUT, каков вариант использования? У меня есть ощущение, что вы хотите передать команду tee для вывода как в STDOUT, так и в файл, но я не могу быть уверен в том, что вы сказали.   -  person JayC    schedule 24.08.2014
comment
@JayC позвольте мне уточнить мой вопрос, в терминале я дал exec 1 > имя_файла.txt, затем я дал команды даты и ls каждый раз, когда я даю новую команду, вывод не отображается в терминале, а вывод перенаправляется в имя_файла.txt Теперь мой вопрос это то, что я должен сделать здесь, чтобы вывод этих команд отображался обратно на терминал, а не перенаправлялся в файл file_name.txt   -  person pawan vinayak    schedule 24.08.2014
comment
Не перенаправлять стандартный вывод в интерактивной оболочке; если вы хотите регистрировать свою работу, используйте скрипт (1) или аналогичный. Чтобы ответить на исходный вопрос: нажмите Ctrl+D   -  person Lorinczy Zsigmond    schedule 26.08.2015


Ответы (4)


Q1

Вы должны подготовиться к восстановлению, прежде чем выполнять первоначальные exec:

exec 3>&1 1>file

Чтобы позже восстановить исходный стандартный вывод:

exec 1>&3 3>&-

Первый exec копирует исходный файловый дескриптор 1 (стандартный вывод) в файловый дескриптор 3, а затем перенаправляет стандартный вывод в указанный файл. Второй exec снова копирует дескриптор файла 3 в стандартный вывод, а затем закрывает дескриптор файла 3.

Q2

Это немного открытый конец. Его можно описать на уровне кода C или на уровне командной строки оболочки.

exec 1>file

просто перенаправляет стандартный вывод (1) оболочки в указанный файл. Первый дескриптор файла теперь ссылается на именованный файл; любой вывод, записанный в стандартный вывод, попадет в файл. (Обратите внимание, что подсказки в интерактивной оболочке записываются в стандартную ошибку, а не в стандартный вывод.)

exec 1>&-

просто закрывает стандартный вывод оболочки. Теперь нет открытого файла для стандартного вывода. Программы могут расстроиться, если они запускаются без стандартного вывода.

Q3

Если вы закроете все три из стандартного ввода, стандартного вывода и стандартной ошибки, интерактивная оболочка закроется, когда вы закроете стандартный ввод (поскольку она получит EOF при чтении следующей команды). Сценарий оболочки будет продолжать работать, но программы, которые он запускает, могут выйти из строя, потому что им гарантировано 3 открытых файловых канала — стандартный ввод, стандартный вывод, стандартная ошибка — и когда ваша оболочка запускает их, если нет другого перенаправления ввода-вывода. , то они не получат файловые каналы, которые им обещали, и может начаться ад (и единственный способ, которым вы будете знать, это то, что статус выхода команды, вероятно, будет не нулевым — успех).

person Jonathan Leffler    schedule 24.08.2014
comment
»Программы могут расстроиться, если они запускаются без стандартного вывода.« Я не мог бы выразиться лучше :-)) - person Alfe; 25.08.2014
comment
Синтаксис @Jonathan для закрытия файловых дескрипторов: exec n>&- (для выходных файловых дескрипторов) и exec n<&- (для входных файловых дескрипторов). способ понять и запомнить это. - person pawan vinayak; 25.08.2014
comment
@pawanvinayak: опечатка... вот и все. Спасибо, что указали на это. - person Jonathan Leffler; 25.08.2014
comment
Хотя ваше предложение технически правильно и является хорошей ссылкой для общего случая, оно несколько слишком сложно в конкретном случае OP. Нет необходимости сохранять стандартный вывод, когда он является управляющим терминалом, он уже сохранен в контексте процесса. - person jlliagre; 25.08.2014
comment
Я реализовал что-то вроде этого exec 3›&1 1›››(redirectToLogger) 2›&1. Теперь я хочу сбросить это перенаправление после того, как моя работа будет выполнена. Как я могу это сделать? - person Ankit Raj; 05.06.2019
comment
exec 1>&3 3>&- — Думаю, не проверив. - person Jonathan Leffler; 05.06.2019

В1. Существует простой способ восстановить вывод стандартного вывода на терминал после его перенаправления в файл:

exec >/dev/tty

Хотя сохранение исходного дескриптора файла stdout обычно требуется для его последующего восстановления, в этом конкретном случае вы хотите, чтобы stdout было /dev/tty, поэтому нет необходимости делать больше.

$ date
Mon Aug 25 10:06:46 CEST 2014
$ exec > /tmp/foo
$ date
$ exec > /dev/tty
$ date
Mon Aug 25 10:07:24 CEST 2014
$ ls -l /tmp/foo
-rw-r--r-- 1 jlliagre jlliagre 30 Aug 25 10:07 /tmp/foo
$ cat /tmp/foo
Mon Aug 25 10:07:05 CEST 2014

Вопрос 2: exec 1>file — это немного более подробный способ выполнения exec >file, который, как уже говорилось, перенаправляет стандартный вывод в указанный файл, если у вас есть права на его создание/запись. Файл создается, если он не существует, и усекается, если существует.

exec 1>&- закрывает стандартный вывод, что в большинстве случаев является плохой идеей.

Q3: команды должны быть

exec 0<&-
exec 1>&-
exec 2>&-

Обратите внимание на обратное перенаправление для стандартного ввода.

Можно упростить так:

exec <&- >&- 2>&-

Эта команда закрывает все три стандартных файловых дескриптора. Это очень плохая идея. Если вы хотите, чтобы скрипт был отключен от этих каналов, я бы предложил этот более надежный подход:

exec </dev/null >/dev/null 2>&1

В этом случае все выходные данные будут отброшены, а не вызовут ошибку, и все входные данные не вернутся, а просто ничего не вернутся.

person jlliagre    schedule 25.08.2014
comment
exec 1>/dev/tty работал для меня, чтобы восстановить стандартный вывод на терминал после того, как он был перенаправлен в файл, и, как упоминалось в моем комментарии в ответе выше, exec 1>/dev/pts/0 также работал. Поскольку exec 1>/dev/pts/0 и exec 1>/dev/tty оба способны выполнять эту задачу, теперь это вызвало вопрос оба эти exec 1>/dev/pts/0 и exec 1>/dev/tty одинаковы? - person pawan vinayak; 25.08.2014
comment
Как я уже писал, exec 1>/dev/tty и exec >/dev/tty полностью эквивалентны, поэтому сохраните одно нажатие клавиши и используйте последнее. С другой стороны, в то время как exec >/dev/tty является переносимым, exec 1>/dev/pts/0 — нет, и это происходит в вашем эксперименте только случайно. Это не будет работать с другим окном терминала и может не работать с другой машиной. Просто используйте exec >/dev/tty, и вы в безопасности. - person jlliagre; 25.08.2014
comment
Обратите внимание, что если вывод оболочки не идет на терминал (например, идет в канал), то использование /dev/tty активно неправильно. Для интерактивного использования перенаправление на /dev/tty, конечно, нормально, но лучше знать, как сделать это правильно, независимо от того, как запускается скрипт (включая «запуск из командной строки»). - person Jonathan Leffler; 25.08.2014
comment
@JonathanLeffler Я, конечно, согласен. Я хочу сказать, что ОП явно заявляет, что он работает с терминала, а не с перенаправленного сценария, поэтому я предпочитаю предлагать простое решение, которое работает для него и в большинстве случаев. - person jlliagre; 25.08.2014

Принятый ответ слишком многословен для меня. Итак, я решил подвести итог ответа на ваш первоначальный ответ.

Использование Bash версии 4.3.39(2)-выпуск

На 32-битной машине x86 на машине Cygwin

ДАНО:

  • Стандартный номер — это fd #0.
  • Стандартный вывод — это fd #1.
  • Штдерр - фд №2.

ОТВЕТ (написано на bash):

exec 1> ./output.test.txt
echo -e "First Line: Hello World!"
printf "%s\n" "2nd Line: Hello Earth!" "3rd Line: Hello Solar System!"

# This is uneccessary, but
# it stops or closes stdout.
# exec 1>&-

# Send stdout back to stdin
exec 1>&0

# Oops... I need to append some more data.
# So, lets append to the file.
exec 1>> ./output.test.txt
echo -e "# Appended this line and the next line is empty.\n"

# Send stdout back to stdin
exec 1>&0

# Output the contents to stdout
cat ./output.test.txt

ПОЛЕЗНЫЕ КЛЮЧЕВЫЕ СЛОВА:

Существуют также здесь-документы, здесь-строки и подстановка процессов для перенаправления ввода-вывода в Bourne, Bash, tcsh, zsh для Linux, BSD, AIX, HP, Busybox, Toybox и так далее.

person MyMightyJoeYoung    schedule 26.08.2015

Хотя я полностью согласен с первым вопросом Джонатана, в некоторых системах есть /dev/stdout, поэтому вы можете сделать exec 1>file; ...; exec 1>/dev/stdout

person glenn jackman    schedule 25.08.2014
comment
после использования exec 1>file, когда я дал exec 1>/dev/stdout, STDOUT по-прежнему не появлялся на терминале, но с помощью этой подсказки и некоторых пробных проб мне, наконец, удалось заставить STDOUT перенаправляться на терминал с помощью exec 1>/dev/pts/0 - person pawan vinayak; 25.08.2014
comment
user@ubuntu:~$ cd /dev user@ubuntu:/dev$ ls -l std* lrwxrwxrwx 1 root root 15 25.08.2014 08:47 stderr -> /proc/self/fd/2 lrwxrwxrwx 1 root root 15 25.08.2014 08:47 stdin -> /proc/self/fd/0 lrwxrwxrwx 1 root root 15 25.08.2014 08:47 stdout -> /proc/self/fd/1 - person pawan vinayak; 25.08.2014
comment
user@ubuntu:/dev$ cd /proc/self/fd/ user@ubuntu:/proc/self/fd$ ls -l всего 0 lr-x- ----- 1 пользователь пользователь 64 25.08.2014 09:40 0 -› /dev/pts/0 l-wx------ 1 пользователь пользователь 64 25.08.2014 09:40 1 -› /dev/pts/0 l-wx------ 1 пользователь пользователь 64 25.08.2014 09:40 2 -› /dev/pts/0 lrwx------ 1 пользователь пользователь 64 2014-08-25 09:47 255 -› /dev/pts/0 - person pawan vinayak; 25.08.2014
comment
user@ubuntu:/proc/self/fd$ cd user@ubuntu:~$ exec 1>file user@ubuntu:~$ date user@ubuntu:~$ exec 1>/dev/pts/0 user@ubuntu:~$ date Пн, 25 августа, 09:48:55 IST 2014` - person pawan vinayak; 25.08.2014
comment
хотя это работало как угодно... но все же я не понял, как работает exec 1>/dev/pts/0..? - person pawan vinayak; 25.08.2014