วิธีใช้ Bash สำหรับ sh ใน Ubuntu


14

ฉันกำลังติดตั้งโปรแกรมขนาดใหญ่ซึ่งมีทรัพยากรเป็นrpmไฟล์ มันติดอยู่ที่เส้นของ

#!/bin/sh
SCITEGICPERLBIN=`dirname $0`
SCITEGICPERLHOME=`dirname $SCITEGICPERLBIN`
if [ $SCITEGICPERLHOME == "." ]

เห็นได้ชัดว่าshทำงานbashใน Red Hat Linux ด้วยไวยากรณ์นี้ แต่ให้ข้อผิดพลาดunexpected operatorใน Ubuntu

ฉันไม่สามารถเปลี่ยนสคริปต์bashเป็นสคริปต์มาจากrpmแพ็คเกจ ฉันสามารถแยกและบรรจุหีบห่อใหม่rpmแต่อาจมีสคริปต์ดังกล่าวจำนวนมาก

มีวิธีการเปลี่ยนค่าเริ่มต้นของเชลล์เพื่อใช้#!/bin/shเป็นbashหรืออย่างอื่นซึ่งสามารถจัดการกับ[โอเปอเรเตอร์ได้หรือไม่?


5
สิ่งเดียวที่ไม่ถูกต้องเป็นที่ควรจะเป็น== =นั่นและการขยายตัวแปรควรจะยกมาสองครั้ง
Kusalananda

4
[ไม่ใช่ตัวดำเนินการ แต่เป็นคำสั่งในตัวที่ถูกเรียกtestใช้ ตัวดำเนินการที่ไม่คาดคิดคือ==และสิ่งนี้ควรถูกแทนที่ด้วย=เนื่องจากไม่เป็นไปตาม POSIX
schily

สิ่งเดียวที่สองที่ผิดคือ$SCITEGICPERLHOMEควรจะยกมา
l0b0

12
คุณควรบ่นกับผู้เขียนโปรแกรม หากพวกเขาใช้#!/bin/shพวกเขาควรตรวจสอบให้แน่ใจว่าพวกเขาใช้คุณสมบัติ POSIX เชลล์เท่านั้นไม่ใช่bashส่วนขยาย โปรแกรมเมอร์คนนี้เลอะเทอะมาก #!/bin/bashเขาก็ควรจะแก้ไขรหัสหรือการใช้งานของเขา
Barmar

สำหรับคนที่สงสัยเกี่ยวกับปัญหาที่คล้ายกันอื่น ๆ นี่คือรายการของ " Bashisms " ดูคำถามนี้ด้วย
Captain Man

คำตอบ:


21

/bin/shมีโปรแกรมหลายตัวที่ใช้ภาษาที่มี บน Ubuntu นั้น/bin/shเป็นเส้นประซึ่งถูกออกแบบมาให้ทำงานเร็วใช้หน่วยความจำเพียงเล็กน้อยและไม่รองรับเกินกว่าที่คาด/bin/shไว้ บน RHEL /bin/shคือ bash ซึ่งช้ากว่าและใช้หน่วยความจำมากกว่า แต่มีคุณสมบัติมากกว่า หนึ่งในคุณสมบัติเหล่านี้คือ==โอเปอเรเตอร์สำหรับ[ไวยากรณ์ตามเงื่อนไข Dash รองรับ[ซึ่งเป็นคุณสมบัติพื้นฐานของ sh แต่ไม่มีตัว==ดำเนินการซึ่งเป็นส่วนขยาย bash (และ ksh และ zsh)

คุณสามารถเปลี่ยนระบบของคุณเป็นการใช้ bash บน Ubuntu, การเชื่อมโยงสัญลักษณ์/bin/sh dashคุณสามารถทำให้มันเป็นลิงค์สัญลักษณ์bashแทน เวอร์ชันปัจจุบันของ Debian และ Ubuntu (และอนุพันธ์) ทำให้ตัวเลือกนี้เป็นตัวเลือกในการติดตั้งของเส้นประ หากต้องการเปลี่ยนให้เรียกใช้

sudo dpkg-reconfigure dash

และตอบ“ ใช่” เพื่อให้รีบเป็น/bin/shหรือ“ ไม่” เพื่อเปลี่ยนเป็นทุบตี

คุณสามารถทุบตีได้/bin/shแต่มันจะทำให้ระบบของคุณช้าลงเล็กน้อย เป็นไปได้ยิ่งที่สคริปต์ระบบบางตัวไม่สามารถใช้ร่วมกับ bash ได้ แต่นั่นไม่น่าเป็นไปได้เนื่องจาก bash นั้นส่วนใหญ่จะเป็นระบบที่มีความเร็วสูง


สำหรับการแจกแจงที่ไม่มีอินเทอร์เฟซให้เลือกระหว่างการนำไปใช้งานต่อไป/bin/shนี้เป็นวิธีเปลี่ยนเป็นทุบตี

sudo ln -s bash /bin/sh.bash
sudo mv /bin/sh.bash /bin/sh

เปิดเทอร์มินัลค้างไว้และตรวจสอบว่าคุณยังคงสามารถเรียกใช้shสคริปต์บางอย่างหลังจากนั้น หากคุณทำให้คำสั่งนี้เลอะเทอะมันจะทำให้ระบบของคุณใช้งานไม่ได้ (โดยวิธีเหตุผลที่ฉันใช้คำสั่งหลายคำสั่งด้านบนแทนที่จะดูแบบตรงไปตรงมาsudo ln -sf bash /bin/shก็คือln -sfมันไม่ได้เป็นแบบอะตอมในกรณีที่คอมพิวเตอร์ของคุณเกิดข้อผิดพลาดในระหว่างการดำเนินการนี้คุณอาจต้องบูตจากสื่อกู้ภัย ในทางตรงกันข้ามmvคืออะตอม)

ในการกู้คืน dash เป็น/bin/sh:

sudo ln -s dash /bin/sh.dash
sudo mv /bin/sh.dash /bin/sh

โปรดทราบว่าถ้า sh เป็น/bin/bashค่าเริ่มต้นในการกระจายของคุณการสลับไปที่เส้นประอาจทำให้สคริปต์ล้มเหลวเนื่องจากทุบตีมีคุณสมบัติมากมายกว่าเส้นประ สคริปต์ Bash ควรเริ่มต้นด้วย#!/bin/bashและสคริปต์ที่ขึ้นต้นด้วย#!/bin/shไม่ควรใช้คุณสมบัติเฉพาะของ bash แต่การแจกแจงที่มาพร้อมกับ bash /bin/shนั้นอาจใช้คุณสมบัติเฉพาะของ bash ใน#!/bin/shสคริปต์ที่เฉพาะเจาะจงสำหรับการแจกจ่ายนั้น (ใช้ได้ตราบใดที่ผู้ใช้ไม่คาดหวัง สามารถสลับไปที่เส้นประเป็น/bin/shและไม่มีความคาดหวังว่าสคริปต์เหล่านี้ทำงานในการกระจายอื่น)


ในความเห็นที่ไม่ถ่อมตนของฉันหากสคริปต์บางตัวล้มเหลวเมื่อ/bin/shBash มันเป็นข้อผิดพลาดทั้งในระบบ (แพคเกจที่มีสคริปต์) หรือใน Bash's sh- โหมด เช่นเดียวกับสตีเฟ่นกล่าวว่าระบบชัดเจนให้สำหรับการตั้งค่ากลับไปทุบตีผ่าน/bin/sh dpkg-reconfigureมีการกล่าวถึงความเป็นไปได้ใน Ubuntu wiki เกี่ยวกับเรื่องนี้: wiki.ubuntu.com/DashAsBinSh
ilkkachu

5
@ilkkachu ใช่ถ้าสคริปต์ล้มเหลวถ้า/bin/shทุบตีก็เป็นข้อผิดพลาด อย่างไรก็ตามข้อผิดพลาดเกิดขึ้น ฉันแนะนำให้ติดกับค่าเริ่มต้นหากคุณไม่สามารถและยินดีที่จะวินิจฉัยข้อผิดพลาดดังกล่าวเพราะคนอื่นได้ทดสอบให้คุณ ฉันใช้เส้นประ/bin/shก่อนที่มันจะรองรับเดเบียนอย่างเป็นทางการ แต่นี่เป็นความเสี่ยงที่ฉันรับรู้ว่าฉันจะสามารถรับมือได้หากมีอะไรบางอย่างเกิดขึ้น
Gilles 'ดังนั้นหยุดความชั่วร้าย'

โปรดทราบว่า symlink ที่แทนที่ด้วยตนเองจะถูกกู้คืนเป็นค่าที่จัดเก็บไว้ในdebconfครั้งต่อไปที่dashมีการอัปเดต เป็นที่ยอมรับว่าจะไม่เกิดขึ้นบ่อยครั้ง (ถ้าเลยในรุ่นที่กำหนด) สำหรับระบบที่ใช้ Debian เสถียร
Stephen Kitt

36

หากต้องการเปลี่ยนshเป็นbash(แทนที่จะdashเป็นค่าเริ่มต้น) ให้กำหนดค่าใหม่dash(ใช่มันค่อนข้างตอบโต้ได้ง่าย):

sudo dpkg-reconfigure dash

สิ่งนี้จะถามว่าคุณต้องการdashเป็นเชลล์ระบบเริ่มต้นหรือไม่ ตอบ“ ไม่” ( Tabจากนั้นEnter) และbashจะกลายเป็นค่าเริ่มต้นแทน ( เช่น /bin/shจะชี้ไปที่/bin/bash)


1
วิธีการแก้ปัญหาของคุณเป็นวิธีที่เหมาะสมที่สุด แต่ฉันยอมรับคำตอบอื่นเนื่องจากคำอธิบายโดยละเอียดชี้แจงปัญหา ขออภัยในความไม่สะดวกใด ๆ.
Googlebot

@Googlebot ไม่จำเป็นต้องขออภัยในการเลือกคำตอบที่ยอมรับได้เป็นสิทธิ์ของผู้ถาม และฉันได้รับเหรียญทองจากมัน ;-)
Stephen Kitt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.