Секрет первой строки в скриптах Линукс: Что такое #!/usr/bin/env bash и #!/bin/bash?
Когда вы пишете скрипты в Линукс, то по привычке добавляете в самом начале одну из этих строк:
#!/usr/bin/env bash
или
#!/bin/bash
На первый взгляд, это похоже на обычный комментарий… Но что на самом деле скрывается за этой строкой? И в чем заключаются их различия? В этой статье мы подробно разберем значение этой строки и выясним, когда какой вариант следует использовать.
1. Это не комментарий: Что такое shebang?
Строка, начинающаяся с #!, называется shebang.
#!/bin/bash
Для оболочки это выглядит как комментарий, поскольку она начинается с #.
Однако для операционной системы (ядра) это не комментарий, а:
"Директива, указывающая, где находится программа-интерпретатор, которая должна выполнить этот скрипт."
То есть:
#!/bin/bash→ "Выполни этот файл с помощью/bin/bash."#!/usr/bin/env bash→ "Найди интерпретаторbashчерезenvи выполни этот файл с его помощью."
Вот такое значение имеет эта строка.
2. Как ядро выполняет скрипты?
Если сильно упростить процесс выполнения, то он выглядит так:
- Пользователь запускает скрипт с правами на исполнение.
chmod +x script.sh
./script.sh
- Ядро считывает
script.sh. - Проверяет, являются ли первые два символа файла
#!. - Если да, то оставшаяся часть строки
- интерпретируется как "путь к интерпретатору + аргументы"
- и запускает эту программу, передавая ей путь к файлу скрипта в качестве аргумента.
Например, если первая строка script.sh выглядит так:
#!/bin/bash
Тогда ядро фактически выполняет что-то вроде:
/bin/bash script.sh
То есть, ядро выполняет действие, аналогичное тому, как если бы мы сами запустили bash script.sh.
Примечание: Перед
#!/не должно быть пробелов. Первым символом файла должен быть#, а вторым —!.
3. Значение и особенности #!/bin/bash
Это наиболее часто встречающаяся форма.
#!/bin/bash
Значение
- "Этот скрипт является bash-скриптом, и
bashнаходится по пути/bin/bash." - При выполнении этого скрипта ядро всегда запускает
/bin/bash.
Преимущества
- Ясность: Всегда используется
/bin/bash, что делает предсказуемым, какая версия bash будет применена. - Производительность/Простота: Выполняется напрямую, без обращения к
env, что исключает процесс поиска пути. - Многие дистрибутивы Линукс рассматривают
/bin/bashфактически как "стандартное расположение".
Недостатки
-
Может быть непереносимым
-
В некоторых системах bash может находиться по другому пути, например,
/usr/bin/bash,/usr/local/bin/bashи т.д. - В некоторых системах bash может быть вообще не установлен, и может присутствовать только
/bin/sh. - В частности, пути могут отличаться в macOS, системах на базе BSD, NixOS, некоторых контейнерных средах и т.д.
4. Значение и особенности #!/usr/bin/env bash
Сегодня эта форма часто встречается в скриптах.
#!/usr/bin/env bash
Ключевым моментом здесь является /usr/bin/env.
-
env— это утилита, которая помогает устанавливать/проверять переменные среды и искать программы вPATH. -
Можно считать, что ядро фактически выполняет это так:
/usr/bin/env bash script.sh
envпросматривает системную переменную средыPATHи находит исполняемый файлbash, а затем запускает его.
Преимущества
- Портативность (хорошо работает в различных средах)
- Независимо от того, находится ли bash в
/bin/bash,/usr/bin/bashили/usr/local/bin/bash, envнайдет его, если он правильно зарегистрирован вPATH.
- Использование bash, соответствующего пользовательской среде
- Если пользователь настроил
PATHтак, чтобы использовать определенную версию bash в первую очередь, то именно эта версия bash будет использоваться.
- Используется тот же шаблон для Python и других языков
#!/usr/bin/env python3
Недостатки
- Предполагается наличие
/usr/bin/env
- Он присутствует практически во всех современных Unix/Линукс системах, но в очень специфических средах может отсутствовать.
- В зависимости от PATH может быть выбран другой интерпретатор
- Если настройка PATH нарушена или неожиданная версия bash находится раньше в PATH, может быть выполнена нежелательная версия.
- Иногда требует осторожности с точки зрения безопасности
- В очень чувствительных к безопасности средах предпочтение отдается абсолютным путям, а не поиску интерпретатора на основе PATH.
5. Сравнение двух подходов
Представим краткую сравнительную таблицу:
| Критерий | #!/bin/bash | #!/usr/bin/env bash |
|---|---|---|
| Метод указания пути к интерпретатору | Фиксированный абсолютный путь | PATH через поиск |
| Портативность (совместимость с разными системами) | Низкая (ломается при изменении пути) | Высокая (достаточно, чтобы bash был в PATH) |
| Какая версия bash используется | Всегда /bin/bash |
Первая найденная bash в PATH |
| Гарантия нужной версии | Относительно легко | Может меняться в зависимости от состояния PATH |
| Безопасность/Контроль | Выше (фиксированный путь) | Немного ниже (зависит от PATH) |
| Современные тенденции | Относительно устаревший стиль | В последнее время чаще рекомендуется |
6. Когда что использовать?
"В итоге, что мне использовать?" — ответим на этот вопрос, разобрав ситуации.
1) Скрипты для личного или командного использования (типичная среда разработки)
- В основном рекомендуется следующее:
#!/usr/bin/env bash
-
Причина:
-
В серверах, локальных средах, CI-средах, управляемых разработчиками, расположение bash может отличаться.
- Поиск и выполнение на основе PATH более гибок, и современные инструменты/скрипты предпочитают этот подход.
2) Операционные скрипты, строго соответствующие конкретной серверной среде
-
Например, если на всех серверах компании bash установлен по общему пути
/bin/bash, -
И среда сервера достаточно статична:
#!/bin/bash
-
Причина:
-
Гарантирует использование всегда одного и того же интерпретатора.
- Помогает избежать непредвиденного поведения, вызванного изменениями PATH.
3) Если вы хотите сделать скрипт максимально переносимым?
-
Если вы предполагаете среду, где "bash может вообще отсутствовать", то стоит задуматься, действительно ли скрипт должен зависеть от bash.
-
Если возможно, пишите на
sh:
#!/bin/sh
- Этот вариант будет работать в гораздо более широком спектре сред.
Однако в этом случае нельзя использовать специфический синтаксис bash (
[[ ]], массивы, расширенная обработка строк и т.д.).
7. Практические советы при использовании #!/usr/bin/env bash
1) Как запускать скрипты
Чтобы shebang работал правильно, не просто делайте так:
bash script.sh # ← При таком запуске shebang практически не имеет смысла
Лучше использовать следующий способ:
chmod +x script.sh # Предоставить права на исполнение
./script.sh # Запустить напрямую
Только так ядро прочитает #! и использует указанный интерпретатор.
2) Проверка передачи аргументов
Предположим, мы создали test.sh следующим образом:
#!/usr/bin/env bash
echo "Интерпретатор: $0"
echo "Аргументы: $@"
Запуск:
chmod +x test.sh
./test.sh hello world
Вывод:
Интерпретатор: ./test.sh
Аргументы: hello world
Здесь $0 — это "путь к самому файлу скрипта", и достаточно помнить, что ядро фактически выполняет его как /usr/bin/env bash test.sh hello world.
8. Часто задаваемые вопросы
Я видел скрипты, написанные без shebang. Это нормально?
-
Верно, он не всегда обязателен.
-
Если вы запускаете скрипт, явно указывая интерпретатор, как показано ниже, shebang не нужен. Даже если он присутствует, он будет проигнорирован.
bash myscript.sh
python3 myscript.py
- Однако, если вы хотите запустить скрипт следующим образом, shebang обязателен.
./myscript.sh
./myscript.py
- Особенно, если это "утилитарный" скрипт, предназначенный для использования другими, shebang почти всегда необходим.
"Я слышал, что #!/bin/env тоже работает, а не только #!/usr/bin/env?"
- В некоторых системах
/bin/envдействительно может существовать. - Однако
/usr/bin/envобычно является гораздо более универсальным стандартным расположением. - Если нет особых причин, безопаснее использовать
#!/usr/bin/env ….
9. Итог
#!/usr/bin/env bashили#!/bin/bash— это не комментарий, а директива, указывающая ядру, какой интерпретатор использовать для выполнения скрипта.-
#!/bin/bash -
Всегда использует
/bin/bash→ предсказуемо в фиксированных средах, но может быть непереносимым. -
#!/usr/bin/env bash -
Ищет bash в
PATH→ более гибок и переносим, но зависит от состояния PATH. - В общих средах разработки/развертывания для "современного" написания скриптов
рекомендуется использовать
#!/usr/bin/env bashв качестве значения по умолчанию.

Комментариев нет.