Время на прочтение
9 мин
Количество просмотров 335K
Bash-скрипты: начало
Bash-скрипты, часть 2: циклы
Bash-скрипты, часть 3: параметры и ключи командной строки
Bash-скрипты, часть 4: ввод и вывод
Bash-скрипты, часть 5: сигналы, фоновые задачи, управление сценариями
Bash-скрипты, часть 6: функции и разработка библиотек
Bash-скрипты, часть 7: sed и обработка текстов
Bash-скрипты, часть 8: язык обработки данных awk
Bash-скрипты, часть 9: регулярные выражения
Bash-скрипты, часть 10: практические примеры
Bash-скрипты, часть 11: expect и автоматизация интерактивных утилит
В прошлый раз, в третьей части этой серии материалов по bash-скриптам, мы говорили о параметрах командной строки и ключах. Наша сегодняшняя тема — ввод, вывод, и всё, что с этим связано.
Вы уже знакомы с двумя методами работы с тем, что выводят сценарии командной строки:
- Отображение выводимых данных на экране.
- Перенаправление вывода в файл.
Иногда что-то надо показать на экране, а что-то — записать в файл, поэтому нужно разобраться с тем, как в Linux обрабатывается ввод и вывод, а значит — научиться отправлять результаты работы сценариев туда, куда нужно. Начнём с разговора о стандартных дескрипторах файлов.
Стандартные дескрипторы файлов
Всё в Linux — это файлы, в том числе — ввод и вывод. Операционная система идентифицирует файлы с использованием дескрипторов.
Каждому процессу позволено иметь до девяти открытых дескрипторов файлов. Оболочка bash резервирует первые три дескриптора с идентификаторами 0, 1 и 2. Вот что они означают.
0
,STDIN —
стандартный поток ввода.1
,STDOUT —
стандартный поток вывода.2
,STDERR —
стандартный поток ошибок.
Эти три специальных дескриптора обрабатывают ввод и вывод данных в сценарии.
Вам нужно как следует разобраться в стандартных потоках. Их можно сравнить с фундаментом, на котором строится взаимодействие скриптов с внешним миром. Рассмотрим подробности о них.
STDIN
STDIN —
это стандартный поток ввода оболочки. Для терминала стандартный ввод — это клавиатура. Когда в сценариях используют символ перенаправления ввода — <
, Linux заменяет дескриптор файла стандартного ввода на тот, который указан в команде. Система читает файл и обрабатывает данные так, будто они введены с клавиатуры.
Многие команды bash принимают ввод из STDIN
, если в командной строке не указан файл, из которого надо брать данные. Например, это справедливо для команды cat
.
Когда вы вводите команду cat
в командной строке, не задавая параметров, она принимает ввод из STDIN
. После того, как вы вводите очередную строку, cat
просто выводит её на экран.
STDOUT
STDOUT —
стандартный поток вывода оболочки. По умолчанию это — экран. Большинство bash-команд выводят данные в STDOUT
, что приводит к их появлению в консоли. Данные можно перенаправить в файл, присоединяя их к его содержимому, для этого служит команда >>
.
Итак, у нас есть некий файл с данными, к которому мы можем добавить другие данные с помощью этой команды:
pwd >> myfile
То, что выведет pwd
, будет добавлено к файлу myfile
, при этом уже имеющиеся в нём данные никуда не денутся.
Перенаправление вывода команды в файл
Пока всё хорошо, но что если попытаться выполнить что-то вроде показанного ниже, обратившись к несуществующему файлу xfile
, задумывая всё это для того, чтобы в файл myfile
попало сообщение об ошибке.
ls –l xfile > myfile
После выполнения этой команды мы увидим сообщения об ошибках на экране.
Попытка обращения к несуществующему файлу
При попытке обращения к несуществующему файлу генерируется ошибка, но оболочка не перенаправила сообщения об ошибках в файл, выведя их на экран. Но мы-то хотели, чтобы сообщения об ошибках попали в файл. Что делать? Ответ прост — воспользоваться третьим стандартным дескриптором.
STDERR
STDERR
представляет собой стандартный поток ошибок оболочки. По умолчанию этот дескриптор указывает на то же самое, на что указывает STDOUT
, именно поэтому при возникновении ошибки мы видим сообщение на экране.
Итак, предположим, что надо перенаправить сообщения об ошибках, скажем, в лог-файл, или куда-нибудь ещё, вместо того, чтобы выводить их на экран.
▍Перенаправление потока ошибок
Как вы уже знаете, дескриптор файла STDERR —
2. Мы можем перенаправить ошибки, разместив этот дескриптор перед командой перенаправления:
ls -l xfile 2>myfile
cat ./myfile
Сообщение об ошибке теперь попадёт в файл myfile
.
Перенаправление сообщения об ошибке в файл
▍Перенаправление потоков ошибок и вывода
При написании сценариев командной строки может возникнуть ситуация, когда нужно организовать и перенаправление сообщений об ошибках, и перенаправление стандартного вывода. Для того, чтобы этого добиться, нужно использовать команды перенаправления для соответствующих дескрипторов с указанием файлов, куда должны попадать ошибки и стандартный вывод:
ls –l myfile xfile anotherfile 2> errorcontent 1> correctcontent
Перенаправление ошибок и стандартного вывода
Оболочка перенаправит то, что команда ls
обычно отправляет в STDOUT
, в файл correctcontent
благодаря конструкции 1>
. Сообщения об ошибках, которые попали бы в STDERR
, оказываются в файле errorcontent
из-за команды перенаправления 2>
.
Если надо, и STDERR
, и STDOUT
можно перенаправить в один и тот же файл, воспользовавшись командой &>
:
Перенаправление STDERR и STDOUT в один и тот же файл
После выполнения команды то, что предназначено для STDERR
и STDOUT
, оказывается в файле content
.
Перенаправление вывода в скриптах
Существует два метода перенаправления вывода в сценариях командной строки:
- Временное перенаправление, или перенаправление вывода одной строки.
- Постоянное перенаправление, или перенаправление всего вывода в скрипте либо в какой-то его части.
▍Временное перенаправление вывода
В скрипте можно перенаправить вывод отдельной строки в STDERR
. Для того, чтобы это сделать, достаточно использовать команду перенаправления, указав дескриптор STDERR
, при этом перед номером дескриптора надо поставить символ амперсанда (&
):
#!/bin/bash
echo "This is an error" >&2
echo "This is normal output"
Если запустить скрипт, обе строки попадут на экран, так как, как вы уже знаете, по умолчанию ошибки выводятся туда же, куда и обычные данные.
Временное перенаправление
Запустим скрипт так, чтобы вывод STDERR
попадал в файл.
./myscript 2> myfile
Как видно, теперь обычный вывод делается в консоль, а сообщения об ошибках попадают в файл.
Сообщения об ошибках записываются в файл
▍Постоянное перенаправление вывода
Если в скрипте нужно перенаправлять много выводимых на экран данных, добавлять соответствующую команду к каждому вызову echo
неудобно. Вместо этого можно задать перенаправление вывода в определённый дескриптор на время выполнения скрипта, воспользовавшись командой exec
:
#!/bin/bash
exec 1>outfile
echo "This is a test of redirecting all output"
echo "from a shell script to another file."
echo "without having to redirect every line"
Запустим скрипт.
Перенаправление всего вывода в файл
Если просмотреть файл, указанный в команде перенаправления вывода, окажется, что всё, что выводилось командами echo
, попало в этот файл.
Команду exec
можно использовать не только в начале скрипта, но и в других местах:
#!/bin/bash
exec 2>myerror
echo "This is the start of the script"
echo "now redirecting all output to another location"
exec 1>myfile
echo "This should go to the myfile file"
echo "and this should go to the myerror file" >&2
Вот что получится после запуска скрипта и просмотра файлов, в которые мы перенаправляли вывод.
Перенаправление вывода в разные файлы
Сначала команда exec
задаёт перенаправление вывода из STDERR
в файл myerror
. Затем вывод нескольких команд echo
отправляется в STDOUT
и выводится на экран. После этого команда exec
задаёт отправку того, что попадает в STDOUT
, в файл myfile
, и, наконец, мы пользуемся командой перенаправления в STDERR
в команде echo
, что приводит к записи соответствующей строки в файл myerror.
Освоив это, вы сможете перенаправлять вывод туда, куда нужно. Теперь поговорим о перенаправлении ввода.
Перенаправление ввода в скриптах
Для перенаправления ввода можно воспользоваться той же методикой, которую мы применяли для перенаправления вывода. Например, команда exec
позволяет сделать источником данных для STDIN
какой-нибудь файл:
exec 0< myfile
Эта команда указывает оболочке на то, что источником вводимых данных должен стать файл myfile
, а не обычный STDIN
. Посмотрим на перенаправление ввода в действии:
#!/bin/bash
exec 0< testfile
count=1
while read line
do
echo "Line #$count: $line"
count=$(( $count + 1 ))
done
Вот что появится на экране после запуска скрипта.
Перенаправление ввода
В одном из предыдущих материалов вы узнали о том, как использовать команду read
для чтения данных, вводимых пользователем с клавиатуры. Если перенаправить ввод, сделав источником данных файл, то команда read
, при попытке прочитать данные из STDIN
, будет читать их из файла, а не с клавиатуры.
Некоторые администраторы Linux используют этот подход для чтения и последующей обработки лог-файлов.
Создание собственного перенаправления вывода
Перенаправляя ввод и вывод в сценариях, вы не ограничены тремя стандартными дескрипторами файлов. Как уже говорилось, можно иметь до девяти открытых дескрипторов. Остальные шесть, с номерами от 3 до 8, можно использовать для перенаправления ввода или вывода. Любой из них можно назначить файлу и использовать в коде скрипта.
Назначить дескриптор для вывода данных можно, используя команду exec
:
#!/bin/bash
exec 3>myfile
echo "This should display on the screen"
echo "and this should be stored in the file" >&3
echo "And this should be back on the screen"
После запуска скрипта часть вывода попадёт на экран, часть — в файл с дескриптором 3
.
Перенаправление вывода, используя собственный дескриптор
Создание дескрипторов файлов для ввода данных
Перенаправить ввод в скрипте можно точно так же, как и вывод. Сохраните STDIN
в другом дескрипторе, прежде чем перенаправлять ввод данных.
После окончания чтения файла можно восстановить STDIN
и пользоваться им как обычно:
#!/bin/bash
exec 6<&0
exec 0< myfile
count=1
while read line
do
echo "Line #$count: $line"
count=$(( $count + 1 ))
done
exec 0<&6
read -p "Are you done now? " answer
case $answer in
y) echo "Goodbye";;
n) echo "Sorry, this is the end.";;
esac
Испытаем сценарий.
Перенаправление ввода
В этом примере дескриптор файла 6 использовался для хранения ссылки на STDIN
. Затем было сделано перенаправление ввода, источником данных для STDIN
стал файл. После этого входные данные для команды read
поступали из перенаправленного STDIN
, то есть из файла.
После чтения файла мы возвращаем STDIN
в исходное состояние, перенаправляя его в дескриптор 6
. Теперь, для того, чтобы проверить, что всё работает правильно, скрипт задаёт пользователю вопрос, ожидает ввода с клавиатуры и обрабатывает то, что введено.
Закрытие дескрипторов файлов
Оболочка автоматически закрывает дескрипторы файлов после завершения работы скрипта. Однако, в некоторых случаях нужно закрывать дескрипторы вручную, до того, как скрипт закончит работу. Для того, чтобы закрыть дескриптор, его нужно перенаправить в &-
. Выглядит это так:
#!/bin/bash
exec 3> myfile
echo "This is a test line of data" >&3
exec 3>&-
echo "This won't work" >&3
После исполнения скрипта мы получим сообщение об ошибке.
Попытка обращения к закрытому дескриптору файла
Всё дело в том, что мы попытались обратиться к несуществующему дескриптору.
Будьте внимательны, закрывая дескрипторы файлов в сценариях. Если вы отправляли данные в файл, потом закрыли дескриптор, потом — открыли снова, оболочка заменит существующий файл новым. То есть всё то, что было записано в этот файл ранее, будет утеряно.
Получение сведений об открытых дескрипторах
Для того, чтобы получить список всех открытых в Linux дескрипторов, можно воспользоваться командой lsof
. Во многих дистрибутивах, вроде Fedora, утилита lsof
находится в /usr/sbin
. Эта команда весьма полезна, так как она выводит сведения о каждом дескрипторе, открытом в системе. Сюда входит и то, что открыли процессы, выполняемые в фоне, и то, что открыто пользователями, вошедшими в систему.
У этой команды есть множество ключей, рассмотрим самые важные.
-p
Позволяет указатьID
процесса.-d
Позволяет указать номер дескриптора, о котором надо получить сведения.
Для того, чтобы узнать PID
текущего процесса, можно использовать специальную переменную окружения $$
, в которую оболочка записывает текущий PID
.
Ключ -a
используется для выполнения операции логического И
над результатами, возвращёнными благодаря использованию двух других ключей:
lsof -a -p $$ -d 0,1,2
Вывод сведений об открытых дескрипторах
Тип файлов, связанных с STDIN
, STDOUT
и STDERR —
CHR (character mode, символьный режим). Так как все они указывают на терминал, имя файла соответствует имени устройства, назначенного терминалу. Все три стандартных файла доступны и для чтения, и для записи.
Посмотрим на вызов команды lsof
из скрипта, в котором открыты, в дополнение к стандартным, другие дескрипторы:
#!/bin/bash
exec 3> myfile1
exec 6> myfile2
exec 7< myfile3
lsof -a -p $$ -d 0,1,2,3,6,7
Вот что получится, если этот скрипт запустить.
Просмотр дескрипторов файлов, открытых скриптом
Скрипт открыл два дескриптора для вывода (3
и 6
) и один — для ввода (7
). Тут же показаны и пути к файлам, использованных для настройки дескрипторов.
Подавление вывода
Иногда надо сделать так, чтобы команды в скрипте, который, например, может исполняться как фоновый процесс, ничего не выводили на экран. Для этого можно перенаправить вывод в /dev/null
. Это — что-то вроде «чёрной дыры».
Вот, например, как подавить вывод сообщений об ошибках:
ls -al badfile anotherfile 2> /dev/null
Тот же подход используется, если, например, надо очистить файл, не удаляя его:
cat /dev/null > myfile
Итоги
Сегодня вы узнали о том, как в сценариях командной строки работают ввод и вывод. Теперь вы умеете обращаться с дескрипторами файлов, создавать, просматривать и закрывать их, знаете о перенаправлении потоков ввода, вывода и ошибок. Всё это очень важно в деле разработки bash-скриптов.
В следующий раз поговорим о сигналах Linux, о том, как обрабатывать их в сценариях, о запуске заданий по расписанию и о фоновых задачах.
Уважаемые читатели! В этом материале даны основы работы с потоками ввода, вывода и ошибок. Уверены, среди вас есть профессионалы, которые могут рассказать обо всём этом то, что приходит лишь с опытом. Если так — передаём слово вам.
Часто возникает необходимость, чтобы скрипт командного интерпретатора Bash выводил результат своей работы. По умолчанию он отображает стандартный поток данных — окно терминала. Это удобно для обработки результатов небольшого объёма или, чтобы сразу увидеть необходимые данные.
В интерпретаторе можно делать вывод в файл Bash. Применяется это для отложенного анализа или сохранения массивного результата работы сценария. Чтобы сделать это, используется перенаправление потока вывода с помощью дескрипторов.
Стандартные дескрипторы вывода
В системе GNU/Linux каждый объект является файлом. Это правило работает также для процессов ввода/вывода. Каждый файловый объект в системе обозначается дескриптором файла — неотрицательным числом, однозначно определяющим открытые в сеансе файлы. Один процесс может открыть до девяти дескрипторов.
В командном интерпретаторе Bash первые три дескриптора зарезервированы для специального назначения:
Дескриптор | Сокращение | Название |
---|---|---|
0 | STDIN | Стандартный ввод |
1 | STDOUT | Стандартный вывод |
2 | STDERR | Стандартный вывод ошибок |
Их предназначение — обработка ввода/вывода в сценариях. По умолчанию стандартным потоком ввода является клавиатура, а вывода — терминал. Рассмотрим подробно последний.
1. Перенаправление стандартного потока вывода
Для того, чтобы перенаправить поток вывода с терминала в файл, используется знак «больше» (>).
#!/bin/bash
echo "Строка 1"
echo "Промежуточная строка" > file
echo "Строка 2" > file
Как результат, «Строка 1» выводится в терминале, а в файл file записывается только «Строка 2»:
Связано это с тем, что > перезаписывает файл новыми данными. Для того, чтобы дописать информацию в конец файла, используется два знака «больше» (>>).
#!/bin/bash
echo "Строка 1"
echo "Промежуточная строка" > file
echo "Строка 2" >> file
Здесь «Промежуточная строка» перезаписала предыдущее содержание file, а «Строка 2» дописалась в его конец.
Если во время использования перенаправления вывода интерпретатор обнаружит ошибку, то он не запишет сообщение о ней в файл.
#!/bin/bash
ls badfile > file2
echo "Строка 2" >> file2
В данном случае ошибка была в том, что команда ls не смогла найти файл badfile, о чём Bash и сообщил. Но вывелось сообщение в терминал, а не записалось в файл. Всё потому, что использование перенаправления потоков указывает интерпретатору отделять мух от котлет ошибки от основной информации.
Это особенно полезно при выполнении сценариев в фоновом режиме, где приходится предусматривать вывод сообщений в журнал. Но так как ошибки в него писаться не будут, нужно отдельно перенаправлять поток ошибок для того, чтобы выполнить их вывод в файл Linux.
2. Перенаправление потока ошибок
В командном интерпретаторе для обработки сообщений об ошибках предназначен дескриптор STDERR, который работает с ошибками, сформированными как от работы интерпретатора, так и самим скриптом.
По умолчанию STDERR указывает в то же место, что и STDOUT, хотя для них и предназначены разные дескрипторы. Но, как было показано в примере, использование перенаправления заставляет Bash разделить эти потоки.
Чтобы выполнить перенаправление вывода в файл Linux для ошибок, следует перед знаком«больше» указать дескриптор 2.
#!/bin/bash
ls badfile 2> errors
echo "Строка 1" > file3
echo "Строка 2" >> file3
В результате работы скрипта создан файл errors, в который записана ошибка выполнения команды ls, а в file3 записаны предназначенные строки. Таким образом, выполнение сценария не сопровождается выводом информации в терминал.
Пример того, как одна команда возвращает и положительный результат, и ошибку:
ls -lh test badtest 2> errors
Команда ls попыталась показать наличие файлов test и badtest. Первый присутствовал в текущем каталоге, а второй — нет. Но сообщение об ошибке было записано в отдельный файл.
Если возникает необходимость выполнить вывод команды в файл Linux, включая её стандартный поток вывода и ошибки, стоит использовать два символа перенаправления, перед которыми стоит указывать необходимый дескриптор.
ls -lh test test2 badtest 2> errors 1> output
Результат успешного выполнения записан в файл output, а сообщение об ошибке — в errors.
По желанию можно выводить и ошибки, и обычные данные в один файл, используя &>.
ls -lh test badtest &> output
Обратите внимание, что Bash присваивает сообщениям об ошибке более высокий приоритет по сравнению с данными, поэтому в случае общего перенаправления ошибки всегда будут располагаться в начале.
Временные перенаправления в скриптах
Если есть необходимость в преднамеренном формировании ошибок в сценарии, можно каждую отдельную строку вывода перенаправлять в STDERR. Для этого достаточно воспользоваться символом перенаправления вывода, после которого нужно использовать & и номер дескриптора, чтобы перенаправить вывод в STDERR.
#!/bin/bash
echo "Это сообщение об ошибке" >&2
echo "Это нормальное сообщение"
При выполнении программы обычно нельзя будет обнаружить отличия:
Вспомним, что GNU/Linux по умолчанию направляет вывод STDERR в STDOUT. Но если при выполнении скрипта будет перенаправлен поток ошибок, то Bash, как и полагается, разделит вывод.
Этот метод хорошо подходит для создания собственных сообщений об ошибках в сценариях.
Постоянные перенаправления в скриптах
Если в сценарии необходимо перенаправить вывод в файл Linux для большого объёма данных, то указание способа вывода в каждой инструкции echo будет неудобным и трудоёмким занятием. Вместо этого можно указать, что в ходе выполнения данного скрипта должно осуществляться перенаправление конкретного дескриптора с помощью команды exec:
#!/bin/bash
exec 1> testout
echo "Это тест перенаправления всего вывода"
echo "из скрипта в другой файл"
echo "без использования временного перенаправления"
Вызов команды exec запускает новый командный интерпретатор и перенаправляет стандартный вывод в файл testout.
Также существует возможность перенаправлять вывод (в том числе и ошибок) в произвольном участке сценария:
#!/bin/bash
exec 2> testerror
echo "Это начально скрипта"
echo "И это первые две строки"
exec 1> testout
echo "Вывод сценария перенаправлен"
echo "из с терминала в другой файл"
echo "но эта строка записана в файл ошибок" >&2
Такой метод часто применяется при необходимости перенаправить лишь часть вывода скрипта в другое место, например в журнал ошибок.
Выводы
Перенаправление в скриптах Bash, чтобы выполнить вывод в файл Bash, является хорошим средством ведения различных журналов, особенно в фоновом режиме.
Использование временного и постоянного перенаправлений в сценариях позволяет создавать собственные сообщения об ошибках для записи в отличное от STDOUT место.
Обнаружили ошибку в тексте? Сообщите мне об этом. Выделите текст с ошибкой и нажмите Ctrl+Enter.
Статья распространяется под лицензией Creative Commons ShareAlike 4.0 при копировании материала ссылка на источник обязательна .
����� 16. ���������������
�����/������
� ������� ��-��������� ������ ������� ��� «�����» — stdin (����������), stdout (�����) � stderr (����� ��������� �� ������� ��
�����). ���, � ����� ������ �������� �����, ����� ����
�������������. � ������ ������, ������
«���������������» �������� �������� ����� �� �����,
�������, ���������, �������� ��� ���� ���������� ����� � ��������
(��. ������ 3-1 � ������ 3-2) � �������� ��� �� ����
� ������ ����, �������, ��������� ��� ��������.
� ������ �������� ������ ������ ����������
�����. [1] ����������� ������ stdin, stdout � stderr — 0, 1 � 2, ��������������. ���
�������� �������������� ������, ����������� � 3 �� 9 ��������
����������. ������ �������������� ����������� ����� ���������
�������� ������, �������� �������� � ���� ������ �� stdin, stdout ��� stderr. [2] ��� �������� �������
������������ � ���������� ��������� ����� ������� ����������� �
���������������� � �������������� (��. ������ 16-1).
COMMAND_OUTPUT > # ��������������� stdout (������) � ����. # ���� ���� ������������, �� �� ��������, ����� -- ����������������. ls -lR > dir-tree.list # ������� ����, ���������� ������ ������ ���������. : > filename # �������� > ������� ���� "filename" �� ������� �����. # ���� �� ���������� �������� ����� �� ������������, # �� ��������� ����� ���� � ������� ������ (��� �� ������ ���� ������� 'touch'). # ������ : ��������� ����� � ���� ����������������, �� ������ ������. > filename # �������� > ������� ���� "filename" �� ������� �����. # ���� �� ���������� �������� ����� �� ������������, # �� ��������� ����� ���� � ������� ������ (��� �� ������ ���� ������� 'touch'). # (��� �� ���������, ��� � ���� -- ": >", �� ���� ������� ���������������� # � ��������� ��������� ���������.) COMMAND_OUTPUT >> # ��������������� stdout (������) � ����. # ������� ����� ����, ���� �� ������������, ����� -- ���������� � ����� �����. # ������������ ������� ��������������� # (����������� ������ �� ������, � ������� ��� �����������): # -------------------------------------------------------------------- 1>filename # ��������������� ������ (stdout) � ���� "filename". 1>>filename # ��������������� ������ (stdout) � ���� "filename", ���� ����������� � ������ ����������. 2>filename # ��������������� stderr � ���� "filename". 2>>filename # ��������������� stderr � ���� "filename", ���� ����������� � ������ ����������. &>filename # ��������������� stdout � stderr � ���� "filename". #============================================================================== # ��������������� stdout, ������ ��� ����� ������. LOGFILE=script.log echo "��� ������ ����� �������� � ���� "$LOGFILE"." 1>$LOGFILE echo "��� ������ ����� ��������� � ����� ����� "$LOGFILE"." 1>>$LOGFILE echo "��� ������ ���� ����� ��������� � ����� ����� "$LOGFILE"." 1>>$LOGFILE echo "��� ������ ����� �������� �� ����� � �� ������� � ���� "$LOGFILE"." # ����� ������ ������, ��������� ��������������� ������������� "������������". # ��������������� stderr, ������ ��� ����� ������. ERRORFILE=script.errors bad_command1 2>$ERRORFILE # ��������� �� ������ ��������� � $ERRORFILE. bad_command2 2>>$ERRORFILE # ��������� �� ������ ��������� � ����� $ERRORFILE. bad_command3 # ��������� �� ������ ����� �������� �� stderr, #+ � �� ������� � $ERRORFILE. # ����� ������ ������, ��������� ��������������� ����� ������������� "������������". #============================================================================== 2>&1 # ���������������� stderr �� stdout. # ��������� �� ������� ���������� ���� ��, ���� � ����������� �����. i>&j # ���������������� ���� � ������������ i � j. # ����� � ���� � ������������ i ���������� � ���� � ������������ j. >&j # ���������������� ���� � ������������ 1 (stdout) � ���� � ������������ j. # ����� �� stdout ���������� � ���� � ������������ j. 0< FILENAME < FILENAME # ���� �� �����. # ������ ������� ">", ����� ����������� � ���������� � ���. # # grep search-word <filename [j]<>filename # ���� "filename" ����������� �� ������ � ������, � ����������� � ������������ "j". # ���� "filename" �����������, �� �� ���������. # ���� ���������� "j" �� ������, ��, ��-���������, ������� ���������� 0, stdin. # # ��� ���� �� ���������� ����� -- ������ � ���������� ������� � �����. echo 1234567890 > File # �������� ������ � ���� "File". exec 3<> File # ������� "File" � ������� � ������������ 3. read -n 4 <&3 # ��������� 4 �������. echo -n . >&3 # �������� ������ �����. exec 3>&- # ������� ���������� 3. cat File # ==> 1234.67890 # ������������ ������, �� � ������! | # �������� (�����). # ������������� �������� ��� ����������� ������ � ���� �������. # ������ �� ">", �� �� ����� ���� -- ����� ��������. # ������������ ��� ����������� ������, ���������, ������ � �������� � ���� ������� (��������). cat *.txt | sort | uniq > result-file # ���������� ���� ������ .txt �����������, ��������� ������������� ������, # ��������� ����������� � ����� "result-file".
�������� ��������������� �/��� ��������� ����� ���������������
� ����� ��������� ������.
command < input-file > output-file command1 | command2 | command3 > output-file
��. ������ 12-23 � ������ A-17.
����������� ��������������� ���������� ������� � ����
����.
ls -yz >> command.log 2>&1 # ��������� � �������� ����� "yz" � ������� "ls" ����� �������� � ���� "command.log". # ��������� stderr ������������� � ����.
�������� ������������ ������
- n<&-
-
������� ���������� �������� ����� n.
- 0<&-, <&-
-
������� stdin.
- n>&-
-
������� ���������� ��������� ����� n.
- 1>&-, >&-
-
������� stdout.
�������� �������� ��������� ����������� �������� ������. ��
���� ������� � �������� ���������. ����� �������������
������������ ������������ — �������� �� ����� �������� ���������
��������.
# � �������� ���������� ������ stderr. exec 3>&1 # ��������� ������� "���������" stdout. ls -l 2>&1 >&3 3>&- | grep bad 3>&- # ������� �����. 3 ��� 'grep' (�� �� ��� 'ls'). # ^^^^ ^^^^ exec 3>&- # ������ ������� ��� ��� ���������� ����� ��������. # ������� S.C.
�������������� �������� � ��������������� �����/������ ��
������� � ���������� D.
16.1. � ������� ������� exec
������� exec <filename �������������� ����
�� stdin �� ����. � ����� ������� ����
����, ������ stdin (������ ��� ����������), �����
������������� �� ����� �����. ��� ���� ����������� ������
���������� �����, ������ �� �������, � ������������� ������
��������� ������ � ������� sed �/��� awk.
������ 16-1. ��������������� stdin � ������� exec
#!/bin/bash # ��������������� stdin � ������� 'exec'. exec 6<&0 # ������� �����. #6 �� ����������� ������ (stdin). # �������� stdin. exec < data-file # stdin ���������� ������ "data-file" read a1 # �������� ������ ������ �� "data-file". read a2 # �������� ������ ������ �� "data-file." echo echo "��������� ������ ���� ��������� �� �����." echo "-----------------------------------------" echo $a1 echo $a2 echo; echo; echo exec 0<&6 6<&- # ����������������� stdin �� �����. #6, ��� �� ��� �������������� ��������, #+ � �����. #6 ����������� ( 6<&- ) ���������� ��� ��� ������ ���������. # # <&6 6<&- ���� ��� �� ���������. echo -n "������� ������ " read b1 # ������ ������� "read", ��� � ��������� �������, ��������� ������ � �������� stdin. echo "������, �������� �� stdin." echo "--------------------------" echo "b1 = $b1" echo exit 0
����������, ����������� exec >filename ��������������
����� �� stdout � �������� ����. ����� �����,
���� ����� �� ������, ������� ������ ������������ �� stdout, ������ ��������� � ����
����.
������ 16-2. ��������������� stdout � ������� exec
#!/bin/bash # reassign-stdout.sh LOGFILE=logfile.txt exec 6>&1 # ������� �����. #6 �� stdout. # �������� stdout. exec > $LOGFILE # stdout ���������� ������ "logfile.txt". # ----------------------------------------------------------- # # ���� ����� �� ������, � ������ �����, ������������ � ���� $LOGFILE. echo -n "Logfile: " date echo "-------------------------------------" echo echo "����� ������� "ls -al"" echo ls -al echo; echo echo "����� ������� "df"" echo df # ----------------------------------------------------------- # exec 1>&6 6>&- # ������������ stdout � ������� �����. #6. echo echo "== stdout ������������� � �������� ��-��������� == " echo ls -al echo exit 0
������ 16-3. ������������� ���������������
���������, stdin � stdout, � ������� �������
exec
#!/bin/bash # upperconv.sh # �������������� �������� �� ������� ����� � ������� �������. E_FILE_ACCESS=70 E_WRONG_ARGS=71 if [ ! -r "$1" ] # ���� �������� ��� ������? then echo "���������� ��������� �� ��������� �����!" echo "������� �������������: $0 input-file output-file" exit $E_FILE_ACCESS fi # � ������, ���� ������� ���� ($1) �� ����� #+ ��� ���������� ����� ���� ��. if [ -z "$2" ] then echo "���������� ������ �������� ����." echo "������� �������������: $0 input-file output-file" exit $E_WRONG_ARGS fi exec 4<&0 exec < $1 # ��������� ���� �� �������� �����. exec 7>&1 exec > $2 # ��������� ����� � �������� ����. # ��������������, ��� �������� ���� �������� ��� ������ # (�������� ��������?). # ----------------------------------------------- cat - | tr a-z A-Z # ������� � ������� ������� # ^^^^^ # ������ �� stdin. # ^^^^^^^^^^ # ������ � stdout. # ������, � stdin � stdout ���� ��������������. # ----------------------------------------------- exec 1>&7 7>&- # ������������ stdout. exec 0<&4 4<&- # ������������ stdin. # ����� ��������������, ��������� ������ ��������� �� stdout, ���� � ��������� �������. echo "������� �� "$1" ������������� � ������� �������, ��������� ������� � "$2"." exit 0
Ну вот к примеру :
/usr/bin/php -f ffmpeg.php
Как мне ошибки записать в файл?
Так же вопрос ещё в том чтобы если данные выводятся не сразу — в файл так же добавлялись эти данные.
- ubuntu
- консоль
- логирование
задан 17 мар 2017 в 13:14
0
1 ответ
Используйте перенаправление вывода 2>
/usr/bin/php -f ffmpeg.php 2> error.log
ответ дан 17 мар 2017 в 13:17
Mikhail VaysmanMikhail Vaysman
14.2k1 золотой знак20 серебряных знаков31 бронзовый знак
4
-
Ну так вот я так и делаю. На выходе файл создается, но пустой
17 мар 2017 в 13:24
-
Разобрался)) Я же чуть чуть другую команду запускаю и там было у меня ffmpeg -f Поменял на ffmpeg -i
17 мар 2017 в 13:27
-
А нет.. Не разобрался.. Если указываю -i — то в log пишется тупо phpinfo, а если вообще убираю — опять файл пустой. В консоли выводится всё.
17 мар 2017 в 13:31
-
Уже исправил и ответил.
17 мар 2017 в 13:35
0
1
Здравствуйте, подскажите пожалуйста, есть bash скрипт и нужно писать в лог, успешно или нет отработала команда или нет в таком формате:
«Команда отработала успешно»
либо
«Команда завершилась с ошибкой». И далее перенаправлять поток ошибок в этот же лог файл
Все работает, за исключением одного момента. У меня сейчас получается сначала идет перенаправление потока ошибок в файл, а далее уже вывод сообщения «Команда завершилась с ошибкой». Не могу понять, как сделать наоборот, чтобы сначала выводилось сообщение, а потом уже сама ошибка
Вот мой скрипт:
# лог файл
LOG_FILE=/log/my.log
# выполняем нужную нам команду
ls -l skldjflkjsdf 2>> $LOG_FILE
# пишем в лог, успешно завершилась команда или нет
if [ $? -eq 0 ]; then
echo "Команда отработала успешно" >> $LOG_FILE
else echo "завершилась ошибкой" > $LOG_FILE
fi