Поиск…


Синтаксис

  • команда </ path / to / file # Перенаправить стандартный ввод в файл
  • command> / path / to / file # Перенаправить стандартный вывод на flie
  • command file_descriptor> / path / to / file # Перенаправить вывод файла file_descriptor в файл
  • command> & file_descriptor # Перенаправить вывод в file_descriptor
  • command file_descriptor> & another_file_descriptor # Перенаправить file_descriptor в another_file_descriptor
  • команда <& file_descriptor # Перенаправить file_descriptor в стандартный ввод
  • command &> / path / to / file # Перенаправить стандартный вывод и стандартную ошибку в файл

параметры

параметр подробности
внутренний файловый дескриптор Целое число.
направление Один из > , < или <>
внешний файловый дескриптор или путь & за ним следует целое число для файлового дескриптора или пути.

замечания

Консольные программы UNIX имеют входной файл и два выходных файла (входные и выходные потоки, а также устройства) рассматриваются как файлы операционной системы.) Обычно это клавиатура и экран, но любой или все из них могут быть перенаправлены из - или перейти к файлу или другой программе.

STDIN является стандартным входом, и как программа получает интерактивный вход. STDIN обычно назначается файловым дескриптором 0.

STDOUT является стандартным выходом. Все, что испускается в STDOUT , считается «результатом» программы. STDOUT обычно назначается файловым дескриптором 1.

STDERR - это то, где отображаются сообщения об ошибках. Как правило, при запуске программы с консоли STDERR выводится на экран и неотличим от STDOUT . Обычно для STDERR назначается файловый дескриптор 2.

Порядок перенаправления важен

command > file 2>&1

Перенаправляет ( STDOUT и STDERR ) в файл.

command 2>&1 > file

Перенаправляет только STDOUT , поскольку дескриптор файла 2 перенаправляется в файл, на который указывает файловый дескриптор 1 (который еще не является файловым file при оценке оператора).

Каждая команда в конвейере имеет свой собственный STDERRSTDOUT ), потому что каждый из них является новым процессом. Это может создать неожиданные результаты, если вы ожидаете, что перенаправление повлияет на весь конвейер. Например, эта команда (завернутая для удобочитаемости):

$ python -c 'import sys;print >> sys.stderr, "Python error!"' \
| cut -f1 2>> error.log

будет печатать "Python error!" на консоль, а не на файл журнала. Вместо этого прикрепите ошибку к команде, которую вы хотите захватить:

$ python -c 'import sys;print >> sys.stderr, "Python error!"' 2>> error.log \
| cut -f1 

Перенаправление стандартного вывода

> перенаправить стандартный вывод (иначе STDOUT ) текущей команды в файл или другой дескриптор.

Эти примеры записывают вывод команды ls в файл file.txt

ls >file.txt
> file.txt ls

Целевой файл создается, если он не существует, иначе этот файл усекается.

Дескриптор перенаправления по умолчанию - стандартный вывод или 1 если ни один не указан. Эта команда эквивалентна предыдущим примерам со стандартным выходом, явно указанным:

ls 1>file.txt

Примечание: перенаправление инициализируется исполняемой оболочкой, а не выполненной командой, поэтому она выполняется перед выполнением команды.

Перенаправление STDIN

< читает его правый аргумент и записывает его левый аргумент.

Чтобы записать файл в STDIN мы должны прочитать /tmp/a_file и записать в STDIN т. STDIN 0</tmp/a_file

Примечание. Внутренний дескриптор файла по умолчанию равен 0 ( STDIN ) для <

$ echo "b" > /tmp/list.txt
$ echo "a" >> /tmp/list.txt
$ echo "c" >> /tmp/list.txt
$ sort < /tmp/list.txt
a
b
c

Перенаправление STDOUT и STDERR

Файловые дескрипторы, такие как 0 и 1 являются указателями. Мы изменим, на что указывают дескрипторы файлов с перенаправлением. >/dev/null означает, что 1 указывает на /dev/null .

Сначала мы укажем 1 ( STDOUT ) на /dev/null затем на точку 2 ( STDERR ) на 1 пункт.

# STDERR is redirect to STDOUT: redirected to /dev/null,
# effectually redirecting both STDERR and STDOUT to /dev/null
echo 'hello' > /dev/null 2>&1
4,0

Это может быть дополнительно сокращено до следующего:

echo 'hello' &> /dev/null

Однако эта форма может быть нежелательной в производстве, если совместимость с оболочкой является проблемой, поскольку она конфликтует с POSIX, вводит разбор синтаксического разбора и оболочки без этой функции, будет неверно истолковывать ее:

# Actual code
echo 'hello' &> /dev/null
echo 'hello' &> /dev/null 'goodbye'

# Desired behavior
echo 'hello' > /dev/null 2>&1
echo 'hello' 'goodbye' > /dev/null 2>&1

# Actual behavior
echo 'hello' &
echo 'hello' & goodbye > /dev/null

ПРИМЕЧАНИЕ. &> , Как известно, работает как в Bash, так и Zsh.

Перенаправление STDERR

2 - STDERR .

$ echo_to_stderr 2>/dev/null # echos nothing

Определения:

echo_to_stderr - это команда, которая записывает "stderr" в STDERR

echo_to_stderr () {
    echo stderr >&2
}

$ echo_to_stderr
stderr

Добавить vs Truncate

Усекать >

  1. Создайте указанный файл, если он не существует.
  2. Truncate (удалить содержимое файла)
  3. Написать в файл
$ echo "first line" > /tmp/lines
$ echo "second line" > /tmp/lines

$ cat /tmp/lines
second line

Добавить >>

  1. Создайте указанный файл, если он не существует.
  2. Добавить файл (запись в конце файла).
# Overwrite existing file
$ echo "first line" > /tmp/lines

# Append a second line
$ echo "second line" >> /tmp/lines

$ cat /tmp/lines
first line
second line

STDIN, STDOUT и STDERR объяснили

Команды имеют один вход (STDIN) и два вида выходов, стандартный вывод (STDOUT) и стандартную ошибку (STDERR).

Например:

STDIN

root@server~# read
Type some text here

Стандартный ввод используется для ввода ввода в программу. (Здесь мы используем для read предопределённого для чтения строки из STDIN.)

STDOUT

root@server~# ls file
file

Стандартный вывод обычно используется для «нормального» вывода из команды. Например, ls перечисляет файлы, поэтому файлы отправляются в STDOUT.

STDERR

root@server~# ls anotherfile
ls: cannot access 'anotherfile': No such file or directory

Стандартная ошибка (как следует из названия) используется для сообщений об ошибках. Поскольку это сообщение не является списком файлов, оно отправляется в STDERR.

STDIN, STDOUT и STDERR являются тремя стандартными потоками. Они идентифицируются с оболочкой числом, а не именем:

0 = Стандарт в
1 = стандартный
2 = стандартная ошибка

По умолчанию STDIN подключается к клавиатуре, и на терминале появляются STDOUT и STDERR. Однако мы можем перенаправить STDOUT или STDERR на все, что нам нужно. Например, допустим, что вам нужен только стандарт, и все сообщения об ошибках, напечатанные на стандартной ошибке, должны быть подавлены. Именно тогда мы используем дескрипторы 1 и 2 .

Перенаправление STDERR в / dev / null
Взяв предыдущий пример,

root@server~# ls anotherfile 2>/dev/null
root@server~#

В этом случае, если есть какой-либо STDERR, он будет перенаправлен на / dev / null (специальный файл, который игнорирует что-либо в нем), поэтому вы не получите никаких ошибок в оболочке.

Перенаправление нескольких команд в один и тот же файл

{
  echo "contents of home directory"
  ls ~
} > output.txt

Использование именованных каналов

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

ls -l | grep ".log"

Вы можете просто записать во временный файл:

touch tempFile.txt
ls -l > tempFile.txt
grep ".log" < tempFile.txt

Это отлично tempFile для большинства приложений, однако никто не будет знать, что делает tempFile , и кто-то может удалить его, если он содержит вывод ls -l в этом каталоге. Здесь вызывается именованная труба:

mkfifo myPipe
ls -l > myPipe
grep ".log" < myPipe

myPipe - это технически файл (все в Linux), поэтому давайте сделаем ls -l в пустой директории, в которой мы только что создали канал:

mkdir pipeFolder
cd pipeFolder
mkfifo myPipe
ls -l

Выход:

prw-r--r-- 1 root root 0 Jul 25 11:20 myPipe

Обратите внимание на первый символ в разрешениях, он указан как канал, а не файл.

Теперь давайте сделаем что-нибудь классное.

Откройте один терминал и обратите внимание на каталог (или создайте его так, чтобы очистка была простой), и создайте канал.

mkfifo myPipe

Теперь давайте поместим что-то в трубку.

echo "Hello from the other side" > myPipe

Вы заметите, что это зависает, другая сторона трубы все еще закрыта. Давайте откроем другую сторону трубы и пропустим это.

Откройте другой терминал и перейдите в каталог, в котором находится труба (или, если вы знаете, добавьте его в трубу):

cat < myPipe

Вы заметите, что после получения hello from the other side программа в первом терминале заканчивается, как и во втором терминале.

Теперь запустите команды в обратном порядке. Начните с cat < myPipe а затем повторите что-нибудь в нем. Он по-прежнему работает, потому что программа будет ждать, пока что-то не будет помещено в трубку до завершения, потому что он знает, что он должен что-то получить.

Именованные каналы могут быть полезны для перемещения информации между терминалами или между программами.

Трубы маленькие. После полной записи автор блокирует, пока какой-либо читатель не прочитает содержимое, поэтому вам нужно либо запустить считыватель и запись на разных терминалах, либо запустить один или другой в фоновом режиме:

 ls -l /tmp > myPipe &
 cat < myPipe

Дополнительные примеры с использованием именованных каналов:

  • Пример 1 - все команды на одном и том же терминале / той же оболочке

    $ { ls -l && cat file3; } >mypipe &
    $ cat <mypipe    
    # Output: Prints ls -l data and then prints file3 contents on screen
    
  • Пример 2 - все команды на одном и том же терминале / той же оболочке

    $ ls -l >mypipe &
    $ cat file3 >mypipe &
    $ cat <mypipe
    #Output: This prints on screen the contents of mypipe. 
    

    Имейте в виду, что первое содержимое file3 отображается, а затем отображаются ls -l данные (конфигурация LIFO).

  • Пример 3 - все команды на одном и том же терминале / той же оболочке

    $ { pipedata=$(<mypipe) && echo "$pipedata"; } &
    $ ls >mypipe 
    # Output: Prints the output of ls directly on screen 
    

    Имейте в виду, что переменная $pipedata недоступна для использования в главном терминале / основной оболочке, так как использование & вызывает подоболочку, а $pipedata доступно только в этой подоболочке.

  • Пример 4 - все команды на одном и том же терминале / той же оболочке

    $ export pipedata
    $ pipedata=$(<mypipe) &
    $ ls -l *.sh >mypipe
    $ echo "$pipedata"   
    #Output : Prints correctly the contents of mypipe
    

    Это правильно печатает значение переменной $pipedata в основной оболочке из-за объявления экспорта переменной. Основной терминал / основная оболочка не висит из-за вызова фоновой оболочки ( & ).

Печатать сообщения об ошибках в stderr

Сообщения об ошибках обычно включаются в сценарий для целей отладки или для обеспечения богатого пользовательского опыта. Просто напишите сообщение об ошибке следующим образом:

cmd || echo 'cmd failed'

может работать для простых случаев, но это не обычный способ. В этом примере сообщение об ошибке будет загрязнять фактический вывод сценария путем смешивания как ошибок, так и успешного вывода в stdout .

Короче говоря, сообщение об ошибке должно идти в stderr не stdout . Это довольно просто:

cmd || echo 'cmd failed' >/dev/stderr

Другой пример:

if cmd; then
    echo 'success'
else
    echo 'cmd failed' >/dev/stderr
fi

В приведенном выше примере сообщение об успешном завершении будет напечатано на stdout пока сообщение об ошибке будет напечатано на stderr .

Лучшим способом печати сообщения об ошибке является определение функции:

err(){
    echo "E: $*" >>/dev/stderr
}

Теперь, когда вам нужно напечатать сообщение об ошибке:

err "My error message"

Перенаправление на сетевые адреса

2,04

Bash рассматривает некоторые пути как специальные и может выполнять некоторую сетевую связь, записывая в /dev/{udp|tcp}/host/port . Bash не может настроить сервер прослушивания, но может инициировать соединение, а TCP может читать результаты как минимум.

Например, чтобы отправить простой веб-запрос, который можно было бы сделать:

exec 3</dev/tcp/www.google.com/80
printf 'GET / HTTP/1.0\r\n\r\n' >&3
cat <&3

и результаты веб-страницы www.google.com умолчанию будут напечатаны на стандартный stdout .

так же

printf 'HI\n' >/dev/udp/192.168.1.1/6666

отправит сообщение UDP, содержащее HI\n слушателю на 192.168.1.1:6666



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow