Где zsh и mksh несовместимы с bash?

11

В какой степени другие POSIX-совместимые оболочки могут служить разумной заменой bash? Они не должны быть настоящими «заменами», но достаточно близки, чтобы работать с большинством сценариев и поддерживать остальные с некоторыми изменениями.

  1. Я хочу, чтобы явные сценарии bash - initscripts, сценарии DHCP-клиента и т. Д. - работали с минимальными изменениями

  2. Я хочу, чтобы моя собственная коллекция более специализированных сценариев оболочки не требовала особых изменений

  3. Я хочу иметь такие функции, как манипуляции со строками и встроенное сопоставление с регулярным выражением

Единственные серьезные соперники, о которых я знаю, это zsh и mksh. Итак, для тех из вас, кто хорошо с одним или обоими из них:

  1. Какие функции есть у bash, чего нет у zsh и mksh соответственно?

  2. Какими функциями оболочки делятся с bash, но используют несовместимый синтаксис?

DanL4096
источник
3
Сравнение командных оболочек: ( en.wikipedia.org/wiki/Comparison_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.
Луа
1
Похоже, что вся эта ракушка не имеет никакого отношения к основному вопросу и просто отвлекает людей, поэтому я убрал ее
Майкл Мрозек
3
Весь вопрос слишком широк. Возможно, вам следует удалить его.
Тайлер Магиннис
1
Единственное, что меня беспокоит, так это то, что BASH хорошо поддерживается Фондом свободного программного обеспечения (FSF). Мои контакты там говорят мне, что раскрытие «фундаментального недостатка» в BASH приведет только к более сильной и более безопасной реализации. Есть так много альтернативных оболочек, что даже начинающих рекомендовать один для вашего требования, я бы потребовал четкого понимания вашего варианта использования. Затем на стороне O / S ... Так много вещей связано с Bash, что вы можете переписать все ваши вызовы O / S на BASH. Лучшее решение, которое я вижу, это выбрать дистрибутив с поддерживаемой alt-shell.
Тайлер Магиннис,

Ответы:

19

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

Наиболее близким к bash будет ATT ksh93 или mksh (оболочка Korn и клон). Zsh также имеет подмножество функций, но вам нужно будет запустить его в режиме эмуляции ksh, а не в собственном режиме zsh.

Я не буду перечислять функции POSIX (которые доступны в любой современной shоболочке), ни относительно неясные функции, ни упомянутые выше функции для интерактивного использования. Наблюдения действительны для bash 4.2, ksh 93u и mksh 40.9.20120630, как указано в Debian wheezy.

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

квотирование

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

Условные конструкции

Mksh и ksh93 должны ;&провалиться в caseутверждении, но не ;;&для проверки последующих случаев. Для этого есть Mksh ;|, а недавний mksh обеспечивает ;;&совместимость.

((…))арифметические выражения и [[ … ]]тесты являются особенностями ksh. Некоторые условные операторы разные, см. «Условные выражения» ниже.

Coprocesses

Ksh и bash оба имеют сопроцессы, но работают по-разному.

функции

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

Расширение скобки

Ksh93 и mksh поддерживают расширение скобки {foo,bar}. Ksh93 поддерживает числовые диапазоны, {1..42}а mksh - нет.

Расширение параметра

Ksh93 и mksh поддерживают извлечение подстрок с помощью ${VAR:offset}и ${VAR:offset:length}, но не сворачивание, как ${VAR^}, ${VAR,}и т. Д. Вы можете выполнить преобразование с помощью typeset -lи typeset -uв bash, и в 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, но не в mksh.

Шаблоны подстановочных знаков

Шаблоны расширенного глобуса ksh, которые необходимо shopt -s extglobактивировать в bash, всегда доступны в ksh93 и mksh.

Mksh не поддерживает классы символов, такие как [[:alpha:]].

Перенаправление ввода / вывода

Bash и ksh93 определяют псевдо-файлы и , но МКШ не делает./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(sticky), -G(принадлежит egid), -O(владелец euid), -ef(тот же файл), -nt(новее чем), -ot(старше чем).

-N FILE (изменено с момента последнего чтения) не поддерживается mksh.

Mksh не имеет оператора соответствия регулярному выражению =~. В Ksh93 есть этот оператор, и он выполняет то же сопоставление, что и в bash, но не имеет эквивалента BASH_REMATCHдля извлечения соответствующих групп впоследствии.

Строковые операторы

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

Другие операторы

-v VARпроверить, определена ли переменная, зависит от bash. В любой оболочке 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. В Мкш наконец-то есть LINENO.

declare, local,typeset

declareспецифичное для bash имя для ksh typeset. Использование typeset: это также работает в Bash.

Мкш определяет localкак псевдоним для typeset. В ksh93 вам нужно использовать typeset(или определить псевдоним).

Mksh не имеет ассоциативных массивов (они предназначены для еще не выпущенной версии).

Я не думаю, что есть точный эквивалент bash typeset -t(функция трассировки) в ksh.

cd

Кш93 не имеет -e.

echo

Кш93 и мкш обрабатывают -eи -nварианты как в bash. Mksh также понимает -E, ksh93 не рассматривает это как вариант. Расширение с обратной косой чертой отключено по умолчанию в ksh93, по умолчанию включено в mksh.

enable

Ksh не предоставляет способ отключить встроенные команды. Чтобы избежать встроенного, ищите путь внешней команды и вызывайте ее явно.

exec

Кш93 есть -aно нет -l. Мкш не имеет ни того, ни другого.

export

Ни ksh93, ни mksh не имеет export -n. Используйте typeset +x fooвместо этого, это работает в bash и ksh.

Ksh не экспортирует функции через окружение.

let

let то же самое в bash и ksh.

mapfile, readarray

Это особенность bash. Вы можете использовать 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

Несколько опций зависят от bash, включая все о readline. Варианты -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 - не игнорируйте точечные файлы в globbing

Чтобы эмулировать 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. У Мкша нет рекурсивных шаров.

shopt -s lastpipe - выполнить последнюю команду конвейера в родительской оболочке

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

shopt -s nocaseglob, shopt -s nocasematch- модель без учета регистра

У Mksh нет сопоставления с регистром без учета регистра. Ksh93 поддерживает его на основе паттернов: паттерн с префиксом ~(i).

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

У Мкша этого нет. Ksh93 поддерживает его на основе паттернов: паттерн с префиксом ~(N).

переменные

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

Mksh и ksh93 оба получают файл, указанный ENVпри запуске.

EUIDи UIDне существует в ksh93. Мкш называет их USER_IDи KSH_UID; это не имеет GROUPS.

FUNCNAMEи FUNCNESTне существует в кш. Кш93 имеет .sh.funи .sh.level. Функции, объявленные с function foo { …; }(без скобок!), Имеют собственное имя в $0.

GLOBIGNOREсуществует в ksh93, но с другим именем и синтаксисом: он называется FIGNORE, и это один шаблон, а не разделенный двоеточиями список. Используйте @(…|…)шаблон. Ksh включает в FIGNOREсебя bash с совершенно другим синтаксисом.

Ksh93 и МКШ не имеют ничего подобного HOSTTYPE, MACHTYPEи OSTYPE. Ни SHELLOPTSили TIMEFORMAT.

Мкш имеет PIPESTATUS, но ksh93 нет.

Мкш и кш93 есть RANDOM.

Жиль "ТАК - перестань быть злым"
источник
если вы не хотите правильно воспроизводить (незарегистрированный) товарный знак «mksh» в начале предложения ( см. также «« дд. »против« «дд». »здесь ), напишите« The MirBSD ». Корн Шелл ». Это всегда неправильно капитализировать любую букву «МКШ». Спасибо.
Мирабилось
Как можно $BASHPIDподражать sh -c 'echo $PPID'? Я пробовал (sh -c 'echo $PPID')в Bash, но он дает мне тот же PID, что и $$.
Франклин Ю
Я думаю, что вопрос здесь подходит лучше . Я скопировал вопрос там.
Франклин Ю
4

Этот вопрос слишком широкий.

И mksh, и zsh являются оболочками, которые поддерживают множество специфичных для GNU bash расширений, но всегда есть некоторые, которые не поняты.

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

В общем, если речь идет о ваших сценариях, просто протестируйте их. (mksh пока не поддерживает ассоциативные массивы в стиле bash4. Команда «Declare» является специфичной для bash, «typeset» является эквивалентом. Я не достаточно знаком с zsh, чтобы что-то прямо сказать об этом. ksh93 не имеет «local» но для этого также используется «typeset».) Но если речь идет, скажем, о запуске системы Debian без bash, забудьте об этом. Существование bash является частью «обещания» (API / ABI системы) и во многом зависит от него.

Отказ от ответственности: я разработчик MKSH.

mirabilos
источник
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} ', где old начинается с #' 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 не очень хорошо принята. Ответственный за оболочку отвечает за безопасную обработку ввода. Поэтому, когда вы пишете сценарии, проверяйте, проверяйте, проверяйте все! Используйте кодовые контракты, чтобы гарантировать правильные результаты каждый раз!

Perl Shell

Заявление FSF о Шок Шелл

Тайлер Магиннис
источник
Если это действительно так, что другие оболочки имеют тот же недостаток - в чем я несколько сомневаюсь, исходя из того, что я видел, - тогда это ОГРОМНАЯ проблема, потому что многие сторонние программы передают переменные в оболочку без какого-либо проверки или что-нибудь. Если это так, мы могли бы также полностью исключить POSIX.
DanL4096
1
У проекта Bash был 10-дневный эксплойт за 10 лет. Microsoft Windows имеет более 10 эксплойтов, все 0 дней, в неделю. Знаете ли вы, сколько людей беспокоило команду разработчиков Bash по этому поводу? Просто обновите его и двигайтесь дальше! Это не большое дело.
Тайлер Магиннис,
1
@ DanL4096. Передача переменных в сценарии оболочки, которые затем не выполняют достаточную проверку исправности переменных, не является причиной для исключения POSIX. Проблема заключается в том, кто написал сценарий оболочки.
fpmurphy
0

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

  • В вашем .mkshrcтолько что установленном:

    export HISTFILE=~/.mksh-history

Стюарт Кардалл
источник