Stderr linux где смотреть

Обновлено: 03.07.2024

Имеется Docker-образ, в который включены NGINX и PHP-FPM, плюс Supervisor для их запуска.

В этот же образ включён код PHP-приложения, которое пишет ошибки PHP в /dev/stderr , как задано в php.ini :

Где проблема? В Docker? Kubernetes? Linux в контейнере?

Подключаемся в под:

kk -n bttrm-application-dev-ns exec -ti bttrm-application-dev-deploy-d4d8db79-lks87 bash kk -n bttrm-application-dev-ns logs -f bttrm-application-dev-deploy-d4d8db79-lks87 [17-Feb-2020 12:29:03] NOTICE: [pool www] child 2595 exited with code 0 after 681.391780 seconds from start [17-Feb-2020 12:29:03] NOTICE: [pool www] child 2605 started

Пробуем написать в /dev/stderr :

В логах по-прежнему пусто.

lrwxrwxrwx 1 root root 15 Feb 13 15:56 /dev/stdout -> /proc/self/fd/1 lrwxrwxrwx 1 root root 15 Feb 13 15:56 /dev/stderr -> /proc/self/fd/2

А куда смотрят /proc/self/fd/1 и 2 ?

lrwx------ 1 nobody nobody 64 Feb 17 12:31 /proc/self/fd/1 -> /dev/pts/0 lrwx------ 1 nobody nobody 64 Feb 17 12:31 /proc/self/fd/2 -> /dev/pts/0

Значит всё, что шлётся в дескриптор /dev/stdout отправляется на /proc/self/fd/1 , а тот, в свою очередь, на /dev/pts/0 , который является нашей консолью, а не отправляется в STDOUT контейнера Docker и, соответственно, не попадает к демону Docker, который сложил бы лог на хост-машину.

Docker STDOUT and STDERR

А что у нас происходит при запуске процесса в контейнере самим Docker?

Проверим дексрипторы процессов в нашем контейнере.

PID 1, supervisor который запускает NGINX и PHP-FPM:

l-wx------ 1 nobody nobody 64 Feb 17 13:24 /proc/1/fd/1 -> pipe:[21223649] l-wx------ 1 nobody nobody 64 Feb 17 13:24 /proc/1/fd/2 -> pipe:[21223650]

pipe:[21223650] шлёт на хост-ноду, где мы видим логи в kubectl logs (или docker logs ).

Находим процессы NGINX и PHP-FPM:

8 nobody 0:00 nginx: master process nginx -g daemon off; 9 nobody 0:00 php-fpm: master process (/etc/php7/php-fpm.conf) l-wx------ 1 nobody nobody 64 Feb 17 13:37 /proc/8/fd/1 -> pipe:[21224126] l-wx------ 1 nobody nobody 64 Feb 17 13:37 /proc/8/fd/2 -> pipe:[21224127]

Тоже в pipe , тоже всё хорошо. И логи NGINX в kubectl logs мы тоже видим.

lrwx------ 1 nobody nobody 64 Feb 17 13:33 /proc/9/fd/1 -> /dev/null l-wx------ 1 nobody nobody 64 Feb 17 13:24 /proc/9/fd/2 -> pipe:[21224131]

STDOUT/ERR для Supervisor:

kk -n bttrm-application-dev-ns logs -f bttrm-application-dev-deploy-656d9dfb69-zf6zc 2020-02-17 13:24:07,504 INFO supervisord started with pid 1 [17-Feb-2020 13:24:08] NOTICE: ready to handle connections 2020-02-17 13:24:09,535 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2020-02-17 13:24:09,535 INFO success: php-fpm entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) [17-Feb-2020 13:35:00] NOTICE: [pool www] child 13 exited with code 0 after 651.735356 seconds from start

В системах Linux и Unix существуют стандартные входной (STDIN) и выходные (STDOUT, STDERR) потоки (каналы). Далее рассмотрим подробнее каждый из них.

В рамках терминала канал STDIN считывает входные данные, а каналы STDOUT и STDERR выводят выходные данные на экран.

Управление потоками

Для перенаправления каналов в терминале, применяют определенные символы. Рассмотрим каждый из них на примере команды поиска системных файлов, которые содержат слово - core. Все найденные файлы будут формироваться в поток STDOUT. Те найденные файлы, к которым у обычного пользователя нет доступа будут попадать в STDERR.

find / -name core > /tmp/testfile

В файл /tmp/testfile попадет список путей ко всем найденным файлам, а список ошибок отобразится в терминале.

Запись в файл

Запись STDOUT в файл

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

find / -name core >> /tmp/testfile

В конец файла /tmp/testfile попадет список путей ко всем найденным файлам, а список ошибок отобразится в терминале.

find / -name core >& /tmp/testfile

С помощью составного символа - >& мы объединяем стандартный выходной поток с выходным потоком ошибок. В файл /tmp/testfile попадет список путей ко всем найденным файлам и список ошибок.

find / -name core 2> /tmp/testfile

В файл /tmp/testfile попадет список ошибок, а список найденных файлов, будет выведен в терминале.

Вывод STDERR

Вывод STDERR

Вывод потоков можно комбинировать и распределять по разным местам. Например, выведем список найденных файлов в /tmp/testfile , а список ошибок отбросим, перенаправив их в /dev/null .

find / -name core > /tmp/testfile 2> /dev/null

Перенаправление потоков

Перенаправление потоков

Для примера, выведем в консоли отдельные процессы системы с именем - chrome .

ps | grep chrome

Здесь результат выполнения команды ps передается в роли входных данных для команды grep , в которых она ищет совпадения с именем chrome .

Заключение

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

Favorite

Добавить в избранное

Главное меню » Linux » Ввод, вывод и перенаправление ошибок в Linux

(1 оценок, среднее: 5,00 из 5)

Ввод, вывод и перенаправление ошибок в Linux

Е сли вы знакомы с основными командами Linux, вам также следует изучить концепцию перенаправления ввода-вывода.

Вы уже знаете, как работает команда в Linux. Она принимает вход и дает вам выход. Здесь есть несколько игроков. Позвольте нам рассказать вам о них.

Stdin, stdout и stderr

Когда вы запускаете команду Linux, в ней играют роль три потока данных:

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

Думайте об этом как о струе воды. Вам нужен источник для воды, например, кран. Вы подключаете к нему трубу и можете хранить ее в ведре (файле) или поливать растения (распечатывать). Вы также можете подключить его к другому крану, если это необходимо. По сути, вы перенаправляете воду.

Позвольте нам показать, как работает перенаправление и как вы можете его использовать.

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

Первой и самой простой формой перенаправления является перенаправление вывода, также называемое перенаправлением stdout.

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

Например, позвольте нам сохранить вывод команды ls в файл с именем output.txt:

Выходной файл создается заранее

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

Вы заметили, что включение output.txt существует ? Мы сознательно выбрали этот пример, чтобы показать вам это.

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

Читать Избавьтесь от проблем с сетевым подключением в SSH с помощью Mosh

Добавить вместо удаления

Одна из часто игнорируемых проблем заключается в том, что если вы перенаправляете файл, который уже существует, оболочка сначала удалит ( замкнет ) файл. Это означает, что существующее содержимое выходного файла будет удалено и заменено выводом команды.

Вы можете добавить вместо перезаписи, используя >> синтаксис перенаправления.

Вы можете запретить забивание в текущем сеансе оболочки, используя: set -C

Зачем вам перенаправлять стандартный вывод? Вы можете сохранить выходные данные для дальнейшего использования и проанализировать их позже. Это особенно полезно, когда вывод команды слишком велик и занимает весь экран. Это как собирать бревна.

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

Прежде чем вы увидите перенаправление stdin, вы должны узнать о перенаправлении канала. Это более распространено, и, вероятно, вы будете часто его использовать.

При перенаправлении канала стандартный вывод команды отправляется на стандартный ввод другой команды.

Позвольте нам показать вам практический пример. Скажем, вы хотите посчитать количество видимых файлов в текущем каталоге. Вы можете использовать ls -1 (это цифра один, а не буква L) для отображения файлов в текущем каталоге:

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

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

Вы увидите результат последней команды в конвейере. Это очевидно, потому что вывод предыдущей команды (команд) подается на следующую команду (команды) вместо перехода на экран.

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

Помните, что stdout/stdin это кусок данных, а не имена файлов

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

Например, если вы используете команду find, чтобы найти все файлы, оканчивающиеся на .txt, вы не можете передать ее через канал для перемещения найденных файлов в новый каталог, а не так:

Читать Управление ресурсами системы с помощью команды Ulimit

Вот почему вы часто будете видеть команду find, используемую в сопряжении с командой exec или xargs. Эти специальные команды «преобразуют текст с кучей имен файлов в имя файла», которые могут быть переданы в качестве аргумента.

Перенаправление ввода

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

Вы не увидите, что stdin часто используется. Это потому, что большинство команд Linux принимают имена файлов в качестве аргумента и, следовательно, перенаправление stdin часто не требуется.

Возьмите это к примеру:

Приведенная выше команда могла быть просто заголовком filename.txt (без <).

Дело не в том, что перенаправление stdin совершенно бесполезно. Некоторые команды полагаются на это. Возьмите команду tr, например. Эта команда может многое, но в приведенном ниже примере она преобразует входной текст из нижнего в верхний регистр:

На самом деле, использование stdin рекомендуется по конвейеру, чтобы избежать ненужного использования команды cat.

Например, многие люди используют приведенный выше пример с cat, а затем используют tr на нем. Честно говоря, здесь нет необходимости использовать cat.

Объединить перенаправления

Вы можете комбинировать перенаправление stdin, stdout и pipe в соответствии с вашими потребностями.

Например, приведенная ниже команда перечисляет все файлы .txt в текущем каталоге, а затем подсчитывает эти файлы .txt и сохраняет выходные данные в новый файл.

Перенаправление ошибок

Но как вы различаете stdout и stderr, когда они оба являются потоком выходных данных? По их идентификатору потока (также называется дескриптором файла).

Поток данных Идентификатор потока
stdin
stdout 1
stderr 2

По умолчанию, когда вы используете выходной символ перенаправления >, это фактически означает 1>. Словом, вы говорите, что здесь выводится поток данных с ID 1.

Примеры перенаправления Stderr

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

Это было просто. Давайте сделаем это немного более сложным (и полезным):

В приведенном ниже примере мы сначала отправляем stderr (с 2 >>) в файл комбинированный .txt в режиме добавления. Затем стандартный вывод (с >>) отправляется в тот же файл в режиме добавления.

Давайте возьмем предыдущий пример и на этот раз используем 2>&1 для перенаправления как stdout, так и stderr в один и тот же файл.

Имейте в виду, что вы не можете использовать 2>>&1, думая об использовании его в режиме добавления. 2>&1 уже переходит в режим добавления.

Резюме

  • Есть три потока данных. Один вход, stdin (0) и два потока выходных данных stdout (1) и stderr (2).
  • Клавиатура является стандартным устройством ввода, а экран является устройством вывода по умолчанию.
  • Перенаправление вывода используется с > или >> (для режима добавления).
  • Перенаправление ввода используется с <.
  • Stderr может быть перенаправлен с помощью 2> или 2>>.
  • Stderr и stdout можно комбинировать, используя 2>&1.

Надеюсь, вам понравилось эта подробная статья по перенаправлению в Linux. Если у вас все еще есть сомнения или у вас есть предложения по улучшению этой статьи, сообщите нам об этом в разделе комментариев.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.


Потоки объединяются в две точки

У потоков данных, как и у водных потоков, есть два конца. У них есть источник и отток. Какую бы команду Linux вы ни использовали, она обеспечивает один конец каждого потока. Другой конец определяется оболочкой, запустившей команду. Этот конец будет подключен к окну терминала, подключен к каналу или перенаправлен к файлу или другой команде в соответствии с командной строкой, запустившей команду.

Стандартные потоки Linux

Потоки обрабатываются как файлы

Каждому файлу, связанному с процессом, присваивается уникальный номер для его идентификации. Это известно как файловый дескриптор. Всякий раз, когда требуется выполнить действие с файлом, дескриптор файла используется для идентификации файла.

Эти значения всегда используются для stdin, stdout и stderr:

0: стандартный ввод
1: стандартный вывод
2: stderr

Реакция на каналы и перенаправления

Аналогичным образом, говоря о stdin, stdout и stderr, удобно использовать общепринятую аксиому о том, что процесс не знает и не заботится о том, где завершаются его три стандартных потока. Должен ли процесс заботиться о том, идет ли его вывод на терминал или перенаправляется в файл? Может ли он даже сказать, идет ли его ввод с клавиатуры или передается в него из другого процесса?

Мы можем очень легко увидеть это изменение в поведении. Попробуйте эти две команды:

ls вывод в окне терминала

Команда ls ведет себя иначе, если ее вывод (stdout) передается другой команде. Это ls, который переключается на вывод в один столбец, это не преобразование, выполняемое cat. И ls делает то же самое, если его вывод перенаправляется:


Перенаправление stdout и stderr

Введите следующий текст в редактор и сохраните его в файл с именем error.sh.

Сделайте скрипт исполняемым с помощью этой команды:

Запустите сценарий с помощью этой команды:

Мы видим, что оба потока вывода, stdout и stderr, были отображены в окнах терминала.

Вывод из стандартного ввода был перенаправлен в файл, как и ожидалось.

Давайте попробуем снова провести наш тест, и на этот раз мы будем использовать 2>:

Перенаправление как stdout, так и stderr

Да мы можем. Эта команда направит stdout в файл с именем capture.txt и stderr в файл с именем error.txt.

Проверим содержимое каждого файла:

Перенаправление stdout и stderr в один файл

Мы можем добиться этого с помощью следующей команды:

Давайте разберемся с этим.

Давайте проверим файл capture.txt и посмотрим, что в нем.

И потоки stdout, и потоки stderr были перенаправлены в один файл назначения.

Чтобы вывод потока перенаправлялся и незаметно отбрасывался, направьте вывод в / dev / null.

Обнаружение перенаправления в сценарии

Мы обсудили, как команда может определить, перенаправляется ли какой-либо из потоков, и может соответствующим образом изменить свое поведение. Можем ли мы сделать это в наших собственных сценариях? Да мы можем. И это очень простой метод для понимания и применения.

Введите следующий текст в редактор и сохраните его как input.sh.

Используйте следующую команду, чтобы сделать его исполняемым:

Проверь это - Как играть в World Of Warcraft на Linux

Если stdin подключен к окну терминала, тест подтвердится. Если stdin подключен к файлу или каналу, тест завершится неудачно.

Мы можем использовать любой удобный текстовый файл для генерации входных данных в скрипт. Здесь мы используем файл dummy.txt.

Сценарий распознает, что его ввод передается по конвейеру. Или, точнее, он еще раз распознает, что поток stdin не подключен к окну терминала.

Запустим скрипт без каналов и перенаправлений.

Поток stdin подключен к окну терминала, и сценарий сообщает об этом соответственно.

Чтобы проверить то же самое с выходным потоком, нам нужен новый скрипт. Введите в редактор следующее и сохраните как output.sh.

Используйте следующую команду, чтобы сделать его исполняемым:

Единственное существенное изменение в этом скрипте - это тест в квадратных скобках. Мы используем цифру 1 для обозначения файлового дескриптора для stdout.

Давай попробуем. Мы пропустим вывод через cat.

Сценарий распознает, что его вывод не идет напрямую в окно терминала.

Мы также можем протестировать скрипт, перенаправив вывод в файл.

В окне терминала нет вывода, мы молча возвращаемся в командную строку. Как и следовало ожидать.

Мы можем заглянуть внутрь файла capture.txt, чтобы увидеть, что было захвачено. Для этого используйте следующую команду.

Опять же, простой тест в нашем скрипте обнаруживает, что поток stdout не отправляется непосредственно в окно терминала.

Если мы запустим скрипт без каналов или перенаправлений, он должен обнаружить, что стандартный вывод доставляется непосредственно в окно терминала.

И это именно то, что мы видим.

Потоки сознания

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

Читайте также: