Ответ 1
Печальный ответ заранее
Это не поможет вам (не так много и надежно, как вы ожидали бы, и так или иначе захотите).
Вот почему.
Одна большая проблема, которая не может быть решена виртуальной "оболочкой POSIX", - это вещи, которые неоднозначно сформулированы или просто не рассматриваются в стандарте, так что оболочки могут реализовывать вещи по-разному, все еще придерживаясь стандарта.
Возьмем два примера, касающиеся трубопроводов, первый из которых хорошо известен:
Пример 1 - обзор
$ ksh -c 'printf "foo" | read s; echo "[${s}]"'
[foo]
$ bash -c 'printf "foo" | read s; echo "[${s}]"'
[]
ksh
выполняет последнюю команду канала в текущей оболочке, тогда как bash
выполняет все - включая последнюю команду - в подоболочке. bash 4
представил параметр lastpipe
, который заставляет его вести себя как ksh
:
$ bash -c 'shopt -s lastpipe; printf "foo" | read s; echo "[${s}]"'
[foo]
Все это (дебативно) согласно стандарт:
Кроме того, каждая команда конвейера с несколькими командами находится в среде подсетей; однако в качестве расширения любые или все команды в конвейере могут выполняться в текущей среде.
Я не на 100% уверен в том, что они имели в виду с расширением, но на основе других примеров в документе это не означает, что оболочка должна обеспечить способ переключения между поведением, а просто, что она может, если она этого пожелает, реализовать вещи в этом "расширенном виде". Другие люди читают это по-другому и спорят о том, что поведение ksh
не соответствует стандартам и я понимаю, почему. Мало того, что формулировка не повезла, не рекомендуется это допускать в первую очередь.
На практике не имеет никакого значения, какое поведение является правильным, так как это "два больших оболочки "" ", и люди подумают, что если вы не используете их расширения и только предположительно POSIX-совместимый код, будет работать в любом случае, но правда в том, что если вы полагаетесь на одно или другое поведение, упомянутое выше, ваш script может разрушиться ужасно.
Пример 2 - перенаправление
Об этом я узнал всего пару дней назад, см. мой ответ здесь:
foo | bar 2>./qux | quux
Здравый смысл и POLA сообщает мне, что, когда поражается следующая строка кода, оба quux
и bar
должны были закончить, что означает, что файл ./qux
полностью заполнен. Правильно? Нет.
POSIX утверждает, что
Если конвейер не находится в фоновом режиме (см. Асинхронные списки), оболочка должна дождаться завершения последней команды, указанной в конвейере, и может также дождаться завершения всех команд.)
Май (!) дождитесь завершения всех команд! WTH!
bash ждет:
Оболочка ожидает завершения всех команд в конвейере перед возвратом значения.
но ksh:
Каждая команда, за исключением, возможно, последней, запускается как отдельный процесс; оболочка ждет завершения последней команды.
Итак, если вы используете перенаправление между каналом, убедитесь, что знаете, что вы делаете, поскольку это обрабатывается по-разному и может ужасно ломаться по крайним случаям, в зависимости от вашего кода.
Я мог бы привести еще один пример, не связанный с конвейерами, но я надеюсь, что этих двух достаточно.
Заключение
Наличие стандарта хорош, постоянно пересматривая его еще лучше, и придерживаться его отлично. Но если стандарт выходит из строя из-за двусмысленности или вседозволенности, все может неожиданно сломаться, фактически оказывая полезность стандартной пустоты.
На практике это означает, что в дополнение к написанию "POSIX-совместимого" кода вам все равно нужно думать и знать, что вы делаете, чтобы предотвратить определенные события.
Все, что сказано, одна оболочка, которая еще не упоминалась, posh
, которая предположительно представляет собой POSIX плюс еще меньшее количество расширений, чем dash
имеет (в основном echo -n
и ключевое слово local
) в соответствии с его man-страницей:
BUGS
Any bugs in posh should be reported via the Debian BTS.
Legitimate bugs are inconsistencies between manpage and behavior,
and inconsistencies between behavior and Debian policy
(currently SUSv3 compliance with the following exceptions:
echo -n, binary -a and -o to test, local scoping).
YMMV.