web-dev-qa-db-ja.com

ディスク/ディスクのコピーを遅くする

Linuxでコピープロセスを遅くする方法はありますか?

10GBという大きなファイルがあり、別のディレクトリにコピーしたいのですが、フルスピードでコピーしたくありません。たとえば、1mb/sの速度でコピーしたいのですが、高速ではありません。標準のLinux cpコマンドを使用したい。

これは可能ですか? (はいの場合、どのように?)

編集:それで、達成しようとしていることにコンテキストを追加します。

大きなファイルをUSB経由で(pendrive、usbディスクなどに)コピーすると、ArchLinuxシステムで問題が発生します。 USBバッファキャッシュがいっぱいになると、システムが応答を停止します(マウスも停止し、散発的にしか動きません)。コピー操作はまだ進行中ですが、ボックスのリソースを100%使用します。コピー操作が完了すると、すべてが正常に戻ります-すべてが再び完全に応答します。

多分それはハードウェアエラーだとは思いませんが、私はこの問題のあるマシンが2台あることを知っています(どちらもArchLinux上にあり、1つはデスクトップボックス、もう1つはラップトップです)。

これに対する最も簡単で最速の「解決策」(私はそれが「実際の」解決策ではなく、単に醜い「ハック」ではないことに同意します)は、USBドライブの平均書き込み速度でファイルをコピーすることによって、このバッファーがいっぱいになるのを防ぐことです。それで十分でしょう。

29
antonone

pv -qL(または cstream -t でも同様の機能を提供します)でパイプをスロットルできます

tar -cf - . | pv -q -L 8192 | tar -C /your/usb -xvf -

-qは、stderr進行状況レポートを削除します。

-Lの制限はバイト単位です。

--rate-limit/-Lman 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.

この回答は元々throttleを指していますが、そのプロジェクトはもう利用できないため、一部のパッケージシステムから抜け出しました。

23
Matt

の代わりに cp -a /foo /barrsyncを使用して、必要に応じて帯域幅を制限することもできます。

rsyncのマニュアルから:

--bwlimit=KBPS

i/O帯域幅を制限します。 1秒あたりのキロバイト

したがって、進捗状況を示す実際のコマンドは次のようになります。

rsync -av --bwlimit=100 --progress /foo /bar
24
user55518

あなたは他の活動を妨害しないように努めていると思います。 Linuxの最近のバージョンにはioniceが含まれており、IOのスケジューリングを制御できます。

さまざまな優先順位を許可することに加えて、ディスクがアイドル状態である時間にIOを制限する追加のオプションがあります。コマンドman ioniceはドキュメントを表示します。

次のようなコマンドを使用してファイルをコピーしてみてください。

ionice -c 3 cp largefile /new/directory

2つのディレクトリが同じデバイス上にある場合、ファイルをリンクすると期待どおりの結果が得られることがあります。バックアップ目的でコピーする場合は、このオプションを使用しないでください。 lnは、ファイル自体がコピーされないため、非常に高速です。試してください:

ln largefile /new/directory

または、別のデバイスのディレクトリからアクセスしたいだけの場合:

ln -s largefile /new/directory
13
BillThor

ioniceソリューションでは十分ではなく(本当に)、I/Oを絶対値に制限したい場合は、いくつかの可能性があります。

  1. おそらく最も簡単です:ssh。帯域幅制限が組み込まれています。あなたは例えば使用しますtarcpの代わりに)または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は、平均転送速度を意図した値に下げるために一時停止し、その時間スリープし、cpkill -CONT $PID)をウェイクアップする必要があります。

7
Hauke Laging

あなたの問題はおそらくあなたのコンピューター自体にはありません、それはおそらく問題ありません。しかし、そのUSBフラッシュトランジションレイヤーには独自のプロセッサがあり、書き込みのすべてをマッピングして、90%の不良のフラッシュチップが何であるかを補償する必要があります。あなたはそれをあふれさせ、それからあなたのバッファをあふれさせ、それからあなたはバス全体をあふれさせ、そしてあなたは立ち往生しています-結局のところ、それはあなたのすべてのものがある場所です。直感に反するように聞こえるかもしれませんが、本当に必要なのはI/Oをブロックすることです。FTLにペースを設定させて、それを維持する必要があります。

(FTLマイクロコントローラーのハッキングについて: http://www.bunniestudios.com/blog/?p=3554

上記の答えはすべて機能するはずなので、これは「私も!」他の何よりも:私は完全にそこに行った、男。私はrsyncの-bwlimitargで自分の問題を解決しました(2.5mbsは、単一のエラーのない実行のスイートスポットのようでした。書き込み保護エラーが発生します)。ファイルシステム全体で作業していたため、rsyncは特に目的に適していました。ファイルがたくさんありました。rsyncを2回実行するだけで、最初の実行の問題がすべて修正されました(焦って試してみるときに必要でした)。 2.5mbsを超えてランプします)。

それでも、これは単一のファイルに対してはそれほど実用的ではないと思います。あなたの場合、パイプを使ってddをraw-writeに設定することができます-その方法で任意の入力を処理できますが、一度に1つのターゲットファイルのみです(もちろん、単一のファイルがブロックデバイス全体になることもあります)。

## 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 [email protected] <<-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  

データトランスポートの場合、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

[編集2]:期限のあるクレジット:ptmanがコメントで5時間ほどこれに負けたことに気づきました。

確かにここで$ bsを調整して乗数を使ってパフォーマンスを上げることができますが、一部のファイルシステムでは、ターゲットのfsのセクターサイズの倍数である必要がある場合があるので注意してください。

5
mikeserv

ダーティページの制限を下げます。デフォルトの制限は非常識です。

/etc/sysctl.d/99-sysctl.confを次のように作成します。

vm.dirty_background_ratio = 3
vm.dirty_ratio = 10

次に、sysctl -pを実行するか、再起動します。

何が起こっているのかというと、宛先ディスクに書き込むよりも速くデータが読み取られています。 Linuxがファイルをコピーするとき、ファイルはRAMに読み込まれ、コピー先への書き込み用にダーティとしてマークされます。ダーティページはスワップアウトできません。したがって、コピー元のディスクがコピー先のディスクよりも高速で、空きRAMの容量よりも多くのデータをコピーしている場合、コピー操作は、利用可能なすべてのRAM(または少なくともダーティページをすべて)消費します。制限は、使用可能なRAMを超える可能性があります)。ダーティページはスワップアウトできず、クリーンページは解放されて使用され、ダーティマークが付けられるため、枯渇します。

彼が問題を完全に解決するわけではないことに注意してください... Linuxが本当に必要とするのは、ダーティページの作成を調停する何らかの方法です。

2
alex.forencich

問題は、コピーが「実行中」のブロックでメモリをいっぱいにし、「有用な」データを詰め込んでいることです。遅いデバイス(この場合はUSB)へのI/OのLinuxカーネル処理における既知の(そしてvery修正が難しい)バグ。

おそらく、あなたはコピーを分割することを試みることができます。次のようなスクリプトによって(概念実証スケッチ、完全に未テスト!):

while true do
  dd if=infile of=outfile bs=4096 count=... seek=... skip=...
  sleep 5
done

各ラウンドでseekskipcountずつ調整します。 countを調整して、メモリがいっぱいにならないようにする必要があります。5それを排出できるようにします。

2
vonbrand

この問題は、ハードウェアまたはソフトウェアのエラーや障害とは何の関係もありません。それは、カーネルがあなたにナイスであり、プロンプトをバックグラウンドでコピーしようとするだけです(カーネル内キャッシュを使用します:より多くのRAM、より多くのキャッシュ、ただし、/ procのどこかに書き込むことで制限できますが、お勧めしません)。フラッシュドライブが遅すぎて、カーネルが書き込みを行っている間、他のIO操作は十分に速く実行できません。ioniceは、他の回答で数回言及されていても問題ありません。しかし、 OSのバッファリングを回避するために-o syncを使用してドライブをマウントしてみましたか?これはおそらく、最も簡単な解決策です。

0
orion