Bad file descriptor в журнале службы
Сообщение Bad file descriptor (номер 9, EBADF) означает обращение к дескриптору, который закрыт или никогда не был открыт. У служб это обычно дефект программы, но есть и характерный случай: неверная работа с переданными сокетами.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Программа неверно работает с переданными дескрипторами
При сокет-активации дескрипторы приходят начиная с номера 3. Программа, рассчитывающая на другой номер или закрывающая их, получает эту ошибку.
-
Дефект в программе
Двойное закрытие дескриптора или обращение после закрытия. Это ошибка в коде, а не в настройке.
-
Служба потеряла дескриптор при перезагрузке настроек
Часть программ переоткрывает файлы при перезагрузке настроек. Ошибка после reload указывает именно на это.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Когда и при каких операциях возникает ошибка.
journalctl -u myapp.service -n 40 --no-pager | grep -i "bad file"Получает ли служба дескрипторы извне.
systemctl show myapp.service -p Sockets -p StandardInputРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- При сокет-активации дескрипторы приходят начиная с номера 3. Программа, рассчитывающая на другой номер или закрывающая их, получает эту ошибку.
- Как проверить
-
Посмотрите, как настроена активация.
systemctl show myapp.service -p Sockets systemctl list-sockets --no-pager | grep myapp
- Как исправить
- Либо используйте программу с поддержкой передачи дескрипторов, либо откажитесь от сокет-активации.
- Почему происходит
- Двойное закрытие дескриптора или обращение после закрытия. Это ошибка в коде, а не в настройке.
- Как проверить
-
Посмотрите журнал и частоту сообщений.
journalctl -u myapp.service -n 40 --no-pager | grep -ci "bad file descriptor"
- Как исправить
- Разбирайтесь с программой. Если она сторонняя, стоит сообщить разработчикам с фрагментом журнала.
- Почему происходит
- Часть программ переоткрывает файлы при перезагрузке настроек. Ошибка после reload указывает именно на это.
- Как проверить
-
Сопоставьте время сообщения и перезагрузки настроек.
journalctl -u myapp.service -n 40 --no-pager | grep -iE "reload|bad file"
- Как исправить
- Используйте перезапуск вместо перезагрузки настроек, если программа не умеет её корректно обрабатывать.
Пример вывода
Программа обращается к закрытому дескриптору. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
myapp[1200]: error: read on socket 3: bad file descriptor
myapp[1200]: warn: reconnecting listener
systemd[1]: myapp.service: Main process exited, code=exited, status=1/FAILURE
Связанные ошибки
- Служба не получает сокет при сокет-активации Сокет активен, служба запускается, но не находит переданный дескриптор. Разбор: Accept, FileDescriptorName, соответствие имён.
- status=202/FDS в systemd Код 202/FDS: systemd не смог закрыть лишние файловые дескрипторы или настроить переданные. Причины и проверка.
- status=208/STDIN в systemd Код 208/STDIN: не удалось настроить стандартный ввод службы. Обычно дело в StandardInput=tty или в отсутствующем файле.
- File exists при создании файла или сокета Ошибка 17: объект уже существует. Разбор для сокетов, файлов блокировки и каталогов службы.
- Argument list too long в службе или скрипте Список аргументов слишком длинный: подстановка имён файлов дала тысячи аргументов. Как переписать вызов.
- Could not open file и cannot open shared object file Программа не может открыть файл или библиотеку: путь, права, отсутствующая зависимость сборки, изоляция.
- Device or resource busy при операции с файлом Ошибка 16: файл или устройство заняты. Разбор для точек монтирования, устройств и файлов конфигурации.
- MySQL: Can't connect to local server through socket Клиент не находит unix-сокет MySQL: сервер не запущен, путь к сокету другой, каталог в /run не создан.
Источники
- read(2): ошибка EBADF
-
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено программой без поддержки переданных сокетов при сокет-активации.