我目前是 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
相比)。bash
dash
它不会严格等效,因为$0
将包含该脚本的路径,而不是argv[0]
cp
最初收到的路径,但至少它会类似于/bin/cp
而不是/bin/cp.distrib
.
答案2
我的解决方案(因为我运行 Gentoo,它真的很方便)是要求包管理器修补它。该补丁默认情况下会调整cp
和install
使用 --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;