ทำไมเสียงก้องเชลล์ในตัวจึงเป็นคำสั่ง?


34
$ which echo
echo: shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat

เพราะเหตุใดจึงไม่ได้สะท้อนยูทิลิตี้ที่เป็นอิสระเช่นls, ps, catetc? ทำไมมันถึงเป็นเปลือกเฉพาะ? มีเหตุผลที่ดีไหม?


5
จำไว้ว่านี่เป็นเชลล์เฉพาะ ZSH สร้างขึ้นใน BASH ไม่ได้
tsvallender

21
@tsv: echoแน่นอนที่สุดคือ Bash builtin ในความเป็นจริงมันเป็น builtin ในทุก ๆ โมเดิร์นเชลล์
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

คำตอบ:


71

มีบิวด์อินสองชั้น:

  1. คำสั่งบางอย่างจะต้องมีการสร้างไว้ในโปรแกรมเชลล์เพราะมันไม่สามารถทำงานได้หากพวกมันอยู่ภายนอก

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

  2. คำสั่งคลาสอื่น ๆ ถูกสร้างไว้ในเชลล์เพื่อประสิทธิภาพอย่างแท้จริง

    หน้าคนมีส่วน builtins ซึ่งกล่าวถึง, และเป็นตัวอย่างของคำสั่งในชั้นนี้dash printfechotest

ระบบ Unix ได้รวมโปรแกรมเรียกทำงานแยกต่างหากสำหรับคำสั่งในคลาสที่สองนั้นเสมอ executables แยกเหล่านี้ยังคงมีอยู่ในระบบ Unixy ทุกระบบที่ฉันใช้แม้ว่าจะสร้างไว้ในเชลล์ทุกตัวที่คุณน่าจะใช้ก็ตาม ( POSIXต้องการให้ไฟล์ปฏิบัติการเหล่านี้มีอยู่จริง)

ฉันเชื่อว่าechoมีการสร้างไว้ในเชลล์ใน AT&T Unix System V Release 3.1 ฐานผมว่าเมื่อเปรียบเทียบสองรุ่นแตกต่างกันของคู่มือสำหรับ AT & Ts 3B1 ชุดระบบ ใครบางคนได้สแกนกรุณา 1,986 ฉบับคู่มือเหล่านี้และทำให้พวกเขาออนไลน์ ; สิ่งเหล่านี้สอดคล้องกับรีลีสดั้งเดิมของ SVR3 คุณจะเห็นว่าไม่ได้echoอยู่ในรายการในหน้า 523 ของคู่มือผู้ใช้ UNIX System V, Volume IIที่คุณคาดหวังหากคำสั่งนั้นถูกสร้างไว้ในเชลล์ ในกระดาษท้องถิ่นของฉันของคู่มือ SVR3.1 จากปี 1987 echo มีการระบุไว้ในส่วนนี้ของคู่มือ

ฉันค่อนข้างแน่ใจว่านี่ไม่ใช่นวัตกรรมCSRG ของ Berkeley ที่ AT&T นำกลับบ้าน 4.3BSD ออกมาในปีเดียวกับ SVR3, 1986 แต่ถ้าคุณดูmanpage ของ sh.1 4.3BSDคุณจะเห็นว่าechoมันไม่ได้อยู่ในรายการคำสั่งในตัว "คำสั่งพิเศษ" ของส่วน หาก CSRG ทำเช่นนี้นั่นทำให้เราต้องการแหล่งเอกสารที่จะพิสูจน์มัน

ณ จุดนี้คุณอาจสงสัยว่าechoมีการสร้างลงในเชลล์ก่อนหน้า SVR3.1 หรือไม่และข้อเท็จจริงนี้ไม่ได้มีการบันทึกไว้จนกว่าจะถึงตอนนั้น pre-SVR3 AT&T Unix ซอร์สโค้ดใหม่ล่าสุดที่มีให้ฉันอยู่ในtarball PDP-11 System IIIซึ่งคุณจะพบซอร์สโค้ดเชลล์บอร์น คุณจะไม่พบechoในตารางคำสั่ง builtin /usr/src/cmd/sh/msg.cซึ่งอยู่ใน จากการประทับเวลาในไฟล์นั้นพิสูจน์echoได้ว่าไม่ได้อยู่ในเชลล์ในปี 1980


เรื่องไม่สำคัญ

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

/*      
    builtin commands are those that Bourne did not intend
    to be part of his shell.
    Redirection of i/o, or rather the lack of it, is still a
    problem..
*/      

ในหน้า 385 ของ SysV UM ฉบับที่สองที่คุณกล่าวถึงนั่นคือในตัวprintคำสั่งสำหรับการ ksh echoซึ่งกล่าวกันว่าทำตัวเหมือน คำสั่งนี้มีอยู่ในบางสิ่งเช่น AT&T Unix SVR4 2.1 i386 จาก ISC เช่นกัน print "\012"ให้ผลลัพธ์เช่นเดียวกับเสียงสะท้อน สงสัยว่าทำไม ksh มีการพิมพ์และไม่ใช่เสียงสะท้อนในตัว? อย่างไรก็ตามน่าสนใจจริงๆ

มีอัญมณีดังกล่าวกี่ปีที่ผ่านมาที่ถูกดักรอที่จะถูกค้นพบโดยการแก้ไขในปี 2016? +1
iruvar

+1 ขอบคุณ คุณสามารถให้แหล่งข้อมูล (การอ้างอิง) เพื่อจุดประสงค์ในการสร้างคำสั่งสำหรับการอ่าน / การเรียนรู้ (เป็นระบบ) ของฉันได้หรือไม่?
ทิม

ฉันต้องการค้นหาข้อมูลอ้างอิงคู่มือหรือมาตรฐานเพื่ออ่านหรือเรียนรู้อย่างเป็นระบบ ฉันพยายามค้นหามันในคู่มืออ้างอิง bash และข้อมูลจำเพาะ POSIX แต่ฉันหามันไม่เจอ ฉันไม่แน่ใจว่าฉันคิดถึงพวกเขาหรือไม่
ทิม

@Tim: เนื่องจากคำตอบนี้และคำตอบอื่น ๆ ที่นี่จะต้องมีคำสั่งบางคำในเชลล์หรือไม่สามารถทำงานได้ คนอื่น ๆ ทั้งหมดที่มีตัวเลือกอย่างหมดจด นั่นเป็นสิ่งที่ข้อมูลโค้ดบอร์นเชลล์ของฉันบอกไว้ข้างต้นในความเป็นจริง เนื่องจากการสร้างคำสั่งดังกล่าวลงในเปลือกเป็นทางเลือกเหตุผลที่เชื่อถือได้สามารถให้ความเห็นของผู้ปฏิบัติงานเพียงคนเดียว
Warren Young

19

มีเหตุผลข้อที่สามสำหรับการสร้างคำสั่งภายใน: สามารถใช้เมื่อคำสั่งภายนอกเป็นไปไม่ได้

บางครั้งระบบจะเสียจนlsคำสั่งไม่ทำงาน ในบางกรณีecho *จะยังคงทำงาน

อีกตัวอย่าง (ที่สำคัญกว่า!) คือkill: หากระบบไม่มี PID ฟรีมันเป็นไปไม่ได้ที่จะเรียกใช้/bin/kill(เพราะมันต้องการ PID :-) แต่ในตัวเครื่องkillจะใช้งานได้

Btw. whichเป็นคำสั่งภายนอก (อย่างน้อยก็ไม่ใช่ภายในเป็น bash) ดังนั้นจึงไม่สามารถแสดงรายการคำสั่งภายในได้ ตัวอย่างเช่น

$ which echo
/bin/echo
$ type -a echo
echo is a shell builtin
echo is /bin/echo

อย่าลืมว่า executables ภายนอกเกือบทั้งหมดใช้ไฟล์ไลบรารี บางครั้งหายนะเกิดขึ้นและไม่สามารถโหลดห้องสมุดเหล่านั้นได้ (คำแนะนำ: ไม่เคยมีปัญหาldconfigเว้นแต่คุณจะรู้ว่าคุณกำลังทำอะไรอยู่) นอกจากนี้จะเกิดอะไรขึ้นถ้าคุณระเบิด / bin ของคุณหรือแย่กว่านั้นพาร์ติชั่น / sbin ของคุณ แต่ยังมีเชลล์ที่โหลดอยู่?
LawrenceC

หากคุณหมด PID อาจเป็นเรื่องยากที่จะหา PID ที่คุณต้องการฆ่า คุณไม่สามารถเรียกใช้psคำสั่งดังนั้นคุณจะต้องไปหา PIDs /procด้วยตนเองผ่าน
kasperd

แม้ว่าเปิด (อย่างน้อย) CentOS whichเป็นนามแฝงทุบตีที่ทำงานalias | /usr/bin/which --read-alias ...เพื่อให้ภายนอกwhich สามารถระบุนามแฝง (แต่ยังไม่ได้สร้างขึ้นภายใน) ฉันไม่สามารถตัดสินใจได้ว่าจะพิจารณาสิ่งที่ยอดเยี่ยมหรือในทางที่ผิด
dave_thompson_085

ณ จุดที่คำสั่ง ls ไม่ทำงานอีกต่อไปฉันคิดว่าคุณควรจะติดตั้งไดรฟ์เป็นสลาฟแทนที่จะเป็นบูท / มาสเตอร์และแก้ไขโครงสร้างไฟล์ในแบบนั้น ฉันไม่แน่ใจว่าคุณจะแก้ไขความเสียหายของระบบในระดับดังกล่าวด้วยเสียงสะท้อนได้อย่างไรถ้าคุณไม่ได้สะท้อนเสียง> เป็นไฟล์และอาจใช้เวลานานในการแก้ไข ได้รับคุณสามารถเขียนสคริปต์ทุบตีที่จะแก้ไขโครงสร้างของระบบ
jonnyjandles

13

ตามคู่มืออ้างอิง Bashมันเป็นเรื่องของความสะดวกสบาย

Shells ยังมีชุดคำสั่งในตัว (builtins) ขนาดเล็กที่ใช้งานฟังก์ชั่นที่เป็นไปไม่ได้หรือไม่สะดวกในการขอรับผ่านยูทิลิตี้แยกต่างหาก ตัวอย่างเช่น cd, break, continue และ exec) ไม่สามารถนำไปใช้นอกเชลล์ได้เพราะพวกมันจัดการเชลล์เองโดยตรง ประวัติ, getopts, kill, หรือ pwd builtins, อื่น ๆ สามารถนำไปใช้ในยูทิลิตี้ที่แยกจากกัน, แต่มันสะดวกกว่าที่จะใช้เป็นคำสั่ง builtin ตัวบิวด์เชลล์ทั้งหมดอธิบายไว้ในส่วนถัดไป

ขั้นสูงทุบตี Scripting คู่มือมีคำอธิบายรายละเอียดเพิ่มเติมได้ที่:

"builtin เป็นคำสั่งที่อยู่ในชุดเครื่องมือทุบตีซึ่งมีอยู่ในตัวนี่เป็นเพราะเหตุผลด้านประสิทธิภาพการทำงาน - builtins จะทำงานได้เร็วกว่าคำสั่งภายนอกซึ่งโดยทั่วไปต้องใช้ การแยก1กระบวนการที่แยกต่างหาก - เข้าถึงเชลล์ภายใน "

โปรดทราบด้วยว่าechoมีอยู่เป็นยูทิลิตี้สแตนด์อโลนในบางระบบ นี่คือสิ่งที่ฉันมีในระบบของดาร์วิน (MacOSX 10.5.8 - Leopard)

$ uname -a
Darwin host.foo.org 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386
$ bash --version
GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
$ which echo
/bin/echo

echoนอกจากนี้ยังมีให้เป็นแบบบิลด์อิน แต่เห็นได้ชัดว่าสคริปต์ของฉันใช้ / bin / echo บน Mac ของฉันและใช้ Bash builtin บนระบบ Linux และ FreeBSD ส่วนใหญ่ของฉัน แต่ดูเหมือนจะไม่สำคัญเพราะสคริปต์ยังคงทำงานได้ทุกที่


3
เมื่อพูดถึงบิวด์อินคุณควรใช้ "type" แทน "ซึ่ง"
ตุ๊กตา

ขอบคุณ @Teddy ฉันเริ่มทำอย่างนั้นเมื่อฉันจำได้ ขอบคุณมาก ๆ สำหรับtypeชีวิต
Stefan Lasiewski

6

เพื่อเติมเต็มคำตอบ BHM ของการพูดให้ของถูกลบออกโดยบังเอิญจากคุณ/bin PATHคุณต้องการที่จะecho $PATHพบว่าใช่มั้ย


2

แม้ว่าเชลล์ส่วนใหญ่จะมีในตัวในechoปัจจุบัน แต่ GNU CoreUtils ยังรวมถึงการใช้งานแบบสแตนด์อโลนของมัน:

$ which echo
/bin/echo
$ dpkg -S /bin/echo
coreutils: /bin/echo

ดูเหมือนว่าคุณไม่ได้ติดตั้ง GNU Coreutils (ส่วนใหญ่ที่ใช้ระบบปฏิบัติการลินุกซ์บนเดสก์ท็อปและเซิร์ฟเวอร์นั้นติดตั้งโดยปริยาย แต่ลินุกซ์ฝังหรือ UNIX อื่น ๆ อาจใช้คอลเลกชันเชลล์แทน)

BTW: หากดูBusybox , คุณจะเห็นว่าls, psและcatในตัวนอกจากนี้ยังมีคำสั่ง (หรืออย่างน้อยสามารถ; มันใช้สำหรับระบบฝังและทุกอย่างไม่จำเป็นต้องสามารถออกซ้าย)


3
การทดสอบของโปสเตอร์ต้นฉบับไม่สนับสนุนสมมติฐานที่/bin/echoไม่มีอยู่ พวกเขาเพิ่งแสดงให้เห็นว่า builtin นั้นมีความสำคัญเหนือกว่าechoโปรแกรมใด ๆใน PATH
Warren Young

1

นี่คือเหตุผลที่แท้จริงว่าทำไมจึงechoควรสร้างเชลล์ในตัว:

$PASSWORDสมมติว่าคุณมีรหัสผ่านในการ คุณเขียนมันไปยังไฟล์ได้./passwordอย่างไร? โปรแกรมเมอร์ธรรมชาติส่วนใหญ่จะเขียน:

echo "$PASSWORD" >./password

อย่างไรก็ตามหากechoไม่ใช่ shell builtin รหัสผ่านจะรั่วไหลไปยังผู้ใช้ทุกคนผ่านpsข้อมูล

แน่นอนถ้าคุณต้องการฉลาดเกี่ยวกับมันคุณสามารถหาวิธีเก็บรหัสผ่านได้โดยไม่ต้องechoใช้คุณสมบัติเชลล์อื่น ๆ :

cat >./password <<EOF
${PASSWORD}
EOF

อย่างไรก็ตามการมีechobuiltin เป็นเข็มขัดนิรภัยที่สำคัญเป็นวิธีที่ชัดเจนที่สุดในการบันทึกรหัสผ่านไปยังไฟล์ควรใช้งานได้เช่นกัน


3
ในขณะที่ผลข้างเคียงที่เป็นประโยชน์ฉันพบว่ามันน่าสงสัยอย่างมากว่านี่คือเหตุผล
plugwash

@DepressedDaniel: อะไรที่ทำให้คุณกลับมา? ข้อมูลอ้างอิงที่คุณใช้สนับสนุนคำตอบของคุณอยู่ที่ไหน
โจ๊ก
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.