สคริปต์ที่คล้ายกันโดยไม่มีsudo
แต่ผลลัพธ์ที่คล้ายกัน:
$ cat script.sh
#!/bin/bash
sed -e 's/^/--/'
whoami
$ bash < script.sh
--whoami
$ dash < script.sh
itvirta
ด้วยbash
ส่วนที่เหลือของสคริปต์ไปเป็นข้อมูลป้อนเข้าsed
ด้วยdash
เชลล์ตีความมัน
ทำงานstrace
กับสิ่งเหล่านั้น: dash
อ่านบล็อกของสคริปต์ (แปด kB ที่นี่มากกว่าพอที่จะเก็บสคริปต์ทั้งหมด) แล้ววางไข่sed
:
read(0, "#!/bin/bash\nsed -e 's/^/--/'\nwho"..., 8192) = 36
stat("/bin/sed", {st_mode=S_IFREG|0755, st_size=73416, ...}) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|...
ซึ่งหมายความว่า filehandle อยู่ท้ายไฟล์และsed
จะไม่เห็นอินพุตใด ๆ dash
ส่วนที่เหลือถูกบัฟเฟอร์ภายใน (หากสคริปต์ยาวกว่าขนาดบล็อก 8 kB ส่วนที่เหลือจะถูกอ่านด้วยsed
)
ในทางกลับกัน Bash จะค้นหากลับไปที่ส่วนท้ายของคำสั่งสุดท้าย:
read(0, "#!/bin/bash\nsed -e 's/^/--/'\nwho"..., 36) = 36
stat("/bin/sed", {st_mode=S_IFREG|0755, st_size=73416, ...}) = 0
...
lseek(0, -7, SEEK_CUR) = 29
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|...
หากอินพุตมาจากไพพ์เช่นเดียวกับที่นี่:
$ cat script.sh | bash
ไม่สามารถกรอกลับได้เนื่องจากท่อและซ็อกเก็ตหาไม่ได้ ในกรณีนี้ Bash จะกลับไปอ่านอินพุตทีละตัวเพื่อหลีกเลี่ยงการโอเวอร์เฮด ( fd_to_buffered_stream()
ในinput.c
) ทำการโทรแบบเต็มระบบสำหรับแต่ละไบต์ไม่ได้มีประสิทธิภาพมากในหลักการ ในทางปฏิบัติฉันไม่คิดว่าการอ่านจะเป็นค่าใช้จ่ายที่ดีเมื่อเทียบกับความจริงที่ว่าสิ่งที่เชลล์ส่วนใหญ่เกี่ยวข้องกับการวางไข่กระบวนการใหม่ทั้งหมด
สถานการณ์คล้ายกันคือ:
echo -e 'foo\nbar\ndoo' | bash -c 'read a; head -1'
เชลล์ย่อยต้องตรวจสอบให้แน่ใจว่าread
อ่านขึ้นบรรทัดใหม่แรกเท่านั้นเพื่อให้head
เห็นบรรทัดถัดไป (ใช้ได้กับdash
ด้วย)
กล่าวอีกนัยหนึ่งทุบตีไปที่ความยาวเพิ่มเติมเพื่อรองรับการอ่านแหล่งเดียวกันสำหรับสคริปต์ตัวเองและสำหรับคำสั่งดำเนินการจากมัน dash
ไม่ zsh
และksh93
บรรจุใน Debian ไปกับทุบตีเกี่ยวกับเรื่องนี้
sudo su
: unix.stackexchange.com/questions/218169/…