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
但该项目不再可用,因此已从某些软件包系统中消失。
小智 26
相反的cp -a /foo /bar
,你也可以使用rsync
和限制带宽,因为你需要。
从rsync
的手册:
Run Code Online (Sandbox Code Playgroud)--bwlimit=KBPS
限制 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)
如果ionice
解决方案还不够(为什么)并且您确实想将 I/O 限制为绝对值,则有几种可能性:
可能是最简单的:ssh
。它有一个内置的带宽限制。您将使用 eg tar
(而不是cp
) or scp
(如果这足够好;我不知道它如何处理符号链接和硬链接)或rsync
. 这些命令可以通过管道传输数据ssh
。如果tar
您写入/dev/stdout
(或-
)并将其通过管道ssh
传输tar
到在“远程”端执行另一个的客户端。
优雅但不在香草内核(AFAIK)中:设备映射器目标ioband
。当然,这仅在您可以卸载源卷或目标卷时才有效。
一些自写的乐趣:grep "^write_bytes: " /proc/$PID/io
为您提供进程写入的数据量。您可以编写一个cp
在后台启动的脚本,例如休眠 1/10 秒,停止后台cp
进程 ( kill -STOP $PID
),检查已写入的数量(并读取?在这种情况下大约相同的值),计算多长时间cp
必须暂停以将平均传输速率降低到预期值,然后休眠、唤醒cp
( kill -CONT $PID
) 等等。
你的问题可能不是你的电脑本身,它可能没问题。但是 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 扇区大小的倍数,因此请记住这一点。