Zsh ve mksh bash ile nerede uyumsuz?


11

POSIX uyumlu diğer mermiler ne ölçüde bash için makul yedek olarak işlev görebilir? Gerçek "drop-in" yedekleri olmaları gerekmez, ancak çoğu komut dosyasıyla çalışacak ve gerisini bazı değişikliklerle destekleyecek kadar yakındırlar .

  1. Açık bash komut dosyalarına sahip olmak istiyorum - initscripts, DHCP istemci komut dosyaları, vb. - minimum değişiklikle çalışmak

  2. Daha özel kabuk komut dosyaları koleksiyonumun çok fazla modifikasyona ihtiyaç duymamasını istiyorum

  3. Dize düzenleme ve yerleşik regex desen eşleştirme gibi özelliklere sahip olmak istiyorum

Bildiğim tek ciddi yarışmacı zsh ve mksh. Yani, burada ikisinden biri veya her ikisi ile iyi olanlarınız için:

  1. Bash'in zsh ve mksh sırasıyla sahip olmadığı özellikleri nelerdir?

  2. Kabuklar bash ile hangi özellikleri paylaşır, ancak uyumsuz sözdizimini kullanır?


3
Komut Kabuklarının Karşılaştırılması: ( en.wikipedia.org/wiki/Comparison_of_command_shells ) Bash Scripting için Gelişmiş Kılavuz: ( tldp.org/LDP/abs/html ) ZSH El Kitabı: ( zsh.sourceforge.net/Guide/zshguide.html ) MirBSD Kabuk El Kitabı: ( mirbsd.org/htman/i386/man1/mksh.htm ). Üzgünüm, ama bu soru çok karmaşık. Belki de belirli Linux dağıtımınızdaki güvenlik açığını gidermek için bash'ı nasıl yamalayacağınızı sormalısınız?
Tyler Maginnis

3
bashMksh ve zsh'nin yerine bir damla olarak işlev görebilecek bir kabuk yoktur, /bin/shçeşitli doğruluk seviyelerinde olduğu gibi çalışabilir , ancak çalışamaz bash.
llua

1
Bütün shellshock şey çekirdek soru ile ilgisi yok gibi görünüyor ve sadece insanları rahatsız ediyor, bu yüzden onu kaldırdım
Michael Mrozek

3
Bütün soru aşırı geniş. Belki de kaldırmalısınız.
Tyler Maginnis

1
Gerçekten sahip olduğum tek endişe, BASH'ın Özgür Yazılım Vakfı (FSF) tarafından iyi bir şekilde sürdürülmesidir. Oradaki temaslarım bana, BASH içindeki "temel kusur" un vahyinin yalnızca daha güçlü ve daha güvenli bir uygulamaya yol açacağını söylüyor. Gereksiniminiz için bir tane tavsiye etmeye bile başlayacak kadar çok alternatif kabuk var, kullanım durumunuzun sağlam bir şekilde anlaşılmasını istiyorum. Sonra O / S tarafında ... Bash'e o kadar çok şey bağlı ki, tüm O / S çağrılarınızı BASH'e yeniden yazabilirsiniz. Görebildiğim en iyi çözüm, korunmuş bir alt kabuğu olan bir dağıtım seçmektir.
Tyler Maginnis

Yanıtlar:


19

Komut dosyası özelliklerine bağlı kalacağım. Zengin etkileşimli özellikler (komut satırı sürümü, tamamlama, bilgi istemleri vb.) Çok farklı olma eğilimindedir ve tamamen uyumsuz şekillerde benzer efektler elde eder. Zsh'de hangi özellikler vardır ve bash'da yoktur veya tersi nedir? etkileşimli kullanım için birkaç işaret verir.

Bash'a en yakın şey ATT ksh93 veya mksh (Korn kabuğu ve bir klon) olacaktır. Zsh'ın bir dizi alt özelliği de vardır, ancak bunu zsh yerel modunda değil, ksh öykünme modunda çalıştırmanız gerekir.

POSIX özelliklerini (herhangi bir modern shkabukta bulunan) veya nispeten belirsiz özellikleri veya etkileşimli kullanım için yukarıda belirtildiği gibi listelemeyeceğim . Gözlemler, Debian wheezy'de bulunan bash 4.2, ksh 93u ve mksh 40.9.20120630'dan itibaren geçerlidir.

Kabuk sözdizimi

Alıntı yapmak

$'…'(ters eğik çizgi enterpolasyonlu gerçek dizeler) ksh93 ve mksh'de kullanılabilir. "$"… "(Çevrilmiş dizeler) bash'a özgüdür.

Koşullu yapılar

Mksh ve ksh93 sahip ;&bir yer düşmeye caseaçıklamada, ancak ;;&daha sonraki durumları test etmek. Mksh bunun ;|için var ve son mksh ;;&uyumluluğa izin veriyor .

((…))aritmetik ifadeler ve [[ … ]]testler ksh özellikleridir. Bazı koşullu işleçler farklıdır, aşağıdaki “koşullu ifadeler” konusuna bakın.

Yardımcı işlemci

Ksh ve bash'ın her ikisi de ortak işlemlere sahiptir, ancak farklı çalışırlar.

Fonksiyonlar

Mksh ve ksh93 function name {…}, standarda ek olarak fonksiyon tanımları için sözdizimini destekler name () {…}, ancak functionksh değişikliklerinde kapsam belirleme kurallarını kullanmak, bu nedenle name () …uyumluluğu korumak için sadık kalın . İşlev adlarında izin verilen karakterler için kurallar değişir; alfanümeriklere bağlı kalmak ve _.

Destek genişletme

Ksh93 ve mksh destek genişletmeyi destekler {foo,bar}. Ksh93 sayısal aralıkları destekler {1..42}ancak mksh desteklemez .

Parametre genişletme

Ksh93 ve mksh destek alt dize ile ekstraksiyon ${VAR:offset}ve ${VAR:offset:length}ancak durum böyle katlanır ${VAR^}, ${VAR,}vb Sen durum dönüştürme yapabilirsiniz typeset -lve typeset -ubash ve ksh hem de.

${VAR/PATTERN/STRING}Veya ile değiştirmeyi desteklerler ${VAR/PATTERN//STRING}. STRING için alıntı kuralları biraz farklıdır, bu nedenle STRING'de ters eğik çizgilerden (ve belki de diğer karakterlerden) kaçının (bir değişken oluşturun ve ${VAR/PATTERN/$REPLACEMENT}yerine alıntı karakterleri içeriyorsa kullanın ).

Dizi genişleme ( ${ARRAY[KEY]}, "${ARRAY[@]}", ${#ARRAY[@]}, ${!ARRAY[@]}ksh gibi bash) çalışır.

${!VAR}Genişleyen ${OTHERVAR}değeri zaman VARolduğu OTHERVAR(dolaylı değişken referansı) bash özgü (Ksh ile birşeylerindeğiştiğini yapmasıdır ${!VAR}). Bu çift genişletmeyi ksh olarak almak için, bunun yerine ( typeset -n VAR=OTHERVAR; echo "$VAR") bir ad başvurusu kullanmanız gerekir . ${!PREFIX*}aynı şekilde çalışır.

Proses ikamesi

Proses ikamesi <(…)ve >(…)ksh93'te desteklenir, ancak mksh'de desteklenmez.

Joker desenleri

shopt -s extglobBash'ta etkinleştirilmesi gereken ksh genişletilmiş glob kalıpları her zaman ksh93 ve mksh'de kullanılabilir.

Mksh gibi karakter sınıflarını desteklemez [[:alpha:]].

ES yönlendirmesi

Bash ve ksh93 sözde dosyaları tanımlamak ve ancak mksh yok./dev/tcp/HOST/PORT/dev/udp/HOST/PORT

Komut dosyalarında yeniden yönlendirmede joker karakterleri genişletmek ( bu dosya adı kalıp için tek eşleme ise var="*.txt"; echo hello >$ayazılı olarak olduğu gibi a.txt) bash'a özgü bir özelliktir (diğer kabuklar bunu komut dosyalarında asla yapmaz).

<<< burada dizeler bash gibi ksh olarak çalışır.

>&Sözdizimi hatalarını yeniden yönlendirme kısayolu da mksh tarafından desteklenir, ancak ksh93 tarafından desteklenmez.

Koşullu ifadeler

[[ … ]] çift ​​parantez sözdizimi

Ksh'nin çift parantez sözdizimi bash'daki gibi ATT ksh93 ve mksh tarafından desteklenir.

Dosya operatörleri

Ksh93, mksh ve bash, -aeski -e, -k(yapışkan), -G( egid'e ait), (euid -Osahibi), -ef(aynı dosya), -nt(daha yeni), -ot(eski) eşanlamlıları da dahil olmak üzere POSIX ile aynı uzantıları destekler .

-N FILE (son okunduğundan beri değiştirildi) mksh tarafından desteklenmiyor.

Mksh'de normal ifade eşleştirme operatörü yok =~. Ksh93 bu operatöre sahiptir ve bash ile aynı eşleşmeyi gerçekleştirir, ancak BASH_REMATCHdaha sonra eşleşen grupları almak için eşdeğeri yoktur .

Dize işleçleri

Ksh93 ve aynı dize karşılaştırma operatörleri mksh destek <ve >Bash yanı sıra sıra ==bir eş anlamlısı =. Mksh, sözlük sırasını belirlemek için yerel ayarları kullanmaz, dizeleri bayt dizeleri olarak karşılaştırır.

Diğer operatörler

-v VARbir değişkenin tanımlanıp tanımlanmadığını bash'a özgü olup olmadığı Herhangi bir POSIX kabuğunda kullanabilirsiniz [ -z "${VAR+1}" ].

yerleşikleri

alias

Takma adlardaki izin verilen karakter kümesi tüm kabuklarda aynı değildir. Bence bu işlevler ile aynıdır (yukarıya bakınız).

builtin

Ksh93 adlı bir yerleşik vardır builtin, ancak yerleşik komut olarak bir ad yürütmez. commandTakma adları ve işlevleri atlamak için kullanın ; bu varsa, yerleşik bir çağrı, aksi takdirde harici bir komut çağıracaktır PATH= command error_out_if_this_is_not_a_builtin.

caller

Bu bash'e özgüdür. Sen benzer bir etkiyi elde edebilirsiniz .sh.fun, .sh.fileve .sh.linenoksh93 içinde. Mksh'de sonunda var LINENO.

declare, local,typeset

declareksh'lar için bash'a özgü bir isimdir typeset. Kullanımı typeset: bash da çalışır.

Mksh, localiçin bir takma ad olarak tanımlar typeset. Ksh93'te, kullanmanız typeset(veya bir takma ad tanımlamanız) gerekir.

Mksh'nin ilişkilendirilebilir dizileri yoktur (henüz yayınlanmamış bir sürüm için sıralanmıştır).

typeset -tKsh'ta bash'ın (izleme fonksiyonu) tam bir eşdeğeri olduğunu sanmıyorum .

cd

Ksh93 sahip değil -e.

echo

Ksh93 ve mksh -eve -nbash gibi seçenekleri işler . Mksh da anlıyor -E, ksh93 bunu bir seçenek olarak görmüyor. Ters eğik çizgi genişletmesi ksh93'te varsayılan olarak kapalı, mksh'de varsayılan olarak açıktır.

enable

Ksh yerleşik komutları devre dışı bırakmanın bir yolunu sunmaz. Bir yerleşkeyi önlemek için, harici komutun yolunu arayın ve açıkça çağırın.

exec

Ksh93 var -aama değil -l. Mksh'ın hiçbiri yok.

export

Ne ksh93 ne de mksh yoktur export -n. Kullanım typeset +x foobunun yerine, bash ve ksh çalışır.

Ksh, işlevleri çevre üzerinden dışa aktarmaz.

let

let bash ve ksh için aynıdır.

mapfile, readarray

Bu bash'a özgü bir özelliktir. Sen kullanabilirsiniz while readbir dosyayı okumak ve çizgiler düzeni bölmek döngüler veya komut ikamesi. Özen IFSve globbing. İşte şuna eşdeğer mapfile -t lines </path/to/file:

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

printf

printfçok benzer. Bence ksh93 bash'ın tüm format direktiflerini destekliyor. mksh desteklemez %qveya %(DATE_FORMAT)T; bazı kurulumlarda printfmksh yerleşik değildir ve bunun yerine harici komutu çağırır.

printf -v VAR bash'a özgüdür, ksh her zaman standart çıktıya yazdırır.

read

Readline ile ilgili olanlar da dahil olmak üzere çeşitli seçenekler bash'a özgüdür. Seçenekleri -r, -d, -n, -N, -t, -ubash, ksh93 ve mksh aynıdır.

readonly

Bir değişkeni Ksh93 ve mksh'de aynı sözdizimiyle salt okunur olarak bildirebilirsiniz. Değişken bir diziyse, önce ona bir dizi atamanız, ardından onu salt okunur hale getirmeniz gerekir readonly VAR. Fonksiyonlar ksh cinsinden salt okunur yapılamaz.

set, shopt

Tüm seçenekler setve set -oPOSIX veya Ksh özellikleridir.

shoptbash'a özgüdür. Birçok seçenek yine de etkileşimli kullanımla ilgilidir. Globbing ve bazı seçeneklerin etkinleştirdiği diğer özellikler üzerindeki efektler için aşağıdaki “Seçenekler” bölümüne bakın.

source

Bu varyant çeşidi de .ksh cinsindendir. Bash ve mksh'de sourcegeçerli dizinden sonra arar PATH, ancak ksh93'te tam olarak eşdeğerdir ..

trap

DEBUGSinyalimsi mksh uygulanmadı. Ksh93'te, bilgiyi raporlamanın farklı bir yolu vardır, ayrıntılar için kılavuza bakın.

type

Ksh, typeiçin bir takma addır whence -v. Mksh'de, type -pyürütülebilir yolun yolunu değil, okunabilir bir iletiyi yazdırır; whence -p COMMANDbunun yerine kullanmanız gerekir .

Seçenekler

shopt -s dotglob - globbing'teki nokta dosyalarını yok saymayın

dotglobKsh93'deki seçeneği taklit etmek için ayarlayabilirsiniz FIGNORE='@(.|..)'. Mksh'de böyle bir şey olduğunu sanmıyorum.

shopt -s extglob - ksh genişletilmiş glob kalıpları

extglobOpsiyon ksh hep etkili bir olduğunu.

shopt -s failglob - bir küre deseni hiçbir şeyle eşleşmezse hata oluştu

Bunun mksh veya ksh93'te olduğunu sanmıyorum. Zsh ile yapılır ( null_globveya csh_null_globayarlanmadığı sürece varsayılan davranış ).

shopt -s globstar**/özyinelemeli globbing

Ksh93 ile birlikte **/, özyinelemeli globbing vardır set -G. Mksh'nin tekrarlayan bir küresi yoktur.

shopt -s lastpipe - üst kabukta bir boru hattının son komutunu çalıştır

Ksh93, her zaman üst kabukta bir boru hattının son komutunu çalıştırır, bu da bash'da lastpipeseçeneğin ayarlanmasını gerektirir . Mksh her zaman bir alt kabuktaki bir boru hattının son komutunu çalıştırır.

shopt -s nocaseglob, shopt -s nocasematch- büyük / küçük harfe duyarlı olmayan desenler

Mksh, büyük / küçük harfe duyarlı olmayan desen eşleşmesine sahip değildir. Ksh93 bunu desene göre destekler: desenin önüne önek ekler ~(i).

shopt -s nullglob - hiçbir dosyayla eşleşen desenleri boş bir listeye genişletme

Mksh buna sahip değil. Ksh93 bunu desene göre destekler: desenin önüne önek ekler ~(N).

Değişkenler

Açıkçası BASH_xxxdeğişkenlerin çoğu ksh cinsinden yok. $BASHPIDpahalı ama taşınabilir özelliklerle taklit edilebilir sh -c 'echo $PPID've son zamanlarda mksh'ye eklenmiştir. BASH_LINEolduğu .sh.linenoksh93 ve LINENOmksh içinde. BASH_SUBSHELLolduğu .sh.subshellksh93 içinde.

Mksh ve ksh93 her ikisi de ENVbaşlatıldıklarında verilen dosyayı kaynak eder .

EUIDve UIDksh93'te yoktur. Mksh onları arar USER_IDve KSH_UID; yok GROUPS.

FUNCNAMEve FUNCNESTksh'ta yok. Ksh93 .sh.funve vardır .sh.level. function foo { …; }(Parantez yok!) İle bildirilen işlevlerin kendi adları vardır $0.

GLOBIGNOREksh93'te var, ancak farklı bir ad ve sözdizimiyle var: denir FIGNOREve iki nokta üst üste işaretli bir liste değil, tek bir modeldir. Bir @(…|…)desen kullanın . Ksh'ın bash'ı FIGNOREtamamen farklı bir sözdizimiyle geçer.

Ksh93 ve mksh gibi bir şey var HOSTTYPE, MACHTYPEve OSTYPE. Ne de SHELLOPTSya TIMEFORMAT.

Mksh var PIPESTATUS, ama ksh93 değil.

Mksh ve ksh93 var RANDOM.


(kayıtlı olmayan) “mksh” ticari markasını bir cümlenin başında doğru bir şekilde üretmek istemiyorsanız ( ayrıca bkz. ““ dd. ”” ve ““ dd ”.” ), lütfen “MirBSD” yazın Korn Shell ”yerine. Öyle her zaman yanlış “mksh” herhangi harfini büyük. Teşekkürler.
mirabilos

Nasıl $BASHPIDtaklit edilebilir sh -c 'echo $PPID'? Ben (sh -c 'echo $PPID')Bash denedim ama bana aynı PID verir $$.
Franklin Yu

Bence soru buraya daha iyi uyuyor . Soruyu oraya kopyaladım.
Franklin Yu

4

Bu soru oldukça geniş.

Hem mksh hem de zsh , çok sayıda GNU bash -spesifik uzantısını destekleyen kabuklardır , ancak her zaman anlaşılmayan bazı şeyler vardır.

zsh daha fazla öğeyi destekler, ancak yalnızca POSIX kabuklarıyla (GNU bash, AT&T ksh93, mksh gibi) uyumlu olmayan yerel zsh modunda destekler . Ayrıca, mksh çok daha yalın ve daha hızlı ve daha taşınabilir.

Genel olarak, bu ise sizin komut yaklaşık, sadece onları test, devam et bahsediyoruz. (mksh henüz bash4 stili ilişkilendirilebilir dizileri desteklemez. “declare” komutu bash'a özgüdür, “dizgi” eşdeğerdir. zsh ile bu açıklık hakkında hiçbir şey belirtecek kadar aşina değilim. ksh93'te “yerel” yok ama bunun için de "dizgi" kullanır.) Fakat bu, örneğin bash'sız bir Debian sistemi çalıştırmakla ilgiliyse unutun. Bash'in varlığı “vaat” in bir parçasıdır (sistemin API / ABI) ve buna çok güvenmektedir.

Feragatname: Ben mksh geliştiricisiyim.


1

Mermilerin ZSH Karşılaştırması

Bununla birlikte, son yıllarda uzantılarda belirli bir miktar çaprazlama olmuştur. Zsh (3.1.6 itibariyle) bash'ın ${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 / # old / new} 've ${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#' veya %' inside a parameter: in other words{var / $ old / new} 'ile eski #' 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,bir dizenin başlangıcıyla başlıyor ve sonuna uyacak şekilde `` #e) 'yi seçin. Bunlar, EXTENDED_GLOB seçeneğinin ayarlanmasını gerektirir.

Mksh'yi en iyi bilmiyorum, bu yüzden bu cevabı nerede arayacağımı bilmiyorum.

Kabuk için güvenli bir yedek arıyorsanız, bu kabukların hiçbiri tartıştığınız doğal kusur kadar Bash'den çok farklı değildir.

Perl gibi bir dil, girdileri daha güvenli bir şekilde işler. Ancak, burada sürdürülebilirlik de kilit öneme sahiptir. Perl mermisinin değiştirilmesi pek iyi kabul görmemiştir. Girdileri güvenli bir şekilde işlemek kabuk bakımcının sorumluluğundadır. Komut dosyaları yazarken , her şeyi doğrulayın, doğrulayın, doğrulayın! Her seferinde doğru sonuçları elde etmek için kod sözleşmelerini kullanın!

Perl Kabuğu

Shell Shock Hakkında FSF Bildirimi


Diğer kabukların aynı kusura sahip olması durumuysa - hangi tartışmayı gördüğüme bağlı olarak biraz şüpheliyim - o zaman bu çok büyük bir sorundur, çünkü birçok üçüncü taraf programın kabuklara herhangi bir tür olmadan değişkenleri iletmesi doğrulama veya herhangi bir şey. Eğer durum buysa, POSIX'i de tamamen atabiliriz.
DanL4096

1
Bash projesi 10 yılda 1 0 günlük istismar gerçekleştirdi. Microsoft Windows haftada 0 gün olmak üzere 10 istismardan yararlanır. Bu konuda kaç kişinin Bash geliştirme ekibini rahatsız ettiğini bile biliyor musunuz? Sadece güncelleyin ve devam edin! Büyük bir sorun değil.
Tyler Maginnis

1
@ DanL4096. Değişkenleri yeterli aklı başında kontrol yapmayan kabuk betiklerine değişkenler geçirmek POSIX'i atmak için bir neden değildir. Sorun, ilk başta kabuk betiğini yazan kişide yatmaktadır.
fpmurphy

0

Bir özellik değil varsayılan olarak etkindir mkshkabuk tarihidir.

  • Yeni .mkshrcayarlarınızda:

    export HISTFILE=~/.mksh-history

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.