Menjalankan skrip shell ketika "/ bin / sh" menunjuk ke "/ bin / bash"

11

Saya telah membaca yang berikut dalam pertanyaan ini :

bash mendukung switch --posix, yang membuatnya lebih sesuai dengan POSIX. Itu juga mencoba untuk meniru POSIX jika dipanggil sebagai sh .

Kutipan di atas mengasumsikan bahwa itu /bin/shadalah tautan yang menunjuk /bin/bash.

Tapi saya tidak begitu mengerti apa yang dimaksud dengan "dipanggil sebagai sh" .


Katakan bahwa saya memiliki skrip berikut yang disebut "script.sh":

#!/bin/bash
echo "Hello World"

Tolong beri tahu saya dalam setiap kasus berikut apakah skrip akan dijalankan dalam bashmode normal atau dalam mode POSIX (asumsikan bahwa saya telah menjalankan perintah berikut di terminal yang sedang berjalan bash):

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

Sekarang katakan bahwa saya memiliki skrip berikut yang disebut "script.sh" (yang seperti skrip di atas tetapi tanpa shebang):

echo "Hello World"

Tolong beri tahu saya dalam setiap kasus berikut apakah skrip akan dijalankan dalam bashmode normal atau dalam mode POSIX (asumsikan bahwa saya telah menjalankan perintah berikut di terminal yang sedang berjalan bash):

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

Jawaban:

19

Hanya case 1 & 4 yang akan berjalan dalam mode POSIX (dengan asumsi itu shadalah bash dan bukan implementasi sh lainnya). Kasus apa pun yang secara eksplisit menelepon bashtanpa --posixtidak akan, apakah dari shebang atau tidak. Kasus apa pun yang secara eksplisit menelepon shakan. Shebang hanya digunakan ketika tidak ada shell yang secara eksplisit dimulai untuk skrip.

Kasus 6, jika terminal Anda berjalan bash, tidak akan berjalan dalam mode POSIX dan Bash akan menggunakannya dengan sendirinya. Jika terminal Anda menjalankan zsh, case 6 juga akan berjalan dalam mode POSIX. POSIX tidak jelas tentang apa yang seharusnya terjadi dalam kasus itu , dan Bash dan zsh membuat pilihan berbeda di sana. Bash memanggil script menggunakan dirinya sendiri, sementara zsh menggunakan sh(apa pun yang terjadi). Kerang lain juga bervariasi pada titik itu.


Salah satu cara sederhana untuk mengetahui mode apa yang Anda gunakan adalah membuat badan skrip:

kill -SIGHUP

yang akan gagal dengan kesalahan dalam mode POSIX , tetapi memberikan instruksi penggunaan untuk di killluar itu. Ini adalah perbedaan yang mudah dan berfungsi melalui sejumlah besar versi Bash yang akan kembali sejauh yang mungkin Anda temui.

Michael Homer
sumber
3
Ada hal-hal lain yang akan memaksa bashuntuk dijalankan dalam mode POSIX seperti POSIXLY_CORRECTvariabel lingkungan atau SHELLOPTS=posix.
Stéphane Chazelas
1
[ -o posix ]adalah cara yang lebih jelas untuk memeriksa bahwa Anda menjalankan dalam mode posix di bash (bukan di shell lain (kecuali yash), jadi Anda tidak ingin melakukannya dalam shskrip). POSIXLY_CORRECT=1 bash -c '[ -o posix ] && echo yes'keluaran yes`
Stéphane Chazelas
2
Dalam kasus 6, bash memanggil script dengan dirinya sendiri dalam mode POSIX ketika itu sendiri dalam mode POSIX seperti yang POSIX butuhkan. POSIX tidak menentukan mekanisme she-bang, dan 6 adalah satu-satunya cara POSIX untuk memiliki skrip yang dapat dieksekusi dan secara jelas ditentukan (dalam lingkungan POSIX, skrip dimaksudkan untuk ditafsirkan oleh utilitas sh yang sesuai).
Stéphane Chazelas
8

"Dipanggil sebagai" mengacu pada apa pun itu bahwa proses mulai Bash menempatkan dalam argumen baris perintah "nol" argv[0],.

Ketika sebuah program dimulai dengan exec*()syscalls , mereka tidak benar-benar mengetahui nama file biner yang berisi program tersebut, tetapi sebaliknya proses panggilan bebas untuk meletakkan apa pun yang diinginkan di sana. Biasanya, tentu saja, nama tersebut diambil dari sistem file, jadi jika Anda menjalankannya /bin/sh, itulah yang akan dimasukkan ke sana. Dan jika /bin/shBash, itu tidak harus symlink, itu bisa berupa tautan keras atau hanya salinan lain dari program shell.

Sebagai contoh pengaturan "nama program", execperintah Bash dapat mengatur argumen nol dengan -aopsi. (Kita bisa melakukan hal yang sama dengan Perl, atau langsung dengan C, dll.)

Di sini, mynameadalah program C sederhana yang hanya mencetak argumen nolnya, nama yang dilihatnya sendiri:

$ ./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

Sumber:

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

Tapi, untuk menjawab pertanyaan bernomor ...

(1 & 4) menjalankan sh somescriptakan menjalankan apa pun yang shada di Anda PATH, mungkin /bin/shtetapi mungkin sesuatu seperti/usr/xpg4/bin/sh .

  • Jika Bash, ini berjalan dalam mode POSIX, karena ia melihat namanya sh.
  • Jika itu adalah shell Z atau shell Korn, maka ia juga akan melihat namanya sh, tetapi ia berjalan dalam mode "SH kompatibel", yang bertujuan untuk menjadi kompatibel dengan shell Bourne dan agak berbeda dengan mode konforman POSIX penuh di kedua shell tersebut. .
  • Bisa jadi shell Almquist, shell Bourne yang sebenarnya, atau sesuatu yang lain, tentu saja.

(2 & 5) Menjalankan bash somescriptakan berjalan dalam mode Bash biasa (sekali lagi, tentu saja tergantung pada apa yang ada bashdi Anda PATH.)

(3) Di sini, nama skrip diberikan langsung ke pemanggilan sistem menggantikan file program. Kernel membaca baris hashbang dan menggunakannya untuk menjalankan skrip.

(6) Ini yang kompleks. Ini mirip dengan (3), tetapi panggilan sistem untuk memulai program gagal ( ENOEXEC (Exec format error)), karena tidak ada garis hashbang. Apa yang terjadi selanjutnya tergantung dari apakah shell yang Anda jalankan sendiri dalam mode POSIX. POSIX mensyaratkan bahwa shell yang sesuai dengan POSIX berperilaku dengan cara tertentu sebagai respons terhadap ENOEXEC. Namun, ada beberapa kelonggaran dalam "perintah yang setara dengan membuat shell dipanggil" yang berarti bahwa shell berbeda melakukan hal yang berbeda.

  • Shell Bourne Again kembali menjalankan dirinya dalam mode yang sama dengan nama skrip sebagai argumen baris perintah pertama. Dalam mode POSIX-conformant-nya, ia tentu saja berjalan sendiri dalam mode POSIX-conformant-nya, sehingga mematuhi persyaratan POSIX untuk menjalankan shell yang sesuai dengan POSIX.
  • Shell Z, shell Almquist, dan shell Korn dijalankan /bin/shdengan nama skrip yang dimasukkan sebelum argumen lain sebagai argumen baris perintah pertama. Cangkang Z, cangkang Almquist, dan cangkang Korn sedang (mencoba) untuk memanggil cangkang yang sesuai dengan POSIX dengan tidak berasumsi bahwa /bin/shprogramnya adalah satu.
ilkkachu
sumber
Bisakah Anda berbagi kode sumber program C ini ..
GypsyCosmonaut
int main(int argc, char *argv[]){printf("I am %s\n",argv[0]);}
Stig Hemmer
Cukup banyak.
ilkkachu
4

Shell dieksekusi adalah salah satu yang disebut pada command line atau satu peristiwa (jika baris perintah tidak menentukan itu).

Jadi, versi 1 dan 4 akan berjalan dengan sh, 2 dan 5 dengan bash dan 6 mungkin tidak berjalan jika Anda menggunakan sh (dan beberapa yang lain) secara interaktif. Bash memulai skrip. Ksh juga. Zsh memulainya sebagai sh.

Hanya yang memulai yang shakan menggunakan opsi posix jika bash ditautkan ke /bin/sh.

Tambahkan baris ini ke skrip Anda untuk mendeteksi jika ada versi bash ksh atau zsh yang menjalankannya:

echo "Hello World $BASH_VERSION $KSH_VERSION $ZSH_VERSION"
NotAnUnixNazi
sumber