Де zsh і mksh несумісні з bash?


11

Наскільки інші сумісні з POSIX оболонки можуть слугувати розумною заміною bash? Їм не потрібно бути справжніми "замінними" замінами, але достатньо близько, щоб працювати з більшістю сценаріїв та підтримувати решту з деякими модифікаціями.

  1. Я хочу мати явні сценарії bash - initscripts, сценарії клієнтських DHCP і т.д. - працювати з мінімальною модифікацією

  2. Я хочу, щоб моя власна колекція більш спеціалізованих скриптів оболонки не потребувала надто великих змін

  3. Я хочу мати такі функції, як маніпуляція з рядками та вбудований узор регулярного вирівнювання

Єдині серйозні претенденти, про яких я знаю, - це zsh і mksh. Отже, для тих із вас, хто хороший з одним або обома:

  1. Які особливості має bash, що zsh і mksh відповідно не мають?

  2. Яким особливостям оболонки діляться з bash, але для чого використовують несумісний синтаксис?


3
Порівняння командних оболонок: ( en.wikipedia.org/wiki/Comppare_of_command_shells ) Розширений посібник із написання сценарію Bash: ( tldp.org/LDP/abs/html ) Керівництво ZSH : ( zsh.sourceforge.net/Guide/zshguide.html ) MirBSD Посібник із оболонки: ( mirbsd.org/htman/i386/man1/mksh.htm ). Вибачте, але це питання занадто складне. Можливо, вам слід запитати, як виправити bash, щоб виправити вразливість для вашого конкретного розповсюдження Linux?
Тайлер Маднніс

3
Немає оболонки, яка може функціонувати як падіння заміни bash, mksh та zsh можуть функціонувати як /bin/shз різними рівнями коректності, але ні bash.
llua

1
Здається, вся річ про обстріли не має нічого спільного з основним питанням і просто відволікає людей, тому я її усунув
Майкл Мрозек

3
Все питання надто широке. Можливо, вам слід її зняти.
Тайлер Маднніс

1
Єдине, що я насправді хвилюю, - це те, що BASH добре підтримується Фондом вільного програмного забезпечення (FSF). Мої контакти там говорять мені про те, що розкриття «основоположного недоліку» в рамках BASH призведе лише до більш сильної, більш безпечної реалізації. Є так багато альтернативних оболонок, що навіть починаючи рекомендувати один для вашої потреби, я зажадав би чіткого розуміння вашого випадку використання. Потім на стороні O / S ... Стільки речей пов'язано з Bash, що ви можете в кінцевому підсумку переписати всі свої дзвінки O / S на BASH. Найкраще рішення, яке я бачу, - це вибір дистрибутива з підтримуваною альт-оболонкою.
Тайлер Маднніс

Відповіді:


19

Я буду дотримуватися сценаріїв. Багаті інтерактивні функції (видання командного рядка, завершення, підказки тощо), як правило, дуже відрізняються, досягаючи подібних ефектів абсолютно несумісними способами. Які особливості є у zsh та відсутні у bash, чи навпаки? дає кілька покажчиків на інтерактивне використання.

Найближчим до баша буде ATT ksh93 або mksh (оболонка Корна та клон). Zsh також має підмножину функцій, але вам потрібно запустити його в режимі емуляції ksh, а не в рідному режимі zsh.

Я не перелічу функції POSIX (які доступні в будь-якій сучасній shоболонці), ні відносно незрозумілі функції, ні як зазначені вище функції для інтерактивного використання. Спостереження є дійсними на основі баш 4.2, кш 93u та мкш 40.9.20120630, як виявлено на Debian wheezy.

Синтаксис оболонки

Цитуючи

$'…'(буквальні рядки з зворотною косою інтерполяцією) доступний у ksh93 та mksh. `$"… "(Перекладені рядки) є специфічними для bash.

Умовні конструкції

Mksh і ksh93 повинні ;&пройти через caseзаяву, але не ;;&перевіряти наступні випадки. Mksh має ;|для цього, і останні mksh дозволяє ;;&сумісність.

((…))арифметичні вирази та [[ … ]]тести - це ksh особливості. Деякі умовні оператори різні, див. «Умовні вирази» нижче.

Копроси

У Ksh і bash є спільні процеси, але вони працюють по-різному.

Функції

Mksh та ksh93 підтримують function name {…}синтаксис для визначення функцій на додаток до стандартних name () {…}, але, використовуючи functionв ksh зміни правил визначення, тому дотримуйтесь name () …сумісності. Правила дозволених символів у назвах функцій різняться; дотримуватися буквено-цифрових і _.

Розширення брекетів

Ksh93 і mksh підтримують розширення дужок {foo,bar}. Ksh93 підтримує числові діапазони, {1..42}але mksh - ні.

Розширення параметрів

Ksh93 і МКШ підтримка витягання підрядка з ${VAR:offset}і ${VAR:offset:length}, але не випадок складання , як ${VAR^}, ${VAR,}і т.д. Ви можете зробити перетворення випадок з typeset -lі typeset -uв обох Баш і KSH.

Вони підтримують заміну на ${VAR/PATTERN/STRING}або ${VAR/PATTERN//STRING}. Правила котирування для STRING дещо відрізняються, тому уникайте зворотних косих рядків (а може бути й інших символів) у STRING (побудуйте змінну та використовуйте ${VAR/PATTERN/$REPLACEMENT}натомість, якщо заміна містить символи, що цитують).

Розширення Array ( ${ARRAY[KEY]}, "${ARRAY[@]}", ${#ARRAY[@]}, ${!ARRAY[@]}) робота в Баш як в KSH.

${!VAR}розширюється до того, ${OTHERVAR}коли значення VARis OTHERVAR(непряма посилання на змінну) є специфічним для bash (ksh робить щось інше з ${!VAR}). Щоб отримати це подвійне розширення в ksh, вам потрібно використовувати посилання на ім’я замість ( typeset -n VAR=OTHERVAR; echo "$VAR"). ${!PREFIX*}працює так само.

Процес заміщення

Підстановка процесів <(…)і >(…)підтримується в ksh93 , але не в МКШ.

Шаблони підстановок

Ksh-розширені глобальні шаблони, які потрібно shopt -s extglobактивувати в bash, завжди доступні в ksh93 та mksh.

Mksh не підтримує класи символів, як [[:alpha:]].

IO перенаправлення

Bash і ksh93 визначають псевдофайли і , але mksh не робить./dev/tcp/HOST/PORT/dev/udp/HOST/PORT

Розширення шаблонів під час переадресації в сценаріях (як у var="*.txt"; echo hello >$aписьмовій формі, a.txtякщо це ім'я файлу є єдиним збігом для шаблону) є специфічною для bash особливістю (інші оболонки ніколи цього не роблять у скриптах).

<<< тут-струни працюють в ksh як у bash.

Ярлик >&для перенаправлення помилок синтаксису також підтримується mksh, але не ksh93.

Умовні вирази

[[ … ]] синтаксис подвійної дужки

Синтаксис подвійної дужки з ksh підтримується як ATT ksh93, так і mksh, як у bash.

Файлові оператори

Ksh93, mksh та bash підтримують однакові розширення до POSIX, включаючи -aяк застарілий синонім -e, -k(липкий), -G(належить egid), -O(власник euid), -ef(той самий файл), -nt(новіший за), -ot(старший за).

-N FILE (змінено з моменту останнього читання) mksh не підтримується.

Mksh не має оператора відповідності регулярного виразу =~. У Ksh93 є цей оператор, і він виконує ті ж відповідність, що і в bash, але не має еквіваленту BASH_REMATCHдля отримання відповідних груп згодом.

Строкові оператори

Ksh93 і mksh підтримують ті ж оператори порівняння рядків, що <і >bash, а також ==синонім =. Mksh не використовує параметри локалі для визначення лексикографічного порядку, він порівнює рядки як рядки байтів.

Інші оператори

-v VARперевірити, чи визначена змінна базова. У будь-якій оболонці POSIX ви можете використовувати [ -z "${VAR+1}" ].

Вбудовані

alias

Набір дозволених символів у псевдонімах не однаковий у всіх оболонках. Я думаю, це те саме, що і для функцій (див. Вище).

builtin

Ksh93 має вбудовану назву builtin, але вона не виконує ім'я як вбудовану команду. Використовувати commandдля обходу псевдонімів та функцій; це викликає вбудований, якщо такий існує, інакше зовнішня команда (ви можете цього уникнути PATH= command error_out_if_this_is_not_a_builtin).

caller

Це специфічно для bash. Ви можете отримати подібний ефект .sh.fun, .sh.fileі .sh.linenoв ksh93. У mksh нарешті LINENO.

declare, local,typeset

declare- специфічна для bash ім'я для bash typeset. Використання typeset: він також працює в базі.

Mksh визначає localяк псевдонім для typeset. У ksh93 вам потрібно використовувати typeset(або визначити псевдонім).

У Mksh немає асоціативних масивів (вони призначені для ще не виданої версії).

Я не думаю, що typeset -tв ksh є точний еквівалент bash's (функція сліду).

cd

Ksh93 не має -e.

echo

Ksh93 і mksh обробляють -eі -nпараметри, як у bash. Mksh також розуміє -E, ksh93 не сприймає це як варіант. Розширення зворотної косої лінії вимкнено за замовчуванням у ksh93, за замовчуванням у mksh

enable

Ksh не забезпечує спосіб відключення вбудованих команд. Щоб уникнути вбудованого пошуку, знайдіть шлях зовнішньої команди та явно попросіть її.

exec

Ksh93 має, -aале ні -l. Мкш не має жодного.

export

Ні ksh93, ні mksh не мають export -n. Використовуйте typeset +x fooзамість цього, він працює в bash та ksh.

Ksh не експортує функції через навколишнє середовище.

let

let те саме в bash і ksh.

mapfile, readarray

Це базова особливість. Ви можете використовувати while readпетлі або підстановку команд, щоб прочитати файл і розділити його на масив рядків. Потурбуйтеся IFSі про глобус. Ось еквівалент mapfile -t lines </path/to/file:

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

printf

printfдуже схожий. Я думаю, що ksh93 підтримує всі директиви щодо формату bash. mksh не підтримує %qабо %(DATE_FORMAT)T; в деяких установках printfне вбудований mksh і натомість викликає зовнішню команду.

printf -v VAR є специфічним для bash, ksh завжди друкує до стандартного виводу.

read

Кілька варіантів є специфічними для башти, включаючи всі, що стосуються функції перегляду рядків. Варіанти -r, -d, -n, -N, -t, -uідентичні в Баш, ksh93 і МКШ.

readonly

Ви можете оголосити змінну як лише для читання в Ksh93 та mksh з тим же синтаксисом. Якщо змінна є масивом, вам потрібно призначити її спочатку, а потім зробити її лише для читання readonly VAR. Функції не можна зробити лише для читання в ksh.

set, shopt

Усі опції для setта set -oє функціями POSIX або ksh.

shoptє специфічним для bash. Багато варіантів стосуються інтерактивного використання. Про ефекти на глобалізацію та інші функції, включені деякими параметрами, див. Розділ "Параметри" нижче.

source

Цей варіант .існує і в ksh. У bash та mksh sourceшукає поточний каталог після PATH, але в ksh93 - це точний еквівалент ..

trap

DEBUGПсевдо-сигнал не реалізований в МКШ. У ksh93 існує інший спосіб повідомляти інформацію, детальну інформацію див. У посібнику.

type

У ksh, typeце псевдонім для whence -v. У mksh type -pне друкується шлях до виконуваного файлу, але читається людиною повідомлення; вам потрібно використовувати whence -p COMMANDзамість цього.

Параметри

shopt -s dotglob - не ігноруйте крапкові файли в глобусі

Для емуляції dotglobпараметра в ksh93 ви можете встановити FIGNORE='@(.|..)'. Я не думаю, що в mksh є щось подібне.

shopt -s extglob - ksh розширені глобальні візерунки

Цей extglobпараметр ефективно завжди включений у ksh.

shopt -s failglob - помилка, якщо глобальний зразок нічого не відповідає

Я не думаю, що це існує ні в mksh, ні в ksh93. Це робиться в zsh (поведінка за замовчуванням, якщо не встановлено null_globабо csh_null_glob).

shopt -s globstar**/рекурсивне глобулювання

Ksh93 має рекурсивний глобул **/, увімкнено за допомогою set -G. Mksh не має рекурсивного глобулювання.

shopt -s lastpipe - запустити останню команду конвеєра в батьківській оболонці

Ksh93 завжди виконує останню команду конвеєра в батьківській оболонці, яка в bash вимагає встановлення lastpipeпараметра. Mksh завжди виконує останню команду конвеєра в підпакеті.

shopt -s nocaseglob, shopt -s nocasematch- нечутливі до регістру моделі

Mksh не відповідає нечутливому до регістру шаблону. Ksh93 підтримує його на основі шаблону: за допомогою префікса ~(i).

shopt -s nullglob - розширити шаблони, які не відповідають жодному файлу, до порожнього списку

У Mksh цього немає. Ksh93 підтримує його на основі шаблону: за допомогою префікса ~(N).

Змінні

Очевидно, що більшість BASH_xxxзмінних не існує в ksh. $BASHPIDможе бути емульовано дорогим, але портативним sh -c 'echo $PPID', і нещодавно додано в mksh. BASH_LINEє .sh.linenoв кш93 та LINENOв мкш. BASH_SUBSHELLзнаходиться .sh.subshellв ksh93.

Mksh та ksh93 обидва джерела передають файл, який ENVвони дають при запуску.

EUIDі UIDне існують у ksh93. Mksh називає їх USER_IDі KSH_UID; цього не має GROUPS.

FUNCNAMEі FUNCNESTне існують в ksh. Кш93 має .sh.funі .sh.level. Функції, оголошені function foo { …; }(без дужок!), Мають власне ім'я $0.

GLOBIGNOREіснує в ksh93, але з іншою назвою та синтаксисом: він називається FIGNORE, і це єдиний шаблон, а не розділений двокрапкою список. Використовуйте @(…|…)візерунок. Ksh's subshes FIGNOREbash's, що має зовсім інший синтаксис.

Ksh93 і mksh не мають нічого подібного HOSTTYPE, MACHTYPEі OSTYPE. Ні SHELLOPTSабо TIMEFORMAT.

Mksh має PIPESTATUS, але ksh93 ні.

Mksh і ksh93 мають RANDOM.


якщо ви не хочете правильно відтворити (незареєстрований) товарний знак "mksh" на початку речення ( див. також "" dd. "" проти "" dd "." ), будь ласка, напишіть "MirBSD Korn Shell »замість цього. Це завжди неправильно капіталізувати будь-яку букву «МКШ». Дякую.
mirabilos

Як можна $BASHPIDнаслідувати sh -c 'echo $PPID'? Я спробував (sh -c 'echo $PPID')у Bash, але це дає мені той самий PID як $$.
Франклін Ю

Я думаю, що питання тут краще підходить . Я скопіював там питання.
Франклін Ю

4

Це питання досить надто широке.

І mksh, і zsh є оболонками, які підтримують безліч розширень GHU bash- специфічних, але завжди є такі, які не зрозумілі.

zsh підтримує більше матеріалів, але лише у рідному режимі zsh, який не сумісний з оболонками POSIX (наприклад, GNU bash, AT&T ksh93 , mksh). Крім того, mksh набагато швидше, швидше і портативніше.

Загалом, якщо це ваші сценарії, про які ми говоримо, продовжуйте їх просто перевірити. (mksh ще не підтримує асоціативні масиви стилю bash4. Команда «оголосити» є специфічною для bash, «typeset» - еквівалент. Я недостатньо знайомий із zsh, щоб щось про це прямо говорити. ksh93 не має «локального» але також використовує "typeset" для цього.) Але якщо мова йде про, скажімо, запуску системи Debian, що не має башти, забудьте про це. Існування bash є частиною "обіцянки" (API / ABI системи), і багато на чому покладається.

Відмова: Я розробник mksh.


1

ZSH Порівняння оболонок

Однак в останні роки спостерігається певна кількість кросоверів у розширеннях. Zsh (станом на 3.1.6) має 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} 'і ${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#' або %' inside a parameter: in other words{var / $ old / new} ', де старий починається з #' 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)', щоб відповідати початку рядка , і `(#e) ', щоб відповідати кінці. Для них потрібен параметр EXTENDED_GLOB.

Мені найбільше незнайомий mksh, тому я не знаю, де шукати цю відповідь.

Якщо ви шукаєте безпечну заміну оболонки, жодна з цих оболонок сильно не відрізняється від Bash, наскільки притаманна вада, яку ви обговорюєте.

Мова, як Perl, захищає введення більш безпечно. Але тут важливим є і технічне обслуговування. Заміна оболонки Perl не дуже добре прийнята. За безпечне поводження з входами входить відповідальність за технічне обслуговування оболонки. Тож коли ви пишете сценарії, перевіряйте, перевіряйте, підтверджуйте все! Використовуйте кодові контракти, щоб забезпечити правильні результати кожного разу!

Перл Шелл

Заява FSF про ударний снаряд


Якщо це справді так, що інші оболонки мають той самий недолік - в чому я певно сумніваюся, виходячи з того, що я обговорював, - це ВЕЛИЧЕЗНА проблема, тому що багато сторонніх програм передають змінні в оболонку без будь-якого виду валідації чи нічого. Якщо це так, ми можемо також викинути POSIX повністю.
DanL4096

1
Проект Bash за 10 років мав 1 0-денний подвиг. Microsoft Windows має понад 10 подвигів, усі 0 днів на тиждень. Ви навіть знаєте, скільки людей турбує команду розробників Bash з цього приводу? Просто оновіть його та рухайтесь далі! Це не велика справа.
Тайлер Маднніс

1
@ DanL4096. Передача змінних скриптам оболонки, які потім не роблять достатньої перевірки надійності змінних, не є причиною викидати POSIX. Проблема полягає в особі, яка написала сценарій оболонки.
fpmurphy

0

Однією з функцій, не включених за замовчуванням, mkshє історія оболонок.

  • У вашому .mkshrcщойно наборі:

    export HISTFILE=~/.mksh-history

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.