รันเชลล์สคริปต์เมื่อ“ / bin / sh” ชี้ไปที่“ / bin / bash”


11

ฉันได้อ่านสิ่งต่อไปนี้ในคำถามนี้:

bash รองรับสวิตช์ --posix ซึ่งทำให้รองรับ POSIX ได้มากขึ้น นอกจากนี้ยังพยายามที่จะเลียนแบบ POSIX ถ้าเรียกว่าเป็นการดวลจุดโทษ

อ้างข้างต้นสันนิษฐานว่าคือการเชื่อมโยงที่ชี้ไปยัง/bin/sh/bin/bash

แต่ผมไม่เข้าใจสิ่งที่หมายโดย"เรียกว่าเป็นการดวลจุดโทษ"


บอกว่าฉันมีสคริปต์ต่อไปนี้ซึ่งเรียกว่า "script.sh":

#!/bin/bash
echo "Hello World"

โปรดบอกฉันในแต่ละกรณีต่อไปนี้ว่าสคริปต์จะทำงานในbashโหมดปกติหรือในโหมด POSIX (สมมติว่าฉันได้ดำเนินการคำสั่งต่อไปนี้ในเทอร์มินัลที่กำลังทำงานอยู่bash):

  1. sh script.sh
  2. bash script.sh
  3. ./script.sh

ตอนนี้บอกว่าฉันมีสคริปต์ต่อไปนี้ซึ่งเรียกว่า "script.sh" (ซึ่งเป็นเหมือนสคริปต์ด้านบน แต่ไม่มี Shebang):

echo "Hello World"

โปรดบอกฉันในแต่ละกรณีต่อไปนี้ว่าสคริปต์จะทำงานในbashโหมดปกติหรือในโหมด POSIX (สมมติว่าฉันได้ดำเนินการคำสั่งต่อไปนี้ในเทอร์มินัลที่กำลังทำงานอยู่bash):

  1. sh script2.sh
  2. bash script2.sh
  3. ./script2.sh

คำตอบ:


19

เฉพาะกรณีที่ 1 & 4 เท่านั้นที่จะทำงานในโหมด POSIX (สมมติว่าshเป็นการทุบตีและไม่ใช่การนำ sh อื่นมาใช้) กรณีใด ๆ ที่โทรออกbashโดยไม่แจ้ง--posixจะไม่มาจาก Shebang หรือไม่ กรณีใด ๆ ที่shจะเรียกอย่างชัดเจน shebang จะใช้เมื่อไม่มีเชลล์เริ่มต้นอย่างชัดเจนสำหรับสคริปต์แล้ว

กรณีที่ 6 หากเทอร์มินัลของคุณกำลังทำงานbashจะไม่ทำงานในโหมด POSIX และBash จะเรียกใช้งานด้วยตัวเอง หากเทอร์มินัลของคุณกำลังรัน zsh แทนกรณีที่ 6 จะทำงานในโหมด POSIX ด้วย POSIX คลุมเครือเกี่ยวกับสิ่งที่ควรเกิดขึ้นในกรณีนั้นและ Bash และ zsh ได้เลือกตัวเลือกที่แตกต่างกัน Bash เรียกใช้สคริปต์โดยใช้ตัวมันเองในขณะที่ zsh ใช้sh(ไม่ว่าจะเกิดอะไรขึ้น) กระสุนอื่น ๆ ก็แตกต่างกันไปตามจุดนั้น


วิธีง่ายๆในการบอกว่าคุณอยู่ในโหมดใดคือสร้างเนื้อหาสคริปต์ของคุณ:

kill -SIGHUP

ซึ่งจะล้มเหลวด้วยข้อผิดพลาดในโหมด POSIXแต่ให้คำแนะนำการใช้งานสำหรับkillนอก นี่คือความแตกต่างที่ง่ายและใช้งานได้ในเวอร์ชั่น Bash ที่หลากหลายย้อนกลับไปนานเท่าที่คุณจะได้พบ


3
มีสิ่งอื่น ๆ ที่จะบังคับให้มีbashการทำงานในโหมด POSIX เช่นตัวแปรสภาพแวดล้อมหรือPOSIXLY_CORRECT SHELLOPTS=posix
Stéphane Chazelas

1
[ -o posix ]เป็นวิธีที่ชัดเจนมากขึ้นในการตรวจสอบว่าคุณกำลังทำงานในโหมด posix ใน bash (ไม่ใช่เชลล์อื่น ๆ (ยกเว้น yash) ดังนั้นคุณไม่ต้องการทำเช่นนั้นในshสคริปต์) POSIXLY_CORRECT=1 bash -c '[ -o posix ] && echo yes'ผลลัพธ์yes`
Stéphane Chazelas

2
ในกรณีที่ 6 bash จะเรียกใช้สคริปต์ด้วยตนเองในโหมด POSIXเมื่ออยู่ในโหมด POSIX ตามที่ต้องการ POSIX POSIX ไม่ได้ระบุกลไก she-bang และ 6 เป็นวิธี POSIX เดียวที่จะมีสคริปต์ที่ปฏิบัติการได้และมีการระบุไว้อย่างชัดเจน (ในสภาพแวดล้อม POSIX สคริปต์จะตีความโดยโปรแกรมอรรถประโยชน์ sh ที่สอดคล้องกัน)
Stéphane Chazelas

8

"การเรียกว่า" หมายถึงสิ่งที่เป็นที่ขั้นตอนการเริ่มต้นทำให้ทุบตีใน "ข้อที่ศูนย์" argv[0]อาร์กิวเมนต์บรรทัดคำสั่งของตน

เมื่อโปรแกรมเริ่มต้นด้วยexec*()syscallsพวกเขาจะไม่รู้จักชื่อของไฟล์ไบนารีที่มีโปรแกรม แต่กระบวนการเรียกมีอิสระที่จะใส่สิ่งที่ต้องการ ปกติแล้วชื่อจะถูกนำมาจากระบบไฟล์ดังนั้นหากคุณเรียกใช้/bin/shนั่นคือสิ่งที่จะนำไปสู่ที่นั่น และถ้า/bin/shเป็น Bash ก็ไม่จำเป็นต้องเป็น symlink ก็อาจเป็นฮาร์ดลิงก์หรือสำเนาของโปรแกรมเชลล์อีกชุด

เป็นตัวอย่างของการตั้งค่า "ชื่อโปรแกรม" execคำสั่งของ Bash สามารถตั้งค่าอาร์กิวเมนต์ zeroth ด้วย-aตัวเลือก (เราสามารถทำเช่นเดียวกันกับ Perl หรือโดยตรงกับ C เป็นต้น)

นี่mynameคือโปรแกรม C อย่างง่ายที่เพิ่งพิมพ์อาร์กิวเมนต์ zeroth ชื่อที่มันเห็นตัวเอง:

$ ./myname 
I am ./myname
$ (exec -a something ./myname )
I am something
$ mv ./myname somename
$ ln -s somename othername
$ ./somename 
I am ./somename
$ ./othername
I am ./othername

ที่มา:

#include <stdio.h>
int main(int argc, char *argv[]) {
    printf("I am %s\n", argv[0]);
    return 0;
}

แต่เพื่อตอบคำถามที่มีหมายเลข ...

(ที่ 1 และ 4) การทำงานsh somescriptจะทำงานอะไรก็ตามที่shอยู่ในของคุณPATHอาจจะเป็น/bin/shแต่อาจจะเป็นสิ่งที่ชอบ/usr/xpg4/bin/sh

  • ถ้ามันทุบตีมันทำงานในโหมด POSIX shเพราะมันเห็นชื่อ
  • ถ้าเป็น Z เชลล์หรือ Korn เชลล์มันก็จะเห็นชื่อshแต่มันจะทำงานในโหมด "SH Compatible" ซึ่งมีวัตถุประสงค์เพื่อให้เข้ากันได้กับ Bourne เชลล์และแตกต่างอย่างสิ้นเชิงกับโหมด POSIX แบบเต็มในเปลือกทั้งสองอย่างนั้น .
  • มันอาจเป็น Almquist shell, Bourne shell ที่แท้จริงหรืออย่างอื่นแน่นอน

(2 & 5) การรันbash somescriptจะทำงานในโหมด Bash ปกติ (อีกครั้งแน่นอนว่ามันขึ้นอยู่กับว่าbashคุณPATHอยู่ในโหมดใด)

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

(6) อันนี้ซับซ้อน คล้ายกับ (3) แต่การเรียกระบบสำหรับการเริ่มโปรแกรมล้มเหลว ( ENOEXEC (Exec format error)) เนื่องจากไม่มีบรรทัด hashbang สิ่งที่เกิดขึ้นต่อไปขึ้นอยู่กับว่าเชลล์ที่คุณใช้อยู่นั้นอยู่ในโหมด POSIX หรือไม่ POSIX ต้องการให้ POSIX ENOEXECสอดคล้องประพฤติเปลือกในแฟชั่นที่เฉพาะเจาะจงในการตอบสนอง อย่างไรก็ตามมีบางระยะใน "คำสั่งเทียบเท่ากับการเรียกเปลือก" ซึ่งหมายความว่าเปลือกที่แตกต่างกันทำสิ่งที่แตกต่างกัน

  • เชลล์ Bourne Again อีกครั้งรันตัวเองในโหมดเดียวกันโดยมีชื่อของสคริปต์เป็นอาร์กิวเมนต์บรรทัดคำสั่งแรก ในโหมดที่สอดคล้องกับ POSIX มันเป็นของหลักสูตรที่ทำงานตัวเองในโหมดที่สอดคล้องกับ POSIX ของมันจึงเชื่อฟังข้อกำหนดของ POSIX เพื่อเรียกใช้เปลือกที่สอดคล้อง POSIX
  • Z เชลล์, Almquist เชลล์และ Korn เชลล์รัน/bin/shด้วยชื่อของสคริปต์ที่แทรกไว้ก่อนหน้าอาร์กิวเมนต์อื่น ๆ เป็นอาร์กิวเมนต์บรรทัดคำสั่งแรก Z เชลล์, Almquist เชลล์และ Korn เชลล์คือ (พยายาม) เพื่อเรียกใช้เชลล์ที่สอดคล้องกับ POSIX โดยอาศัยการสมมติว่า/bin/shโปรแกรมนั้นเป็นหนึ่ง

คุณช่วยแบ่งปันซอร์สโค้ดของโปรแกรม C นี้ได้
ไหม

int main(int argc, char *argv[]){printf("I am %s\n",argv[0]);}
เฮมเมอร์

นั่นมันสวยมาก
ilkkachu

4

เชลล์ดำเนินการอย่างใดอย่างหนึ่งเรียกว่าในบรรทัดคำสั่งหรืออย่างใดอย่างหนึ่งใน shebang (ถ้าบรรทัดคำสั่งไม่ได้ระบุ)

ดังนั้นเวอร์ชัน 1 และ 4 จะทำงานด้วยsh2 และ 5 กับ bash และ 6 อาจไม่ทำงานหากคุณใช้ sh (และบางคน) โต้ตอบ Bash เริ่มสคริปต์ Ksh ยัง Zsh เริ่มเป็น SH

เฉพาะผู้ที่เริ่มเป็นshจะใช้ตัวเลือก POSIX /bin/shถ้าทุบตีเชื่อมโยงกับ

เพิ่มบรรทัดนี้ในสคริปต์ของคุณเพื่อตรวจสอบว่ามี bash ksh หรือ zsh เวอร์ชันใดที่กำลังรันอยู่:

echo "Hello World $BASH_VERSION $KSH_VERSION $ZSH_VERSION"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.