mv vs cp: en quoi le fichier résultant est-il différent?

3

J'avais un bogue lorsqu'un fichier de configuration pour une application n'était pas inclus correctement. Pour essayer d'isoler la ligne problématique du fichier, j'ai copié l'ancien contenu dans un nouveau fichier, quelques lignes à la fois.

À la fin, j’avais fait une copie conforme du fichier, mais l’ancien ne fonctionnait toujours pas alors que le nouveau fonctionnait parfaitement.

Plus précisément, si j'utilise la mvcommande pour déplacer le fichier de l'endroit où je l'ai stocké à l'endroit où il se trouve, cela provoque des erreurs. Si j’ai l'habitude cpde copier le fichier là où il veut être, il n'y a pas d'erreur.

Évidemment, des éléments tels que diff, fileou ls -lne révèlent aucune différence entre les deux fichiers, car l’un est une copie de l’autre, dans la mesure où il en cpfait une copie exacte .

Je ne peux pas partager trop d'informations sur le fichier, car il s'agit d'un travail. L'essentiel est que les commandes cp fileA fileBet mv fileA fileBproduisent un fileB « différent ». Ma meilleure hypothèse est qu'un attribut de très bas niveau de fileB est laissé derrière cp( cp -pproduit même le même comportement).

Que fait mv différemment de cp en ce qui concerne le contenu exact du fichier résultant?

EDIT: avec 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: L’application est mysql et le fichier est un fichier .cnf et l’élément de ce fichier de configuration particulièrement intéressant est le nom du journal binaire utilisé dans la réplication de la base de données maître-esclave. L'erreur "est que vous n'utilisez pas de journalisation binaire" car il n'y a pas de journal binaire car cet élément n'a jamais été "lu" par mysql.

Ma pensée initiale était qu'il y avait une erreur de syntaxe dans le fichier de configuration qui empêchait toute la lecture, ce qui m'a amené à le recréer manuellement en copiant des blocs de texte.

EDIT: Aller quelque part ... Enfin, quelque chose de différent à propos des fichiers

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
Andrew Pearce
la source
Avez-vous vérifié la propriété du fichier?
Art Gertner
Vous exécutez en cp -ptant qu'utilisateur régulier? Voir Pourquoi un utilisateur normal ne peut-il pas créer chownun fichier? En général, à moins d'être root, vous cp -pne conserverez pas la propriété. mvvolonté.
Kamil Maciorowski
1
Qu'en est-il cp -aau lieu de cp -p?
Kamil Maciorowski
1
Que signifie "ne pas être inclus correctement"? Cela pourrait aider si vous disiez exactement ce qui ne va pas avec l'original.
Steve Smith
1
avec SELinux (principalement par défaut sur RHEL et ses dérivés), même le contexte doit être vérifié:ls -lZ
AB

Réponses:

3

TL; DR: dans un système où SELinux est utilisé, les fichiers utilisés par le système (par exemple, les démons) doivent être copiés ou déplacés avec cp -aZet à la mv -Zplace de cp -aet mv. Si cela n'a pas été fait, il suffit d'utiliser restorecon -v -rou restorecon -v -F -rsur la destination pour demander au système de restaurer les contextes SELinux par défaut. C'est toujours une bonne idée d'utiliser restoreconà la fin d'un script qui a fonctionné sur des fichiers de configuration clés.

RHEL et donc la plupart de ses dérivés utilisent SELinux par défaut .

Donc, pour résoudre votre problème, si votre système est basé sur RHEL et utilise le mariadb-serverpackage, procédez à l'étape finale lorsque le fichier se trouve au bon endroit :

# 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

(Notez que sans -Fcela, unconfined_ula configuration ne changerait pas system_u. Cela n'aurait pas d'importance pour les systèmes courants. Ma connaissance de la différence et de la raison pour laquelle cela n'a aucune importance ne va pas aussi loin).

Ce serait simplement plus de travail de mettre le bon contexte sur le fichier ailleurs . chconpeut le faire (soit en l'indiquant avec -u -tetc., plus simplement en copiant le contexte depuis un autre fichier avec --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

Si vous suspectez des problèmes avec SELinux, vérifiez les /var/log/audit/audit.logentrées avec le mot deniedassocié à votre processus ou fichier. Vous pouvez toujours demander temporairement à SELinux d'autoriser les opérations, puis de les restaurer, avec respectivement setenforce Permissiveet setenforce Enforcingpour comparer le comportement. Ne le laissez pas Permissivespécialement pour la production.

Diverses explications suivantes ...

Exemple et ce qu'il faut faire pour travailler sur des fichiers de configuration

Exemple de comportement avec diverses cpoptions et mvsur un système activé pour 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

Donc, utiliser cp -aZou mv -Zfonctionne bien lorsque les contextes de sécurité importent tout en préservant les autres attributs. Un script système de fichiers doit se déplacer toujours utiliser l' -Zoption pour tout cpou mvcommande, ou bien il suffit d' utiliser restorecondans son étape finale pour éviter des problèmes inattendus.

Pourquoi ces différences?

La mvcommande conserve un comportement cohérent. Si cela se produisait dans le même système de fichiers, bien entendu tout ce qui serait attaché à un fichier, y compris son contexte de sécurité, ne serait pas modifié puisqu'il ne s'agit que d'un "renommer". Ainsi, sur deux systèmes de fichiers, où il s’agit d’une copie puis d’une suppression, il copie également tout ce qui est attaché au fichier et qui est connu, ainsi que son contexte de sécurité, pour des raisons de cohérence.

La cpcommande par défaut vient de créer un nouveau fichier, si ce fichier hérite du contexte de SELinux du parent comme d' habitude, à moins bien sûr dit autrement --preserve=contextinclus dans -a. --preserve=contextpeut être soustrait -aà l’option de -Zsorte que le meilleur choix lors de la copie d’arborescences entières est de l’utiliser à la -aZplace de -asi SELinux est important.

Par défaut, lors de la création d’un fichier, ce qui est le cas habituel, ce nouveau fichier hérite du contexte du répertoire SELinux, c’est pourquoi tout fonctionne correctement le nom du noyau ne l’intéressera pas, des programmes comme le démon restorecondseront nécessaires pour le gérer).

Qu'est-ce que SELinux?

SELinux est un mécanisme de contrôle d'accès obligatoire ( MAC ), utilisé en plus de tous les autres mécanismes (autorisations Unix aka DAC , Listes de contrôle d'accès aka ACL, etc.). Lorsqu'un processus s'exécute dans un contexte de sécurité de processus, une "matrice de règles" permet de vérifier si ce contexte de processus peut effectuer l'opération demandée (ouvrir, lire, écrire, mmap, ...) sur le contexte de fichier sur lequel il tente de travailler.

Exemple pour le cas d'OP: Si le mysqldcontexte de processus de 's n'est autorisé qu'à accéder à quelques types de contexte de fichier, l'inclusion mysqld_etc_tmais pas au user_home_tdémarrage mysqldéchouera car il ne pourrait pas lire son fichier de configuration avec un user_home_ttype incorrect .

Sur les systèmes habituels, cela n'a pas d'importance pour l'utilisateur interactif / connecté, car son contexte de processus habituel n'est pas confiné, ce qui signifie qu'aucune règle SELinux ne s'appliquera. Chaque démon a commencé par systemdou d' autres mécanismes similaires seront recevoir un contexte de processus, ce qui peut être vérifié avec psdes » -Zoption. Exemple sur un système Debian exécutant 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
UN B
la source
3

Oui, il y a une différence principale:

  • cp fait une copie du fichier
  • mv (si vous restez dans le système de fichiers) ne fait que déplacer des pointeurs sur le disque.

Essayez ce qui suit:

touch a
ls -i a
cp a b
ls -i a b
mv a c
ls -i b c

Vous verrez que b est un nouveau fichier avec un nouveau numéro d'inode, où c est exactement le même fichier avec le numéro d'inode de l'ancien a.

Pourtant, cela n'explique pas votre comportement étrange.

Ljm Dullaart
la source
J'avais aussi pensé aux pointeurs d'inode, mais si quelque chose est corrompu, cpne devrait pas fonctionner correctement, ou copier le travail cassé également.
Andrew Pearce
Je m'attendrais cpà créer un inode entièrement nouveau, en utilisant uniquement le nom / chemin de destination. N'oubliez pas que le code pour ces fonctionnalités peut être implémenté de nombreuses façons. Je suis sûr par exemple que cp appelle une méthode du noyau en transmettant des paramètres. ces paramètres peuvent ou non provenir de ou être lus à partir de l'inode, et il est possible que du code anti-corruption ait été ajouté d'un côté ou de l'autre, ou seulement pour un argument particulier, etc. Des hypothèses sérieuses sur le problème, si ce n'est que vous avez une corruption d'inode, et cp l'ont corrigé en créant un nouvel inode.
Frank Thomas
3

C’est peut- être ce qui se passe (vous partagez très peu d’informations sur l’application ou ces erreurs, alors je ne peux que deviner).

Sous Linux, le verrouillage de fichier obligatoire est rare . Des appels comme flock(2)gérer les verrous consultatifs . Cela signifie que le noyau garde la trace des verrous mais ne les applique pas, il appartient aux applications de les respecter.

Si quelque chose se verrouille fileAet que votre application respecte le verrou, elle peut refuser le service. Supposons que c'est ce qui se passe.

Le verrou affecte inode plutôt que chemin ou nom. Déplacement (changement de nom) , le verrouillage fileAà l' fileBintérieur d' un seul système de fichiers ne fait rien à l'inode, le fichier est toujours verrouillé, l'application refuse toujours de travailler avec elle. La copie du fichier crée un fichier séparé fileBavec son propre inode qui n'est pas verrouillé, l'application fonctionne.

(Remarque: déplacer un fichier vers un autre système de fichiers est en fait une copie + suppression, il devrait donc briser le verrou, le cas échéant).

Kamil Maciorowski
la source
L'application spécifique est mysql et je m'inquiète d'un fichier .cnf. La ligne spécifique est log-bin = fichier-bin.log, et mysql ne créait pas correctement les journaux binaires (casserait ainsi tout le matériel maître-esclave). Je verrai si mysql fait des choses de verrouillage de fichiers.
Andrew Pearce