mv vs cp: o que há de diferente no arquivo resultante?

mv vs cp: o que há de diferente no arquivo resultante?

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 mvcomando para mover o arquivo de onde ele está armazenado para o local que ele deseja, isso causará erros. Se eu cpcopiar o arquivo para o local que ele deseja, não haverá erros.

Obviamente, coisas como diff, fileou ls -lnão revelam diferenças entre os dois arquivos porque um é uma cópia do outro,na medida em que cpfaz 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 fileBproduzem mv fileA fileBum arquivo B "diferente". Meu melhor palpite é que algum atributo de nível superbaixo do arquivo B é deixado para trás durante cp(até cp -pproduz 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 -aZe mv -Zem vez de cp -ae mv. Se isso não foi feito, deve-se apenas usar restorecon -v -rou restorecon -v -F -rno destino para solicitar ao sistema que restaure os contextos padrão do SELinux. É sempre uma boa ideia usarrestoreconno 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-serverpacote, 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 -Fele não mudaria unconfined_upara 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.chconpode fazer isso (declarando-o com -u -tetc., 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.logse há entradas com a palavra deniedrelacionada ao seu processo ou arquivo. Você sempre pode pedir temporariamente ao SELinux para permitir operações e depois restaurá-las, respectivamente, setenforce Permissivee setenforce Enforcingpara comparar o comportamento. Não deixe isso Permissiveespecialmente 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 cpopções e mvem 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 -aZor mv -Zfunciona 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 -Zopção para qualquer comando cpou , ou então apenas usar na etapa final para evitar problemas inesperados.mvrestorecon

Por que essas diferenças?

O mvcomando 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 cpcomando 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=contexto qual está incluído em -a. --preserve=contextpode ser substituído -acom a opção -Z, então a melhor aposta ao copiar arborescências inteiras é usar -aZem vez de -ase 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 daemonrestorecondserá 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 mysqldcontexto do processo do tiver permissão para acessar apenas alguns tipos de contexto de arquivo, incluindo, mysqld_etc_tmas não user_home_t, a inicialização mysqldfalhará porque não foi possível ler seu arquivo de configuração com o user_home_ttipo 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 systemdou outros mecanismos similaresvairecebe um contexto de processo, que pode ser verificado com psa 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 fileAe 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 fileApara fileBum ú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 fileBcom 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).

informação relacionada