ทำไมซอฟต์ลิงค์นี้ใช้งานไม่ได้ตามที่คาดไว้?


11
bash4.3 # pwd
/bin
bash4.3 # ll sh
lrwxrwxrwx. 1   root    root    4   May 17 22:22 sh -> bash
bash4.3 # ll bash
-rwxr-xr-x. 1   root    root    1072056 May 17 22:22 bash
bash4.3 # bash
bash4.3 # sh
sh-4.3#

ระบบปฏิบัติการของฉันคือ fedora 24 (รุ่น GNOME เริ่มต้น)

จากตัวอย่างที่เราสามารถรู้ภายใต้/bin, bashเป็นไบนารี; คือการเชื่อมโยงที่อ่อนนุ่มshbash

ดังนั้นเพื่อความรู้ของฉันควรจะมีผลกระทบต่อผลเดียวกันตรงตามที่type bash and press entertype sh and press enter

เมื่อฉันtype bash and press enterฉันได้รับ[root@localhost bin]#ตามที่คาดไว้

แต่ถ้าผมผมแปลกใจที่ได้รับtype sh and press entersh-4.3#

สาเหตุคืออะไร


ข้อความที่สามารถคัดลอกวางลงในเครื่องมือแก้ไข SE ได้อย่างง่ายดายเนื่องจากรูปภาพค่อนข้างน่ารำคาญดังนั้นโปรดอย่าทำเช่นนี้ เลือกข้อความในเทอร์มินัลของคุณและกด CTRL-SHIFT-C แทน
แมว

คำตอบ:


25

นั่นคือคุณสมบัติที่บันทึกไว้

หากคุณรัน bash ผ่าน symlink ที่ชื่อว่าshbash จะเริ่มในshโหมดความเข้ากันได้

จากman bash:

หาก bash ถูกเรียกใช้ด้วยชื่อ sh มันจะพยายามเลียนแบบพฤติกรรมการเริ่มต้นของ sh เวอร์ชั่นที่ผ่านมาที่สุดเท่าที่จะทำได้ในขณะที่สอดคล้องกับมาตรฐาน POSIX เช่นกัน เมื่อเรียกใช้เป็นเชลล์ล็อกอินแบบโต้ตอบหรือเชลล์แบบไม่มีการโต้ตอบที่มีตัวเลือก --login อันดับแรกจะพยายามอ่านและดำเนินการคำสั่งจาก / etc / profile และ ~ / .profile ตามลำดับนั้น --oprofile ตัวเลือกอาจถูกใช้เพื่อยับยั้งพฤติกรรมนี้ เมื่อเรียกใช้เป็นเชลล์เชิงโต้ตอบที่มีชื่อ sh, bash จะมองหาตัวแปร ENV, ขยายค่าของมันหากมีการกำหนดไว้และใช้ค่าที่ขยายเป็นชื่อของไฟล์เพื่ออ่านและดำเนินการ เนื่องจากเชลล์เรียกใช้โดย sh ไม่ได้พยายามอ่านและเรียกใช้คำสั่งจากไฟล์เริ่มต้นอื่น ๆ อ็อพชัน --rcfile จะไม่มีผลใด ๆ เชลล์ที่ไม่มีการโต้ตอบถูกเรียกใช้ด้วยชื่อ sh จะไม่พยายามอ่านไฟล์เริ่มต้นอื่น ๆ เมื่อเรียกใช้เป็น sh bash จะเข้าสู่โหมด posix หลังจากอ่านไฟล์เริ่มต้น

โปรแกรมรู้ได้อย่างไรว่าใช้ชื่อใดในการเริ่มต้นโปรแกรม

หากเป็นโปรแกรม ac ก็สามารถตรวจสอบargv[0]ได้ หากเป็นเชลล์หรือสคริปต์ Perl ก็สามารถตรวจสอบ$0ได้

เป็นตัวอย่างลองพิจารณา shell script แบบง่าย ๆ นี้:

$ cat utc
#!/bin/sh
case "${0##*/}" in
        utc) date -u ;;
        et) TZ=US/Eastern date ;;
esac

$0คือชื่อที่สคริปต์ถูกเรียกใช้ ${0##*/}เป็นชื่อที่สคริปต์ถูกเรียกด้วยชื่อไดเรกทอรีใด ๆ ที่ถูกลบ

มาสร้าง symlink นี้กัน:

ln -s utc et

ดังนั้นutcและetทั้งคู่เรียกใช้ไฟล์ปฏิบัติการเดียวกัน แต่ให้ผลลัพธ์ที่แตกต่างกัน เมื่อเรียกใช้utcจะส่งสัญญาณเวลาสากล เมื่อเรียกใช้เป็นetเอาต์พุตเวลาตะวันออกของสหรัฐอเมริกา ตัวอย่างเช่น:

$ utc
Wed Jul 20 18:14:18 UTC 2016
$ et
Wed Jul 20 14:14:20 EDT 2016

4
อาจต้องการเพิ่มความเป็นไปได้เนื่องจาก OP คาดว่าการโทรจะเหมือนกัน ( argv[0], obvs)
การแข่งขัน Lightness ใน Orbit

@LightnessRacesinOrbit ความคิดที่ดี ฉันเพิ่มตัวอย่าง
John1024

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