cp -a 无法复制 virtfs 上的符号链接

cp -a 无法复制 virtfs 上的符号链接

问题:

尝试将一个目录的全部内容复制到另一个目录,其中包括隐藏文件/目录和符号链接。

这相当简单cp -a ${src} ${dst}

它在我的本地虚拟机上按预期工作,但是它在我的 VPS (hostgator) 上无法正常工作。如果链接目标位于目录列表的后面,则无法复制符号链接。

考虑到原始链接目标有效,是设备本地的并且我在同一设备上复制,确保准确复制整个目录结构的最佳方法是什么?

我花了很长时间,但我发现我实际上需要做的就是运行复制命令两次,第二遍添加丢失的链接。还有比这更好的方法吗?

有效但黑客式的解决方案:

src=".default/.";
dst="tld.domain/";
cp -a ${src} ${dst};
cp -a ${src} ${dst};

我不需要重复命令来确保所有内容都正确复制。

我也尝试了 tar,同样的问题。我没有尝试 rsync,但对于一些本来应该是一件非常微不足道的事情来说,这两种解决方案似乎都太过分了。

设想:

如果重要或我不清楚的话,请提供额外的观点。

我已经为网站域创建了一个模板目录结构。在我的网络主机上创建新的子域后,我将模板复制到子域的文档根目录。

这是我的子域和模板 (.default/) 目录结构:

sites/
    .default/
        .htaccess
        .www -> production/
        production/
    tld.domain.x/
    tld.domain.y/
    tld.domain.z/

因此,我创建一个新的子域,然后使用模板目录的内容填充它的文档根目录。这里的问题是,这.www/是一个符号链接,production/cp等人按排序顺序创建所有内容,因此它尝试.www/在创建之前创建production/,因此失败。

我的网络主机是运行 CentOS6 的 HostGator VPS

我可以将问题深入到创建符号链接的一些限制。我的猜测是,VPS 不允许符号链接到外部源,而外部源的行为通常与无效链接目标相同。 IE 来源不明。

如果两个名字都不存在,请调用我的 VPS:

ln -s foo bar

输出:

ln: creating symbolic link `bar': Permission denied

如果我先创建 foo/ 然后链接,它会按预期工作。

df -T .表明文件系统类型是virtfs

答案1

通常,符号链接是惰性的:它可以存储任何字节序列(空字节除外,并且只能存储一定长度)。创建符号链接时,内容是否恰好指向现有文件并不重要。只有在访问符号链接时目标的存在才重要。因此,您在 VPS 上看到的内容是异常的(启动时也是不寻常的)。

虚拟文件系统是专为 KVM/QEMU 虚拟机设计的文件系统,其中来宾和主机都运行 Linux。该文件系统在来宾中呈现主机文件系统的一部分。它允许以简单快速的方式(比网络文件系统更快)在来宾和主机之间共享文件。例如,它在 VPS 上很有用,因为所有来宾都运行相同的操作系统,因此操作系统文件在主机和所有来宾之间共享(希望是只读的)。它还可用于特定于访客的文件(不与任何其他访客共享)。

Virtfs提供两种存储模式:映射的直通。直通模式,顾名思义,只是将文件操作命令从来宾传递到主机;例如,在来宾中创建符号链接会在主机上创建符号链接。映射模式使用主机中的扩展属性来存储文件的元数据,并使所有文件都由运行 QEMU 的用户拥有。映射模式适合存储每个来宾文件,因为它们由运行 QEMU 的一个用户拥有,无论来宾中哪个用户拥有它们。您的站点可能以映射模式存储在 virtfs 实例上。

在映射模式下,符号链接存储为常规文件,并具有指示它们是符号链接的扩展属性。这本身并不能解释你的问题。然而,它为出现问题打开了机会之窗。似乎有些东西正在检查符号链接目标是否存在,如果目标不存在则拒绝创建它们。

我缺乏 virtfs 的经验,所以我无法告诉你这是否是由于某些配置选项造成的。我确实找到了与你的问题类似的问题。受影响的用户也在 VPS 上,并且在尝试创建悬空符号链接时也遇到了“权限被拒绝”错误。他的结论是

仅供参考,问题不在于 RedHat 4.4 - 该ln -s命令被系统提供商故意破坏,以阻止用户安装 RVM 之类的东西。

您可能需要联系您的 VPS 提供商以请求解释并希望修复。

如果无法获得修复,解决方法是首先复制目录和常规文件,然后复制符号链接。我认为任何常用的复制程序(GNU cp、rsync、cpio、tar、pax)都没有办法复制所有内容,但只保留符号链接。一个简单的解决方法是执行两次复制(使用 rsync,以便已复制的文件不会再次复制),忽略第一轮中的错误:

rsync -a source/ destination/ 2>/dev/null
rsync -a source/ destination/

相关内容