ฉันพบว่าสิ่งนี้จะทำให้เกิดข้อผิดพลาด "การโต้เถียงนานเกินไป":
ls *.*
และนี่จะไม่ยกมันขึ้นมา:
for file in *.*
do
echo $file
done
ทำไม?
ฉันพบว่าสิ่งนี้จะทำให้เกิดข้อผิดพลาด "การโต้เถียงนานเกินไป":
ls *.*
และนี่จะไม่ยกมันขึ้นมา:
for file in *.*
do
echo $file
done
ทำไม?
คำตอบ:
ข้อผิดพลาด“ การโต้แย้งยาวเกินไป” E2BIGเกิดจากการexecveเรียกระบบหากขนาดรวมของการขัดแย้ง (รวมถึงสภาพแวดล้อมในบางระบบ) มีขนาดใหญ่เกินไป การexecveเรียกเป็นสิ่งที่เริ่มต้นกระบวนการภายนอกโดยเฉพาะอย่างยิ่งการโหลดไฟล์เรียกทำงานที่แตกต่างกัน (มีการเรียกที่แตกต่างกันforkสำหรับการเรียกใช้กระบวนการที่แยกต่างหากซึ่งรหัสยังคงมาจากไฟล์ปฏิบัติการเดียวกัน) ห่วงเป็นโครงสร้างเปลือกภายในดังนั้นจึงไม่เกี่ยวข้องกับการเรียกร้องfor execveคำสั่งls *.*ทำให้เกิดข้อผิดพลาดไม่ใช่เมื่อ glob ถูกขยาย แต่เมื่อlsถูกเรียก
execveล้มเหลวด้วยข้อผิดพลาดE2BIGเมื่อขนาดรวมของการขัดแย้งกับคำสั่งที่มีขนาดใหญ่กว่าขีด จำกัดARG_MAX คุณสามารถเห็นคุณค่าของขีด จำกัด getconf ARG_MAXนี้ในระบบของคุณด้วยคำสั่ง (เป็นไปได้ว่าคุณสามารถไปได้เกินขีด จำกัด นี้หากคุณมีหน่วยความจำเพียงพอให้อยู่ภายใต้ARG_MAXการรับประกันที่execveจะทำงานตราบเท่าที่ไม่มีข้อผิดพลาดที่ไม่เกี่ยวข้องเกิดขึ้น)
execveข้อ จำกัด ถูกบังคับใช้โดยเคอร์เนลทำให้มีข้อ จำกัด เนื่องจากอาร์กิวเมนต์ต้องถูกคัดลอกผ่านหน่วยความจำเคอร์เนล ณ จุดเดียวและกระบวนการของผู้ใช้ไม่สามารถอนุญาตให้ร้องขอจำนวนหน่วยความจำเชลล์โดยพลการ ภายในเชลล์นั้นไม่มีเหตุผลที่จะ จำกัด อะไรเลยสิ่งที่เหมาะกับหน่วยความจำเสมือนก็ใช้ได้
ผมคิดว่าในตัวอย่างแรกlsจะดำเนินการจากbashผ่านfork/ สายระบบคู่ในหนึ่งวินาทีทั้งหมดทำงานอยู่ภายในexecbash
การexecโทรมีข้อ จำกัด การทำงานภายในของbashแทนไม่ได้ (หรือดีกว่ามีข้อ จำกัด ต่าง ๆ ที่ไม่มีส่วนเกี่ยวข้องกับexecจำนวนหน่วยความจำที่มีอยู่)
execในมักจะกำหนดให้เป็น/usr/include/linux/limits.h ARG_MAX
เพราะในกรณีที่lsมันเป็นข้อโต้แย้งและจำนวนข้อโต้แย้งมี จำกัด
ในกรณีของforรอบมันเป็นเพียงรายการ ไม่มีข้อ จำกัด (เท่าที่ฉันทราบ) สำหรับสิ่งนั้น
for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
/bin/bashเทียบกับ/bin/sh(ซึ่งอาจเป็นลิงก์ไปยังเส้นประ)