解决方案一(本地)

解决方案一(本地)

我目前是 BTRFS 的用户,希望利用 CoW,这样当在同一 btrfs 文件系统上复制文件时,它们会通过重用现有范围自动进行重复数据删除。我可以认为有两种方法可以做到这一点:

解决方案一(本地)

我可以简单地在 .bashrc 中设置一个别名,以便每当我调用cp它时都会自动附加该--reflink=auto标志。

alias cp='cp --reflink=auto'

解决方案二(全球)

我能想到的另一个解决方案是创建/usr/local/bin/cp在 PATH 变量中具有更高优先级的解决方案。该脚本将类似于:

#!/bin/sh

CP=/bin/cp

exec $CP --reflink=auto $*

我认为替换不是一个好主意,/bin/cp因为 coreutils 的更新最终会覆盖我的更改。然而,这希望意味着从 PATH 调用 cp (而不是直接通过/bin/cp)的应用程序将始终自动使用引用链接。

问题

是否有任何反对这一点的论据,或者强加这一点会导致问题的任何情况?我假设将其设置为auto它会自动确定底层文件系统是否支持引用链接,以及它们是否位于同一设备上,使用引用链接意味着当我连接外部 ext4 文件系统或在 btrfs 之间复制时不会出现问题文件系统?

我读过了为什么 cp --reflink=auto 不是默认行为?看起来主要的论点是 cp 可以用于创建文件的备份,但我认为对我来说,我宁愿能够在本地消耗更少的空间并将数据完全复制到另一台机器,其中我的目标是备份数据。在这种情况下,实施解决方案 2 是否安全?

在最大限度地减少本地磁盘空间使用方面,我已经看到了设置建议--sparse=always,因此我认为类似的问题也适用于此。

答案1

请注意,您的代码有问题。$*不加引号绝不说得通。$*是位置参数与第一个字符 的串联$IFS。然后,虽然当 IFS 为空时行为会有一些变化,但这会受到分词和文件名生成的影响。在这里,您想要:

#!/bin/sh -
exec /bin/cp --reflink=auto "$@"

"$@"扩展为所有位置参数作为单独的参数。

如果您想要更新/bin/cp并在更新时保留更改,那么大多数系统都会有一个规范的方法来做到这一点。在 Debian 及其衍生版本上,您可以:

$ sudo dpkg-divert --local --rename /bin/cp
Adding 'local diversion of /bin/cp to /bin/cp.distrib'

然后写/bin/cp为:

#! /bin/sh -
exec "$0.distrib" --reflink=auto "$@"

coreutils 的每次更新都会更新cp.distrib而不是cp.

请注意,这会对性能产生影响,因为它需要sh在运行之前加载并运行cp。这/bin/sh在基于 . 的Debian 上还没有那么糟糕dash

这也意味着错误消息和帮助消息将提及cp.distrib而不是cp

$ cp
/bin/cp.distrib: missing file operand
Try '/bin/cp.distrib --help' for more information.

最后一部分,您可以通过将脚本编写为以下方式来解决:

#! /bin/bash -
exec -a "$0" "$0.distrib" --reflink=auto "$@"

(与臃肿的贝壳相同ksh93或与之zsh相比)。bashdash

它不会严格等效,因为$0将包含该脚本的路径,而不是argv[0] cp最初收到的路径,但至少它会类似于/bin/cp而不是/bin/cp.distrib.

答案2

我的解决方案(因为我运行 Gentoo,它真的很方便)是要求包管理器修补它。该补丁默认情况下会调整cpinstall使用 --reflink=auto ,并且它比使用包装器进行破解更有效和通用:

∞ cat /etc/portage/patches/sys-apps/coreutils/coreutils-reflink-auto.patch 
--- a/src/install.c.orig    2021-04-10 15:13:14.698039128 +0300
+++ a/src/install.c 2021-04-10 15:13:24.114292838 +0300
@@ -264,7 +264,7 @@
 {
   cp_options_default (x);
   x->copy_as_regular = true;
-  x->reflink_mode = REFLINK_NEVER;
+  x->reflink_mode = REFLINK_AUTO;
   x->dereference = DEREF_ALWAYS;
   x->unlink_dest_before_opening = true;
   x->unlink_dest_after_failed_open = false;
--- a/src/cp.c.orig 2021-04-10 15:12:03.591111323 +0300
+++ a/src/cp.c  2021-04-10 15:12:40.576190820 +0300
@@ -793,7 +793,7 @@
   x->move_mode = false;
   x->install_mode = false;
   x->one_file_system = false;
-  x->reflink_mode = REFLINK_NEVER;
+  x->reflink_mode = REFLINK_AUTO;
 
   x->preserve_ownership = false;
   x->preserve_links = false;

相关内容