Модуль 01 — Первый скрипт

Файл с командами, который запускается как программа

Прогресс курса Модуль 1 из 9

Что вы освоите в этом модуле

01

Зачем скрипты

Скрипт — текстовый файл с командами оболочки, которые выполняются по порядку, как если бы вы набирали их сами. Всё, что работает в терминале, работает и в скрипте; плюс появляются переменные, условия, циклы и функции.

Когда писать скрипт

  • Повторяется. Одна и та же последовательность команд нужна каждый день или на десяти серверах.
  • Ошибка дорого стоит. Пропущенный шаг при выкладке или резервном копировании обнаружится, когда будет поздно.
  • Должно работать без вас. Ночью по расписанию, при загрузке, по событию.
  • Нужно передать другому. Скрипт — исполняемая инструкция: в ней нельзя «забыть упомянуть».

Bash хорош для склейки системных команд: файлы, процессы, службы, архивы, запуск утилит. Если в задаче сложные структуры данных, вычисления или работа с JSON и HTTP API, удобнее Python — граница проходит примерно на сотне строк сложной логики.

02

Первый скрипт

Создайте файл hello.sh в любом редакторе (nano hello.sh):

#!/bin/bash
# hello.sh — первый скрипт: кто я, где я, сколько места
echo "Пользователь: $USER"
echo "Каталог: $(pwd)"
echo "Свободно на /: $(df -h --output=avail / | tail -1)"

Первая строка #!/bin/bash называется shebang. Когда файл запускается как программа, ядро читает её и передаёт файл указанному интерпретатору. Остальные строки, начинающиеся с #, — комментарии. $USER — переменная, $(команда) подставляет вывод команды; подробно — в модуле 02.

$ bash hello.sh                  # 1. явно указать интерпретатор
Пользователь: student
Каталог: /home/student
Свободно на /:   24G

$ ./hello.sh                      # 2. как программу — нужны права
-bash: ./hello.sh: Отказано в доступе
$ chmod +x hello.sh
$ ./hello.sh
Пользователь: student
Каталог: /home/student
Свободно на /:   24G

Без права x файл нельзя запустить как программу — только передать интерпретатору. chmod +x делается один раз.

03

Почему ./ и что такое PATH

Без ./ оболочка ищет команду не в текущем каталоге, а в каталогах из переменной PATH:

$ hello.sh
-bash: hello.sh: команда не найдена
$ echo "$PATH"
/usr/local/bin:/usr/bin:/bin:/usr/games

Текущего каталога в PATH нет намеренно: иначе злоумышленник мог бы положить в /tmp файл с именем ls, и вы запустили бы его вместо настоящей команды. ./ явно говорит: «запусти файл отсюда».

Чтобы скрипт запускался по имени из любого каталога, его кладут в один из каталогов PATH:

КаталогДля чего
/usr/local/binСкрипты для всех пользователей сервера, ставятся через sudo install -m 755 backup.sh /usr/local/bin/backup
~/.local/binСвои скрипты; в Debian попадает в PATH через ~/.profile, если каталог существует при входе
/usr/binТолько для программ из пакетов — руками туда не кладут

Расширение .sh для Linux ничего не значит. Скрипты, которые ставят как команды, обычно называют без него: backup, а не backup.sh.

04

bash и sh — не одно и то же

В Debian /bin/sh — это не bash, а dash: маленькая быстрая оболочка, которая понимает только стандарт POSIX. В ней нет многих удобств bash.

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 фев  4  2025 /bin/sh -> dash

Скрипт ниже написан с конструкциями bash, но начинается с #!/bin/sh:

#!/bin/sh
name="мир"
if [[ $name == м* ]]; then echo "начинается на м"; fi
arr=(a b c); echo "${arr[1]}"
$ ./bashism.sh
./bashism.sh: 3: [[: not found
./bashism.sh: 4: Syntax error: "(" unexpected
$ bash ./bashism.sh
начинается на м
b

Правило курса: скрипт начинается с #!/bin/bash и запускается как ./script или bash script, но не sh script — так shebang игнорируется и скрипт выполнит dash. Такие ошибки называют «башизмами»; они же всплывают в контейнерах Alpine, где bash нет вовсе.

05

Как оболочка читает строку

Большинство ошибок в скриптах — не от незнания команд, а от того, как оболочка превращает строку в команду. Порядок действий упрощённо такой:

ШагЧто происходитПример
1. РазборСтрока делится на слова по пробелам с учётом кавычек; находятся |, >, ;echo "a b" c → echo, a b, c
2. Подстановки$переменные, $(команды), $((арифметика))$USER → student
3. РазбиениеРезультат подстановки без кавычек снова делится на словамодуль 02
4. Шаблоны*, ?, […] раскрываются в имена файлов*.log → a.log b.log
5. ЗапускПервое слово — команда, остальные — её аргументы

Пробелы — синтаксис, а не оформление. a=1 — присваивание, a = 1 — запуск команды a с аргументами = и 1. [ -f x ] — проверка, [-f x] — команда [-f, которой нет.

06

ShellCheck

ShellCheck — анализатор скриптов: находит забытые кавычки, башизмы под #!/bin/sh, опечатки в переменных и десятки типичных ошибок до того, как скрипт что-то сломает. Ставится из репозитория Debian:

$ sudo apt install shellcheck
$ shellcheck bashism.sh

In bashism.sh line 3:
if [[ $name == м* ]]; then echo "начинается на м"; fi
   ^---------------^ SC3010 (warning): In POSIX sh, [[ ]] is undefined.


In bashism.sh line 4:
arr=(a b c); echo "${arr[1]}"
    ^-----^ SC3030 (warning): In POSIX sh, arrays are undefined.
                   ^-------^ SC3054 (warning): In POSIX sh, array references are undefined.
...

У каждого замечания есть код (SC3010) и страница с объяснением на shellcheck.net/wiki/SC3010. Тот же анализатор подключается к VS Code (расширение ShellCheck) и подчёркивает ошибки прямо при наборе. Правило курса: скрипт сдаётся без замечаний ShellCheck или с объяснением, почему замечание неприменимо.

07

Оформление

Скрипт читают чаще, чем пишут: вы сами через полгода, коллега ночью во время аварии. Минимальный порядок оформления:

#!/bin/bash
# disk-report — отчёт о занятом месте по файловым системам.
# Запуск: disk-report [ПОРОГ_%]   (по умолчанию 80)
# Код возврата: 0 — всё в норме, 1 — есть заполненные выше порога.

threshold=${1:-80}

df -h --output=pcent,target -x tmpfs -x devtmpfs

Соглашения

  • В шапке — что делает, как запускать, что возвращает.
  • Отступ — 4 пробела; одна команда на строку; длинные строки переносятся через \ в конце.
  • Имена переменных — строчными: threshold, backup_dir. Заглавными — переменные окружения (PATH, HOME), чтобы случайно их не затереть.
  • Комментарий объясняет зачем, а не пересказывает команду.
  • Скрипт хранится в git — тогда видно, кто и когда его менял.
Скрипт, сохранённый в Windows, может иметь окончания строк CRLF. Тогда bash выдаст непонятное /bin/bash^M: bad interpreter или $'\r': команда не найдена. В VS Code переключите окончания на LF (в строке состояния внизу), на сервере исправьте sed -i 's/\r$//' script.sh.

Ключевые выводы модуля

Запомните главное

  • Скрипт — файл с командами; первая строка #!/bin/bash выбирает интерпретатор
  • Запуск: chmod +x и ./script, или bash script; по имени — из каталога в PATH
  • В Debian sh — это dash: конструкции bash в нём не работают
  • Пробелы — часть синтаксиса: a=1 и a = 1 — разные вещи
  • ShellCheck — перед каждым запуском; окончания строк — LF
Практические задания — на учебном портале. Задания, критерии оценивания, сдача работ и оценки преподавателя — в курсе на portal.nevabit.ru. Учётную запись выдаёт преподаватель.
Все модули Модуль 02: Переменные