Ресурсы для программирования переносимых оболочек

65

Какие ресурсы существуют для программирования переносимых оболочек? Окончательный ответ - тестирование на всех целевых платформах, но это редко бывает практичным.

Спецификация POSIX / Single UNIX - это только начало, но она не говорит вам ни об уровне поддержки каждой реализации, ни о том, какие существуют общие расширения. Вы можете прочитать документацию по каждой реализации, но это очень много времени и не совсем точно.

Мне кажется, что идеальным форматом была бы некая аннотированная версия спецификации POSIX, где каждая функция аннотирована уровнем поддержки среди различных реализаций. Что-то подобное существует? Или есть другие полезные ресурсы?

Например, есть страницы переносимости оболочек Свена Машика , но речь идет только о синтаксических элементах и ​​нескольких встроенных модулях, и охватывает только старые оболочки. Я ищу более полный ресурс.

Жиль "ТАК - перестань быть злым"
источник
2
NB. Пожалуйста, не отвечайте здесь только для того, чтобы привести документ о соответствии одной конкретной реализации. Если у вас есть один из них, соответствующий тег Wiki будет хорошим местом.
Жиль "ТАК - перестань быть злым"
1
Кто-то должен добыть историю изменений для autoconfи Metaconfig(Perl, rn) и собрать все приемы и их пояснительные комментарии в одном месте.
geekosaur
@geekosaur: Хорошее предложение. Я никогда не смотрел на внутренности autoconf, есть ли что-то, что можно использовать в качестве руководства при написании собственных сценариев? Если так, то это был бы хороший ответ на мой вопрос, даже если он не окончательный.
Жиль "ТАК ... перестать быть злым"
5
Я уверен, что вы оба могли бы легко найти это, но для других людей, которые следуют этой теме, вот ссылка на соответствующую страницу из руководства autoconf: gnu.org/software/hello/manual/autoconf/Portable- Shell.html
Дж. Тейлор
1
Связанный: Как я могу проверить на соответствие POSIX для сценариев оболочки?
Жиль "ТАК ... перестать быть злым"

Ответы:

32

В руководстве по autoconf есть раздел, посвященный программированию переносимых оболочек .

Хотя это и не предназначено специально для POSIX, это, вероятно, наиболее полный набор того, что нужно и чего не следует делать при попытке написать переносимый код оболочки.

Риккардо Мурри
источник
3
Это один из лучших ресурсов, созданный при написании кода на M4, который должен был создавать код оболочки, который был бы переносим на максимально возможное количество оболочек.
Тим Пост
6

В дополнение к dashи posh, есть bournesh(или bsh), Оболочка Борна из семейной реликвии , которую можно использовать для обнаружения Bashisms .

Проект «Семейная реликвия» также включает в себя «Инструмент семейной реликвии», набор из более чем 100 стандартных утилит Unix (которые могут служить отправной точкой для сравнения параметров командной строки).

Ralf
источник
2
Обратите внимание, что оболочка Bourne не является оболочкой POSIX, поэтому перенос вашего сценария в оболочку Bourne будет означать понижение синтаксиса сценария со стандартного языка POSIX sh до общего знаменателя между этим и синтаксисом оболочки Bourne. Не стоит тратить время, если вы не хотите переноситься на древние системы (или Solaris 10 и более ранние, и у вас нет выбора использовать стандартный sh, который был в / usr / xpg4 / bin).
Стефан Шазелас
5

Аналогично этому ответу , попробуйте выполнить ваш скрипт в шикарном стиле .

Кроме того, не забудьте установить для POSIXLY_CORRECTпеременной среды значение true, поскольку это заставляет многие программы (не только оболочку) более строго придерживаться стандартов POSIX.

человек, любящий учиться
источник
4

Написание ваших сценариев с использованием тире может быть началом.

Гленн Джекман
источник
3
Тестирование с помощью тира голого минимума , чтобы избежать случайной зависимости от особенностей КШ / Баша, но я после более чем: зная о недостатках в других оболочках (бедные обработки ловушки , например , ЗШ в), и прежде всего в коммунальном хозяйстве оболочки (например , в OpenBSD findеще не реализовано -exec +).
Жиль "ТАК - перестань быть злым"
FWIW, OpenBSD findделает в -exec utility {} +настоящее время.
Кусалананда
2

Чтобы немного расширить, вы можете попробовать checkbashismsв devscriptsпакете Debian / Ubuntu .

Он не идеален, но имеет преимущество в том, что является существующей отправной точкой. Например, он не видит классических глюков с sed/ findотносительно GNU против BSD / других отличий.

По умолчанию он ориентирован на Debian + dash, -pфлаг может быть полезен в вашем случае.

shellholic
источник
2

Сегодня в системе обычно можно найти оболочку POSIX, и это, как правило, означает, что вы можете создавать сценарии на языке POSIX (по модулю, сталкивающемуся с ошибками соответствия).

Единственная проблема заключается в том, что /bin/shиногда это не оболочка POSIX. И вы должны жестко закодировать #!строку в сценарии, которые должны вести себя как хорошие исполняемые файлы; Вы не можете просто попросить пользователя исследовать проблему и затем вызвать свой скрипт как /path/to/posix/shell myscript.

Итак, хитрость заключается в том, чтобы использовать функции POSIX в вашем скрипте, но заставить скрипт автоматически находить оболочку POSIX. Один из способов сделать это так:

#!/bin/sh

# At this point, we may be running under some old shell
# we have to tread carefully.

# note how we use test rather than [ ] syntax and avoid
# depending on test with no argument producing a failure;
# i.e. "test $posix_shell".

if ! test x$posix_shell = x ; then
  # the three possible shell paths are just an example;
  # please extend as necessary.

  for shell in /usr/xpg4/bin/sh /bin/bash /usr/bin/bash ; do
    if test -x $shell ; then
       posix_shell=$shell
    fi
  done
  if test x$posix_shell = x ; then
    echo "no POSIX shell found"
    exit 1
    # or we could avoid bailing here and just fall back on /bin/sh:
    # echo "falling back on /bin/sh: cross your fingers that it works"
    # posix_shell=/bin/sh
  fi
  export posix_shell

  # plain "$@" is broken in ancient shells! 
  # I seem to recall ${@+"$@"}: not sure if that's the right trick.

  exec $posix_shell $0 ${@+"$@"}  # can we count on exec in legacy shells? 
fi

# phew, at this point in the script we have been re-executed and are
# being interpreted by some reasonably modern shell. We can use $(...)
# command substitution, and other features.

Есть и другие подходы, такие как генерация кода. Ускорьте ваши сценарии с помощью небольшого сценария, который принимает текстовые файлы без символа #! линия, и добавляет один.

Худшее, что вы можете сделать, это начать писать целые сценарии таким образом, чтобы они запускались на оболочке Bourne с 1981 года. Это необходимо, только если вы должны писать для системы, у которой на самом деле нет другой оболочки ,

Kaz
источник