Eu tive um bug em que um arquivo de configuração de algum aplicativo não estava sendo incluído corretamente, então, para tentar isolar a linha problemática do arquivo, copiei o conteúdo antigo para um novo arquivo, algumas linhas por vez.
No final, eu tinha feito uma duplicata exata do arquivo, mas o antigo ainda não funcionava, enquanto o novo funcionava perfeitamente.
Mais especificamente, se eu usar o mv
comando para mover o arquivo de onde ele está armazenado para o local que ele deseja, isso causará erros. Se eu cp
copiar o arquivo para o local que ele deseja, não haverá erros.
Obviamente, coisas como diff
, file
ou ls -l
não revelam diferenças entre os dois arquivos porque um é uma cópia do outro,na medida em que cp
faz uma cópia exata do arquivo.
Não posso compartilhar muitas informações sobre o arquivo porque isso é uma questão de trabalho. O resultado final é que os comandos cp fileA fileB
produzem mv fileA fileB
um arquivo B "diferente". Meu melhor palpite é que algum atributo de nível superbaixo do arquivo B é deixado para trás durante cp
(até cp -p
produz o mesmo comportamento).
O que mv faz de diferente do cp, referente ao conteúdo exato do arquivo resultante?
EDITAR: Com 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: O aplicativo é mysql e o arquivo é um arquivo .cnf e o item neste arquivo de configuração que foi especificamente de interesse é o nome do log binário usado na replicação do banco de dados mestre-escravo. O "erro" é "você não está usando log binário" porque não há log binário porque esse item nunca foi "lido" pelo mysql.
Meu pensamento inicial foi que havia um erro de sintaxe no arquivo de configuração que fazia com que tudo não fosse lido, o que me levou a recriá-lo manualmente, copiando blocos de texto
EDIT: Chegando a algum lugar... Finalmente algo diferente sobre os arquivos.
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
Responder1
TL;DR: em um sistema ondeSELinuxestá em uso, os arquivos usados pelo sistema (ou seja: daemons) devem ser copiados ou movidos com cp -aZ
e mv -Z
em vez de cp -a
e mv
. Se isso não foi feito, deve-se apenas usar restorecon -v -r
ou restorecon -v -F -r
no destino para solicitar ao sistema que restaure os contextos padrão do SELinux. É sempre uma boa ideia usarrestorecon
no final de um script que funcionou nos principais arquivos de configuração.
RHEL e, portanto, a maioria de seus derivadosuse SELinux por padrão.
Então para resolver o seu problema, se o seu sistema for baseado em RHEL e usar o mariadb-server
pacote, basta fazer na etapa final quando o arquivo estiver nolugar correto:
# 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
(Observe que sem -F
ele não mudaria unconfined_u
para o configurado system_u
. Não faria diferença para sistemas comuns. Meu conhecimento da diferença e por que isso não importa não vai tão longe).
Seria apenas mais trabalhoso colocar o contexto correto no arquivo de uma formaoutrolugar.chcon
pode fazer isso (declarando-o com -u
-t
etc., mais simplesmente copiando o contexto de outro arquivo com --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
Se você suspeitar de problemas no SELinux, verifique /var/log/audit/audit.log
se há entradas com a palavra denied
relacionada ao seu processo ou arquivo. Você sempre pode pedir temporariamente ao SELinux para permitir operações e depois restaurá-las, respectivamente, setenforce Permissive
e setenforce Enforcing
para comparar o comportamento. Não deixe isso Permissive
especialmente para produção.
Várias explicações a seguir...
Exemplo e o que deve ser feito ao trabalhar em arquivos de configuração
Exemplo de comportamento com várias cp
opções e mv
em um sistema habilitado para 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
Portanto, usar cp -aZ
or mv -Z
funciona bem quando os contextos de segurança são importantes e ainda preserva outros atributos. Um script que move arquivos do sistema deve sempre usar a -Z
opção para qualquer comando cp
ou , ou então apenas usar na etapa final para evitar problemas inesperados.mv
restorecon
Por que essas diferenças?
O mv
comando mantém um comportamento consistente. Se isso acontecesse no mesmo sistema de arquivos, é claro que qualquer coisa anexada a um arquivo, incluindo seu contexto de segurança, não seria alterada, pois é apenas uma "renomeação". Portanto, em dois sistemas de arquivos, onde na verdade é uma cópia e depois uma exclusão, ele também copia inalterado tudo o que está anexado ao arquivo e conhece, incluindo seu contexto de segurança, para consistência.
O cp
comando por padrão apenascriaum novo arquivo, então este arquivo herda o contexto selinux do pai como de costume, a menos que seja informado o contrário com --preserve=context
o qual está incluído em -a
. --preserve=context
pode ser substituído -a
com a opção -Z
, então a melhor aposta ao copiar arborescências inteiras é usar -aZ
em vez de -a
se o SELinux for importante.
Por padrão, ao criar um arquivo, que é o caso usual, este novo arquivo herda seu contexto de diretório SELinux, é por isso que tudo funciona bem (fora do tópico: em casos raros, o contexto do arquivo deve ser diferente do contexto de seu diretório apenas por causa de um governe seu nome, o kernel não se importará, programas como o daemonrestorecond
será necessário para lidar com isso).
O que é SELinux
SELinux é um mecanismo de controle de acesso obrigatório (também conhecido comoMAC) usado além de todos os outros mecanismos (permissões unix, também conhecidas comoDAC, Listas de controle de acesso, também conhecidas comoLCAetc.). Quando um processo é executado em um contexto de segurança de processo, existe uma "matriz de regras" para verificar se issoprocessocontexto pode fazer a operação solicitada (abrir, ler, escrever, mmap,...) noarquivocontexto em que tenta trabalhar.
Exemplo para o caso do OP: Se o mysqld
contexto do processo do tiver permissão para acessar apenas alguns tipos de contexto de arquivo, incluindo, mysqld_etc_t
mas não user_home_t
, a inicialização mysqld
falhará porque não foi possível ler seu arquivo de configuração com o user_home_t
tipo errado.
Em sistemas normais, isso não importa para o usuário interativo/logado, porque seu contexto de processo usual não é confinado, o que significa que nenhuma regra do SELinux será aplicada. Todo daemon iniciado por systemd
ou outros mecanismos similaresvairecebe um contexto de processo, que pode ser verificado com ps
a opção ' -Z
. Exemplo em um sistema Debian rodando 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
Responder2
Sim, há uma diferença fundamental:
- cp faz uma cópia do arquivo
- mv (se você permanecer no sistema de arquivos) apenas move alguns ponteiros no disco.
Experimente o seguinte:
touch a
ls -i a
cp a b
ls -i a b
mv a c
ls -i b c
Você verá que b é um novo arquivo com um novo número de inode, enquanto c é exatamente o mesmo arquivo com o número de inode do antigo a.
Ainda assim, isso não explica o seu comportamento estranho.
Responder3
Isso é o quepoderiaestar acontecendo (você compartilha muito pouca informação sobre o aplicativo ou esses erros, então só posso adivinhar).
No Linuxo bloqueio obrigatório de arquivos é incomum. Chamadas comoflock(2)
gerenciarconsultivofechaduras. Isso significa que o kernel controla os bloqueios, mas não os impõe; cabe aos aplicativos obedecê-los.
Se algo for bloqueado fileA
e seu aplicativo obedecer ao bloqueio, ele poderá recusar o serviço. Vamos supor que é isso que acontece.
O bloqueio afeta o inode em vez do caminho ou nome. Mover (renomear) o bloqueado fileA
para fileB
um único sistema de arquivos não afeta o inode, o arquivo ainda está bloqueado e o aplicativo ainda se recusa a trabalhar com ele. Copiar o arquivo cria um inode separado fileB
com seu próprio inode que não está bloqueado, o aplicativo funciona.
(Nota: mover um arquivo para outro sistema de arquivos é, na verdade, copiar + excluir, portanto, deve quebrar o bloqueio, se houver).