Kapan #!/bin/bash
lebih tepat daripada #!/bin/sh
dalam skrip shell?
linux
shell-script
Hendré
sumber
sumber
bash
fungsi dan sintaks daripadash
fungsi dan sintaksis.vim
akan menyorotibash
-ism jika skrip Anda memiliki#!/bin/sh
shebang. Saya hanya mengubahnyabash
jika semuanya menjadi cukup berbulu untuk mulai membutuhkan fitur bash.$(...)
sangat menjengkelkan. Juga, beberapa di antaranya tidak jelas [<(...)
dancmd >& file
tidak mendapatkan sorotan kesalahan, misalnya, mereka tidak memiliki sorotan khusus untuk apa yang mereka maksud, dengan atau tanpag:is_bash
]Jawaban:
Pendeknya:
Ada beberapa shell yang menerapkan superset dari spesifikasi sh POSIX . Pada sistem yang berbeda,
/bin/sh
mungkin tautan ke ash, bash, dash, ksh, zsh, & c. (Akan selalu kompatibel dengan sh - tidak pernah csh atau ikan.)Selama Anda tetap berpegang pada
sh
fitur saja, Anda dapat (dan mungkin bahkan harus) menggunakan#!/bin/sh
dan skrip harus bekerja dengan baik, tidak peduli yang shell itu.Jika Anda mulai menggunakan fitur khusus bash (misalnya array), Anda harus secara spesifik meminta bash - karena, bahkan jika
/bin/sh
sudah memanggil bash pada sistem Anda , mungkin tidak pada sistem orang lain , dan skrip Anda tidak akan berjalan di sana. (Hal yang sama tentu saja berlaku untuk zsh dan ksh.) Anda dapat menggunakan shellcheck untuk mengidentifikasi bashism.Meskipun skrip ini hanya untuk penggunaan pribadi, Anda mungkin memperhatikan bahwa beberapa OS berubah
/bin/sh
selama peningkatan - misalnya pada Debian dulu bash, tetapi kemudian diganti dengan tanda hubung yang sangat minimal. Script yang menggunakan bashism tapi#!/bin/sh
tiba - tiba pecah.Namun:
Bahkan
#!/bin/bash
tidak terlalu benar. Pada sistem yang berbeda, bash mungkin hidup di/usr/bin
atau/usr/pkg/bin
atau/usr/local/bin
.Opsi yang lebih andal adalah
#!/usr/bin/env bash
, yang menggunakan $ PATH. (Meskipunenv
alat itu sendiri juga tidak dijamin ketat,/usr/bin/env
masih berfungsi pada lebih banyak sistem daripada yang/bin/bash
dilakukan.)sumber
/bin/sh
saat itu maka ia akan mencoba menirush
fitur (lihat halaman manual ), tidak yakin fitur spesifik bash tersedia dalam mode ini.env
tool adalah alat posix yang harus ditemukan di sebagian besar distribusi, tetapi saya tidak yakin karena beberapa mungkin tidak menghargai posix./bin
: " Aplikasi harus mencatat bahwa PATH standar untuk shell tidak dapat dianggap sebagai / bin / sh atau / usr / bin / sh, dan harus ditentukan dengan menginterogasi PATH yang dikembalikan oleh getconf PATH, memastikan bahwa pathname yang dikembalikan adalah pathname absolut dan bukan sebuah shell built-in ". Lihat juga pertanyaan ini dan, khususnya jawaban ini .#!
skrip berfungsi?echo foo ^ cat
memancarkanfoo ^ cat
dalam POSIX sh, dan memancarkan hanyafoo
dalam Bourne (seperti^
karakter pipa di sana).Gunakan shebang yang sesuai dengan shell yang sebenarnya Anda gunakan untuk mengembangkan dan men-debug skrip Anda. Yaitu jika shell login Anda
bash
, dan Anda menjalankan skrip Anda sebagai executable di terminal Anda, gunakan#!/bin/bash
. Jangan hanya berasumsi bahwa karena Anda belum menggunakan array (ataubash
fitur apa pun yang Anda ketahui), Anda aman untuk memilih shell apa pun yang Anda suka. Ada banyak perbedaan halus antara shell (echo
, fungsi, loop, sebut saja) yang tidak dapat ditemukan tanpa pengujian yang tepat.Pertimbangkan ini: jika Anda pergi
#!/bin/bash
dan pengguna Anda tidak memilikinya, mereka akan melihat pesan kesalahan yang jelas, kira-kira sepertiSebagian besar pengguna dapat memperbaiki ini dalam waktu kurang dari satu menit dengan menginstal paket yang sesuai. Di sisi lain, jika Anda mengganti shebang dengan
#!/bin/sh
dan mengujinya pada sistem/bin/sh
yang memiliki symlink/bin/bash
, pengguna Anda yang tidak memilikibash
akan bermasalah. Mereka kemungkinan besar akan melihat pesan kesalahan samar seperti:Mungkin perlu waktu berjam-jam untuk memperbaikinya, dan tidak akan ada petunjuk tentang cangkang mana yang seharusnya mereka gunakan.
Tidak banyak alasan mengapa Anda ingin menggunakan shell yang berbeda di shebang. Salah satu alasannya adalah ketika shell yang Anda gunakan tidak tersebar luas. Yang lain adalah untuk mendapatkan kinerja
sh
yang secara signifikan lebih cepat pada beberapa sistem, DAN skrip Anda akan menjadi hambatan kinerja. Dalam hal ini, uji skrip Anda secara menyeluruh dengan shell target, lalu ubah shebang.sumber
Anda seharusnya hanya menggunakan
#! /bin/sh
.Anda seharusnya tidak menggunakan ekstensi bash (atau zsh, atau fish, atau ...) dalam skrip shell.
Anda harus hanya pernah menulis skrip shell yang bekerja dengan setiap pelaksanaan bahasa shell (termasuk semua "utilitas" program yang pergi bersama dengan shell itu sendiri). Saat ini Anda mungkin dapat menggunakan POSIX.1-2001 ( tidak -2008) sebagai otoritatif untuk kemampuan shell dan utilitas, tetapi perlu diketahui bahwa suatu hari Anda mungkin diminta untuk mem-porting skrip Anda ke sistem lawas (mis. Solaris atau AIX) yang cangkangnya dan utilitasnya dibekukan sekitar tahun 1992.
Apa, serius ?!
Ya, serius.
Begini masalahnya: Shell adalah bahasa pemrograman yang mengerikan . Satu-satunya hal yang telah terjadi adalah bahwa
/bin/sh
adalah satu-satunya juru bahasa script yang setiap instalasi Unix dijamin miliki.Inilah hal lainnya: beberapa iterasi dari interpreter inti Perl 5 (
/usr/bin/perl
) lebih mungkin tersedia pada instalasi Unix yang dipilih secara acak daripada(/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash
. Bahasa scripting lain yang bagus (Python, Ruby, node.js, dll. - Saya bahkan akan memasukkan PHP dan Tcl dalam kategori itu ketika membandingkan dengan shell) juga kira-kira tersedia sebagai bash dan shell diperluas lainnya.Oleh karena itu, jika Anda memiliki opsi untuk menulis skrip bash, Anda memiliki opsi untuk menggunakan bahasa pemrograman yang tidak buruk.
Sekarang, skrip shell sederhana , jenis yang hanya menjalankan beberapa program secara berurutan dari pekerjaan cron atau sesuatu, tidak ada yang salah dengan membiarkannya sebagai skrip shell. Tetapi skrip shell sederhana tidak membutuhkan array atau fungsi atau
[[
bahkan. Dan Anda hanya harus menulis skrip shell rumit ketika Anda tidak punya pilihan lain. Skrip autoconf, misalnya, adalah skrip shell yang benar. Tetapi skrip-skrip tersebut harus dijalankan pada setiap inkarnasi/bin/sh
yang relevan dengan program yang sedang dikonfigurasi. dan itu berarti mereka tidak dapat menggunakan ekstensi apa pun. Anda mungkin tidak perlu peduli dengan Unix lama yang sudah dipatenkan belakangan ini, tetapi Anda mungkin harus peduli dengan BSD sumber terbuka saat ini, beberapa di antaranya tidak menginstalbash
secara default, dan lingkungan tertanam yang memberi Anda hanya shell minimal danbusybox
.Kesimpulannya, saat Anda mendapati diri Anda menginginkan fitur yang tidak tersedia dalam bahasa shell portabel, itu adalah tanda bahwa skrip menjadi terlalu rumit untuk tetap menggunakan skrip shell. Tulis ulang dalam bahasa yang lebih baik.
sumber
sh
. Namun, itu jauh dari pernyataan bahwa Anda tidak boleh menggunakan kerang lainnya. Ada ribuan (mungkin lebih banyak) skrip yang ditulis setiap hari dan sebagian besar dari mereka hanya akan berjalan pada satu mesin. Saran Anda masuk akal pada kode produksi, tetapi tidak untuk pekerjaan "sysdaminy" harian yang ditulis untuk sebagian besar skrip. Jika saya tahu bahwa skrip saya hanya akan digunakan oleh saya dan di mesin Linux, bash baik-baik saja.Umumnya jika waktu lebih penting daripada fungsi, Anda akan menggunakan shell yang lebih cepat. sh sering disebut dengan tanda hubung dan cenderung digunakan untuk tugas cron root atau operasi batch di mana setiap (nano) detik diperhitungkan.
sumber
Agar lebih singkat, gunakan
sh
jika portabilitas di sebagian besar sistem adalah yang paling penting danbash
jika Anda ingin menggunakan beberapa fitur spesifiknya, seperti array, jika versi bash mendukungnya.sumber
Jalan teraman. ketika hard coded, akan menjadi / usr / bin /
shellOfChoice
tetapi konvensi baru yang saya coba gunakan selalu sekarang - karena 'lokasi default' melalui perubahan yang PATH dapat ubah adalah:#! / usr / bin / env sh atau
#! / usr / bin / env bash
atau untuk misalnya, skrip perl
#! / usr / bin / env perl -w
Tentu saja, ketika Anda memiliki alasan untuk skrip TIDAK PERNAH secara otomatis mengambil PATH baru kemudian terus memilikinya hard-kode - dan kemudian / usr / bin / sesuatu harus menjadi jalan yang paling mungkin untuk digunakan.
sumber