Di mana zsh dan mksh tidak kompatibel dengan bash?

11

Sejauh mana cangkang kompatibel POSIX lainnya berfungsi sebagai pengganti yang wajar untuk bash? Mereka tidak perlu menjadi pengganti "drop-in" yang sebenarnya, tetapi cukup dekat untuk bekerja dengan sebagian besar skrip dan mendukung sisanya dengan beberapa modifikasi.

  1. Saya ingin memiliki skrip bash eksplisit - skrip init, skrip klien DHCP, dll. - bekerja dengan modifikasi minimal

  2. Saya ingin koleksi skrip shell saya yang lebih khusus tidak perlu terlalu banyak modifikasi

  3. Saya ingin memiliki fitur seperti manipulasi string dan pencocokan pola regex bawaan

Satu-satunya pesaing serius yang saya tahu adalah zsh dan mksh. Jadi, bagi Anda di sini yang baik dengan salah satu atau keduanya:

  1. Fitur apa yang dimiliki bash yang tidak dimiliki zsh dan mksh?

  2. Fitur apa yang digunakan shell untuk menggunakan bash, tetapi gunakan sintaks yang tidak kompatibel?

DanL4096
sumber
3
Perbandingan Shell Perintah: ( en.wikipedia.org/wiki/Comparison_of_command_shells ) Panduan Tingkat Lanjut untuk Script Bash: ( tldp.org/LDP/abs/html ) Manual ZSH: ( zsh.sourceforge.net/Guide/zshguide.html ) MirBSD Manual Shell: ( mirbsd.org/htman/i386/man1/mksh.htm ). Maaf, tapi pertanyaan ini terlalu rumit. Mungkin Anda harus bertanya bagaimana menambal bash untuk memperbaiki kerentanan di dalam untuk distribusi Linux Anda yang spesifik?
Tyler Maginnis
3
Tidak ada shell yang dapat berfungsi sebagai setetes penggantian bash, mksh dan zsh dapat berfungsi seperti /bin/shberbagai tingkat kebenaran, tetapi tidak bash.
llua
1
Masalah shellshock keseluruhan tampaknya tidak ada hubungannya dengan pertanyaan inti dan hanya mengganggu orang, jadi saya menghapusnya
Michael Mrozek
3
Seluruh pertanyaan terlalu luas. Mungkin Anda harus menghapusnya.
Tyler Maginnis
1
Satu-satunya kekhawatiran saya benar-benar miliki adalah bahwa BASH dikelola dengan baik oleh Free Software Foundation (FSF). Kontak saya di sana memberi tahu saya bahwa pengungkapan "cacat mendasar" dalam BASH hanya akan mengarah pada implementasi yang lebih kuat dan lebih aman. Ada begitu banyak kerang alternatif yang bahkan mulai merekomendasikan satu untuk kebutuhan Anda, saya akan membutuhkan pemahaman yang kuat tentang kasus penggunaan Anda. Kemudian di sisi O / S ... Begitu banyak hal terkait dengan Bash sehingga Anda akhirnya dapat menulis ulang seluruh panggilan O / S Anda ke BASH. Solusi terbaik yang bisa saya lihat adalah memilih distribusi dengan alt-shell yang dipertahankan.
Tyler Maginnis

Jawaban:

19

Saya akan tetap menggunakan fitur scripting. Fitur-fitur interaktif yang kaya (edisi baris perintah, penyelesaian, konfirmasi, dll.) Cenderung sangat berbeda, mencapai efek yang sama dengan cara yang sepenuhnya tidak kompatibel. Fitur apa yang ada di zsh dan hilang dari bash, atau sebaliknya? memberikan beberapa petunjuk tentang penggunaan interaktif.

Hal terdekat dengan bash adalah ATT ksh93 atau mksh (shell Korn dan klon). Zsh juga memiliki subset fitur, tetapi Anda harus menjalankannya dalam mode emulasi ksh, bukan dalam mode asli zsh.

Saya tidak akan mencantumkan fitur POSIX (yang tersedia di shshell modern ), atau fitur yang relatif tidak jelas, atau seperti yang disebutkan di atas untuk penggunaan interaktif. Pengamatan valid pada bash 4.2, ksh 93u dan mksh 40.9.20120630 seperti yang ditemukan di Debian wheezy.

Sintaks shell

Mengutip

$'…'(string literal dengan interpolasi backslash) tersedia dalam ksh93 dan mksh. `$" ... "(string yang diterjemahkan) adalah khusus untuk bash.

Konstruksi bersyarat

Mksh dan ksh93 harus ;&melalui casepernyataan, tetapi tidak ;;&untuk menguji kasus selanjutnya. Mksh memiliki ;|untuk itu, dan mksh baru-baru ini memungkinkan ;;&untuk kompatibilitas.

((…))ekspresi dan [[ … ]]tes aritmatika adalah fitur ksh. Beberapa operator kondisional berbeda, lihat “ekspresi kondisional” di bawah.

Proses ulang

Ksh dan bash keduanya memiliki proses ulang tetapi mereka bekerja secara berbeda.

Fungsi

Mksh dan ksh93 mendukung function name {…}sintaks untuk definisi fungsi di samping standar name () {…}, tetapi menggunakan functiondalam ksh mengubah aturan pelingkupan, jadi pertahankan name () …untuk menjaga kompatibilitas. Aturan untuk karakter yang diizinkan dalam nama fungsi bervariasi; tetap menggunakan alfanumerik dan _.

Ekspansi penjepit

Ksh93 dan mksh mendukung ekspansi brace {foo,bar}. Ksh93 mendukung rentang numerik {1..42}tetapi mksh tidak.

Ekspansi parameter

Ksh93 dan mksh dukungan ekstraksi substring dengan ${VAR:offset}dan ${VAR:offset:length}, tetapi tidak terjadi lipat seperti ${VAR^}, ${VAR,}, dll Anda dapat melakukan konversi kasus dengan typeset -ldan typeset -udi kedua bash dan ksh.

Mereka mendukung penggantian dengan ${VAR/PATTERN/STRING}atau ${VAR/PATTERN//STRING}. Aturan kutip untuk STRING sedikit berbeda, jadi hindari garis miring terbalik (dan mungkin karakter lain) di STRING (buat variabel dan gunakan ${VAR/PATTERN/$REPLACEMENT}sebagai gantinya jika pengganti berisi karakter kutip).

Ekspansi Array ( ${ARRAY[KEY]}, "${ARRAY[@]}", ${#ARRAY[@]}, ${!ARRAY[@]}) bekerja di bash seperti di ksh.

${!VAR}meluas ke ${OTHERVAR}saat nilai VARis OTHERVAR(referensi variabel tidak langsung) spesifik-bash (ksh melakukan sesuatu yang berbeda dengan ${!VAR}). Untuk mendapatkan ekspansi ganda dalam ksh, Anda harus menggunakan referensi nama sebagai gantinya ( typeset -n VAR=OTHERVAR; echo "$VAR"). ${!PREFIX*}bekerja sama.

Substitusi proses

Proses substitusi <(…)dan >(…)didukung dalam ksh93 tetapi tidak dalam mksh.

Pola wildcard

Pola ksh extended glob yang perlu shopt -s extglobdiaktifkan dalam bash selalu tersedia di ksh93 dan mksh.

Mksh tidak mendukung kelas karakter seperti [[:alpha:]].

Pengalihan IO

Bash dan ksh93 mendefinisikan pseudo-file dan , tetapi mksh tidak./dev/tcp/HOST/PORT/dev/udp/HOST/PORT

Memperluas wildcard dalam pengalihan dalam skrip (seperti dalam var="*.txt"; echo hello >$apenulisan a.txtjika nama file itu satu-satunya yang cocok dengan pola) adalah fitur khusus bash (shell lain tidak pernah melakukannya dalam skrip).

<<< di sini-string bekerja di ksh seperti di bash.

Jalan pintas >&untuk mengarahkan ulang kesalahan sintaks juga didukung oleh mksh tetapi tidak oleh ksh93.

Ekspresi bersyarat

[[ … ]] sintaks braket ganda

Sintaks braket ganda dari ksh didukung oleh ATT ksh93 dan mksh seperti pada bash.

Operator file

Ksh93, mksh dan bash mendukung ekstensi yang sama untuk POSIX, termasuk -asebagai sinonim usang -e, -k(sticky), -G(dimiliki oleh egid), -O(pemilik oleh euid), -ef(file yang sama), -nt(lebih baru dari), -ot(lebih tua dari).

-N FILE (dimodifikasi sejak baca terakhir) tidak didukung oleh mksh.

Mksh tidak memiliki operator pencocokan regexp =~. Ksh93 memiliki operator ini, dan melakukan pencocokan yang sama seperti di bash, tetapi tidak memiliki yang setara dengan BASH_REMATCHuntuk mengambil grup yang cocok setelahnya.

Operator string

Ksh93 dan mksh mendukung operator perbandingan string yang sama <dan >juga bash serta ==sinonim dari =. Mksh tidak menggunakan pengaturan lokal untuk menentukan urutan leksikografis, ia membandingkan string sebagai string byte.

Operator lain

-v VARuntuk menguji apakah suatu variabel didefinisikan spesifik-bash. Di setiap shell POSIX, Anda dapat menggunakan [ -z "${VAR+1}" ].

Dibangun

alias

Set karakter yang diizinkan dalam nama alias tidak sama di semua shell. Saya pikir itu sama dengan fungsi (lihat di atas).

builtin

Ksh93 memiliki builtin yang dipanggil builtin, tetapi tidak menjalankan nama sebagai perintah built-in. Gunakan commanduntuk memotong alias dan fungsi; ini akan memanggil builtin jika ada, jika tidak, perintah eksternal (Anda dapat menghindari ini dengan PATH= command error_out_if_this_is_not_a_builtin).

caller

Ini khusus untuk bash. Anda bisa mendapatkan efek serupa dengan .sh.fun, .sh.filedan .sh.linenodi ksh93. Di mksh akhirnya ada LINENO.

declare, local,typeset

declareadalah nama spesifik-bash untuk ksh typeset. Gunakan typeset: ini juga bekerja di bash.

Mksh mendefinisikan localsebagai alias untuk typeset. Di ksh93, Anda perlu menggunakan typeset(atau mendefinisikan alias).

Mksh tidak memiliki array asosiatif (mereka dijadwalkan untuk versi yang belum dirilis).

Saya tidak berpikir ada yang sama persis dengan typeset -t(fungsi jejak) bash di ksh.

cd

Ksh93 tidak punya -e.

echo

Ksh93 dan mksh memproses -edan -nopsi seperti di bash. Mksh juga mengerti -E, ksh93 tidak memperlakukannya sebagai opsi. Ekspansi Backslash dimatikan secara default di ksh93, diaktifkan secara default di mksh.

enable

Ksh tidak menyediakan cara untuk menonaktifkan perintah builtin. Untuk menghindari builtin, cari jalur perintah eksternal dan aktifkan secara eksplisit.

exec

Ksh93 memiliki -atetapi tidak -l. Mksh tidak memiliki keduanya.

export

Baik ksh93 maupun mksh tidak export -n. Gunakan typeset +x foosebagai gantinya, ia bekerja di bash dan ksh.

Ksh tidak mengekspor fungsi melalui lingkungan.

let

let sama di bash dan ksh.

mapfile, readarray

Ini adalah fitur khusus bash. Anda dapat menggunakan while readloop atau substitusi perintah untuk membaca file dan membaginya menjadi array baris. Jaga IFSdan globbing. Ini setara dengan mapfile -t lines </path/to/file:

IFS=$'\n'; set -f
lines=($(</path/to/file))
unset IFS; set +f

printf

printfsangat mirip. Saya pikir ksh93 mendukung semua arahan format bash. mksh tidak mendukung %qatau %(DATE_FORMAT)T; pada beberapa instalasi, printfbukan mksh builtin dan memanggil perintah eksternal sebagai gantinya.

printf -v VAR spesifik-bash, ksh selalu mencetak ke output standar.

read

Beberapa opsi spesifik untuk bash, termasuk semua opsi tentang readline. Pilihan -r, -d, -n, -N, -t, -uidentik di bash, ksh93 dan mksh.

readonly

Anda bisa mendeklarasikan variabel sebagai read-only di Ksh93 dan mksh dengan sintaks yang sama. Jika variabelnya adalah array, Anda harus menetapkannya terlebih dahulu, kemudian membuatnya hanya-baca readonly VAR. Fungsi tidak dapat dibuat hanya-baca dalam ksh.

set, shopt

Semua opsi ke setdan set -omerupakan fitur POSIX atau ksh.

shoptspesifik untuk bash. Banyak pilihan yang menyangkut penggunaan interaktif. Untuk efek pada penggumpalan dan fitur lain yang diaktifkan oleh beberapa opsi, lihat bagian "Opsi" di bawah ini.

source

Varian ini .ada di ksh juga. Di bash dan mksh, sourcecari direktori saat ini setelahnya PATH, tetapi di ksh93, ini persis sama dengan ..

trap

The DEBUGpseudo-sinyal tidak dilaksanakan di mksh. Di ksh93, ia ada dengan cara berbeda untuk melaporkan informasi, lihat manual untuk detailnya.

type

Di ksh, typeadalah alias untuk whence -v. Di mksh, type -ptidak mencetak path ke executable, tetapi pesan yang bisa dibaca manusia; Anda harus menggunakannya whence -p COMMANDsebagai gantinya.

Pilihan

shopt -s dotglob - jangan abaikan file dot di globbing

Untuk meniru dotglobopsi dalam ksh93, Anda dapat mengatur FIGNORE='@(.|..)'. Saya tidak berpikir ada yang seperti ini di mksh.

shopt -s extglob - ksh diperpanjang pola gumpalan

The extglobpilihan adalah efektif selalu di ksh.

shopt -s failglob - Kesalahan jika pola glob tidak cocok dengan apa pun

Saya tidak berpikir ini ada di mksh atau ksh93. Itu dalam zsh (perilaku default kecuali null_globatau csh_null_globdiatur).

shopt -s globstar**/globbing rekursif

Ksh93 memiliki globbing rekursif dengan **/, diaktifkan dengan set -G. Mksh tidak memiliki globbing rekursif.

shopt -s lastpipe - Jalankan perintah terakhir dari sebuah pipa di shell induk

Ksh93 selalu menjalankan perintah terakhir dari sebuah pipeline di shell induk, yang dalam bash membutuhkan lastpipeopsi untuk diatur. Mksh selalu menjalankan perintah terakhir dari sebuah pipa dalam sebuah subkulit.

shopt -s nocaseglob, shopt -s nocasematch- pola case-insensitive

Mksh tidak memiliki pencocokan pola case-insensitive. Ksh93 mendukungnya berdasarkan pola-demi-pola: awali pola dengan ~(i).

shopt -s nullglob - perluas pola yang tidak cocok dengan file ke daftar kosong

Mksh tidak punya ini. Ksh93 mendukungnya berdasarkan pola-demi-pola: awali pola dengan ~(N).

Variabel

Jelas sebagian besar BASH_xxxvariabel tidak ada di ksh. $BASHPIDdapat ditiru dengan mahal tapi portabel sh -c 'echo $PPID', dan baru-baru ini ditambahkan ke mksh. BASH_LINEada .sh.linenodi ksh93 dan LINENOdi mksh. BASH_SUBSHELLada .sh.subshelldi ksh93.

Mksh dan ksh93 keduanya sumber file yang diberikan ENVketika mereka memulai.

EUIDdan UIDtidak ada di ksh93. Mksh memanggil mereka USER_IDdan KSH_UID; tidak ada GROUPS.

FUNCNAMEdan FUNCNESTtidak ada di ksh. Ksh93 memiliki .sh.fundan .sh.level. Fungsi yang dideklarasikan dengan function foo { …; }(tanpa tanda kurung!) Memiliki nama sendiri di $0.

GLOBIGNOREada di ksh93 tetapi dengan nama dan sintaks yang berbeda: itu disebut FIGNORE, dan itu adalah pola tunggal, bukan daftar yang dipisahkan titik dua. Gunakan @(…|…)pola. Ksh FIGNOREmengelompokkan bash, dengan sintaks yang sama sekali berbeda.

Ksh93 dan mksh tidak ada yang suka HOSTTYPE, MACHTYPEdan OSTYPE. Atau SHELLOPTSatau TIMEFORMAT.

Mksh punya PIPESTATUS, tapi ksh93 tidak.

Mksh dan ksh93 miliki RANDOM.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
jika Anda tidak ingin mereproduksi merek dagang "mksh" (tidak terdaftar) dengan benar di awal kalimat ( lihat juga "" dd. "" vs. "" dd "." di sini ), silakan tulis "The MirBSD Korn Shell ”sebagai gantinya. Itu selalu salah untuk huruf besar huruf "mksh". Terima kasih.
mirabilos
Bagaimana bisa $BASHPIDditiru sh -c 'echo $PPID'? Saya mencoba (sh -c 'echo $PPID')di Bash tetapi memberi saya PID yang sama dengan $$.
Franklin Yu
Saya pikir pertanyaannya lebih cocok di sini . Saya menyalin pertanyaan di sana.
Franklin Yu
4

Pertanyaan ini agak terlalu luas.

Baik mksh dan zsh adalah shell yang mendukung banyak ekstensi GNU bash -specific, tetapi selalu ada beberapa yang tidak dimengerti.

zsh mendukung lebih banyak hal, tetapi hanya dalam mode zsh aslinya, yang tidak kompatibel dengan shell POSIX (seperti GNU bash, AT&T ksh93 , mksh). Juga, mksh jauh lebih ramping dan lebih cepat dan lebih portabel.

Secara umum, jika ini adalah skrip Anda yang sedang kita bicarakan, silakan, coba saja. (mksh belum mendukung array asosiatif bash4-style. Perintah "mendeklarasikan" adalah spesifik-bash, "typeset" adalah setara. Saya tidak cukup familiar dengan zsh untuk menyatakan apa pun tentang hal itu secara langsung. ksh93 tidak memiliki "lokal" tetapi juga menggunakan "typeset" untuk itu.) Tetapi jika ini tentang, katakanlah, menjalankan sistem Debian kurang-bash, lupakan saja. Keberadaan bash adalah bagian dari "janji" (API / ABI sistem), dan banyak yang bergantung padanya.

Penafian: Saya adalah pengembang mksh.

mirabilos
sumber
1

ZSH Perbandingan Kerang

Namun, dalam beberapa tahun terakhir telah terjadi crossover dalam ekstensi. Zsh (per 3.1.6) memiliki bash ${var/old/new}' feature for replacing the text old with the text new in the parameter $var. Note one difference here: while both shells implement the syntax$ {var / # tua / baru} 'dan ${var/%old/new}' for anchoring the match of old to the start or end of the parameter text, respectively, in zsh you can't put the#' atau %' inside a parameter: in other words{var / $ lama / baru} 'di mana tua dimulai dengan #' treats that as an ordinary character in zsh, unlike bash. To do this sort of thing in zsh you can use (from 3.1.7) the new syntax for anchors in any pattern,(# s)' untuk mencocokkan awal string , dan `(#e) 'untuk mencocokkan akhir. Ini membutuhkan opsi EXTENDED_GLOB untuk ditetapkan.

Saya paling tidak terbiasa dengan mksh, jadi saya tidak tahu ke mana harus mencari jawaban itu.

Jika Anda mencari pengganti shell yang aman, tidak ada shell yang berbeda jauh dari Bash sejauh cacat bawaan yang Anda diskusikan.

Bahasa seperti Perl menangani input dengan lebih aman. Tetapi perawatan juga merupakan kunci di sini. Penggantian shell Perl tidak diadopsi dengan baik. Merupakan tanggung jawab pengelola shell untuk menangani input dengan aman. Jadi ketika Anda menulis skrip, validasi, validasikan, validasi semuanya! Gunakan kontrak kode untuk memastikan hasil yang benar setiap waktu!

Perl Shell

Pernyataan FSF tentang Shell Shock

Tyler Maginnis
sumber
Jika memang benar shell lain memiliki kelemahan yang sama - yang saya agak ragu, berdasarkan diskusi yang saya lihat - maka itu adalah masalah BESAR , karena banyak program pihak ketiga meneruskan variabel ke shell tanpa jenis apa pun. validasi atau apapun. Jika itu masalahnya, kami mungkin akan membuang POSIX sepenuhnya.
DanL4096
1
Proyek Bash telah memiliki 1 0-hari eksploitasi dalam 10 tahun. Microsoft Windows memiliki lebih dari 10 exploit, semuanya 0-hari, per minggu. Apakah Anda tahu berapa banyak orang yang mengganggu tim pengembangan Bash tentang ini? Cukup perbarui dan lanjutkan! Bukan masalah besar.
Tyler Maginnis
1
@ DanL4096. Melewatkan variabel ke skrip shell yang kemudian tidak melakukan pemeriksaan kewarasan yang memadai pada variabel bukan alasan untuk membuang POSIX. Masalahnya terletak pada orang yang menulis skrip shell di tempat pertama.
fpmurphy
0

Salah satu fitur yang tidak diaktifkan secara default mkshadalah riwayat shell.

  • Di .mkshrcset hanya Anda :

    export HISTFILE=~/.mksh-history

Stuart Cardall
sumber