У меня есть проект, состоящий из около 20 небольших .sh
файлов. Я называю их «маленькими», потому что обычно ни один файл не содержит более 20 строк кода. Я выбрал модульный подход, потому что, таким образом, я верен философии Unix, и мне легче поддерживать проект.
В начале каждого .sh
файла я ставлю #!/bin/bash
.
Проще говоря, я понимаю, что объявления скриптов имеют две цели:
- Они помогают пользователю вспомнить, какая оболочка необходима для выполнения файла (скажем, через несколько лет без использования файла).
- Они гарантируют, что скрипт выполняется только с определенной оболочкой (в данном случае Bash), чтобы предотвратить непредвиденное поведение в случае использования другой оболочки.
Когда проект начинает расти, скажем, с 5 файлов до 20 файлов или с 20 файлов до 50 файлов (не в этом случае, а просто для демонстрации), у нас есть 20 или 50 строк объявлений сценариев. Я признаю, что хотя это может показаться забавным для некоторых, мне кажется немного излишним использовать 20 или 50 вместо того, чтобы говорить только 1 на проект (возможно, в основном файле проекта).
Есть ли способ избежать этой предполагаемой избыточности в 20 или 50 или намного большего числа строк объявлений скриптов, используя некое «глобальное» объявление скриптов в каком-то основном файле?
источник
/bin/bash -x "$script"
Ответы:
Даже если ваш проект теперь может состоять исключительно из 50 скриптов Bash, он рано или поздно начнет накапливать скрипты, написанные на других языках, таких как Perl или Python (из-за преимуществ, которые эти скриптовые языки имеют, которых нет у Bash).
Без правильной
#!
строки в каждом сценарии было бы чрезвычайно трудно использовать различные сценарии, не зная, какой интерпретатор использовать. Не имеет значения, выполняется ли каждый отдельный скрипт из других скриптов , это только переносит сложность от конечных пользователей к разработчикам. Ни одна из этих двух групп людей не должна знать, на каком языке написан сценарий, чтобы иметь возможность его использовать.Сценарии оболочки, выполняемые без
#!
строки и без явного интерпретатора, выполняются по-разному, в зависимости от того, какая оболочка их вызывает (см., Например, вопрос « Какой интерпретатор оболочки запускает сценарий без шебанга?» И особенно ответ Стефана ), а это не то, что вам нужно в производственной среде (вам нужно согласованное поведение и, возможно, даже переносимость).Скрипты, выполняемые с явным интерпретатором, будут запускаться этим интерпретатором независимо от того, что
#!
говорит -line. Это вызовет проблемы в дальнейшем, если вы решите повторно реализовать, скажем, скрипт Bash на Python или любом другом языке.Вы должны потратить эти дополнительные нажатия клавиш и всегда добавлять
#!
-линии к каждому сценарию.В некоторых средах в каждом сценарии в каждом сценарии содержатся стандартные текстовые юридические тексты. Будьте очень рады, что это всего лишь
#!
линия, которая кажется «избыточной» в вашем проекте.источник
#!
строке, как только файл имеет доступное разрешение и загружается не интерпретатором, а оболочкой. То есть/path/to/myprog.pl
запускает perl-программу, если#!
есть строка (указывающая на интерпретатор perl) и файл имеет разрешение exec.Вы неправильно поняли смысл
#!
. На самом деле это указание операционной системе запускать эту программу под определенным интерпретатором.Таким образом, сценарий может быть
#!/usr/bin/perl
и результирующая программа может быть запущена как./myprogram
и Perl интерпретатор может быть использован. Подобное#!/usr/bin/python
приведет к запуску программы под python.Таким образом, строка
#!/bin/bash
указывает ОС запускать эту программу под bash.Вот пример:
Таким образом, несмотря на то, что моя оболочка - ksh, программа "x" запускается в bash из-за
#!
строки, и мы можем увидеть это явно в списке процессов.источник
ps -aux
может дать предупреждение,ps
дает предупреждениеWarning: bad syntax, perhaps a bogus '-'?
.ps
suooprts и синтаксис аргументов BSD и UXIX .-aux
неправильно UNIX Стивен, вероятно, означает,aux
что это правильно BSDps
показывает вызовbash
), а не на явном синтаксисе; (2)ps -aux
отлично работает на CentOS 7 и Debian 9 без предупреждений; эта паста была именно результатом моей машины; все обсуждение того-
, нужен ли он или нет, применимо к более ранним версиям Linux-процедур, а не к текущим версиям.На
.sh
Что плохо, это
.sh
в конце имени файла.Представьте, что вы переписываете один из скриптов на python.
Что ж, теперь вам нужно изменить первую строку,
#!/usr/bin/python3
это не так уж и плохо, так как вам нужно было также изменить каждую строку кода в файле. Однако вы также должны изменить имя файла сprog.sh
наprog.py
. И затем вам нужно найти повсюду в других скриптах и всех ваших пользовательских скриптах (те, о которых вы даже не подозревали), и изменить их, чтобы использовать новый скрипт.sed -e 's/.sh/.py/g'
может помочь тем, о ком ты знаешь. Но теперь ваш инструмент контроля версий показывает изменение во множестве несвязанных файлов.В качестве альтернативы делать это так , Unix и название программы
prog
неprog.sh
.На
#!
Если у вас есть правильный
#!
, и установите разрешение / режим, чтобы включить выполнение. Тогда вам не нужно знать переводчика. Компьютер сделает это за вас.Для не-GNU систем прочитайте руководство для
chmod
(и изучите восьмеричное), возможно, прочитайте его в любом случае.источник
.image
для фотографий..audio
для звука и т. д. Таким образом, говоря вам, что это такое, но не о реализации / кодировании.launch-missiles
илиdelete-project-and-make-manager-pissed
я не хочу "просто запустить его", когда мне было интересно узнать о языке :)file
команду. он распознает большинство типов файлов.Вероятно, стоит отметить, что это совершенно неправильно. Строка hashbang никоим образом не мешает вам пытаться передать файл неправильной оболочке / интерпретатору:
(или аналогично с
awk -f array.sh
т. д.)Но в любом случае, другой подход к модульности должен был бы определить функции оболочки в файлах, одну функцию на файл, если хотите, и затем
source
файлы из основной программы. Таким образом, вам не понадобятся хэш-банги: они будут рассматриваться как любые другие комментарии, и все будет работать с использованием одной и той же оболочки. Недостатком будет то, что вам понадобятсяsource
файлы с функциями (напримерfor x in functions/*.src ; do source "$x" ; done
), и все они будут работать в одной оболочке, поэтому вы не сможете напрямую заменить одну из них на Perl-реализацию.источник
Существует - это называется переносимость или соответствие POSIX. Старайтесь всегда писать сценарии в переносимом, нейтральном для оболочки виде, исходить из него следует только из сценария, который использует
#!/bin/sh
или когда вы используете/bin/sh
интерактивно (или, по крайней мере, POSIX-совместимую оболочку, такую какksh
).Однако переносимые скрипты не спасут вас от:
/bin/sh
скрипт сcsh
.Если я могу высказать свое мнение, «избегать избыточности» путем устранения
#!
является неправильной целью. Целью должна быть стабильная производительность и фактически работающий скрипт, который работает и рассматривает ключевые случаи, следуя определенным общим правилам, таким как not-parsing-ls или всегда-цитирование-переменные-если-не-необходимость-разбиение слов .Они действительно не для пользователя - они для операционной системы, чтобы запустить надлежащий интерпретатор. «Правильный» в данном случае означает, что ОС находит то, что находится в шебанге; если код ниже его для неправильной оболочки - это вина автора. Что касается пользовательской памяти, я не думаю, что «пользователю» таких программ, как Microsoft Word или Google Chrome, когда-либо нужно было знать, на каких языках написаны программы; авторы могут понадобиться.
С другой стороны, сценарии, написанные переносимо, могут избавить от необходимости даже помнить, какую оболочку вы использовали изначально, потому что переносимые сценарии должны работать в любой POSIX-совместимой оболочке.
Они не Что на самом деле предотвращает неожиданное поведение, так это написание переносимых скриптов.
источник
Причина, по которой вам нужно поместить
#!/bin/bash
в начало каждого скрипта, заключается в том, что вы запускаете его как отдельный процесс.Когда вы запускаете скрипт как новый процесс, ОС видит, что это текстовый файл (в отличие от двоичного исполняемого файла), и ей нужно знать, какой интерпретатор выполнять. Если вы этого не скажете, ОС может только догадываться, используя настройки по умолчанию (которые может изменить администратор). Таким образом,
#!
строка (плюс, конечно, добавление разрешений на выполнение) превращает простой текстовый файл в исполняемый файл, который можно запускать напрямую, с уверенностью, что ОС знает, что с ним делать.Если вы хотите удалить
#!
строку, то ваши варианты:Выполните сценарий напрямую (как вы делаете сейчас) и надейтесь, что интерпретатор по умолчанию соответствует сценарию - вы, вероятно, в безопасности на большинстве систем Linux, но не переносимы на другие системы (например, Solaris), и его можно изменить на что угодно (я мог даже настроить его
vim
на файл!).Выполните скрипт, используя
bash myscript.sh
. Это прекрасно работает, но вы должны указать путь к сценарию, и это грязно.Использовать исходный код сценария
. myscript.sh
, который запускает сценарий в текущем процессе интерпретатора (т.е. не как подпроцесс). Но это почти наверняка потребует изменений в ваших скриптах и сделает их менее модульными / многократно используемыми.В случаях 2 и 3, файл не нуждается (и не должен иметь) разрешений на выполнение, и предоставление ему
.sh
(или.bash
) суффикса - хорошая идея.Но ни один из этих вариантов не выглядит подходящим для вашего проекта, так как вы сказали, что хотите, чтобы ваши скрипты были модульными (=> независимыми и автономными), поэтому вы должны держать свою
#!/bin/bash
строку в верхней части скриптов.В своем вопросе вы также сказали, что придерживаетесь философии Unix. Если это правда, тогда вы должны узнать, для чего эта
#!
строка на самом деле, и продолжать использовать ее в каждом исполняемом скрипте!источник
then you should learn what the #! line is really for, and keep using it in every executable script!
. Можно следовать философии У. до определенной точки знания. После всех этих ответов я понял, почему его можно включить в этот термин. Я предлагаю отредактировать ответ, заменив его на «Посмотрите на Шебанг как на внутреннюю часть философии Unix, которую вы уважаете и принимаете».