Как стать автором
Обновить

Комментарии 7

tl;dr stdout/stderr не умеют seek и возвращают ошибку, которую mariadb не может обработать. На то, чтобы это понять, ушло два дня.

Убогая статья о том, как диагностировать плохо забитые гвозди микроскопом. В первом же куске вывода написано, что stderr не поддерживает seek(). Все, на этом можно было закончить.

По-моему в ошибке ясно написано, что случилось. Can't seek in file '/dev/stderr' (Errcode: 29 "Invalid seek")

Мускуль хочет сделать seek (вероятнее всего, на конец файла), а /dev/stderr справедливо возражает, что конца ошибкам нет.

Что делать? Писать патч, потому что весь интернет уверенно говорит, что нельзя из-за кривости мускуля. И дело тут не в правах.

Альтернативно - запускать sidecart, который будет реэкспортировать локальный ротируемый файл в stderr.

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

Статья оставляет желать лучшего. Местами полно голословных утверждений и неправильных выводов.

Однако тут есть странность: пользователю без root-прав все равно нужен tty для перенаправления вывода процесса (а, следовательно, и Docker-логов) в stdio.

TTY нужен только для взаимодействия с пользователем в интерактивном режиме, он не является обязательной составляющей для запуска приложений-демонов, вроде СУБД.

Без TTY внутри контейнера /proc/self/fd/{0..2} начинают ссылаться не на /dev/pts/0, а на pipe, который докер-демон на хосте сам читает и раскладывает в файлы с логами:

В Alpine Linux писать в stdio могут только члены группы tty.

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

Вот только entrypoint различных СУБД, например mysql и postgres, запускаются под пользователем root. Это нужно, чтобы перед запуском непосредственно самого приложения исправить владельца папки с файлами БД и конфигами, а уже затем выполнить запуск СУБД с помощью su или sudo.

И тут действительно можно столкнуться с issue, на которое ссылается автор - без TTY владельцем pipe будет тот пользователь, под которым был запущен корневой процесс в контейнере, т.е. root. И так как это pipe, а не файл, к нему нельзя применить chown или chmod. Поэтому приходится использовать обходной вариант с TTY и добавлением пользователя в группу tty либо выполнением chmod o+g /dev/pts/0

Специальный Bash-скрипт может извлекать эти обычные файлы из запущенного контейнера с помощью команды копирования — docker cp

Ага, по пути еще и изобретать свой logrotate вместо того, чтобы создать issue в репозиторий MariaDB.

Гораздо быстрее скачать исходники mariadb и посмотреть в исходный код в котором происходит ошибка ( файл sql/log.cc ) Более того, легко увидеть, что в случае pipe ситуация обрабатывается и в pipe логи писать можно.

is_fifo = my_stat(log_file_name, &f_stat, MYF(0)) &&
MY_S_ISFIFO(f_stat.st_mode);
...
if (is_fifo)
seek_offset= 0;
else if ((seek_offset= mysql_file_tell(file, MYF(MY_WME))))
goto err;

Далее, можно найти feature request для этого в жире mariadb https://jira.mariadb.org/browse/MDEV-6870 и создать подобный для character device, либо написать патч самому, либо извернуться и писать логи в pipe и настроить rsyslog, чтобы данные из пайпа отправлять куда нравится.

Спасибо за дополнение!

Зарегистрируйтесь на Хабре, чтобы оставить комментарий