Урок 8. Скрипты bash: первый скрипт, переменные и аргументы
Скрипт — текстовый файл с командами, которые оболочка выполняет по порядку, как если бы вы набирали их сами. Всё, что делалось в прошлых уроках руками, можно записать в скрипт и запускать одной командой: резервные копии, очистку старых файлов, установку программ на новый сервер.
Первый скрипт
Создайте файл в редакторе nano:
nano hello.shНаберите две строки, сохраните (Ctrl+O, Enter) и выйдите (Ctrl+X):
#!/bin/bash
echo "Привет из скрипта"Дайте файлу право на выполнение и запустите:
$ chmod +x hello.sh
$ ./hello.sh
Привет из скрипта./ перед именем значит «файл из текущей папки». Без него оболочка будет искать hello.sh в папках из PATH и не найдёт (урок Переменные окружения, PATH, .bashrc и alias).
Строка #!
Первая строка #!/bin/bash называется shebang («шебанг»). Она говорит системе, какой программой выполнять файл. Пишется в самой первой строке, без пробелов перед #!. Часто встречается и вариант #!/usr/bin/env bash — он находит bash через PATH, это удобно там, где bash лежит не в /bin.
Запустить скрипт можно и без права на выполнение — передав его оболочке: bash hello.sh. А вот sh hello.sh выполнит его другой оболочкой: в Ubuntu и Debian sh — это dash, и всё, что есть только в bash (например, [[ ]] и {1..5}), там не сработает.
Расширение .sh для запуска не нужно, оно только подсказывает человеку, что внутри скрипт. Важны первая строка и право на выполнение.
Комментарии, переменные и кавычки
Всё после # в строке — комментарий, bash его пропускает. Переменные — как в терминале: без пробелов вокруг =.
#!/bin/bash
# Имя файла с пробелами — обязательно в кавычках
file="отчёт за март.txt"
echo "Файл: $file"
echo 'Файл: $file'
echo "Копия: ${file%.txt}.bak"Файл: отчёт за март.txt
Файл: $file
Копия: отчёт за март.bakЗапись ${file%.txt} — значение переменной без .txt в конце. Таких приёмов в bash много, они описаны в справочнике bash (раздел о раскрытии параметров).
Главное правило скриптов: переменную в команде берите в двойные кавычки — "$file". Без кавычек rm $file получит три аргумента — «отчёт», «за» и «март.txt» — и попробует удалить три других файла.
Подстановка команд и арифметика
$(команда) подставляет вывод команды:
today=$(date +%F)
count=$(ls | wc -l)
echo "Сегодня $today, файлов в папке: $count"
tar -czf "backup-$(date +%F).tar.gz" ~/projectsdate +%F печатает дату в виде 2026-03-12, поэтому у каждого дня будет свой архив. В старых скриптах встречается та же подстановка в обратных кавычках (знак на клавише с буквой Ё) — это устаревшая запись, в новых скриптах пишут $(…).
Целочисленная арифметика — $(( )):
#!/bin/bash
a=7
b=2
echo "Сумма: $((a + b))"
echo "Частное: $((a / b))"
echo "Остаток: $((a % b))"
echo "Степень: $((a ** b))"Сумма: 9
Частное: 3
Остаток: 1
Степень: 49Деление целочисленное: дробная часть отбрасывается. Дробные числа bash не считает — для них есть, например, команда bc.
Аргументы
Слова, которые вы пишете после имени скрипта, — его аргументы. Внутри они доступны так:
| Запись | Что это |
|---|---|
$0 | имя скрипта, как его запустили |
$1, $2 … | первый, второй и следующие аргументы |
$# | сколько аргументов передано |
"$@" | все аргументы по отдельности, каждый — с сохранением пробелов |
Скрипт args.sh:
#!/bin/bash
echo "Скрипт: $0"
echo "Аргументов: $#"
echo "Первый: $1"
echo "Второй: $2"$ ./args.sh отчёт.txt "фото с моря.jpg"
Скрипт: ./args.sh
Аргументов: 2
Первый: отчёт.txt
Второй: фото с моря.jpgКавычки при запуске сделали «фото с моря.jpg» одним аргументом. Если аргумент не передан, $2 просто пустой — ошибки не будет, поэтому важные аргументы проверяют (об условиях — в следующем уроке).
Ввод с клавиатуры: read
#!/bin/bash
read -r -p "Как вас зовут? " name
echo "Привет, $name"$ ./ask.sh
Как вас зовут? Анна
Привет, Аннаread ждёт строку и кладёт её в переменную; -p — текст приглашения, -r — не трогать обратную косую черту во вводе. Пароль читают с ключом -s — набранное не показывается.
Код возврата
Каждая команда, заканчиваясь, сообщает код возврата (exit code): 0 — успех, любое другое число — ошибка. Код последней команды хранится в $?:
$ grep -q root /etc/passwd
$ echo $?
0
$ grep -q nosuchuser /etc/passwd
$ echo $?
1grep -q ничего не печатает, а только сообщает кодом, нашлось ли. Частые коды:
| Код | Значение |
|---|---|
0 | успех |
1 | общая ошибка; у grep — «не найдено» |
2 | неверное использование команды, серьёзная ошибка |
126 | файл найден, но не запускается (нет права на выполнение) |
127 | команда не найдена |
130 | команда прервана Ctrl+C |
Скрипт задаёт свой код командой exit: exit 0 — всё хорошо, exit 1 — ошибка. Без exit код скрипта — это код последней выполненной в нём команды. Коды нужны, чтобы другие программы (cron, systemd, другие скрипты) понимали, удалась ли работа.
Как искать ошибки
bash -n script.sh— проверить синтаксис, ничего не выполняя;bash -x script.sh— выполнить, печатая каждую команду перед запуском (строки с+);- shellcheck — программа, которая находит типичные ошибки: забытые кавычки, опечатки в переменных. Ставится пакетом
shellcheck:shellcheck script.sh.
Коротко
- Скрипт — файл с командами; первая строка
#!/bin/bash, затемchmod +xи запуск./script.sh. - Переменные —
имя=значение; в командах —"$имя"в двойных кавычках. $(команда)— подставить вывод,$(( ))— целочисленная арифметика.$1,$2— аргументы,$#— их число,"$@"— все сразу.read -r -p "Вопрос " имя— ввод с клавиатуры.0— успех, остальное — ошибка;$?— код последней команды,exit N— код скрипта.