ทำดิสก์ / ดิสก์ให้ช้าลง


28

มีวิธีการชะลอกระบวนการคัดลอกบน Linux หรือไม่

ฉันมีไฟล์ขนาดใหญ่พูด 10GB และฉันต้องการคัดลอกไปยังไดเรกทอรีอื่น แต่ฉันไม่ต้องการคัดลอกด้วยความเร็วเต็ม สมมติว่าฉันต้องการคัดลอกด้วยความเร็ว 1mb / s ไม่ใช่เร็วขึ้น ฉันต้องการใช้cpคำสั่งLinux มาตรฐาน

เป็นไปได้ไหม (ถ้าใช่เป็นอย่างไร)

แก้ไข : ดังนั้นฉันจะเพิ่มบริบทเพิ่มเติมให้กับสิ่งที่ฉันพยายามจะทำให้สำเร็จ

ฉันมีปัญหาเกี่ยวกับระบบ ArchLinux เมื่อคัดลอกไฟล์ขนาดใหญ่ผ่าน USB (ไปยัง pendrive, ดิสก์ usb ฯลฯ ) หลังจากเติมบัฟเฟอร์บัฟเฟอร์ usb แล้วระบบของฉันจะหยุดการตอบสนอง (แม้กระทั่งเมาส์จะหยุดทำงาน แต่จะเคลื่อนที่เป็นระยะ ๆ ) การดำเนินการคัดลอกยังคงดำเนินต่อไป แต่ใช้ทรัพยากร 100% ของกล่อง เมื่อการคัดลอกเสร็จสิ้นทุกอย่างกลับสู่ปกติ - ทุกอย่างตอบสนองได้อย่างสมบูรณ์แบบอีกครั้ง

อาจเป็นข้อผิดพลาดของฮาร์ดแวร์ฉันไม่รู้ แต่ฉันรู้ว่าฉันมีสองเครื่องที่มีปัญหานี้ (ทั้งสองอยู่ใน ArchLinux, หนึ่งคือกล่องเดสก์ท็อป, ที่สองคือแล็ปท็อป)

"แก้ปัญหา" ที่ง่ายที่สุดและเร็วที่สุดในเรื่องนี้ (ฉันยอมรับว่าไม่ใช่โซลูชัน 'ของจริง' เพียงแค่น่าเกลียด 'แฮ็ค') เพื่อป้องกันไม่ให้บัฟเฟอร์นี้เติมโดยการคัดลอกไฟล์ด้วยความเร็วในการเขียนเฉลี่ยของไดรฟ์ USB ฉันว่าจะเพียงพอ


7
หากคุณต้องการ จำกัด ความเร็วในการคัดลอกข้อมูลจากดิสก์สู่ดิสก์ในความพยายามที่จะ "ดี" สำหรับกระบวนการ I / O แบบ จำกัด อื่น ๆ ในระบบคุณน่าจะดีกว่าที่จะใช้ประโยชน์จากความสามารถของเคอร์เนลในการปรับการตั้งเวลา I / O แทน. โดยเฉพาะioniceสามารถใช้เพื่อให้แน่ใจว่ากระบวนการคัดลอกดิสก์ต่อดิสก์ของคุณถูกกำหนดเวลา I / O ที่ระดับความสำคัญต่ำกว่ากระบวนการปกติ
Steven วันจันทร์ที่

3
นี่เป็นคำถามปัญหา XYแบบคลาสสิก คุณควรถามเกี่ยวกับสาเหตุที่เดสก์ท็อปของคุณไม่ตอบสนองเมื่อคุณคัดลอกไฟล์ไปยังอุปกรณ์ USB
Michael Hampton

4
Linux มีบัฟเฟอร์ I / O ขนาดใหญ่อย่างน่าขันในปัจจุบัน ขนาด RAM เติบโตเร็วกว่าความเร็วในการจัดเก็บข้อมูลจำนวนมาก บางทีคุณสามารถทำสำเนาโดยใช้ dd (1) และซิงค์เพื่อที่จะซิงค์เป็นระยะแทนที่จะถูกบัฟเฟอร์? และไปป์วิวเวอร์ (pv) มีตัวเลือก จำกัด อัตรา cat file | pv -L 3k > outfileสิ่งที่ชอบ ไม่เหมือนกับการใช้ cp (1)
ptman

@MichaelHampton มีหลายหัวข้อที่ไม่ได้รับการแก้ไขในฟอรัมของ ArchLinux ดังนั้นฉันคิดว่าฉันจะพยายามรับมือกับมันในวิธีที่แตกต่างกันเพื่อให้มันทำงานได้
antonone

@antonone But Unix.SE ไม่ใช่ฟอรัมของ ArchLinux บางคนที่นี่อาจมีทางออก
Izkata

คำตอบ:


23

คุณสามารถเค้นท่อด้วยpv -qL(หรือcstream -tมีฟังก์ชั่นที่คล้ายกัน)

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

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

แต่เดิมคำตอบนี้ชี้ไปที่throttleแต่โครงการนั้นไม่สามารถใช้งานได้อีกต่อไปดังนั้นจึงหลุดออกมาจากระบบแพคเกจบางระบบ


หากcpไม่สามารถทำให้ช้าลงได้การใช้คำสั่งกำหนดเองเป็นตัวเลือกเดียวที่ฉันเดา
antonone

1
ฟังดูซับซ้อนเกินไปเมื่อเทียบกับrsync
LinuxSecurityFreak

ดูซับซ้อนกว่า แต่ใช้ได้กับฉันมากขึ้น จำเป็นต้องทดสอบ lockingechanism ของไฟล์และต้องการชะลอการคัดลอกลงไปบางไบต์ / s ซึ่งดูเหมือนว่าเป็นไปไม่ได้ด้วย rsync ฉันจะลองและ 'cat' ไฟล์ผ่านท่อปีกผีเสื้อ
cljk

เศร้าที่จะพูด แต่โครงการนี้เป็นบั๊กที่
cljk

1
@cljk pvปรับปรุงเพื่อ ขอบคุณ
แมตต์

23

แทนที่จะcp -a /foo /barคุณยังสามารถใช้rsyncและ จำกัด แบนด์วิดธ์ที่คุณต้องการ

จากrsyncคู่มือของ:

--bwlimit=KBPS

จำกัด แบนด์วิดท์ I / O; กิโลไบต์ต่อวินาที

ดังนั้นคำสั่ง actuall ยังแสดงความคืบหน้าเช่นนี้:

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

นี่เป็นความคิดที่ดีสำหรับการคัดลอกไดรฟ์เก่าที่ฉันไม่ต้องการเอาชนะ
jeremyjjbrown

ไม่ทำงานสำหรับการอ่านจาก/dev/zeroหรือ/dev/random
cdosborn

rsync -a --bwlimit=1500 /source /destinationทำงานได้อย่างสมบูรณ์เพื่อคัดลอกโฟลเดอร์ขนาดยักษ์ที่ความเร็ว 1,5 MB / s (ซึ่งเป็นการแลกเปลี่ยนที่ดีระหว่างการหลีกเลี่ยงเซิร์ฟเวอร์ใด ๆ ที่ช้าลงและไม่ใช้เวลามากเกินไป)
lucaferrario

Sidenote: แม้ในขณะที่ man page อาจบอกว่าคุณสามารถใช้ตัวอักษรสำหรับหน่วยเช่น20mมันไม่ได้รับการสนับสนุนในทุกแพลตฟอร์มดังนั้นควรติดสัญลักษณ์ KBytes
Hubert Grzeskowiak

บันทึกวันของฉัน! cgroup cgexec -g ... cp /in /outไม่ทำงานตลอดเวลา (จากเทอร์มินัลทำงานบางครั้งไม่เคยเขียนสคริปต์) และฉันก็ไม่รู้ว่าทำไม ...
Aquarius Power

13

ฉันจะสมมติว่าคุณกำลังพยายามที่จะไม่ขัดขวางกิจกรรมอื่น ๆ Linux เวอร์ชันล่าสุดประกอบด้วยioniceซึ่งอนุญาตให้คุณควบคุมการกำหนดตารางเวลาของ IO

นอกเหนือจากการอนุญาตให้มีการจัดลำดับความสำคัญต่าง ๆ มีตัวเลือกเพิ่มเติมเพื่อ จำกัด IO กับเวลาเมื่อดิสก์ไม่ได้ใช้งาน คำสั่งman ioniceจะแสดงเอกสาร

ลองคัดลอกไฟล์โดยใช้คำสั่งเช่น:

ionice -c 3 cp largefile /new/directory

หากทั้งสองไดเรกทอรีอยู่ในอุปกรณ์เดียวกันคุณอาจพบว่าการลิงก์ไฟล์นั้นเป็นสิ่งที่คุณต้องการ หากคุณกำลังคัดลอกเพื่อวัตถุประสงค์ในการสำรองข้อมูลอย่าใช้ตัวเลือกนี้ lnเร็วมากเนื่องจากไฟล์จะไม่ถูกคัดลอก ลอง:

ln largefile /new/directory

หรือถ้าคุณเพียงต้องการเข้าถึงจากไดเรกทอรีบนอุปกรณ์อื่นลอง:

ln -s largefile /new/directory

ionice ทำงานได้ดีใน linux หรือไม่ ฉันอ่านมันแค่ "เลียนแบบ" งานและไม่มีความแตกต่างจริงหรือ +1 สำหรับลิงก์
Nick

1
@Nick เมื่อฉันใช้มันก็มีพฤติกรรมตามที่คาดไว้ กระบวนการที่ฉันใช้อิออนิสชะลอตัวลงอย่างมีนัยสำคัญกระบวนการอื่น ๆ ที่จำเป็นต้องใช้ I / O สามารถดำเนินการได้ตามที่คาดไว้ ด้วยการโหลด I / O ในระดับปานกลางจากกระบวนการอื่น ๆ ฉันสามารถระงับกระบวนการ I / O ที่มีประสิทธิภาพได้อย่างมีประสิทธิภาพด้วยการใช้ 'ความดี' สูงสุดตามที่คาดไว้ เมื่อไม่มี I / O ที่แข่งขันกันแล้วกระบวนการไอออไนซ์ก็ดำเนินการตามปกติ
BillThor

ด้วยไฟล์ 400MB ที่ฉันกำลังคัดลอกจาก HD หนึ่งไปยัง SSD, 10s แรกทำงานได้อย่างสมบูรณ์แบบจากนั้นฉันก็เห็นว่าฉันโหลด IO สูงและต้องรอเช่น 1minute machine Frozen: / ฉันมีปัญหาเดียวกันกับ cgroup เขียน io throttle ที่บางครั้งมันทำงานและอื่น ๆ ที่มันไม่ทำงานเลย
กุมภ์ Power

7

หากการioniceแก้ปัญหาไม่เพียงพอ (ไม่ว่าจะด้วยเหตุผลใด) และคุณต้องการ จำกัด I / O ให้มีค่าสัมบูรณ์แน่นอนมีความเป็นไปได้หลายประการ:

  1. sshอาจจะง่ายที่สุด: มีขีด จำกัด แบนด์วิดท์ในตัว คุณจะใช้เช่นtar(แทนcp) หรือscp(ถ้าดีพอฉันไม่รู้ว่ามันจัดการกับลิงก์และฮาร์ดลิงก์) หรือrsyncไม่ sshคำสั่งเหล่านี้สามารถท่อข้อมูลของพวกเขามากกว่า ในกรณีที่tarคุณเขียนไปยัง/dev/stdout(หรือ-) และไปป์ที่ลงในsshไคลเอนต์ซึ่งดำเนินการอื่นtarในด้าน "ระยะไกล"

  2. สง่างาม แต่ไม่ได้อยู่ในวานิลลาเคอร์เนล (AFAIK): iobandเป้าหมาย แน่นอนว่าทำงานได้ก็ต่อเมื่อคุณสามารถขยายปริมาณแหล่งข้อมูลหรือปริมาณเป้าหมายได้

  3. ความสนุกที่เขียนขึ้นเอง: grep "^write_bytes: " /proc/$PID/ioให้ปริมาณข้อมูลที่กระบวนการเขียน คุณสามารถเขียนสคริปต์ที่เริ่มต้นcpในพื้นหลังนอนเป็นเวลาเช่น 1 / 10th วินาทีหยุดcpกระบวนการพื้นหลัง( kill -STOP $PID) ตรวจสอบจำนวนเงินที่ได้รับการเขียน (และอ่านเกี่ยวกับค่าเดียวกันในกรณีนี้) คำนวณระยะเวลาcpจะต้องหยุดชั่วคราวเพื่อให้อัตราการถ่ายโอนโดยเฉลี่ยลดลงตามค่าที่ตั้งใจไว้พักในเวลานั้นตื่นขึ้นcp( kill -CONT $PID) และอื่น ๆ


ใช่ปกติฉันแค่ใช้ lftp เพื่อเชื่อมต่อ localhost ผ่าน scp และ จำกัด bandwich จากที่นั่น
antonone

5

ปัญหาของคุณอาจไม่ได้อยู่ที่คอมพิวเตอร์ของคุณ แต่เลเยอร์การเปลี่ยนแปลงของ USB flash นั้นมีหน่วยประมวลผลของตัวเองที่ต้องแมปการเขียนทั้งหมดของคุณเพื่อชดเชยสิ่งที่อาจเป็นชิปแฟลชที่ผิดพลาด 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  

คุณอาจพบว่า 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 เอาชนะฉันได้โดยชอบในความคิดเห็นห้าชั่วโมง

แน่นอนคุณสามารถปรับแต่ง $ bs เพื่อประสิทธิภาพที่นี่ด้วยตัวคูณ - แต่ระบบไฟล์บางระบบอาจต้องการให้มันเป็นเซกเตอร์ของ fs เป้าหมายหลายตัวดังนั้นอย่าลืมว่า


บนเครื่องของฉันธง--getiooptไม่ใช่--getoptio
Michael Mior

2

ปัญหาคือการคัดลอกจะเติมหน่วยความจำของคุณด้วยบล็อก "ในเที่ยวบิน" ข้อมูล "ประโยชน์" เบียดเสียด ข้อผิดพลาดที่รู้จัก (และยากมากในการแก้ไข) ในการจัดการเคอร์เนล Linux ของ I / O เพื่อทำให้อุปกรณ์ช้าลง (USB ในกรณีนี้)

บางทีคุณอาจจะพยายามที่จะคัดลอกพัสดุออกเช่นโดยสคริปต์เช่นต่อไปนี้เป็น (หลักฐานของแนวคิดร่างทั้งหมดยังไม่ทดลอง!):

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

ปรับseekและskipโดยcountในแต่ละรอบ จำเป็นต้องปรับแต่งcountเพื่อไม่ให้หน่วยความจำเต็ม (มากเกินไป) และ5อนุญาตให้ระบายได้


2

ลดขีด จำกัด หน้ากระดาษสกปรก ขีด จำกัด เริ่มต้นนั้นบ้า

สร้าง /etc/sysctl.d/99-sysctl.conf ด้วย:

vm.dirty_background_ratio = 3
vm.dirty_ratio = 10

จากนั้นรัน sysctl -p หรือรีบูต

สิ่งที่เกิดขึ้นคือข้อมูลกำลังอ่านเร็วกว่าที่สามารถเขียนลงดิสก์ปลายทางได้ เมื่อ linux คัดลอกไฟล์สิ่งที่มันจะถูกอ่านลงใน RAM จากนั้นทำเครื่องหมายหน้าที่สกปรกสำหรับการเขียนไปยังปลายทาง ไม่สามารถสลับหน้าสกปรกได้ ดังนั้นหากดิสก์ต้นทางเร็วกว่าดิสก์ปลายทางและคุณกำลังคัดลอกข้อมูลมากกว่าที่คุณมี RAM ว่างการดำเนินการคัดลอกจะกิน RAM ที่มีอยู่ทั้งหมด (หรืออย่างน้อยสิ่งที่ขีด จำกัด ของหน้ากระดาษสกปรกซึ่งอาจมากกว่า RAM ที่มีอยู่) และก่อให้เกิดความอดอยากเนื่องจากไม่สามารถสลับหน้าสกปรกออกไปได้

โปรดทราบว่าเขาจะไม่สามารถแก้ปัญหาได้อย่างสมบูรณ์ ... สิ่งที่ linux ต้องการจริงๆคือวิธีที่จะตัดสินการสร้างหน้าสกปรกดังนั้นการถ่ายโอนครั้งใหญ่จึงไม่กิน RAM ที่มีอยู่ทั้งหมด / หน้าสกปรกที่ได้รับอนุญาตทั้งหมด


0

ปัญหานี้ไม่มีอะไรเกี่ยวข้องกับข้อผิดพลาดหรือความผิดพลาดในฮาร์ดแวร์หรือซอฟต์แวร์มันเป็นเพียงเคอร์เนลของคุณพยายามที่จะดีกับคุณและให้พรอมต์ของคุณกลับมาและคัดลอกในพื้นหลัง (ใช้แคชในเคอร์เนล: RAM เพิ่มเติมแคชเพิ่มเติม แต่คุณสามารถ จำกัด ได้ด้วยการเขียนบางแห่งใน / proc - ไม่แนะนำอีกครั้งแม้ว่า) แฟลชไดรฟ์ช้าเกินไปและในขณะที่เคอร์เนลเขียนการดำเนินการ IO อื่น ๆ ไม่สามารถทำได้เร็วพอ ioniceกล่าวถึงหลายครั้งในคำตอบอื่น ๆ ก็โอเค แต่คุณลองติดตั้งไดรฟ์ด้วย-o syncเพื่อหลีกเลี่ยงการบัฟเฟอร์ระบบปฏิบัติการหรือไม่ มันอาจเป็นทางออกที่ง่ายที่สุด


หลังจากเปิดใช้งาน -o sync อินเทอร์เน็ตของฉันเร็วกว่าเขียนความเร็วลงในไดรฟ์ USB นี้ สิ่งที่ฉันไม่เข้าใจคือสาเหตุที่เคอร์เนลไม่ติดตามว่าหน้าแคชกำลังถูกฟลัชเร็วแค่ไหนและกำหนดเวลาการฟลัชในอนาคตตามนั้น มันเหมือนความเร็วเต็มเสมอแม้ว่าไดร์ฟที่ไม่ดีนี้จะไม่สามารถรักษาความเร็วได้ แต่นั่นเป็นหัวข้อสำหรับคำถามอื่นที่ฉันเดา
antonone
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.