Назад | Перейти на главную страницу

Сценарий Bash не работает с `sh`

Я тестирую простой скрипт, и мне интересно, почему он отлично работает при запуске из каталога: ./test.sh но когда я пытаюсь использовать команду "sh" sh test.sh это не работает:

test.sh: 3: test.sh: [[: not found
test.sh: 7: test.sh: [[: not found

Сценарий:

#!/usr/bin/env bash

if [[ $1 = one ]]
        then
        printf "%b" "two\n" >&2
        exit 0
elif [[ $1 = two ]]
then
        printf "%b" "one\n" >&2
        exit 0
else
        printf "%b" "Specify argument: one/two\n"
        exit 1
fi

Резюме

sh это другая программа, чем bash.

Деталь

Проблема в том, что оболочка Борна (sh) не является оболочкой Bourne Again (bash). А именно sh не понимает [[ прагма. На самом деле он не понимает [ либо. [ это фактическая программа или ссылка на / bin / test (или / usr / bin / [, / usr / bin / test).

$ which [
/bin/[
$ ls -lh /bin/[
-r-xr-xr-x  2 root  wheel    42K Feb 29 17:11 /bin/[

Когда вы выполняете свой скрипт напрямую через ./test.sh, вы вызываете сценарий в качестве первого аргумента программы, указанной в первой строке. В таком случае:

#!/usr/bin/env bash

Часто это напрямую интерпретатор (/bin/bashили любое количество других интерпретаторов скриптов), но в вашем случае вы используете env для запуска программы в измененной среде, но этот следующий аргумент по-прежнему является bash. Фактически, ./test.sh является bash test.sh.

Так как sh и bash это разные оболочки с разной интерпретацией синтаксиса, вы видите эту ошибку. Если ты бежишь bash test.sh, вы должны увидеть то, что ожидается.

Больше информации

Другие отметили в комментариях, что /bin/sh может быть ссылка или другая оболочка. Исторически, sh была оболочкой Борна в старой AT&T Unix и, на мой взгляд, каноническим происхождением. Однако это отличается в вариациях BSD и со временем разошлось в других системах и дистрибутивах на основе Unix. Если вас действительно интересует внутренняя работа (включая то, как / bin / sh и / bin / bash могут быть одной и той же программой и вести себя совершенно по-разному), прочтите следующее:

SuperUser: В чем разница между bash и sh

Википедия: оболочка Борна

Как уже отмечалось: / bin / sh обычно (хотя и не всегда) вызывает POSIX-совместимую оболочку Bourne. Баш - это не Борн.

Bash попытается имитировать Борна при вызове как 'sh' (например, когда символические ссылки / bin / sh или ссылки на / bin / bash) или если $ POSIXLY_CORRECT определен в вызывающей среде, при вызове с параметром вызова --posix, или когда было выполнено 'set -o posix'. Это позволяет протестировать сценарий / команду оболочки Bourne на соответствие POSIX.

Как вариант, запускайте сценарии / тестовые команды с известной POSIX-совместимой оболочкой. «тире» близко, оболочка Korn (ksh) IIRC также предлагает вариант, совместимый с POSIX.