Перейти к содержимому

Bash-скрипты: аргументы, условия и циклы

40 мин

В прошлом уроке вы написали первый скрипт — одну команду в файле. Настоящие скрипты принимают аргументы, проверяют условия и обрабатывают много файлов в цикле. Это главный инструмент автоматизации: резервные копии, разбор журналов, массовые проверки, сканеры.

Каркас скрипта

#!/bin/bash
set -euo pipefail          # падать на ошибках, а не продолжать молча

LOG_DIR="$HOME/logs"       # переменная: без пробелов вокруг =
echo "Разбираю $LOG_DIR"

set -euo pipefail — хорошая привычка:

  • -e — остановиться, если команда завершилась с ошибкой;
  • -u — ошибка при обращении к несуществующей переменной (спасает от rm -rf "$DIR/"* с пустым DIR);
  • -o pipefail — конвейер считается неуспешным, если упала любая его часть.

Аргументы

ПеременнаяЗначение
$0имя скрипта
$1, $2 …первый, второй … аргумент
$#количество аргументов
"$@"все аргументы, каждый отдельно
$?код возврата последней команды
#!/bin/bash
if [ $# -ne 1 ]; then
  echo "Использование: $0 ФАЙЛ" >&2     # >&2 — в поток ошибок
  exit 1
fi
wc -l < "$1"

Коды возврата и условия

Каждая команда возвращает число: 0 — успех, всё остальное — ошибка. На этом построены условия:

if grep -q 'root' /etc/passwd; then
  echo "нашёл"
fi

[ -f "$file" ]      # существует и это обычный файл
[ -d "$dir" ]       # каталог
[ -r "$file" ]      # можно прочитать
[ -z "$var" ]       # строка пустая
[ "$a" = "$b" ]     # строки равны
[ "$n" -gt 10 ]     # число больше 10 (-lt, -ge, -le, -eq, -ne)

Короткая запись: команда1 && команда2 выполнит вторую только при успехе первой, || — только при ошибке: mkdir -p "$out" || exit 1.

Циклы

for f in "$HOME"/logs/*.log; do         # по файлам
  echo "$(basename "$f") $(grep -c ERROR "$f")"
done

for i in 1 2 3; do echo "$i"; done        # по списку

while read -r ip; do                      # по строкам файла
  echo "проверяю $ip"
done < targets.txt

basename отрезает путь и оставляет имя файла: /home/student/logs/app.log → app.log.

Кавычки: главный источник ошибок

ЗаписьЧто происходит
"$var"значение подставляется целиком, пробелы сохраняются — используйте так
$varзначение разбивается по пробелам и раскрываются шаблоны: файл my notes.txt станет двумя
'$var'никакой подстановки: буквально $var
$(команда)подставить вывод команды

Правило: всегда берите переменные в двойные кавычки, если не уверены в обратном.

С точки зрения безопасности

Скрипт, который подставляет недоверенные данные (имена файлов, ввод пользователя) без кавычек или передаёт их в eval, уязвим для внедрения команд. Имя файла ; rm -rf ~ — вполне допустимое имя в Linux. Кавычки, -- перед аргументами (rm -- "$f") и отказ от eval закрывают большинство таких проблем.

🧪 Практика

Напишите скрипт, который проверяет аргументы и считает строки в файле, и скрипт с циклом, который подсчитывает ошибки в каждом журнале.

Bash-скрипты: аргументы, условия и циклы — Основы Linux — CyberLab