Написание скриптов оболочки, которые будут работать в любой оболочке (использование нескольких строк shebang?)

Написание скриптов оболочки, которые будут работать в любой оболочке (использование нескольких строк shebang?)

Я только начал углубляться в скрипты оболочки, и я всегда просто закидывал свой скрипт в файл, помечал его, chmod +xа затем делал /path/to/script.shтак, как хочет интерпретатор по умолчанию, которым я считал zsh, потому что я использовал его для своей оболочки. По-видимому, это просто /bin/shпо умолчанию, даже если я запускаю скрипт из командной строки zsh, потому что я начал добавлять специфичные для zsh вещи в свои скрипты, и они не работают, пока я не запущу zsh /path/to/script.sh.

Чтобы перейти к сути, вот мои вопросы:

  1. #!/path/to/shellКакая оболочка выполняет скрипты, если в начале нет строки shebang ( )? Я предполагаю /bin/sh, но не могу подтвердить.
  2. Что считается «лучшими практиками» с точки зрения написания сценариев оболочки, которые будут работать на любой платформе? (ладно, это своего рода открытый вопрос)
  3. Можно ли написать скрипт, который пытается использовать zsh и возвращается к bash, если zsh недоступен? Я пробовал вставлять две строки shebang, как показано ниже, но он просто выдает ошибки, bad interpreter: /bin/zsh: no such file or directoryесли я пробую его на машине без zsh.

    #!/bin/zsh

    #!/bin/bash

решение1

Какая оболочка выполняет скрипты, если в начале нет строки shebang (#!/path/to/shell)? Я предполагаю /bin/sh, но не могу подтвердить.

Ядро отказывается выполнять такие скрипты и возвращает ENOEXEC, поэтому точное поведение зависит от программы, в которой вы запускаете такой скрипт.от.

  • bash 4.2.39 – использует сам себя
  • busybox-ash 1.20.2 – использует сам себя
  • dash 0.5.7 – запускает /bin/sh
  • fish 1.23.1 – жалуется на ENOEXEC, а затем винит не тот файл
  • AT&T ksh 93u+2012.08.01 – использует сам себя
  • mksh R40f – запускает /bin/sh
  • pdksh 5.2.14 – запускает /bin/sh
  • sh-heirloom 050706 – использует себя
  • tcsh 6.18.01 – запускает /bin/sh
  • zsh 5.0.0 – запускает /bin/sh
  • cmd.exe 5.1.2600 – смотрит на тебя странно.

Вглибк, функции execv()или execve()просто возвращают ENOEXEC. Но execvp()скрывает этот код ошибки и автоматически вызывает /bin/sh. (Это задокументировано висполнитель(3п).)

Что считается «лучшими практиками» с точки зрения написания сценариев оболочки, которые будут работать на любой платформе? (ладно, это своего рода открытый вопрос)

Либо придерживайтесь shтолько определенных POSIX функций, либо просто используйте полныйБаш(который широко доступен) и укажите это в своих требованиях, если вы его распространяете.

(Теперь, когда я об этом думаю, Perl — или, возможно, Python — был бы еще более переносимым, не говоря уже о лучшем синтаксисе.)

Всегдадобавьте строку shebang. Если вы используете bash или zsh, используйте #!/usr/bin/env bashвместо жесткого кодирования путь к оболочке. (Однако оболочка POSIX гарантированно находится в /bin/sh, поэтому в этом случае пропустите env.)

(К сожалению, даже /bin/shне всегда одно и то же. GNUавтоконфпрограмма должна иметь дело смного разных причуд.)

Можно ли написать скрипт, который пытается использовать zsh и возвращается к bash, если zsh недоступен? Я пробовал вставить две строки shebang, как показано ниже, но он просто выдает ошибки сплохой интерпретатор: /bin/zsh: нет такого файла или каталогаесли я попробую это на машине без zsh.

Строка shebang может быть только одна; все, что находится после символа новой строки, ядром даже не читается и воспринимается оболочками как комментарий.

Еговозможныйнаписать скрипт, который запускается как #!/bin/sh, проверяет, какая оболочка доступна, и запускает exec zsh "$0" "$@"или exec bash "$0" "$@"в зависимости от результата. Однако синтаксис, используемый bash и zsh, настолько отличается в разных местах, что я быне рекомендую этого делатьдля вашего собственного рассудка.

решение2

1) Текущая оболочка, в которой вы работаете. (какая бы она ни была)

2) Придерживайтесь одного и того же типа оболочки (bash/dash/ash/csh/какая вам нравится) и убедитесь, что ваши «поддерживаемые платформы» устанавливают оболочку, которую вы хотите использовать по умолчанию. Также старайтесь использовать общедоступные команды в системах. Избегайте машинно-специфичных опций.

3) На самом деле в . нет логики "если-то-иначе" interpreter directive. Вам следует указать оболочку, которая должна существовать во всех системах, которые вы хотите поддерживать... т. е. #!/bin/bashили указать универсальную, #!/bin/shесли ваш скрипт достаточно универсален для всех оболочек.

Связанный контент