Вопрос по shell, unix – заголовки сценариев оболочки (#! / bin / sh vs #! / bin / csh)

65

Почему все файлы сценариев начинаются с

#!/bin/sh

или с

#!/bin/csh

Это требуется? Какова цель этого? И в чем разница между ними?

Для сценария csh, вы должны использовать#!/bin/csh -f;-f говорит оболочке не использовать исходные тексты пользователя.login а также.cshrc, что ускоряет выполнение сценария и позволяет избежать зависимостей от настроек пользователя. (Или еще лучше, не пишите сценарии csh.) Не используйте-f для скриптов sh или bash; оно не имеет того же значения. Keith Thompson

Ваш Ответ

3   ответа
38

#! строка сообщает ядру (в частности, о реализацииexecve системный вызов), что эта программа написана на интерпретируемом языке; Абсолютный путь, который следует, идентифицирует интерпретатор. Программы, скомпилированные в машинный код, начинаются с другой последовательности байтов - в большинстве современных Unix-систем,7f 45 4c 46 (^?ELF) который идентифицирует их как таковые.

Вы можете поставить абсолютный путь кany program you want после#!До тех пор, пока эта программа сама по себе не#! скрипт. Ядро переписывает вызов

./script arg1 arg2 arg3 ...

где./script начинается с, скажем,#! /usr/bin/perl, как будто командная строка была на самом деле

/usr/bin/perl ./script arg1 arg2 arg3

Или, как вы видели, вы можете использовать#! /bin/sh написать сценарий, предназначенный для интерпретацииsh.

#! строка обрабатывается только если выdirectly вызвать скрипт (./script в командной строке); файл также должен быть исполняемым (chmod +x script). Если вы делаетеsh ./script #! строка не обязательна (и будет игнорироваться, если имеется), и файл не обязательно должен быть исполняемым.point этой функции позволяет вам напрямую вызывать программы с интерпретируемым языком, не зная, на каком языке они написаны.grep '^#!' /usr/bin/* - вы обнаружите, что очень многие стоковые программы на самом деле используют эту функцию.)

Вот несколько правил использования этой функции:

The #! must be the very first two bytes in the file. In particular, the file must be in an ASCII-compatible encoding (e.g. UTF-8 will work, but UTF-16 won't) and must not start with a "byte order mark", or the kernel will not recognize it as a #! script. The path after #! must be an absolute path (starts with /). It cannot contain space, tab, or newline characters. It is good style, but not required, to put a space between the #! and the /. Do not put more than one space there. You cannot put shell variables on the #! line, they will not be expanded. You can put one command-line argument after the absolute path, separated from it by a single space. Like the absolute path, this argument cannot contain space, tab, or newline characters. Sometimes this is necessary to get things to work (#! /usr/bin/awk -f), sometimes it's just useful (#! /usr/bin/perl -Tw). Unfortunately, you cannot put two or more arguments after the absolute path. Some people will tell you to use #! /usr/bin/env interpreter instead of #! /absolute/path/to/interpreter. This is almost always a mistake. It makes your program's behavior depend on the $PATH variable of the user who invokes the script. And not all systems have env in the first place. Programs that need setuid or setgid privileges can't use #!; they have to be compiled to machine code. (If you don't know what setuid is, don't worry about this.)

относительноcshэто относится кsh примерно как NutrimatРасширенный заменитель чая делает чай. Он имеет (или, скорее, имел; современные реализацииsh догнали) ряд преимуществ передsh для интерактивного использования, но используя его (или его потомкаtcsh) для скриптинга естьпочти всегда ошибка, Если вы новичок в сценариях оболочки в целом, я настоятельно рекомендую вам игнорировать его и сосредоточиться наsh, Если вы используетеcsh относительно вашей оболочки входа в систему, переключитесь наbash или жеzshтак что интерактивный командный язык будет таким же, как и язык сценариев, который вы изучаете.

отличный совет
Последние версии Linux позволяют указывать интерпретатор как скрипт. Обычная практика - пропускать пробел после#!; без комментариев о том, является ли это хорошим стилем. Увидетьthis question а такжеmy answer для обсуждения плюсов и минусов#!/usr/bin/env хак.
@ KeithThompson У меня сложилось впечатление, что Linux - этоonly распространенный вариант Unix, который позволяет интерпретатору быть сценарием, поэтому на него все же не стоит полагаться. Так как я написал это, я сам столкнулся с ситуацией, когда#!/usr/bin/env была правильная вещь, но я по-прежнему считаю, что это почти всегда плохая идея.
74

Shebang:

http://en.wikipedia.org/wiki/Shebang_(Unix)

#!interpreter [optional-arg]

Шебанг имеет значение только тогда, когда скрипт имеет разрешение на выполнение (например, chmod u + x script.sh).

Когда оболочка выполняет скрипт, она будет использовать указанный интерпретатор.

Пример:

#!/bin/bash
# file: foo.sh
echo 1

$ chmod u+x foo.sh
$ ./foo.sh
  1
Вам нужно добавить#!/bin/sh в.profile?
Ссылка выше нуждается в исправлении.
@Kolob Canyon вам не нужен, но он может помочь некоторым редакторам с подсветкой синтаксиса (хотя обычно есть и другие способы добиться того же):unix.stackexchange.com/a/88730/193985
4

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

Когда вы вводите команду в командной строке Unix, вы взаимодействуете с оболочкой.

Например.,#!/bin/csh относится к C-оболочке,/bin/tcsh Т-оболочка,/bin/bash оболочка bash и т. д.

Вы можете сказать, какую интерактивную оболочку вы используете

 echo $SHELL

команда, или в качестве альтернативы

 env | grep -i shell

Вы можете изменить командную оболочку с помощьюchsh команда.

Каждый из них имеет свой набор команд и способ назначения переменных, а также свой набор программных конструкций. Например, оператор if-else с bash выглядит не так, как в C-оболочке.

Эта страница может представлять интерес, поскольку он «переводит» между командами / синтаксисом bash и tcsh.

Использование директивы в сценарии оболочки позволяет запускать программы с использованием другой оболочки. Например, я используюtcsh Оболочка в интерактивном режиме, но часто запускает сценарии bash, используя / bin / bash в файле сценария.

В сторону:

Эта концепция распространяется и на другие сценарии. Например, если вы программируете на Python, вы добавляете

 #!/usr/bin/python

в верхней части вашей программы Python

@OneTwoThree:#! строка должна соответствовать синтаксису скрипта,not интерактивная оболочка, используемая тем, кто запускает скрипт.
Значение$SHELL не обязательно говорит вам, какую оболочку вы используете в данный момент; это обычно говорит вам вашdefault ракушка. наборы тсш$version а также$tcsh; наборы баш$BASH_VERSION, Не все оболочки обязательно имеют сходные механизмы.
@OneTwoThree Большинство систем имеют стандартные оболочки, и если вы напишите bash или csh-скрипт, у вас все будет в порядке. Какую оболочку они используют в интерактивном режимеdoesn't Дело в том, что красота, например,!#/bin/bashдирективы. Он сообщает системе, какую оболочку использовать для выполнения сценария оболочки.
Так это обязательно? Как узнать, какую оболочку я действительно использую? One Two Three
Поэтому, если я пишу сценарии, которые кто-то может использовать на своей машине, и я не знаю, какую оболочку они используют. (К сожалению, этот человек ничего не знает об этом, поэтому все, что он может сделать, это запустить скрипт, не меняя ничего). Могу ли я сделать что-то вроде#! $SHELL ? Это поместило бы правильную раковину в Shebang? One Two Three

Похожие вопросы