Shell и Bash

Материал из llmdocs — справочник разработчика
Shell и Bash
Типкомандная оболочка Unix и язык сценариев
Автор BashБрайан Фокс (проект GNU)
Первый выпуск Bash1989
СопровождающийЧет Рэми (с 1990-х)
ПредшественникBourne shell (sh, Стивен Борн, 1979)
СтандартPOSIX Shell Command Language
ЛицензияGNU GPL v3 (с версии 4.0)
АльтернативыZsh, fish, dash, ksh

Командная оболочка (англ. shell, «оболочка», «шелл») — программа, которая читает команды пользователя, запускает соответствующие программы и показывает результат. Это главный текстовый интерфейс Linux и других Unix-подобных систем. Оболочка одновременно служит и интерактивной средой, и языком программирования: последовательность команд можно сохранить в файл-скрипт и запускать как программу.

Bash (Bourne Again Shell — игра слов: «снова Борн» и «рождённый заново») — самая распространённая оболочка Linux, стандартная во многих дистрибутивах и в образах Docker. Под словом «шелл-скрипт» обычно понимают скрипт на Bash или на совместимом с POSIX sh.

История

Первая оболочка Unix (Thompson shell, 1971) умела только запускать команды и перенаправлять ввод-вывод. В 1979 году в Unix Version 7 появилась Bourne shell (sh) Стивена Борна — уже с переменными, условиями и циклами. Затем возникли C shell (csh), KornShell (ksh), а в 1989 году Брайан Фокс написал для проекта GNU свободную замену sh — Bash.[2] Вскоре сопровождение перешло к Чету Рэми, который ведёт проект до сих пор.

Язык оболочки стандартизирован в POSIX: скрипт, использующий только возможности POSIX sh, переносим между Bash, dash, ksh и Zsh.[3] В Debian и Ubuntu /bin/sh — это минималистичная оболочка dash, а Bash используется для интерактивной работы. Apple в macOS Catalina (2019) сменила оболочку по умолчанию на Zsh, оставив в системе старую Bash 3.2 — последнюю версию под GPL v2.[5]

Как оболочка выполняет команду

Прежде чем запустить программу, оболочка разбирает строку в несколько этапов: разбивает её на слова, раскрывает фигурные скобки ({a,b}), тильду (~), переменные ($HOME), подстановку команд ($(date)), арифметику ($((1+2))), затем снова делит результат на слова по пробелам и раскрывает шаблоны имён файлов (*.txt). Только после этого ищется программа в каталогах из переменной PATH и запускается через системные вызовы fork и exec.[1]

Отсюда главное правило: заключайте переменные в двойные кавычки. rm $file при имени файла с пробелом удалит два разных файла, а rm "$file" — ровно один.

Основы синтаксиса

#!/usr/bin/env bash
set -euo pipefail                 # падать на ошибках и неопределённых переменных

name="мир"                        # без пробелов вокруг =
echo "Привет, $name"

files=(*.log)                     # массив (возможность Bash, не POSIX)
echo "логов: ${#files[@]}"

if [[ -d /var/log ]]; then        # [[ ]] — расширенная проверка Bash
    echo "каталог есть"
fi

for f in "${files[@]}"; do
    gzip -- "$f"
done

count=$(grep -c ERROR app.log || true)   # подстановка вывода команды
(( count > 0 )) && echo "ошибок: $count"

backup() {                         # функция
    local src=$1
    tar czf "/tmp/$(basename "$src").tgz" "$src"
}
backup /etc/nginx

Каждая команда возвращает код выхода: 0 — успех, любое другое число — ошибка. На кодах выхода построены if, операторы && и ||. Строка set -euo pipefail заставляет скрипт останавливаться при первой ошибке, при обращении к неопределённой переменной и при сбое любой команды в конвейере.

Перенаправление и конвейеры

Запись Смысл
cmd > file вывод в файл (перезаписать)
cmd >> file дописать в конец файла
cmd 2> err.log поток ошибок в файл
cmd > out.log 2>&1 оба потока в один файл
cmd < file ввод из файла
a | b вывод a на вход b

Конвейеры — суть философии Unix: маленькие программы, каждая делает одно дело, соединяются в цепочку. Например, десять самых частых IP-адресов в логе: cut -d' ' -f1 access.log | sort | uniq -c | sort -rn | head. Для поиска по тексту используют grep, для преобразования — sed и awk, для обхода файлов — find и xargs.

Интерактивная работа

Bash хранит историю команд (Ctrl+R — поиск по ней), дополняет имена по Tab, поддерживает горячие клавиши в стиле Emacs (Ctrl+A/Ctrl+E — начало и конец строки). Настройки и псевдонимы (alias ll='ls -la') хранятся в ~/.bashrc. Справку по встроенным командам даёт help, по остальным — man-страницы и краткие примеры tldr-pages.

Когда не писать на Bash

Bash хорош для склейки программ, автоматизации развёртывания и коротких сценариев. Когда скрипт перерастает сотню строк, требует сложных структур данных, разбора JSON (хотя есть jq) или обработки ошибок, его лучше переписать на Python. Для проверки скриптов незаменим статический анализатор ShellCheck: он находит пропущенные кавычки, непереносимые конструкции и типичные ловушки.[4]

См. также

Источники

  1. GNU Bash Reference Manual
  2. Bash — домашняя страница Чета Рэми
  3. POSIX.1-2024 — Shell Command Language
  4. ShellCheck — статический анализатор shell-скриптов
  5. Apple — Use zsh as the default shell on your Mac