使磁盘/磁盘复制变慢

ant*_*one 31 linux performance file-copy limit block-device

有没有一种方法可以减慢 Linux 上的复制过程?

我有一个大文件,比如 10GB,我想将它复制到另一个目录,但我不想全速复制它。假设我想以 1mb/s 的速度复制它,而不是更快。我想使用标准的 Linuxcp命令。

这可能吗?(如果是,如何?)

编辑:因此,我将为我要实现的目标添加更多上下文。

在通过 USB 复制大文件(到 U 盘、U 盘等)时,我在 ArchLinux 系统上遇到了问题。填满 USB 缓冲区缓存后,我的系统停止响应(甚至鼠标停止;它只是偶尔移动)。复制操作仍在进行中,但它占用了 box 100% 的资源。当复制操作完成后,一切都恢复正常——一切又恢复了完美的响应。

也许是硬件错误,我不知道,但我知道我有两台机器有这个问题(都在 ArchLinux 上,一个是台式机,第二个是笔记本电脑)。

对此最简单和最快的“解决方案”(我同意这不是“真正的”解决方案,只是一个丑陋的“黑客”)是通过以 USB 驱动器的平均写入速度复制文件来防止此缓冲区填满,例如我这就够了。

Mat*_*att 27

您可以使用pv -qL(或cstream -t提供类似功能)限制管道

tar -cf - . | pv -q -L 8192 | tar -C /your/usb -xvf -
Run Code Online (Sandbox Code Playgroud)

-q 删除 stderr 进度报告。

-L限制是以字节为单位。

更多关于--rate-limit/-L国旗的信息man pv

-L RATE, --rate-limit RATE

    Limit the transfer to a maximum of RATE bytes per second.
    A suffix of "k", "m", "g", or "t" can be added to denote
    kilobytes (*1024), megabytes, and so on.
Run Code Online (Sandbox Code Playgroud)

这个答案最初指出,throttle但该项目不再可用,因此已从某些软件包系统中消失。

  • 与 [`rsync`] 相比听起来太复杂了(https://unix.stackexchange.com/a/117711/126755) (2认同)

小智 26

相反的cp -a /foo /bar,你也可以使用rsync和限制带宽,因为你需要。

rsync的手册:

--bwlimit=KBPS
Run Code Online (Sandbox Code Playgroud)

限制 I/O 带宽;每秒千字节

因此,也显示进度的实际命令将如下所示:

rsync -av --bwlimit=100 --progress /foo /bar
Run Code Online (Sandbox Code Playgroud)


Bil*_*hor 14

我假设您正在努力不破坏其他活动。最新版本的 Linux 包括ionice允许您控制 IO 的调度。

除了允许各种优先级之外,还有一个附加选项可以将 IO 限制为磁盘空闲时的时间。该命令man ionice将显示文档。

尝试使用如下命令复制文件:

ionice -c 3 cp largefile /new/directory
Run Code Online (Sandbox Code Playgroud)

如果这两个目录在同一设备上,您可能会发现链接文件可以满足您的需求。如果您出于备份目的进行复制,请不要使用此选项。 ln速度非常快,因为文件本身不会被复制。尝试:

ln largefile /new/directory
Run Code Online (Sandbox Code Playgroud)

或者,如果您只想从不同设备上的目录访问它,请尝试:

ln -s largefile /new/directory
Run Code Online (Sandbox Code Playgroud)


Hau*_*ing 8

如果ionice解决方案还不够(为什么)并且您确实想将 I/O 限制为绝对值,则有几种可能性:

  1. 可能是最简单的:ssh。它有一个内置的带宽限制。您将使用 eg tar(而不是cp) or scp(如果这足够好;我不知道它如何处理符号链接和硬链接)或rsync. 这些命令可以通过管道传输数据ssh。如果tar您写入/dev/stdout(或-)并将其通过管道ssh传输tar到在“远程”端执行另一个的客户端。

  2. 优雅但不在香草内核(AFAIK)中:设备映射器目标ioband。当然,这仅在您可以卸载源卷或目标卷时才有效。

  3. 一些自写的乐趣:grep "^write_bytes: " /proc/$PID/io为您提供进程写入的数据量。您可以编写一个cp在后台启动的脚本,例如休眠 1/10 秒,停止后台cp进程 ( kill -STOP $PID),检查已写入的数量(并读取?在这种情况下大约相同的值),计算多长时间cp必须暂停以将平均传输速率降低到预期值,然后休眠、唤醒cp( kill -CONT $PID) 等等。


mik*_*erv 5

你的问题可能不是你的电脑本身,它可能没问题。但是 USB 闪存过渡层有一个自己的处理器,它必须映射您的所有写入,以补偿可能高达 90% 故障的闪存芯片,谁知道呢?你淹没它,然后淹没缓冲区,然后淹没整个公共汽车,然后你就被卡住了,伙计——毕竟,这就是你所有的东西。这听起来可能违反直觉,但您真正需要的是阻塞 I/O - 您需要让 FTL 设定速度,然后跟上。

(关于黑客 FTL 微控制器:http : //www.bunniestudios.com/blog/? p=3554 )

以上所有答案都应该有效,所以这更像是“我也是!” 最重要的是:我完全去过那里,伙计。我用 rsync 的--bwlimit arg解决了我自己的问题(2.5mbs 似乎是单次无错误运行的最佳点 - 再多的话,我会遇到写保护错误)。rsync 特别适合我的目的,因为我正在处理整个文件系统 - 所以有很多文件 - 只需第二次运行 rsync 就可以解决所有第一次运行的问题(当我不耐烦并尝试超过 2.5mbs)。

不过,我想这对于单个文件来说不太实用。在您的情况下,您可以通过管道将 dd 设置为 raw-write - 您可以通过这种方式处理任何输入,但一次只能处理一个目标文件(当然,该单个文件可能是整个块设备)。

## OBTAIN OPTIMAL IO VALUE FOR TARGET HOST DEV ##
## IT'S IMPORTANT THAT YOUR "bs" VALUE IS A MULTIPLE ##
## OF YOUR TARGET DEV'S SECTOR SIZE (USUALLY 512b) ##
% bs=$(blockdev --getoptio /local/target/dev)

## START LISTENING; PIPE OUT ON INPUT ##
% nc -l -p $PORT | lz4 |\ 
## PIPE THROUGH DECOMPRESSOR TO DD ## 
>    dd bs=$bs of=/mnt/local/target.file \
## AND BE SURE DD'S FLAGS DECLARE RAW IO ##
>        conv=fsync oflag=direct,sync,nocache

## OUR RECEIVER'S WAITING; DIAL REMOTE TO BEGIN ##
% ssh user@remote.host <<-REMOTECMD
## JUST REVERSED; NO RAW IO FLAGS NEEDED HERE, THOUGH ## 
>    dd if=/remote/source.file bs=$bs |\
>    lz4 -9 | nc local.target.domain $PORT
> REMOTECMD  
Run Code Online (Sandbox Code Playgroud)

如果您试一试,您可能会发现 netcat 在数据传输方面比 ssh 快一点。不管怎样,其他的想法已经被采纳了,为什么不呢?

[编辑]:我注意到在另一篇文章中提到了 lftp、scp 和 ssh,并认为我们在谈论远程复制。本地更容易:

% bs=$(blockdev --getoptio /local/target/dev)
% dd if=/src/fi.le bs=$bs iflag=fullblock of=/tgt/fi.le \
>    conv=fsync oflag=direct,sync,nocache
Run Code Online (Sandbox Code Playgroud)

[EDIT2]:应该归功于:刚刚注意到 ptman 在评论中击败了我大约五个小时。

当然,您可以在这里使用乘数来调整 $bs 的性能 - 但某些文件系统可能要求它是目标 fs 扇区大小的倍数,因此请记住这一点。