mv 与 cp:生成的文件有何不同?

mv 与 cp:生成的文件有何不同?

我遇到了一个错误,某些应用程序的配置文件没有被正确包含,因此为了尝试隔离文件中有问题的行,我将旧内容一次几行复制到新文件中。

最后,我制作了该文件的完全副本,但旧文件仍然无法工作,而新文件却可以正常工作。

更确切地说,如果我使用命令mv将文件从存储位置移动到它想要的位置,则会导致错误。如果我使用cp将文件复制到它想要的位置,则不会出现任何错误。

显然,诸如difffile或 之类的内容ls -l不会揭示两个文件之间的任何差异,因为一个是另一个的副本,只要cp制作文件的精确副本

我不能分享太多关于文件的信息,因为这是工作上的事情。最重要的是,这些命令cp fileA fileBmv 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

编辑:应用程序是 mysql,文件是 .cnf 文件,此配置文件中特别令人感兴趣的项是主从数据库复制中使用的二进制日志的名称。“错误”是“您未使用二进制日志记录”,因为没有二进制日志,因为 mysql 从未“读取”过该项。

我最初的想法是配置文件中存在语法错误,导致整个内容无法读取,这导致我通过复制文本块手动重新创建它

编辑:取得进展...最后文件有一些不同。

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或移动。如果没有这样做,应该在目标上使用或来要求系统恢复默认的 SELinux 上下文。使用mv -Zcp -amvrestorecon -v -rrestorecon -v -F -rrestorecon在处理关键配置文件的脚本的末尾。

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 Permissivesetenforce Enforcing比较行为。不要将其留在Permissive生产环境中。

以下是各种解释...

示例以及处理配置文件时应做的事情

在启用 SELinux 的系统上具有各种cp选项的 bahaviour 示例:mv

$ 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 -aZmv -Z可以正常工作。移动系统文件的脚本应始终-Z对任何cpmv命令使用选项,否则仅restorecon在最后一步使用以避免意外问题。

为什么会有这些差异呢?

mv命令保持一致的行为。如果它发生在同一个文件系统中,那么附加到文件的任何内容(包括其安全上下文)当然都不会被更改,因为它只是一个“重命名”。因此,在两个文件系统中,它实际上是复制然后删除,它还​​会复制附加到文件的任何未更改的内容,并且它知道这些内容,包括其安全上下文,以保持一致性。

默认情况下,命令cp只是创建一个新文件,因此该文件照常继承父级的 selinux 上下文,除非另有说明,其中--preserve=context包含-a。可以使用选项--preserve=context从中减去,因此复制整个树状图时最好的选择是使用,而不是如果 SELinux 确实很重要。-a-Z-aZ-a

默认情况下,在创建文件时(通常情况下),这个新文件会继承其目录的 SELinux 上下文,这就是一切正常的原因(题外话:在极少数情况下,文件上下文应该与其目录的上下文不同,只是因为其名称上有规则,内核不会关心,像守护进程这样的程序restorecond需要处理它)。

什么是 SELinux

SELinux 是一种强制访问控制机制(又称苹果) 除了所有其他机制(unix 权限又称数模转换器,又称访问控制列表访问控制列表等)。当一个进程在进程安全上下文中运行时,有一个“规则矩阵”来检查这个进程是否过程上下文可以对文件它试图发挥作用的背景。

OP 的情况示例:如果mysqld的进程上下文仅允许访问少数文件上下文类型,则包括mysqld_etc_t但不包括user_home_t启动mysqld将失败,因为它无法读取具有错误user_home_t类型的配置文件。

在通常的系统上,这对于交互/登录用户来说并不重要,因为其通常的进程上下文不受限制,这意味着不适用任何 SELinux 规则。由systemd或其他类似机制启动的每个守护进程将要接收进程上下文,可以使用 选项进行检查ps-Z在运行 SELinux 的 Debian 系统上的示例:

# 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 是一个具有新 inode 编号的新文件,而 c 只是具有旧 a 的 inode 编号的同一个文件。

但这并不能解释你的奇怪行为。

答案3

这是什么可能正在发生(您分享的有关应用程序或这些错误的信息很少,所以我只能猜测)。

在 Linux 中强制文件锁定并不常见. 调用类似flock(2)管理咨询锁。这意味着内核会跟踪锁,但不会强制执行,而是由应用程序来遵守它们。

如果某个东西被锁定fileA,并且您的应用程序遵守该锁定,它可能会拒绝服务。我们假设这是发生的情况。

锁定会影响 inode,而不是路径或名称。将锁定的文件移动(重命名)fileAfileB单个文件系统内不会对 inode 产生任何影响,文件仍处于锁定状态,应用程序仍拒绝使用它。复制文件会创建一个单独的文件,该文件fileB有自己的 inode,但未被锁定,应用程序可以正常工作。

(注意:将文件移动到另一个文件系统实际上是复制+删除,因此如果有的话,它应该打破锁)。

相关内容