เชลล์ได้รับอนุญาตให้ออปติไมซ์คำสั่งยุติการใช้งานอย่างไร้ประโยชน์หรือไม่?


27

หากมีการขอให้เชลล์ดำเนินการคำสั่งที่ไร้ประโยชน์ ( หรือไร้ประโยชน์บางส่วน ) ที่ทราบว่าจะยุติเช่นcat hugeregularfile.txt > /dev/nullมันสามารถข้ามการดำเนินการของคำสั่งนั้น ( หรือดำเนินการเทียบเท่าที่ถูกกว่าพูด touch -a hugeregularfile.txt )

โดยทั่วไปแล้วเชลล์มีลักษณะคล้ายกับคอมไพเลอร์ C ซึ่งมันอาจทำการแปลงใด ๆ ในซอร์สโค้ดตราบใดที่พฤติกรรมที่สังเกตได้จากภายนอกนั้นเหมือนกับถ้าเครื่องนามธรรมประเมินค่าหรือไม่

แก้ไข

Nota Bene: คำถามของฉันตามที่โพสต์ในตอนแรกมีชื่อเรื่องที่ถามว่าเชลล์ได้รับอนุญาตให้ทำการปรับแต่งเหล่านี้ได้หรือไม่ ฉันสนใจในทฤษฎีมากกว่าการปฏิบัติแม้ว่าทั้งสองยินดี


ไม่เชลล์ไม่ฉลาดเท่าคอมไพเลอร์สมัยใหม่ จริงๆแล้วมันค่อนข้างโง่ มันจะไม่ปรับรหัสที่ไร้ประโยชน์ใด ๆ
devnull

12
การคาดเดาว่าเจตนาของผู้ใช้ไม่ใช่สิ่งที่เชลล์ควรทำ ผู้ใช้อาจพยายามทำทุกอย่างด้วยคำสั่งนั้นการปรับให้เหมาะสมจะเป็นสิ่งที่ผิดแม้ว่าจะเป็นไปได้ก็ตาม
Chris Down

1
ไม่ว่าถ้าไฟล์เป็นอุปกรณ์แล้วcatก็ทำให้มันแตกต่างกันมาก เชลล์สามารถรับรู้ว่าไฟล์เป็นอุปกรณ์ แต่ไม่จำเป็นต้องเชื่อถือได้
yo '

3
@ StephaneChazelas C คอมไพเลอร์ไม่จำเป็นต้อง "ขออนุญาตจากใครบางคน" เพื่อเพิ่มประสิทธิภาพโปรแกรมที่คอมไพล์แล้ว; มีกฎราวกับว่าในมาตรฐาน C ซึ่งอนุญาตให้พวกเขาทำเช่นนั้น มาตรฐาน POSIX ดูเหมือนจะมีมาตรฐานอย่างน้อยหนึ่งเชลล์ ( pubs.opengroup.org/onlinepubs/009695399/utilities/… ) รวมถึงยูทิลิตี้อื่น ๆ อีกมากมาย ( pubs.opengroup.org/onlinepubs/009604499/utilities/wc.htmlสำหรับwcตัวอย่างเช่น) แต่เพื่อความรู้ที่ดีที่สุดของฉัน POSIX ไม่ได้รับตำแหน่งในการปรับเชลล์ให้เหมาะสม หรือไม่
Iwillnotexist Idonotexist

2
การเพิ่มประสิทธิภาพคือการปรับปรุงประสิทธิภาพด้วยทางลัดโดยไม่มีผลต่อการทำงาน ตราบใดที่รับประกันการใช้งานฉันไม่เห็น POSIX objecting การเพิ่มประสิทธิภาพที่เสนอของคุณจะทำลายข้อมูลจำเพาะของแมวแม้ว่า มีกรมธรรม์ที่ระบุในข้อมูลจำเพาะ POSIX kshว่าจะมีการรองรับประเภทของการเพิ่มประสิทธิภาพที่ทำโดยมี เช่นที่พวกเขาไม่ได้พูดกระบวนการแยกแต่สภาพแวดล้อม subshellเพื่อให้การเพิ่มประสิทธิภาพการประหยัดส้อม
Stéphane Chazelas

คำตอบ:


26

ไม่นั่นเป็นความคิดที่ไม่ดี

cat hugeregularfile.txt > /dev/nullและtouch -a hugeregularfile.txtไม่เหมือนกัน จะอ่านไฟล์ทั้งหมดแม้ว่าคุณจะเปลี่ยนเส้นทางออกไปcat /dev/nullและการอ่านไฟล์ทั้งหมดอาจเป็นสิ่งที่คุณต้องการ ตัวอย่างเช่นเพื่อแคชมันเพื่อให้การอ่านในภายหลังจะเร็วขึ้นอย่างมีนัยสำคัญ เปลือกไม่ทราบเจตนาของคุณ

ในทำนองเดียวกันคอมไพเลอร์ C จะไม่เพิ่มประสิทธิภาพการอ่านไฟล์แม้ว่าคุณจะไม่ได้ดูสิ่งที่คุณอ่าน


2
@Iwillnotexist: ทุกคำสั่งที่เป็นประโยชน์ (ยกเว้นเนื้อหาtrueและfalse) มีผลข้างเคียงที่อาจเกิดขึ้นและผลข้างเคียงมักเป็นจุดที่เรียกใช้คำสั่ง เชลล์ไม่สามารถรู้ผลข้างเคียงเหล่านั้นล่วงหน้า (สำหรับโปรแกรมภายนอกเช่นcat) โดยไม่ต้องแก้ไขปัญหาการหยุดชะงัก ดังนั้นจึงไม่ถูกต้องและถือว่าคุณหมายถึงสิ่งที่คุณพูด
cHao

5
@IwillnotexistIdonotexist ไม่เชลล์ไม่สามารถเห็นทุกสิ่งที่กำลังจะเกิดขึ้น catแต่ก็มีความคิดเกี่ยวกับไม่มี ที่จริงแล้วcatสามารถทำอะไรก็ได้ตั้งแต่การฟอร์แมตฮาร์ดไดรฟ์ของคุณไปจนถึงการดาวน์โหลดอินเทอร์เน็ต
scai

5
"Unix ไม่ได้ถูกออกแบบมาเพื่อหยุดผู้ใช้จากการทำสิ่งที่โง่เขลาเพราะมันจะหยุดพวกเขาจากการทำสิ่งที่ฉลาด" - Doug Gwyn
Agi Hammerthief

7
และแม้กระทั่ง @cHao trueและชุดfalse $?
Kyle Strand

3
ตามที่ @ scai ชี้ให้เห็นข้างต้นไฟล์ปฏิบัติการไม่เหมือนกับคำหลักภาษา: catและ/dev/nullมีความหมายทั่วไป แต่ไม่รับประกันว่าจะทำงานเช่นนั้น เพื่อทำการปรับให้เหมาะสมในขณะที่รับประกันว่าจะไม่มีการเปลี่ยนแปลงพฤติกรรมที่คาดหวังการปรับให้เหมาะสมนั้นทำได้เฉพาะการสร้างที่ดำเนินการภายในตัวเชลล์เองและไม่พบสิ่งต่าง ๆ ในสภาพแวดล้อมการดำเนินการ ...
andybuckley

20

ไม่เนื่องจาก/dev/nullเป็นเพียงชื่อซึ่งสามารถใช้กับอุปกรณ์อื่นหรือสำหรับไฟล์อื่นที่ไม่ใช่ "ปกติ" คืออ่างข้อมูล

ดังนั้นเชลล์ (หรือโปรแกรมอื่น ๆ ) จึงไม่มีความคิดขึ้นอยู่กับชื่อไม่ว่าไฟล์นั้นจะถูกเขียนไปยังทำอะไรบางอย่าง "ของจริง" กับข้อมูล มี AFAIK ที่ไม่มีระบบเรียกว่าโปรแกรมเชลล์สามารถสร้างได้เพื่อตรวจสอบว่าเช่นตัวอธิบายไฟล์ไม่ได้ทำอะไรเลย

การเปรียบเทียบของคุณกับการปรับโค้ดไม่ให้เหมาะสมในโปรแกรม C ไม่ทำงานเนื่องจากเชลล์ไม่มีภาพรวมทั้งหมดที่คอมไพเลอร์ C มีรหัสแหล่งที่มา เชลล์ไม่รู้จักพอที่/dev/nullจะเพิ่มประสิทธิภาพตัวอย่างของคุณออกไปมากขึ้นเช่นคอมไพเลอร์ C ไม่ทราบมากพอเกี่ยวกับโค้ดในฟังก์ชั่นเรียกว่ามันเชื่อมโยงแบบไดนามิกเพื่อไม่ให้โทร


4
เมื่อมันปรากฏออกมา ksh93 จะปฏิบัติ/dev/nullเป็นพิเศษบางครั้ง builtin ที่ได้ stdout ของมันนำไป/dev/nullเช่นจะไม่ส่งผลในการเขียนมีการกระทำใดecho foo >/dev/null/dev/nullมันไม่ได้ทำอะไรเป็นพิเศษถ้ามันเป็นคำสั่งที่ไม่ใช่ builtin (เช่นcat file >/dev/null)
Mark Plotnick

ความจริงcatอาจเป็นอย่างอื่นก็ได้ สิ่งอื่นใดในความเป็นจริง
orion

3
ที่จริง/dev/nullเป็นหนึ่งในไม่กี่เส้นทางที่ได้มาตรฐานพร้อมกับ/dev/tty, /dev/console, /tmp, และ/dev/ /
Gilles 'SO- หยุดความชั่วร้าย'

2
@MarkPlotnick จริง ๆ แล้วcat เป็น ksh93 ในตัว (ไม่เปิดใช้งานเว้นแต่คุณ/opt/ast/binจะใส่ก่อนหน้า/bin(หรือที่ใดก็ตามที่catมีให้) $PATH) และใช่แม้ว่าบิวด์อินนั้นcat file > /dev/nullจะทำreadเนื้อหาของfileมัน แต่ก็ไม่ได้เขียนลงใน / dev / null (แม้ว่ามันจะเปิดและ fstats)
Stéphane Chazelas

14

มันจะไม่ปรับคำสั่งที่ใช้งานให้เหมาะสม (และคุณได้รับคำตอบที่ดีจำนวนหนึ่งแล้วบอกคุณว่าทำไมไม่ควรทำ) แต่มันอาจทำให้ส้อมท่อ / ซ็อกเก็ตคู่อ่านได้ดีขึ้นในบางกรณี ประเภทของการเพิ่มประสิทธิภาพที่อาจทำ:

  • ด้วยเชลล์ที่ทันสมัยส่วนใหญ่คำสั่งสุดท้ายในสคริปต์โดยทั่วไปจะถูกดำเนินการในกระบวนการของเชลล์ยกเว้นบางtraps ถูกตั้งค่า ยกตัวอย่างเช่นในsh -c lsส่วนใหญ่ shการใช้งาน ( bash, mksh, ksh, zsh, yash, บางรุ่นash) lsจะไม่แยกกระบวนการทำงาน
  • ในการksh93ทดแทนคำสั่งจะไม่สร้างไพพ์หรือแยกกระบวนการจนกว่าคำสั่งภายนอกจะถูกเรียก ( $(echo foo)ตัวอย่างเช่นจะขยายเป็นfooไม่มีไพพ์ / ซ็อกเก็ตแพร์หรือส้อม)
  • readในตัวของเปลือกหอยบางคน ( bashAT & T ksh) จะไม่ทำแบบไบต์เดี่ยวอ่านถ้าพวกเขาตรวจสอบ stdin เป็น seekable (ในกรณีที่พวกเขาจะทำขนาดใหญ่อ่านและแสวงหากลับไปยังจุดสิ้นสุดของสิ่งที่พวกเขาจะหมายถึงการอ่าน)

ฉันชอบคำตอบนี้ แต่ก็ไม่ชัดเจนว่านี่เป็นเหตุผลดั้งเดิมหรือไม่ว่าข้อมูลจะมาจากการอ้างอิง (ซึ่งฉันต้องการเจาะ)
yoniLavi

3
@yoniYalovitsky ว่าเป็นเหตุผลเดิม ksh93เป็นเปลือกนำวิธีการในการเพิ่มประสิทธิภาพหน้าเป็นจุดมุ่งหมายของมันคือ / perlก็จะเห็นว่าเป็นที่ตราไว้กับการเขียนโปรแกรมภาษาเช่น ดังนั้นคุณสามารถดูkshเอกสารรหัส (โชคดี) และรายชื่อผู้รับจดหมายสำหรับข้อมูลเพิ่มเติม
Stéphane Chazelas

1
@HenkLangeveld ใช่คุณสามารถตรวจสอบว่ามีsh -c 'ps -p "$$"'ที่จะให้คุณpsและไม่ได้อยู่shกับผู้shใช้งานหรือ strace / นั่งร้าน / TUSC ...
Stéphane Chazelas

1
ความแตกต่างระหว่างksh -c 'ps; ps'และ bash -c 'ps; ps' นั้นน่าสนใจ Ksh93 ดำเนินต่อไปในการเพิ่มประสิทธิภาพ
Henk Langeveld

1
@ HenkLangeveld ขึ้นอยู่กับสิ่งที่kshเรากำลังพูดถึงการดำเนินการที่นี่ พฤติกรรมเช่นmksh พฤติกรรมที่มีความหมายส่วนใหญ่จะเพิ่มประสิทธิภาพของสิ่งที่ต้องการbash system("some command")โปรดทราบว่ามีผลข้างเคียงของการเพิ่มประสิทธิภาพนั้นเมื่อมันมาถึงสถานะทางออกของกระบวนการที่ยุติโดยสัญญาณ (ในบางเชลล์) ksh93เคยมีข้อผิดพลาดในการที่จะทำการเพิ่มประสิทธิภาพแม้ในขณะที่ตั้งกับดัก
Stéphane Chazelas

7

เมื่อเห็นcat hugeregularfile.txt > /dev/nullเปลือกไม่ได้รับอนุญาตให้เชื่อว่าการกระทำนั้นไร้ประโยชน์ - catไม่ได้เป็นส่วนหนึ่งของเปลือกหอยและสามารถทำทุกอย่างได้ในทางทฤษฎีและในทางปฏิบัติ

ตัวอย่างเช่นผู้ใช้อาจมีการเปลี่ยนชื่อปฏิบัติการrmไปcatและก็สายดำเนินการติดตามพฤติกรรมภายนอกเช่นการลบไฟล์

ผู้ใช้อาจคอมไพล์รุ่นcatที่เข้าสู่วงวนไม่ จำกัด ดังนั้นเชลล์ไม่สามารถสันนิษฐานได้ว่ามันเป็น 'รู้จักที่จะยุติ' ตามที่คุณแนะนำ

บางคนอาจติดตั้งรุ่นcatที่ใช้งานได้ตามต้องการ แต่ด้วยผลข้างเคียงเพิ่มเติมของการติดตั้งรูทคิทหากมีการรันด้วยสิทธิ์ที่เพียงพอ - อีกครั้งเชลล์ควรดำเนินการอย่างถูกต้อง


2
ที่จริงแล้วมีการmkshเพิ่มประสิทธิภาพV=$(cat file)โดยการสร้างมันขึ้นมาในตัว ดังนั้นเปลือกอาจเพิ่มประสิทธิภาพของมันออกมา แต่ไม่ได้เปลี่ยนtouch -aให้มันเป็นเพียงแค่
Steve Schnepp

1
@SteveSchnepp, cat เป็น builtin ในmkshแต่ที่รีสอร์ทในตัวกับระบบที่catผ่านตัวเลือกใด ๆ ซึ่งเป็นเหตุผลที่มี GNU ถ้าcat, mksh -c 'cat /dev/null --help'ไม่ได้ให้ผลเช่นเดียวกับbash -c 'cat /dev/null --help'แต่mksh -c 'cat --help /dev/null'ไม่ให้คุณเช่นเดียวกับbash -c 'cat --help /dev/null'(เป็นmkshแมวตัวเลือกในตัวแยกวิเคราะห์ POSIX ทางในขณะที่แมว GNU แยกวิเคราะห์พวกเขาทาง GNU)
Stéphane Chazelas

ใน bash และ ksh93 V=$(cat file)สามารถปรับให้เหมาะสมV=$(< file)ได้ นี้ความเร็วสิ่งที่แม้จะไม่มี catbuiltin
Henk Langeveld
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.