У меня возникла ошибка, из-за которой файл конфигурации для некоторого приложения не был подключен должным образом, поэтому, чтобы попытаться изолировать проблемную строку файла, я скопировал старое содержимое в новый файл по несколько строк за раз.
В конце концов я сделал точную копию файла, но старая все равно не работала, а вот новая работала отлично.
Более того, если я использую mv
команду для перемещения файла из того места, где он хранится, в то место, где он должен быть, это приводит к ошибкам. Если я использую команду cp
для копирования файла в то место, где он должен быть, ошибок не возникает.
Очевидно, что такие вещи, как diff
, file
, или ls -l
, не показывают никаких различий между двумя файлами, поскольку один является копией другого,поскольку cp
делает точную копию файла.
Я не могу поделиться слишком большой информацией о файле, потому что это рабочая вещь. Суть в том, что команды cp fileA fileB
и mv fileA fileB
создают "другой" файлB. Моя лучшая догадка - какой-то атрибут супернизкого уровня из файлаB остается позади во время cp
(даже cp -p
производит то же самое поведение).
Чем mv отличается от cp в отношении точного содержимого результирующего файла?
ИЗМЕНИТЬ: С ls -l
:
-rw-r--r--. 1 root root 3389 Aug 8 22:53 fileA
-rw-r--r--. 1 root root 3389 Aug 8 23:03 fileB
EDIT: Приложение — mysql, файл — файл .cnf, и элемент в этом файле конфигурации, который особенно интересен, — это имя двоичного журнала, используемого в репликации базы данных master-slave. «Ошибка» — «вы не используете двоичное ведение журнала», поскольку двоичного журнала нет, поскольку этот элемент никогда не «читался» mysql.
Сначала я подумал, что в файле конфигурации есть синтаксическая ошибка, из-за которой весь файл не считывается, что и привело к тому, что мне пришлось вручную пересоздать его, скопировав блоки текста.
EDIT: К чему-то приближаемся... Наконец-то что-то новое в файлах.
ls -lZ
-rw-r--r--. root root unconfined_u:object_r:user_home_t:s0 server.cnf.bad
-rw-r--r--. root root unconfined_u:object_r:mysqld_etc_t:s0 server.cnf.good
решение1
TL;DR: в системе, гдеSELinuxиспользуется, файлы, используемые системой (например, демоны), следует копировать или перемещать с помощью cp -aZ
и mv -Z
вместо cp -a
и mv
. Если это не было сделано, следует просто использовать restorecon -v -r
или restorecon -v -F -r
на месте назначения, чтобы попросить систему восстановить контексты SELinux по умолчанию. Всегда полезно использоватьrestorecon
в конце скрипта, который работал с ключевыми файлами конфигурации.
RHEL и, следовательно, большинство его производныхиспользовать SELinux по умолчанию.
Итак, чтобы решить вашу проблему, если ваша система основана на RHEL и использует mariadb-server
пакет, просто сделайте это на последнем шаге, когда файл находится вправильное место:
# restorecon -v -F /etc/my.cnf.d/server.cnf
Relabeled /etc/my.cnf.d/server.cnf from unconfined_u:object_r:user_home_t:s0 to system_u:object_r:mysqld_etc_t:s0
(Обратите внимание, что без -F
этого не произошло бы изменения unconfined_u
в настроенном system_u
. Это не имело бы значения для обычных систем. Мои знания о разнице и о том, почему это не имеет значения, не простираются так далеко).
Просто потребовалось бы больше работы, чтобы поместить правильный контекст в файлдругойместо.chcon
можно сделать это (либо указав это с помощью -u
-t
и т. д., либо проще скопировав контекст из другого файла с помощью --reference
):
# ls -lZ /home/test/server.cnf.bad
-rw-r--r--. 1 root root unconfined_u:object_r:user_home_t:s0 744 Apr 30 2017 /home/test/server.cnf.bad
# chcon -v -u system_u -t mysqld_etc_t /home/test/server.cnf.bad
changing security context of '/home/test/server.cnf.bad'
# ls -lZ /home/test/server.cnf.bad
-rw-r--r--. 1 root root system_u:object_r:mysqld_etc_t:s0 744 Apr 30 2017 /home/test/server.cnf.bad
Если вы подозреваете проблемы с SELinux, проверьте /var/log/audit/audit.log
записи со словом, denied
связанным с вашим процессом или файлом. Вы всегда можете временно попросить SELinux разрешить операции, а затем восстановить их, соответственно, setenforce Permissive
и setenforce Enforcing
для сравнения поведения. Не оставляйте его на, Permissive
особенно для производства.
Различные объяснения ниже...
Пример и что следует делать при работе с файлами конфигурации
Пример поведения с различными cp
параметрами и mv
в системе с включенным SELinux:
$ id
uid=1034(test) gid=1034(test) groups=1034(test)
$ pwd
/home/test
test@glasswalker:~$ ls -lZ foo
-rw-r--r--. 1 test test unconfined_u:object_r:user_home_t:s0 0 Aug 11 11:25 foo
$ cp foo /tmp/foo1
$ cp --preserve=context foo /tmp/foo2
$ cp -a foo /tmp/foo3
$ cp -aZ foo /tmp/foo4
$ mv foo /tmp/foo5
$ ls -lZ /tmp/foo?
-rw-r--r--. 1 test test unconfined_u:object_r:user_tmpfs_t:s0 0 Aug 11 11:25 /tmp/foo1
-rw-r--r--. 1 test test unconfined_u:object_r:user_home_t:s0 0 Aug 11 11:25 /tmp/foo2
-rw-r--r--. 1 test test unconfined_u:object_r:user_home_t:s0 0 Aug 11 11:25 /tmp/foo3
-rw-r--r--. 1 test test unconfined_u:object_r:user_tmpfs_t:s0 0 Aug 11 11:25 /tmp/foo4
-rw-r--r--. 1 test test unconfined_u:object_r:user_home_t:s0 0 Aug 11 11:25 /tmp/foo5
$ touch bar
$ ls -lZ bar
-rw-r--r--. 1 test test unconfined_u:object_r:user_home_t:s0 0 Aug 11 11:49 bar
$ mv -Z bar /tmp
$ ls -lZ /tmp/bar
-rw-r--r--. 1 test test unconfined_u:object_r:user_tmpfs_t:s0 0 Aug 11 11:49 /tmp/bar
Поэтому использование cp -aZ
or mv -Z
работает нормально, когда контексты безопасности имеют значение, и при этом сохраняет другие атрибуты. Скрипт, перемещающий системные файлы, всегда должен использовать опцию -Z
для любой команды cp
or mv
или просто использовать restorecon
на своем последнем шаге, чтобы избежать неожиданных проблем.
Почему такие различия?
Команда mv
сохраняет согласованное поведение. Если бы это произошло в той же файловой системе, конечно, все, что прикреплено к файлу, включая его контекст безопасности, не было бы изменено, поскольку это просто «переименование». Таким образом, в двух файловых системах, где это фактически копирование с последующим удалением, она также копирует без изменений все, что прикреплено к файлу и о чем она знает, включая его контекст безопасности, для согласованности.
Команда cp
по умолчанию простосоздаетновый файл, поэтому этот файл наследует контекст selinux родителя, как обычно, если, конечно, не указано иное, с помощью --preserve=context
которого включен в -a
. --preserve=context
можно вычесть из -a
с помощью опции -Z
, поэтому лучшим вариантом при копировании целых древовидных структур является использование -aZ
вместо , -a
если SELinux имеет значение.
По умолчанию при создании файла, что является обычным случаем, этот новый файл наследует контекст SELinux своего каталога, поэтому все работает нормально (не по теме: в редких случаях контекст файла должен отличаться от контекста его каталога просто из-за правила для его имени, ядру все равно, программы вроде демонаrestorecond
потребуется для его обработки).
Что такое SELinux
SELinux — это механизм обязательного контроля доступа (он жеМАК) используется в дополнение ко всем другим механизмам (разрешениям Unix, также известным какЦАП, Списки контроля доступа, также известные какACLи т. д.). Когда процесс выполняется в контексте безопасности процесса, существует «матрица правил», чтобы проверить, соответствует ли этопроцессконтекст может выполнить требуемую операцию (открыть, прочитать, записать, mmap,...) нафайлконтекст, в котором он пытается работать.
Пример для случая OP: если mysqld
контексту процесса разрешен доступ только к нескольким типам контекста файла, включая , mysqld_etc_t
но не user_home_t
, то запуск mysqld
завершится ошибкой, поскольку процесс не сможет прочитать свой файл конфигурации с неправильным user_home_t
типом.
В обычных системах это не имеет значения для интерактивного/вошедшего в систему пользователя, поскольку его обычный контекст процесса не ограничен, что означает, что никакое правило SELinux не будет применяться. Каждый запущенный демон systemd
или другие подобные механизмыволяполучить контекст процесса, который можно проверить с помощью ps
параметра -Z
. Пример в системе Debian, работающей под управлением SELinux:
# ps -Z -p $$
LABEL PID TTY TIME CMD
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 22498 pts/7 00:00:00 bash
# ps -Z -p $(pidof /sbin/getty)
LABEL PID TTY STAT TIME COMMAND
system_u:system_r:getty_t:s0 6158 tty1 Ss+ 0:00 /sbin/getty 38400 tty1
system_u:system_r:getty_t:s0 6159 tty2 Ss+ 0:00 /sbin/getty 38400 tty2
system_u:system_r:getty_t:s0 6160 tty3 Ss+ 0:00 /sbin/getty 38400 tty3
system_u:system_r:getty_t:s0 6161 tty4 Ss+ 0:00 /sbin/getty 38400 tty4
system_u:system_r:getty_t:s0 6162 tty5 Ss+ 0:00 /sbin/getty 38400 tty5
system_u:system_r:getty_t:s0 6163 tty6 Ss+ 0:00 /sbin/getty 38400 tty6
решение2
Да, есть принципиальная разница:
- cp делает копию файла
- mv (если вы остаетесь в пределах файловой системы) просто перемещает некоторые указатели на диске.
Попробуйте следующее:
touch a
ls -i a
cp a b
ls -i a b
mv a c
ls -i b c
Вы увидите, что b — это новый файл с новым номером инода, тогда как c — это тот же самый файл с номером инода старого a.
Однако это не объясняет вашего странного поведения.
решение3
Это то, чтоможет(Вы предоставили очень мало информации о приложении или этих ошибках, поэтому я могу только догадываться).
В Линуксеобязательная блокировка файлов встречается редко. Звонки типаflock(2)
управлятьконсультативныйблокировки. Это означает, что ядро отслеживает блокировки, но не применяет их, приложения должны сами их соблюдать.
Если что-то блокируется fileA
и ваше приложение подчиняется блокировке, оно может отказать в обслуживании. Предположим, что это то, что происходит.
Блокировка влияет на inode, а не на путь или имя. Перемещение (переименование) заблокированного fileA
в fileB
пределах одной файловой системы ничего не делает с inode, файл по-прежнему заблокирован, приложение по-прежнему отказывается с ним работать. Копирование файла создает отдельный файл fileB
с собственным inode, который не заблокирован, приложение работает.
(Примечание: перемещение файла в другую файловую систему фактически является копированием+удалением, поэтому оно должно снять блокировку, если таковая имеется).