Làm cho đĩa / đĩa sao chép chậm hơn


28

Có phương pháp nào làm chậm quá trình sao chép trên Linux không?

Tôi có một tệp lớn, giả sử là 10 GB và tôi muốn sao chép nó sang một thư mục khác, nhưng tôi không muốn sao chép nó với tốc độ tối đa. Giả sử tôi muốn sao chép nó với tốc độ 1mb / s, không nhanh hơn. Tôi muốn sử dụng một cplệnh Linux tiêu chuẩn .

Điều này có thể không? (Nếu có, làm thế nào?)

Chỉnh sửa : vì vậy, tôi sẽ thêm nhiều bối cảnh vào những gì tôi đang cố gắng đạt được.

Tôi gặp sự cố trên hệ thống ArchLinux khi sao chép các tệp lớn qua USB (vào ổ đĩa, đĩa USB, v.v.). Sau khi lấp đầy bộ đệm bộ đệm usb, hệ thống của tôi dừng đáp ứng (ngay cả chuột cũng dừng; nó chỉ di chuyển lẻ tẻ). Hoạt động sao chép vẫn đang tiếp diễn, nhưng phải mất 100% tài nguyên của hộp. Khi hoạt động sao chép kết thúc, mọi thứ trở lại bình thường - mọi thứ hoàn toàn đáp ứng trở lại.

Có thể đó là lỗi phần cứng, tôi không biết, nhưng tôi biết tôi có hai máy gặp sự cố này (cả hai đều có trên ArchLinux, một là hộp máy tính để bàn, thứ hai là máy tính xách tay).

"Giải pháp" dễ nhất và nhanh nhất cho vấn đề này (tôi đồng ý rằng đó không phải là giải pháp 'thực sự', chỉ là một 'hack' xấu xí) sẽ ngăn không cho bộ đệm này lấp đầy bằng cách sao chép tệp với tốc độ ghi trung bình của ổ USB, cho tôi thế là đủ


7
Nếu bạn đang tìm cách hạn chế tốc độ sao chép từ đĩa sang đĩa trong nỗ lực "đẹp" với các quy trình ràng buộc I / O khác trong hệ thống, có lẽ tốt hơn hết là bạn nên tận dụng khả năng lập lịch trình I / O của kernel thay thế. Cụ thể, ionicecó thể được sử dụng để đảm bảo rằng quá trình sao chép từ đĩa sang đĩa của bạn được lên lịch I / O ở mức ưu tiên thấp hơn các quy trình thông thường.
Steven Thứ Hai

3
Đây là một câu hỏi vấn đề XY cổ điển . Thay vào đó, bạn nên hỏi về lý do tại sao máy tính để bàn của bạn không phản hồi khi bạn sao chép tệp vào thiết bị USB.
Michael Hampton

4
Linux thực sự có bộ đệm I / O lớn một cách lố bịch ngày nay. Kích thước RAM đã tăng nhanh hơn tốc độ lưu trữ lớn. Có lẽ bạn có thể thực hiện sao chép bằng dd (1) và đồng bộ hóa để nó thực sự được đồng bộ hóa định kỳ thay vì được đệm? Và trình xem ống (pv) có tùy chọn giới hạn tốc độ. Một cái gì đó như cat file | pv -L 3k > outfile. Không giống như sử dụng cp (1), mặc dù.
ptman

@MichaelHampton, có một số chủ đề chưa được giải quyết về vấn đề này trên diễn đàn của ArchLinux, vì vậy tôi cho rằng tôi sẽ cố gắng đối phó với nó theo một cách khác, chỉ để làm cho nó hoạt động.
antonone

@antonone Nhưng Unix.SE không phải là diễn đàn của ArchLinux. Ai đó ở đây có thể có một giải pháp.
Izkata

Câu trả lời:


23

Bạn có thể điều tiết một đường ống có pv -qL(hoặc cstream -tcung cấp chức năng tương tự)

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

-q loại bỏ báo cáo tiến độ stderr.

Các -Lgiới hạn là tính bằng byte.

Thông tin thêm về --rate-limit/-Lcờ từ 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.

Câu trả lời này ban đầu chỉ ra throttlenhưng dự án đó không còn nữa nên đã trượt ra khỏi một số hệ thống gói.


Nếu cpkhông thể làm chậm, thì sử dụng lệnh tùy chỉnh là lựa chọn duy nhất tôi đoán.
antonone

1
Nghe có vẻ quá phức tạp so vớirsync
LinuxSecurityFreak

có vẻ phức tạp hơn nhưng có thể sử dụng nhiều hơn với tôi. Cần kiểm tra cơ chế khóa tệp và cần làm chậm việc sao chép xuống một số byte / s mà dường như không thể với rsync. Ill hãy thử và 'mèo' một tập tin qua ống tiết lưu
cljk

thật buồn khi nói nhưng dự án đã chết bug.debian.org/cgi-bin/ormsreport.cgi?orms=426891
cljk

1
@cljk cập nhật lên pv. cảm ơn.
Matt

23

Thay vì cp -a /foo /barbạn cũng có thể sử dụng rsyncvà giới hạn băng thông khi bạn cần.

Từ rsynchướng dẫn của:

--bwlimit=KBPS

giới hạn băng thông I / O; KByte mỗi giây

Vì vậy, lệnh Actuall, cũng hiển thị tiến trình, sẽ trông như thế này:

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

Điều này nghe có vẻ là một ý tưởng hay để sao chép các ổ đĩa cũ mà tôi không muốn đánh bại.
jeremyjjbrown

Không hoạt động để đọc từ /dev/zerohoặc/dev/random
cdosborn

rsync -a --bwlimit=1500 /source /destinationhoạt động hoàn hảo để sao chép các thư mục khổng lồ với tốc độ 1,5 MB / giây (đó là một sự đánh đổi tốt giữa việc tránh bất kỳ máy chủ nào bị chậm và không mất quá nhiều thời gian)
lucaferrario

Sidenote: ngay cả khi trang man có thể nói rằng bạn có thể sử dụng các chữ cái cho các đơn vị, ví dụ: 20mnó không được hỗ trợ trên tất cả các nền tảng, vì vậy tốt hơn hãy sử dụng ký hiệu KBytes.
Hubert Grzeskowiak

đã cứu ngày của tôi! cgroup cgexec -g ... cp /in /outkhông hoạt động mọi lúc (từ thiết bị đầu cuối hoạt động một số lần, từ kịch bản không bao giờ) và tôi không biết tại sao ...
Aquarius Power

13

Tôi sẽ cho rằng bạn đang cố gắng không làm gián đoạn hoạt động khác. Các phiên bản gần đây của Linux bao gồm ionicecho phép bạn kiểm soát lịch trình của IO.

Bên cạnh việc cho phép các ưu tiên khác nhau, có một tùy chọn bổ sung để giới hạn IO trong thời gian khi đĩa không hoạt động. Lệnh man ionicesẽ hiển thị tài liệu.

Hãy thử sao chép tệp bằng lệnh như:

ionice -c 3 cp largefile /new/directory

Nếu hai thư mục trên cùng một thiết bị, bạn có thể thấy việc liên kết tệp sẽ làm những gì bạn muốn. Nếu bạn đang sao chép cho mục đích sao lưu, không sử dụng tùy chọn này. lnlà cực kỳ nhanh chóng vì tập tin không được sao chép. Thử:

ln largefile /new/directory

Hoặc nếu bạn chỉ muốn truy cập nó từ một thư mục trên một thiết bị khác, hãy thử:

ln -s largefile /new/directory

ionice có hoạt động tốt trong linux không? tôi đọc nó chỉ "giả lập" công việc và không có sự khác biệt thực sự? +1 cho các liên kết
Nick

1
@Nick Khi tôi đã sử dụng nó, nó đã hoạt động như mong đợi. Quá trình tôi áp dụng ionice bị chậm lại đáng kể, một quá trình khác cần I / O có thể thực hiện như mong đợi. Với tải I / O vừa phải từ các quy trình khác, tôi có thể tạm dừng hiệu quả quy trình I / O cao bằng cách áp dụng 'tính độc đáo' tối đa như mong đợi. Khi không có I / O cạnh tranh, quá trình ion hóa được thực hiện như bình thường.
BillThor

với tệp 400 MB tôi đã sao chép từ một HD sang SSD, 10 giây ban đầu nó hoạt động hoàn hảo, sau đó đột nhiên tôi thấy tôi tải IO cao và phải chờ máy 1 phút như bị đóng băng: /. Tôi có cùng một vấn đề với cgroup viết io điều tiết đôi khi nó hoạt động và những người khác nó không hoạt động.
Sức mạnh Bảo Bình

7

Nếu ionicegiải pháp là không đủ (tại sao) và bạn thực sự muốn giới hạn I / O ở một giá trị tuyệt đối, có một số khả năng:

  1. có lẽ dễ nhất : ssh. Nó có một giới hạn băng thông tích hợp. Bạn sẽ sử dụng ví dụ tar(thay vì cp) hoặc scp(nếu đủ tốt; tôi không biết cách nó xử lý các liên kết tượng trưng và liên kết cứng) hoặc rsync. Các lệnh này có thể dẫn dữ liệu của họ qua ssh. Trong trường hợp tarbạn viết thư cho /dev/stdout(hoặc -) và chuyển nó vào sshmáy khách thực thi lệnh khác tarở phía "từ xa".

  2. tao nhã nhưng không có trong hạt nhân vani (AFAIK): Mục tiêu của trình ánh xạ thiết bị ioband. Tất nhiên, điều này chỉ hoạt động nếu bạn có thể vượt qua cả nguồn hoặc khối lượng đích.

  3. một số niềm vui tự viết: grep "^write_bytes: " /proc/$PID/iocung cấp cho bạn lượng dữ liệu mà một quá trình đã viết. Bạn có thể viết một tập lệnh bắt đầu cptrong nền, ngủ trong ví dụ 1/10 giây, dừng cpquá trình nền ( kill -STOP $PID), kiểm tra số tiền đã được viết (và đọc? Về cùng một giá trị trong trường hợp này), tính toán trong bao lâu cpphải tạm dừng để giảm tốc độ truyền trung bình xuống giá trị dự định, ngủ trong thời gian đó, thức dậy cp( kill -CONT $PID), v.v.


Có, thông thường tôi chỉ sử dụng lftp để kết nối với localhost thông qua scp và giới hạn băng thông từ đó.
antonone

5

Vấn đề của bạn có lẽ không phải là với máy tính của bạn, có lẽ nó vẫn ổn. Nhưng lớp chuyển đổi flash USB đó có một bộ xử lý riêng để vạch ra tất cả các ghi của bạn để bù cho những gì có thể nhiều như một chip flash bị lỗi 90%, ai biết? Bạn làm ngập nó sau đó bạn làm ngập bộ đệm của bạn sau đó bạn làm ngập toàn bộ xe buýt, sau đó bạn bị mắc kẹt, người đàn ông - sau tất cả, đó là nơi tất cả các công cụ của bạn. Nghe có vẻ phản trực giác nhưng điều bạn thực sự cần là chặn I / O - bạn cần để FTL thiết lập tốc độ và sau đó chỉ cần theo kịp.

(Về việc hack vi điều khiển FTL: http://www.bunniestudios.com/blog/?p=3554 )

Tất cả các câu trả lời ở trên nên hoạt động vì vậy đây là một "tôi cũng vậy!" hơn bất cứ điều gì khác: tôi đã hoàn toàn ở đó, anh bạn. Tôi đã giải quyết vấn đề của riêng mình với --bwlimit arg của rsync (2,5mbs dường như là điểm hấp dẫn cho một lần chạy duy nhất, không có lỗi - bất cứ điều gì nữa và tôi sẽ gặp phải lỗi bảo vệ chống ghi). rsync đặc biệt phù hợp với mục đích của tôi vì tôi đã làm việc với toàn bộ hệ thống tệp - vì vậy có rất nhiều tệp - và chỉ cần chạy rsync lần thứ hai sẽ khắc phục tất cả các sự cố của lần chạy đầu tiên (cần thiết khi tôi thiếu kiên nhẫn và thử để vượt qua 2,5mbs).

Tuy nhiên, tôi đoán rằng điều đó không thực tế cho một tệp. Trong trường hợp của bạn, bạn chỉ có thể chuyển sang dd được đặt thành raw-write - bạn có thể xử lý bất kỳ đầu vào nào theo cách đó, nhưng mỗi lần chỉ có một tệp mục tiêu (mặc dù tệp đó có thể là toàn bộ thiết bị khối).

## 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  

Bạn có thể thấy netcat nhanh hơn một chút so với ssh cho việc truyền dữ liệu nếu bạn cho nó một shot. Dù sao, những ý tưởng khác đã được thực hiện, vậy tại sao không?

[EDIT]: Tôi nhận thấy đề cập đến lftp, scp và ssh trong bài đăng khác và nghĩ rằng chúng ta đang nói về một bản sao từ xa. Địa phương dễ dàng hơn nhiều:

% 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

[EDIT2]: Tín dụng khi đến hạn: chỉ cần chú ý ptman đã đánh bại tôi với điều này bằng cách năm giờ trong các bình luận.

Chắc chắn bạn có thể điều chỉnh $ bs cho hiệu suất ở đây với số nhân - nhưng một số hệ thống tệp có thể yêu cầu nó phải là bội số của các phân vùng của fs mục tiêu, vì vậy hãy ghi nhớ điều đó.


Trên máy của tôi, cờ --getiooptkhông phải là--getoptio
Michael Mior

2

Vấn đề là bản sao đang lấp đầy bộ nhớ của bạn với các khối "trong chuyến bay", thu thập dữ liệu "hữu ích". Một lỗi đã biết (và rất khó sửa) trong xử lý nhân I / O của Linux đối với các thiết bị chậm (USB trong trường hợp này).

Có lẽ bạn có thể cố gắng đưa ra bản sao, ví dụ bằng một đoạn script như sau (bản phác thảo bằng chứng, hoàn toàn chưa được kiểm tra!):

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

điều chỉnh seekskiptheo counttừng vòng. Cần điều chỉnh countđể nó không lấp đầy (quá nhiều) bộ nhớ và 5để cho phép nó thoát.


2

Hạ giới hạn trang bẩn. Giới hạn mặc định là điên rồ.

Tạo /etc/sysctl.d/99-sysctl.conf bằng:

vm.dirty_background_ratio = 3
vm.dirty_ratio = 10

Sau đó chạy sysctl -p hoặc khởi động lại.

Điều đang xảy ra là dữ liệu đang được đọc nhanh hơn dữ liệu có thể được ghi vào đĩa đích. Khi linux sao chép các tập tin, những gì nó làm là đọc chúng vào RAM, sau đó đánh dấu các trang là bẩn để ghi vào đích. Các trang bẩn không thể được hoán đổi. Vì vậy, nếu đĩa nguồn nhanh hơn đĩa đích và bạn đang sao chép nhiều dữ liệu hơn RAM miễn phí, thao tác sao chép sẽ ăn hết tất cả RAM có sẵn (hoặc ít nhất là bất kể giới hạn trang bẩn là gì, có thể nhiều hơn RAM khả dụng) và gây chết đói vì các trang bẩn không thể bị tráo đổi và các trang sạch sẽ được sử dụng và bị đánh dấu bẩn khi chúng được giải phóng.

Lưu ý rằng anh ta sẽ không giải quyết được hoàn toàn vấn đề ... những gì linux thực sự cần là một cách nào đó để phân xử việc tạo ra các trang bẩn để việc chuyển tiền lớn diễn ra không ăn hết RAM / tất cả các trang bẩn được phép.


0

Vấn đề này không liên quan đến lỗi hoặc lỗi trong phần cứng hoặc phần mềm, đó chỉ là hạt nhân của bạn đang cố gắng trở nên tốt đẹp với bạn và đưa lại lời nhắc và sao chép trong nền (nó sử dụng bộ đệm trong kernel: nhiều RAM hơn, nhiều bộ đệm hơn, nhưng bạn có thể giới hạn nó bằng cách viết ở đâu đó trong / Proc - mặc dù không được giới thiệu lại). Ổ đĩa flash quá chậm và trong khi kernel ghi vào nó, các hoạt động IO khác không thể được thực hiện đủ nhanh. ioniceđề cập một vài lần trong các câu trả lời khác là ok. Nhưng bạn đã thử gắn ổ đĩa -o syncđể tránh bộ đệm hệ điều hành chưa? Đây có lẽ là giải pháp đơn giản nhất hiện có.


Sau khi bật đồng bộ -o, Internet của tôi nhanh hơn tốc độ ghi vào ổ USB này. Điều tôi không hiểu là tại sao kernel không theo dõi các trang bộ nhớ cache được xóa nhanh như thế nào và lên lịch cho các lần xóa trong tương lai dựa trên điều đó. Nó giống như nó luôn luôn chạy ở tốc độ tối đa, ngay cả khi ổ đĩa kém này không thể theo kịp tốc độ. Nhưng đó là một chủ đề cho một câu hỏi khác tôi đoán.
antonone
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.