2

У меня есть сценарий bash test.sh который ничего особенного не делает:

#!/bin/bash
echo Hello!

Если я запустлю это так . test.sh , это работает.

kopparberg:dev marek$ . test.sh
Hello!

Если я запускаю это так ./test.sh , это не так.

kopparberg:dev marek$ ./test.sh 
-bash: ./test.sh: /bin/bash^M: bad interpreter: No such file or directory

В чем разница?

2 ответа2

5

Разница между поиском (. test.sh) сценария и его выполнением (test.sh или ./test.sh) заключается в первой строке.

Если вы используете исходный текст сценария, первая строка является только комментарием и игнорируется. Но если вы запустите его, ядро проверяет первую строку на наличие первых двух символов, и если они " #!msgstr ", остальная часть строки будет использоваться как путь и первый аргумент для интерпретатора. То есть ядро будет искать исполняемый файл с именем /bin/bash и передавать ему имя скрипта в качестве первого аргумента. Вот так : /bin/bash ./test.sh .

Это то, что обычно происходит, и вы правы, это должно иметь тот же эффект для вашего сценария. Но ваш скрипт содержит проблему: первая строка заканчивается окончанием строки DOS (CR LF) вместо окончания строки unix (LF). Таким образом, имя интерпретатора, как видит ядро, это /bin/bash^M которого нет на вашем диске (^ M означает ложный CR перед окончанием строки). Что еще хуже, символ ^ M обычно невидим.

Вы можете доказать, что это имеет место с cat -v test.sh (который печатает замену ^ M для невидимого символа CR).

2

Первое решение - это псевдоним для команды "источник".

Притон считается как #comment для источника

Когда вы вызываете скрипт с помощью ./script , оболочка выполнит скрипт с шебангом #!/bin/bash

Кажется, ошибка, которую вы выдавали, является проблемой CRLF, вы можете запустить:

dos2unix script.sh

удалить конечные строки Windows.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .