Gdzie zsh i mksh są niezgodne z bash?

11

W jakim stopniu inne powłoki zgodne z POSIX mogą funkcjonować jako rozsądne zamienniki bash? Nie muszą to być prawdziwe „zastępcze” zamienniki, ale wystarczająco blisko, aby pracować z większością skryptów i obsługiwać resztę z pewnymi modyfikacjami.

  1. Chcę mieć wyraźne skrypty bash - skrypty startowe, skrypty klienta DHCP itp. - pracujące z minimalnymi modyfikacjami

  2. Chcę, aby moja kolekcja bardziej wyspecjalizowanych skryptów powłoki nie wymagała zbyt wielu modyfikacji

  3. Chcę mieć takie funkcje, jak manipulacja ciągiem znaków i wbudowane dopasowanie wzorca wyrażeń regularnych

Jedynymi poważnymi pretendentami, o których wiem, są zsh i mksh. Tak więc dla tych z was, którzy są dobrzy dla jednego lub obu z nich:

  1. Jakie funkcje ma bash, odpowiednio, zsh i mksh?

  2. Jakie funkcje współdzielą powłoki z bash, ale używają niekompatybilnej składni?

DanL4096
źródło
3
Porównanie powłok poleceń: ( en.wikipedia.org/wiki/Comparison_of_command_shells ) Zaawansowany przewodnik po skryptach Bash: ( tldp.org/LDP/abs/html ) Podręcznik ZSH: ( zsh.sourceforge.net/Guide/zshguide.html ) MirBSD Podręcznik powłoki: ( mirbsd.org/htman/i386/man1/mksh.htm ). Przepraszam, ale to pytanie jest zbyt złożone. Być może powinieneś zapytać, jak załatać bash, aby naprawić lukę w zabezpieczeniach dla konkretnej dystrybucji Linuksa?
Tyler Maginnis
3
Nie ma powłoki, która mogłaby funkcjonować jako kropla zastępująca bash, mksh i zsh mogłyby funkcjonować jak /bin/shz różnymi poziomami poprawności, ale nie bash.
llua
1
Wydaje się, że cała ta sprawa z muszlami nie ma nic wspólnego z głównym pytaniem i po prostu rozprasza ludzi, więc usunąłem ją
Michael Mrozek
3
Całe pytanie jest zbyt ogólne. Być może powinieneś to usunąć.
Tyler Maginnis
1
Jedyne, co naprawdę mnie niepokoi, to to, że BASH jest dobrze utrzymywany przez Free Software Foundation (FSF). Tamtejsze kontakty mówią mi, że ujawnienie „podstawowej wady” w BASH doprowadzi jedynie do silniejszej, bezpieczniejszej implementacji. Jest tak wiele alternatywnych powłok, że nawet zaczynając polecać jedną z twoich wymagań, wymagałbym solidnego zrozumienia twojego przypadku użycia. Następnie po stronie O / S ... Tak wiele rzeczy jest powiązanych z Bash, że możesz w końcu przepisać całe swoje wywołania O / S do BASH. Najlepszym rozwiązaniem, jakie widzę, jest wybór dystrybucji z zachowaną powłoką Alt.
Tyler Maginnis

Odpowiedzi:

19

Będę trzymać się funkcji skryptów. Bogate funkcje interaktywne (edycja wiersza poleceń, uzupełnianie, monity itp.) Bywają bardzo różne, osiągając podobne efekty w całkowicie niezgodny sposób. Jakie funkcje są w Zsh i brakuje w bash, lub odwrotnie? daje kilka wskazówek na temat interaktywnego użytkowania.

Najbliższą rzeczą do uderzenia byłoby ATT ksh93 lub mksh (skorupa Korna i klon). Zsh ma również podzbiór funkcji, ale trzeba go uruchomić w trybie emulacji ksh, a nie w trybie macierzystym zsh.

Nie wymienię funkcji POSIX (które są dostępne w żadnej nowoczesnej shpowłoce), ani stosunkowo mało znanych funkcji, ani też, jak wspomniano powyżej, funkcji interaktywnych. Obserwacje obowiązują od wersji bash 4.2, ksh 93u i mksh 40.9.20120630, jak stwierdzono w wheezy Debiana.

Składnia powłoki

Cytowanie

$'…'(dosłowne ciągi z interpolacją odwrotnego ukośnika) jest dostępny w ksh93 i mksh. `$„… ”(Przetłumaczone ciągi) jest specyficzne dla bash.

Konstrukcje warunkowe

Mksh i ksh93 muszą ;&przejść przez caseinstrukcję, ale nie ;;&testować kolejnych przypadków. Mksh ma ;|na to, a najnowszy mksh pozwala ;;&na kompatybilność.

((…))wyrażenia arytmetyczne i [[ … ]]testy są cechami ksh. Niektóre operatory warunkowe są różne, patrz „wyrażenia warunkowe” poniżej.

Koprocesy

Zarówno Ksh, jak i bash mają koprocesy, ale działają inaczej.

Funkcje

Mksh i ksh93 obsługują function name {…}składnię definicji funkcji oprócz standardu name () {…}, ale używając functionw ksh zmian zasad zakresu, więc trzymaj się, name () …aby zachować kompatybilność. Reguły dotyczące dozwolonych znaków w nazwach funkcji są różne; trzymać się alfanumerycznych i _.

Rozszerzenie klamry

Ksh93 i mksh obsługują rozszerzenie nawiasu klamrowego {foo,bar}. Ksh93 obsługuje zakresy liczbowe, {1..42}ale mksh nie.

Rozszerzenie parametrów

Ksh93 i mksh wsparcie podciąg z ekstrakcji ${VAR:offset}i ${VAR:offset:length}, ale nie przypadek składana jak ${VAR^}, ${VAR,}itd można zrobić konwersję z liter typeset -li typeset -uzarówno bash i ksh.

Obsługują zamianę na ${VAR/PATTERN/STRING}lub ${VAR/PATTERN//STRING}. Reguły cytowania dla STRING są nieco inne, więc unikaj odwrotnych ukośników (i być może innych znaków) w STRING (zbuduj zmienną i użyj ${VAR/PATTERN/$REPLACEMENT}zamiast tego, jeśli zamiennik zawiera znaki cytowania).

Rozszerzanie tablicy ( ${ARRAY[KEY]}, "${ARRAY[@]}", ${#ARRAY[@]}, ${!ARRAY[@]}) działa w bash jak w KSH.

${!VAR}rozwijanie do ${OTHERVAR}momentu, w którym wartość VARis OTHERVAR(odwołanie do zmiennej pośredniej) jest specyficzna dla bash (ksh robi coś innego z ${!VAR}). Aby uzyskać to podwójne rozszerzenie w ksh, musisz zamiast tego użyć odwołania do nazwy ( typeset -n VAR=OTHERVAR; echo "$VAR"). ${!PREFIX*}działa tak samo.

Zastąpienie procesu

Zmiana procesu <(…)i >(…)jest obsługiwana w ksh93 ale nie mksh.

Wzory symboli wieloznacznych

Rozszerzone wzorce globu ksh, które należy shopt -s extglobaktywować w bash, są zawsze dostępne w ksh93 i mksh.

Mksh nie obsługuje takich klas postaci jak [[:alpha:]].

Przekierowanie IO

Bash i ksh93 definiują pseudopliki i , ale mksh nie./dev/tcp/HOST/PORT/dev/udp/HOST/PORT

Rozwijanie symboli wieloznacznych w przekierowaniu w skryptach (tak jak w var="*.txt"; echo hello >$apisaniu do a.txttego, czy ta nazwa pliku jest jedynym dopasowaniem do wzorca) jest funkcją specyficzną dla bash (inne powłoki nigdy tego nie robią w skryptach).

<<< ciągi tutaj działają w ksh jak w bash.

Skrót >&do błędów składniowych przekierowania jest także obsługiwany przez mksh, ale nie przez ksh93.

Wyrażenia warunkowe

[[ … ]] składnia podwójnego nawiasu

Składnia podwójnego nawiasu od ksh jest obsługiwana zarówno przez ATT ksh93, jak i mksh jak w bash.

Operatorzy plików

Ksh93, mksh i bash obsługują te same rozszerzenia POSIX, w tym -ajako przestarzały synonim -e, -k(sticky), -G(własność egid), -O(właściciel przez euid), -ef(ten sam plik), -nt(nowszy niż), -ot(starszy niż).

-N FILE (zmodyfikowany od ostatniego odczytu) nie jest obsługiwany przez mksh.

Mksh nie ma operatora dopasowującego wyrażenia regularne =~. Ksh93 ma ten operator i wykonuje to samo dopasowanie, co w bash, ale nie ma odpowiednika BASH_REMATCHdo pobierania dopasowanych grup później.

Operatory strunowe

Ksh93 i mksh obsługują te same operatory porównywania ciągów <oraz >jako bash i ==synonim =. Mksh nie używa ustawień regionalnych do określenia porządku leksykograficznego, porównuje ciągi jako ciągi bajtów.

Inni operatorzy

-v VARtestowanie, czy zmienna jest zdefiniowana, jest specyficzne dla bash. Możesz użyć dowolnej powłoki POSIX [ -z "${VAR+1}" ].

Wbudowane

alias

Zestaw znaków dozwolonych w nazwach aliasów nie jest taki sam we wszystkich powłokach. Myślę, że jest tak samo jak w przypadku funkcji (patrz wyżej).

builtin

Ksh93 ma wbudowaną funkcję o nazwie builtin, ale nie wykonuje nazwy jako wbudowanej komendy. Służy commanddo pomijania aliasów i funkcji; wywoła to wbudowane, jeśli takie istnieje, w przeciwnym razie zewnętrzne polecenie (możesz tego uniknąć za pomocą PATH= command error_out_if_this_is_not_a_builtin).

caller

Jest to specyficzne dla bash. Można uzyskać podobny efekt .sh.fun, .sh.filea .sh.linenow ksh93. W mksh wreszcie jest LINENO.

declare, local,typeset

declarejest specyficzną dla bash nazwą ksh typeset. Użyj typeset: działa również w bash.

Mksh definiuje się localjako alias dla typeset. W ksh93 musisz użyć typeset(lub zdefiniować alias).

Mksh nie ma tablic asocjacyjnych (są one przeznaczone na jeszcze niepublikowaną wersję).

Nie sądzę, że typeset -tw ksh istnieje dokładny odpowiednik bash (funkcja śledzenia).

cd

Ksh93 nie ma -e.

echo

Ksh93 i mksh przetwarzają opcje -ei -njak w bash. Mksh również rozumie -E, ksh93 nie traktuje tego jako opcji. Rozwinięcie ukośnika odwrotnego jest domyślnie wyłączone w ksh93, domyślnie włączone w mksh.

enable

Ksh nie zapewnia sposobu na wyłączenie wbudowanych poleceń. Aby uniknąć wbudowania, sprawdź ścieżkę zewnętrznego polecenia i wywołaj je jawnie.

exec

Ksh93 ma, -aale nie ma -l. Mksh nie ma.

export

Ani ksh93, ani mksh nie ma export -n. Użyj typeset +x foozamiast tego działa w bash i ksh.

Ksh nie eksportuje funkcji przez środowisko.

let

let jest taki sam w bash i ksh.

mapfile, readarray

Jest to funkcja specyficzna dla bash. Możesz użyć while readpętli lub podstawienia poleceń, aby odczytać plik i podzielić go na tablicę wierszy. Zadbaj o IFSi globbing. Oto odpowiednik mapfile -t lines </path/to/file:

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

printf

printfjest bardzo podobny. Myślę, że ksh93 obsługuje wszystkie dyrektywy formatujące bash. mksh nie obsługuje %qlub %(DATE_FORMAT)T; w niektórych instalacjach printfnie jest wbudowany w mksh i zamiast tego wywołuje zewnętrzne polecenie.

printf -v VAR jest specyficzny dla bash, ksh zawsze drukuje na standardowe wyjście.

read

Kilka opcji jest specyficznych dla bash, w tym wszystkie dotyczące readline. Opcje -r, -d, -n, -N, -t, -usą identyczne w bash, ksh93 i mksh.

readonly

Możesz zadeklarować zmienną jako tylko do odczytu w Ksh93 i mksh z tą samą składnią. Jeśli zmienna jest tablicą, musisz ją najpierw przypisać, a następnie ustawić jako tylko do odczytu za pomocą readonly VAR. Funkcje nie mogą być ustawione tylko do odczytu w ksh.

set, shopt

Wszystkie opcje seti set -osą funkcjami POSIX lub ksh.

shoptjest specyficzny dla bash. Zresztą wiele opcji dotyczy użytkowania interaktywnego. Aby zapoznać się z efektami globowania i innymi funkcjami włączonymi przez niektóre opcje, zobacz sekcję „Opcje” poniżej.

source

Ten wariant .istnieje również w ksh. W bash i mksh sourceprzeszukuje bieżący katalog po PATH, ale w ksh93 jest to dokładny odpowiednik ..

trap

DEBUGPseudo-sygnał nie jest realizowany w mksh. W ksh93 istnieje inny sposób zgłaszania informacji, szczegółowe informacje można znaleźć w instrukcji obsługi.

type

W ksh typejest aliasem dla whence -v. W mksh type -pnie drukuje ścieżki do pliku wykonywalnego, ale komunikat czytelny dla człowieka; musisz użyć whence -p COMMANDzamiast tego.

Opcje

shopt -s dotglob - nie ignoruj ​​plików kropek podczas globowania

Aby emulować dotglobopcję w ksh93, możesz ustawić FIGNORE='@(.|..)'. Nie sądzę, że coś takiego jest w mksh.

shopt -s extglob - ksh rozszerzone wzorce globów

Ta extglobopcja jest zawsze włączona w ksh.

shopt -s failglob - błąd, jeśli wzór globu nic nie pasuje

Nie sądzę, że istnieje to zarówno w mksh, jak i ksh93. Robi to w Zsh (zachowanie domyślne, chyba że null_globlub csh_null_globsą ustawione).

shopt -s globstar**/globowanie rekurencyjne

Ksh93 ma globalne rekurencyjne z **/, włączone z set -G. Mksh nie ma rekurencyjnego globowania.

shopt -s lastpipe - uruchom ostatnie polecenie potoku w powłoce nadrzędnej

Ksh93 zawsze uruchamia ostatnie polecenie potoku w powłoce nadrzędnej, która w bash wymaga ustawienia lastpipeopcji. Mksh zawsze uruchamia ostatnie polecenie potoku w podpowłoce.

shopt -s nocaseglob, shopt -s nocasematch- wzorce bez rozróżniania wielkości liter

Mksh nie ma dopasowywania wzorca bez rozróżniania wielkości liter. Ksh93 obsługuje go na zasadzie wzorca po wzorze: przedrostek wzorca za pomocą ~(i).

shopt -s nullglob - rozwiń wzorce, które nie pasują do żadnego pliku, na pustą listę

Mksh tego nie ma. Ksh93 obsługuje go na zasadzie wzorca po wzorze: przedrostek wzorca za pomocą ~(N).

Zmienne

Oczywiście większość BASH_xxxzmiennych nie istnieje w ksh. $BASHPIDmoże być emulowany kosztownym, ale przenośnym sh -c 'echo $PPID', i został niedawno dodany do mksh. BASH_LINEjest .sh.linenow ksh93 i LINENOmksh. BASH_SUBSHELLjest .sh.subshellw ksh93.

Zarówno Mksh, jak i ksh93 pobierają plik podany ENVpodczas uruchamiania.

EUIDi UIDnie istnieją w ksh93. Mksh nazywa je USER_IDi KSH_UID; nie ma GROUPS.

FUNCNAMEi FUNCNESTnie istnieją w ksh. Ksh93 ma .sh.funi .sh.level. Funkcje zadeklarowane za pomocą function foo { …; }(bez nawiasów!) Mają swoje własne nazwy w $0.

GLOBIGNOREistnieje w ksh93, ale z inną nazwą i składnią: nazywa się FIGNOREi jest to pojedynczy wzorzec, a nie lista oddzielona dwukropkami. Użyj @(…|…)wzoru. Ksh FIGNOREpodbija bash z zupełnie inną składnią.

Ksh93 i mksh mają nic podobnego HOSTTYPE, MACHTYPEi OSTYPE. Ani SHELLOPTSlub TIMEFORMAT.

Mksh ma PIPESTATUS, ale ksh93 nie.

Mksh i ksh93 mają RANDOM.

Gilles „SO- przestań być zły”
źródło
jeśli nie chcesz reprodukować (niezarejestrowanego) znaku towarowego „mksh” na początku zdania ( patrz także „„ dd. ”” vs. „„ dd ”.” tutaj ), napisz „The MirBSD Zamiast tego Korn Shell ”. Jest to zawsze źle się wykorzystać każdą literę „mksh”. Dzięki.
mirabilos
Jak można $BASHPIDemulować sh -c 'echo $PPID'? Próbowałem (sh -c 'echo $PPID')w Bash, ale daje mi ten sam PID co $$.
Franklin Yu
Myślę, że pytanie pasuje tutaj lepiej . Skopiowałem tam pytanie.
Franklin Yu
4

To pytanie jest zbyt ogólne.

Zarówno mksh, jak i zsh są powłokami, które obsługują wiele rozszerzeń specyficznych dla bash GNU , ale zawsze są takie, które nie są zrozumiane.

zsh obsługuje więcej rzeczy, ale tylko w natywnym trybie zsh, który nie jest kompatybilny z powłokami POSIX (takimi jak GNU bash, AT&T ksh93 , mksh). Ponadto mksh jest znacznie szczuplejszy, szybszy i bardziej przenośny.

Ogólnie, jeśli chodzi o twoje skrypty, mówimy, po prostu je przetestuj. (mksh nie obsługuje jeszcze tablic asocjacyjnych w stylu bash4. Polecenie „deklaruj” jest specyficzne dla bash, „skład zestawu” jest równoważny. Nie znam wystarczająco dużo zsh, aby powiedzieć coś o tym wprost. ksh93 nie ma „lokalnego” ale używa do tego również „składu”). Ale jeśli chodzi o, powiedzmy, uruchamianie bezproblemowego systemu Debian, zapomnij o tym. Istnienie bash jest częścią „obietnicy” (API / ABI systemu) i wiele na nim polega.

Oświadczenie: Jestem programistą mksh.

mirabilos
źródło
1

Porównanie ZSH pocisków

Jednak w ostatnich latach w rozszerzeniach pojawiła się pewna liczba zwrotnic. Zsh (od 3.1.6) ma 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 / # old / new} 'i ${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#' lub %' inside a parameter: in other words{var / $ old / new} 'gdzie old zaczyna się od #' 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)', aby dopasować początek łańcucha i `(#e) ', aby dopasować koniec. Wymagają one ustawienia opcji EXTENDED_GLOB.

Najbardziej nie znam się na mksh, więc nie wiem, gdzie szukać tej odpowiedzi.

Jeśli szukasz bezpiecznego zamiennika pocisku, żadna z tych pocisków nie różni się tak bardzo od Basha, jak wrodzona wada, którą omawiasz.

Język taki jak Perl obsługuje dane wejściowe bezpieczniej. Ale kluczem jest tutaj również łatwość konserwacji. Zastąpienie powłoki Perla nie jest zbyt dobrze przyjęte. Obowiązkiem opiekuna powłoki jest bezpieczne przetwarzanie danych wejściowych. Więc kiedy piszesz skrypty, sprawdzaj, sprawdzaj, sprawdzaj wszystko! Używaj kontraktów kodowych, aby zapewnić poprawne wyniki za każdym razem!

Perl Shell

Oświadczenie FSF w sprawie Shock Shock

Tyler Maginnis
źródło
Jeśli tak naprawdę jest tak, że inne powłoki mają tę samą wadę - co nieco wątpię w oparciu o dyskusję, którą widziałem - to jest OGROMNY problem, ponieważ wiele programów innych firm przekazuje zmienne do powłoki bez żadnego rodzaju walidacji lub cokolwiek innego. W takim przypadku równie dobrze możemy całkowicie wyrzucić POSIX.
DanL4096
1
Projekt Bash miał 10-dniowy exploit w ciągu 10 lat. Microsoft Windows ma ponad 10 exploitów, wszystkie 0 dni, tygodniowo. Czy w ogóle wiesz, ile osób przeszkadzało zespołowi programistycznemu Bash? Po prostu zaktualizuj i przejdź dalej! To nic wielkiego.
Tyler Maginnis
1
@ DanL4096. Przekazywanie zmiennych do skryptów powłoki, które nie sprawdzają dostatecznie poprawności zmiennych, nie jest powodem do odrzucenia POSIX. Problem leży przede wszystkim w osobie, która napisała skrypt powłoki.
fpmurphy
0

Jedną z funkcji, która nie jest domyślnie włączona w mkshhistorii powłoki.

  • W twoim .mkshrcwłaśnie zestawie:

    export HISTFILE=~/.mksh-history

Stuart Cardall
źródło