Вывод ошибок скрипта в файл

Время на прочтение
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-скриптам, мы говорили о параметрах командной строки и ключах. Наша сегодняшняя тема — ввод, вывод, и всё, что с этим связано.

image

Вы уже знакомы с двумя методами работы с тем, что выводят сценарии командной строки:

  • Отображение выводимых данных на экране.
  • Перенаправление вывода в файл.

Иногда что-то надо показать на экране, а что-то — записать в файл, поэтому нужно разобраться с тем, как в 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 License

Статья распространяется под лицензией 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
      # ���������������� ���� � ������������ ij.
      # ����� � ���� � ������������ 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
  • консоль
  • логирование

Mikhail Vaysman's user avatar

задан 17 мар 2017 в 13:14

Shevtsov Eugene's user avatar

0

1 ответ

Используйте перенаправление вывода 2>

/usr/bin/php -f ffmpeg.php 2> error.log

ответ дан 17 мар 2017 в 13:17

Mikhail Vaysman's user avatar

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

Понравилась статья? Поделить с друзьями:
  • Вывод ошибок в файле htaccess
  • Вывод ошибки для 1 страницы
  • Вывести сообщение с помощью команды echo в канал ошибок
  • Вывести на форму сообщение об ошибке
  • Вывести все ошибки скриптов php