- Стандартные потоки ввода вывода linux зачем нужны
- Перенаправление ввода и вывода
- Использование состыкованных команд (конвейер)
- Недеструктивное перенаправление вывода
- Стандартные потоки ввода/вывода
- Материал из Xgu.ru
- Содержание
- [править] Потоки и файлы
- [править] Каналы
- [править] Переменные командного интерпретатора и потоки
- [править] Именованные каналы
- [править] Потоки ввода/вывода и терминал
- [править] Подстановка процесса
- [править] Перенаправление вывода скрипта
- [править] Поменять местами стандартный поток вывода и стандартный поток ошибок
- [править] Просмотр прогресса и скорости обработки данных в потоке
Стандартные потоки ввода вывода linux зачем нужны
Программа обычно ценна тем, что может обрабатывать данные: принимать одно, на выходе выдавать другое, причём в качестве данных может выступать практически что угодно: текст, числа, звук, видео. Потоки входных и выходных данных для команды называются ввод и вывод. Потоков ввода и вывода у каждой программы может быть и по несколько. В Linux каждый процесс, при создании в обязательном порядке получает так называемые стандартный ввод (standard input, stdin) и стандартный вывод (standard output, stdout) и стандартный вывод ошибок (standard error, stderr).
Стандартные потоки ввода/вывода предназначены в первую очередь для обмена текстовой информацией. Тут даже не важно, кто общается с помощью текстов: человек с программой или программы междй собой — главное, чтобы у них был канал передачи данных и чтобы они говорили « на одном языке ».
Текстовый принцип работы с машиной позволяет отвлечься от конкретных частей компьютера, вроде системной клавиатуры и видеокарты с монитором, рассматривая единое оконечное устройство , посредством которого пользователь вводит текст (команды) и передаёт его системе, а система выводит необходимые пользователю данные и сообщения (диагностику и ошибки). Такое устройство называется терминалом. В общем случае терминал — это точка входа пользователя в систему, обладающая способностью передавать текстовую информацию. Терминалом может быть отдельное внешнее устройство, подключаемое к компьютеру через порт последовательной передачи данных (в персональном компьютере он называется « COM port »). В роли терминала может работать (с некоторой поддержкой со стороны системы) и программа (например, xterm или ssh). Наконец, виртуальные консоли Linux — тоже терминалы, только организованные программно с помощью подходящих устройств современного компьютера.
При работе с командной строкой, стандартный ввод командной оболочки связан с клавиатурой, а стандартный вывод и вывод ошибок — с экраном монитора (или окном эмулятора терминала). Покажем на примере простейшей команды — cat. Обычно команда cat читает данные из всех файлов, которые указаны в качестве её параметров, и посылает считанное непосредственно в стандартный вывод (stdout). Следовательно, команда
выведет на экран сначала содержимое файла history-final , а затем — файла masters-thesis .
Однако если имя файла не указано, программа cat читает входные данные из stdin и немедленно возвращает их в stdout (никак не изменяя). Данные проходят через cat , как через трубу. Приведём пример:
Каждую строчку, вводимую с клавиатуры, программа cat немедленно возвращает на экран. При вводе информации со стандартного ввода конец текста сигнализируется вводом специальной комбинации клавиш, как правило Ctrl — D .
Приведём другой пример. Команда sort читает строки вводимого текста (также из stdin, если не указано ни одного имени файла) и выдаёт набор этих строк в упорядоченном виде на stdout. Проверим её действие.
Как видно, после нажатия Ctrl — D , sort вывела строки упорядоченными в алфавитном порядке.
Перенаправление ввода и вывода
Допустим, вы хотите направить вывод команды sort в некоторый файл, чтобы сохранить упорядоченный по алфавиту список на диске. Командная оболочка позволяет перенаправить стандартный вывод команды в файл, используя символ > . Приведём пример:
Можно увидеть, что результат работы команды sort не выводится на экран, однако он сохраняется в файле с именем shopping-list . Выведем на экран содержимое этого файла:
Пусть теперь исходный неупорядоченный список находится в файле items . Этот список можно упорядочить с помощью команды sort , если указать ей, что она должна читать из данного файла, а не из своего стандартного ввода, и кроме того, перенаправить стандартный вывод в файл, как это делалось выше. Пример:
Однако можно поступить иначе, перенаправив не только стандартный вывод, но и стандартный ввод утилиты из файла, используя для этого символ :
Результат команды sort эквивалентен команде sort items , однако первая из них демонстрирует следующее: при выдаче команды sort система ведёт себя так, как если бы данные, которые содержатся в файле items , были введены со стандартного ввода. Перенаправление осуществляется командной оболочкой. Команде sort не сообщалось имя файла items : эта команда читала данные из своего стандартного ввода, как если бы мы вводили их с клавиатуры.
Введём понятие фильтра. Фильтром является программа, которая читает данные из стандартного ввода, некоторым образом их обрабатывает и результат направляет на стандартный вывод. Когда применяется перенаправление, в качестве стандартного ввода и вывода могут выступать файлы. Как указывалось выше, по умолчанию, stdin и stdout относятся к клавиатуре и к экрану соответственно. Программа sort является простым фильтром — она сортирует входные данные и посылает результат на стандартный вывод. Совсем простым фильтром является программа cat — она ничего не делает с входными данными, а просто пересылает их на выход.
Использование состыкованных команд (конвейер)
Выше уже демонстрировалось, как использовать программу sort в качестве фильтра. В этих примерах предполагалось, что исходные данные находятся в некотором файле или что эти исходные данные будут введены с клавиатуры (стандартного ввода). Однако как поступить, если вы хотите отсортировать данные, которые являются результатом работы какой-либо другой команды, например, ls ?
Будем сортировать данные в обратном алфавитном порядке; это делается опцией -r команды sort . Если вы хотите перечислить файлы в текущем каталоге в обратном алфавитном порядке, один из способов сделать это будет таким. Применим сначала команду ls :
Теперь перенаправляем выход команды ls в файл с именем file-list
Здесь выход команды ls сохранен в файле, а после этого этот файл был обработан командой sort -r . Однако этот путь является неизящным и требует использования временного файла для хранения выходных данных программы ls .
Решением в данной ситуации может служить создание состыкованных команд (pipelines). Стыковку осуществляет командная оболочка, которая stdout первой команды направляет на stdin второй команды. В данном случае мы хотим направить stdout команды ls на stdin команды sort . Для стыковки используется символ | , как это показано в следующем примере:
Эта команда короче, чем совокупность команд, и её проще набирать.
Рассмотрим другой полезный пример. Команда
выдаёт длинный список файлов. Большая часть этого списка пролетает по экрану слишком быстро, чтобы содержимое этого списка можно было прочитать. Попробуем использовать команду more для того, чтобы выводить этот список частями:
Теперь можно этот список « перелистывать ».
Можно пойти дальше и состыковать более двух команд. Рассмотрим команду head , которая является фильтром следующего свойства: она выводит первые строки из входного потока (в нашем случае на вход будет подан выход от нескольких состыкованных команд). Если мы хотим вывести на экран последнее по алфавиту имя файла в текущем каталоге, можно использовать следующую длинную команду:
где команда head -1 выводит на экран первую строку получаемого ей входного потока строк (в нашем случае поток состоит из данных от команды ls ), отсортированных в обратном алфавитном порядке.
Недеструктивное перенаправление вывода
Эффект от использования символа > для перенаправления вывода файла является деструктивным; иными словами, команда
уничтожит содержимое файла file-list , если этот файл ранее существовал, и создаст на его месте новый файл. Если вместо этого перенаправление будет сделано с помощью символов >> , то вывод будет приписан в конец указанного файла, при этом исходное содержимое файла не будет уничтожено. Например, команда
приписывает вывод команды ls в конец файла file-list .
Следует иметь в виду, что перенаправление ввода и вывода и стыкование команд осуществляется командными оболочками, которые поддерживают использование символов > , >> и | . Сами команды не способны воспринимать и интерпретировать эти символы.
Источник
Стандартные потоки ввода/вывода
Материал из Xgu.ru
Стандартные потоки ввода и вывода в UNIX/Linux наряду с файлами являются одним из наиболее распространённых средств для обмена информацией процессов с внешним миром, а перенаправления >, >> и |, одной из самых популярных конструкций командного интерпретатора.
На этой странице рассматриваются как базовые вопросы использования потоков ввода/вывода, так и тонкости и хитрости, например, почему не работает echo text | read ver и многие другие.
Содержание
[править] Потоки и файлы
Процесс взаимодействия с пользователем выполняется в терминах записи и чтения в файл. То есть вывод на экран представляется как запись в файл, а ввод — как чтение файла. Файл, из которого осуществляется чтение, называется стандартным потоком ввода, а в который осуществляется запись — стандартным потоком вывода.
Стандартные потоки — воображаемые файлы, позволяющие осуществлять взаимодействие с пользователем как чтение и запись в файл. Кроме потоков ввода и вывода, существует еще и стандартный поток ошибок, на который выводятся все сообщения об ошибках и те информативные сообщения о ходе работы программы, которые не могут быть выведены в стандартный поток вывода.
Стандартные потоки привязаны к файловым дескрипторам с номерами 0, 1 и 2.
- Стандартный поток ввода (stdin) — 0;
- Стандартный поток вывода (stdout) — 1;
- Стандартный поток ошибок (stderr) — 2.
Вывод данных на экран и чтение их с клавиатуры происходит потому, что по умолчанию стандартные потоки ассоциированы с терминалом пользователя. Это не является обязательным — потоки можно подключать к чему угодно — к файлам, программам и даже устройствам. В командном интерпретаторе bash такая операция называется перенаправлением.
Использовать файл как источник данных для стандартного потока ввода. > файл Направить стандартный поток вывода в файл. Если файл не существует, он будет создан; если существует — перезаписан сверху. 2> файл Направить стандартный поток ошибок в файл. Если файл не существует, он будет создан; если существует — перезаписан сверху. >>файл Направить стандартный поток вывода в файл. Если файл не существует, он будет создан; если существует — данные будут дописаны к нему в конец. 2>>файл Направить стандартный поток ошибок в файл. Если файл не существует, он будет создан; если существует — данные будут дописаны к нему в конец. &>файл или >&файл Направить стандартный поток вывода и стандартный поток ошибок в файл. Другая форма записи: >файл 2>&1. >&- Закрыть поток вывода перед вызовом команды (спасибо [1]); 2>&- Закрыть поток ошибок перед вызовом команды (спасибо [2]); cat
Весь текст между блоками EOF (в общем случае вместо EOF можно использовать любое слово) будет выведен на экран. Важно: перед последним EOF не должно быть пробелов! (heredoc синтаксис).
EOF Аналогично, но только для одной строки (для bash версии 3 и выше)
Пример. Эта команда объединяет три файла: header, body и footer в один файл letter:
Команда cat по очереди выводит содержимое файлов, перечисленных в качестве параметров на стандартный поток вывода. Стандартный поток вывода перенаправлен в файл letter.
Здесь используется сразу перенаправление стандартного потока ввода и стандартного потока вывода:
Программа sort сортирует данные, поступившие в стандартный поток ввода, и выводит их на стандартный поток вывода. Стандартный поток ввода подключен к файлу unsortedlines, а выход записывается в sortedlines.
Здесь перенаправлены потоки вывода и ошибок:
Программа find ищет в каталоге /home файлы с суффиксом .rpm. Список найденных файлов записывается в файл rpmlist. Все сообщения об ошибках удаляются. Удаление достигается при помощи перенаправления потока ошибок на устройство /dev/null — специальный файл, означающий ничто. Данные, отправленные туда, безвозвратно исчезают. Если же прочитать содержимое этого файла, он окажется пуст.
Для того чтобы лучше понять, что потоки работают как файлы, рассмотрим такой пример:
Программа cat запускается для записи данных в файл /tmp/fff. Он запускается в фоне (&), и получает номер работы 1 ([1]). Процесс этой программы имеет номер 28378.
Информация о процессе 28738 находится в каталоге /proc/28738 специальной псевдофайловой системы /proc. В частности, в подкаталоге /proc/28738/fd/ находится список файловых дескрипторов для открытых процессом файлов.
Здесь видно, что стандартный поток ввода (0), и стандартный поток ошибок (2) процесса подключены на терминал, а вот стандартный поток вывода (1) перенаправлен в файл.
Завершить работу программы cat можно командой kill %1.
Командный интерпретатор — это тоже процесс. И у него есть стандартные потоки ввода и вывода. Если интерпретатор работает в интерактивном режиме, то они подключены на консоль (вывода на экран; чтение с клавиатуры). Можно обратиться напрямую к этим потокам изнутри интерпретатора:
- /dev/stdin — стандартный поток ввода;
- /dev/stdout — стандартный поток вывода;
- /dev/stderr — стандартный поток ошибок.
Например, здесь видно, что потоки ссылаются в конечном итоге на файл-устройство терминала, с которым работает интерпретатор:
[править] Каналы
Стандартные потоки можно перенаправлять не только в файлы, но и на вход других программ. Если поток вывода одной программы соединить с потоком ввода другой программы, получится конструкция, называемая каналом, конвейером или пайпом (от англ. pipe, труба).
В bash канал выглядит как последовательность команд, отделенных друг от друга символом |:
команда1 | команда2 | команда3 .
Стандартный поток вывода команды1 подключается к стандартному потоку ввода команды2, стандартный поток вывода команды2 в свою очередь подключается к потоку ввода команды3 и т.д.
В UNIX/Linux существует целый класс команд, предназначенных для преобразования потоков данных в каналах. Такие программы известны как фильтры. Программа-фильтр читает данные, поступающие со стандартного потока ввода (на вход), преобразовывает их требуемым образом и выводит на стандартный поток вывода (на выход). Существует множество хорошо известных фильтров, призванных решать определенные задачи, и являющихся незаменимым инструментом в руках пользователя ОС.
Каналы в ОС Linux являются одной из наиболее часто применяемых конструкций, а фильтры — наиболее часто применяемых программ. Большинство повседневных задач в Linux легко решаются при помощи конструкций построенных на основе нескольких фильтров.
Программы, образующие канал, выполняются параллельно как независимые процессы.
Можно создавать ответвление в каналах. Команда tee позволяет сохранять данные, передающиеся в канале:
Программа tee копирует данные, поступающие на стандартный поток ввода, в указанные в качестве аргументов команды файлы, и передает данные на стандартный поток вывода.
Рассмотренный ниже пример: сортируется файл unsortedlines и результат записывается в sortedlines.
Команда выполняет те же действия, но запись является более наглядной.
Вот пример посложнее. Вывести название и размер пользовательского каталога, занимающее наибольшее место на диске.
Программа du, при вызове ее с ключом -s, сообщает суммарный объем каждого каталога или файла, перечисленного в ее параметрах.
Ключ -n команды sort означает, что сортировка должна быть арифметической, т.е. строки должны рассматриваться как числа, а не как последовательности символов (Например, 12>5 в то время как строка ’12’ [править] Программы фильтры
В UNIX/Linux существует целый класс команд, которые принимают данные со стандартного потока ввода, каким-то образом обрабатывают их, и выдают результат на стандартный поток вывода. Такие программы называются программами-фильтрами.
Как правило, все эти программы работают как фильтры, если у них нет аргументов (опции могут быть), но как только им в качестве аргумента передаётся файл, они считывают данные из этого файла, а не со стандартного потока ввода (существуют и исключения, например, программа tr, которая обрабатывает данные поступающие исключительно через стандартный поток ввода).
[править] Переменные командного интерпретатора и потоки
Для того чтобы вывести содержимое переменной командного интерпретатора на стандартный поток вывода, используется команда echo:
На стандартный поток ошибок данные можно передать с помощью перенаправления:
Содержимое переменной (или любой другой текст) поступят не на стандартный поток вывода, а на стандартный поток ошибок.
Считать данные со стандартного потока ввода внутрь одной или нескольких переменных можно при помощи команды read:
Строка из стандартного потока ввода считается внутрь переменной VAR.
Если указать несколько переменных, то в первую попадёт первое слово; во вторую — второе слово; в последнюю — всё остальное.
Обратите внимание на конструкцию <read VAR; echo $VAR >. Переменная считанная из канала с помощью read будет доступна только внутри < >. Например echo text | read var; echo $var выведет пустое место. Это связано с тем, что для перенаправления внутрь read shell порождает дочерний процесс, в котором и исполняет read. Переменная дочернего процесса не передаётся наружу. (Внимание. В zsh всё работает и без этих костылей).
Если прочитать данные со стандартного потока ввода не удалось, то команда read возвращает код завершения отличный от нуля. Это позволяет использовать read, например, в такой конструкции:
В этом примере read считывает строки из файла users, и для каждой прочитанной строки вызывается команда useradd, которая добавляет пользователя в системе. В результате: создаются учётные записи пользователей, имена которых перечислены в файле users.
Переменная user после выхода из цикла остаётся в том же виде, в каком она была до входа в цикл (а не содержит последнее значение файла, как можно было бы предположить). Это связано с тем, что для обработки while, на вход которому направлен канал, порождается дочерний интерпретатор, и модификация переменной происходит внутри него.
[править] Именованные каналы
Безымянный канал можно построить только между процессами, которые порождены от одного процесса (и на практике они должны быть порождены одновременно, а не последовательно, хотя теоретически это не обязательно). Если же процессы имеют разных родителей, то между ними обычный, безымянный канал построить не получится.
Например, в данном случае d и e, и f и g легко могут быть соединены при помощи канала, но e и f соединить с помощью канала не получится.
Для решения этой задачи используются именованные каналы fifo (first in, first out). Они во всём повторяют обычные каналы (pipe), только имеют привязку к файловой системе. Создать именованный канал можно командой mkfifo:
Созданный канал можно использовать для соединения процессов между собой. Например, эти перенаправления будут работать одинаково:
(здесь f и g — процессы из вышеуказанной иерархии процессов). Процессы f и g имеют общего предка. А вот для процессов e и g, не связанных между собой, обычный канал использовать не получится, только именованный:
[править] Потоки ввода/вывода и терминал
Большинство программ, которые работают с потоками ввода и вывода, работают с ними как с простыми файлами, и не рассчитывают на то, что поток подключен к терминалу. Но не все. Если потоки ввода/вывода отключаются от терминала и перенаправляются в файл, часть возможностей программы может пропасть.
Например, если командный интерпретатор отвязать от терминала, то у него потеряется множество интерактивных возможностей:
Например, возможности прокручивать историю команд у него теперь нет. Возможности по редактированию теперь тоже сильно урезаны. Фактически, редактирование команды теперь выполняется уже с помощью программы cat, которая держит терминал, а интерпретатору поступают уже полностью введённые команды.
Проверить, подключен ли наш стандартный поток к терминалу, или он перенаправлен в файл, можно при помощи test, ключ -t:
[править] Подстановка процесса
Есть хитрый трюк, который в чистом виде перенаправлением потока ввода/вывода не является, но имеет к нему отношение — подстановка процесса. Результат выполнения процесса можно представить в виде воображаемого файла и передать его другому процессу.
При таком вызове процессу команда1 передаётся файл (созданный налету канал или файл /dev/fd/. ), в котором находятся данные, которые выводит команда2.
Например, у вас есть два файла с различными словами по одному в строке. Вы хотите определить, какие из них встречаются в одном файле, но не встречаются во втором. И наоборот.
Получается, что в первом файле присутствует слово, которое отсутствует во втором (слово b).
[править] Перенаправление вывода скрипта
Потоки ввода/вывода скрипта, исполняющегося сейчас, изнутри самого скрипта можно следующим образом:
- How do I redirect the output of an entire shell script within the script itself?
[править] Поменять местами стандартный поток вывода и стандартный поток ошибок
- IO Redirection - Swapping stdout and stderr (Advanced)
[править] Просмотр прогресса и скорости обработки данных в потоке
Если пропустить данные, передающиеся в канале, через программу pv, то будет видна скорость обработки, время в течение которого работает канал и, если известно сколько данных должно быть обработано, приблизительное время окончания выполнения.
Источник