Перейти к содержанию

Bash — автоматизация в терминале

Bash — оболочка Linux, в которой живёт инфраструктура дата-инженера: Docker, Airflow, cron, серверы. Умение работать в терминале — не опция, а базовый навык. В этой статье — команды и приёмы, которые ты используешь каждый день.


Навигация и файлы

Bash
# Где я?
pwd

# Список файлов (подробный, с размерами)
ls -lah

# Перейти в директорию
cd /srv/repos/etl-project

# Создать вложенные директории
mkdir -p data/raw/2025

# Копировать, переместить, удалить
cp config.yml config.yml.bak
mv old_name.py new_name.py
rm -rf __pycache__/

rm -rf — без подтверждения

rm -rf удаляет без вопросов и без корзины. Перед выполнением убедись, что путь правильный. Хорошая практика: сначала ls путь, потом rm.


Пайпы и перенаправления

Пайп (|) передаёт вывод одной команды на вход другой. Это основа работы в Bash.

Bash
# Найти процессы Airflow
ps aux | grep airflow

# Посчитать строки в CSV
wc -l sales.csv

# Первые 5 строк файла
head -5 sales.csv

# Последние строки лога в реальном времени
tail -f /var/log/airflow/scheduler.log

# Сортировка и уникальные значения
cut -d',' -f3 sales.csv | sort | uniq -c | sort -rn | head -10

Перенаправления

Bash
# Записать вывод в файл (перезаписать)
echo "SELECT 1;" > query.sql

# Дописать в конец
echo "SELECT 2;" >> query.sql

# Ошибки в отдельный файл
python etl.py 2> errors.log

# Всё (stdout + stderr) в один файл
python etl.py > output.log 2>&1

Поиск: grep, find, awk

grep — поиск по содержимому

Bash
# Найти строку в файле
grep "ERROR" /var/log/airflow/scheduler.log

# Рекурсивно по всем .py файлам
grep -rn "def extract" dags/

# Без учёта регистра
grep -i "select" models/staging/*.sql

# Инвертировать (всё КРОМЕ)
grep -v "DEBUG" app.log

find — поиск файлов

Bash
# Все .sql файлы
find . -name "*.sql"

# Файлы больше 100 МБ
find /data -size +100M

# Файлы изменённые за последний час
find . -mmin -60 -name "*.py"

# Найти и удалить __pycache__
find . -type d -name "__pycache__" -exec rm -rf {} +

awk — обработка колонок

Bash
# Вывести 1-ю и 3-ю колонку CSV
awk -F',' '{print $1, $3}' sales.csv

# Сумма значений в 4-й колонке
awk -F',' '{sum += $4} END {print sum}' sales.csv

# Фильтр строк по условию
awk -F',' '$4 > 1000 {print $0}' sales.csv

jq — работа с JSON

jq — незаменимый инструмент для работы с JSON-ответами API и конфигами.

Bash
# Красивый вывод
cat config.json | jq .

# Извлечь поле
curl -s https://dummyjson.com/products/1 | jq '.title'

# Массив → список значений
curl -s https://dummyjson.com/products?limit=3 | jq '.products[].title'

# Фильтр по условию
cat products.json | jq '.products[] | select(.price > 50) | {title, price}'

# Собрать CSV из JSON
curl -s https://dummyjson.com/products?limit=5 | \
  jq -r '.products[] | [.id, .title, .price] | @csv'
Text Only
1,"Essence Mascara Lash Princess",9.99
2,"Eyeshadow Palette",19.99
3,"Powder Canister",14.99
4,"Red Lipstick",12.99
5,"Red Nail Polish",8.99

jq — must-have для DE

Установка: sudo apt install jq. Используй для отладки API-ответов, разбора конфигов Airflow, фильтрации логов в JSON-формате.


Bash-скрипты

Базовая структура

backup_db.sh
#!/bin/bash
set -euo pipefail  # останов при ошибке, неинициализированных переменных

DB_NAME="${1:-etl_kitchen}"  # аргумент или default
BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d_%H%M%S)
FILENAME="${BACKUP_DIR}/${DB_NAME}_${DATE}.sql.gz"

echo "Backing up ${DB_NAME}..."
pg_dump -U etl_user "${DB_NAME}" | gzip > "${FILENAME}"
echo "Done: ${FILENAME}"

# Удалить бэкапы старше 7 дней
find "${BACKUP_DIR}" -name "*.sql.gz" -mtime +7 -delete
echo "Old backups cleaned."
Bash
chmod +x backup_db.sh
./backup_db.sh etl_kitchen

Переменные и условия

Bash
#!/bin/bash

ENV="${ENV:-dev}"  # переменная окружения или default

if [ "$ENV" = "prod" ]; then
    echo "Production mode"
    DB_HOST="prod-db.internal"
else
    echo "Development mode"
    DB_HOST="localhost"
fi

echo "Connecting to ${DB_HOST}..."

Циклы

Bash
#!/bin/bash

# Обработать все CSV в директории
for file in data/raw/*.csv; do
    echo "Processing: ${file}"
    python transform.py --input "${file}" --output "data/processed/$(basename "${file}")"
done

set -euo pipefail

Всегда добавляй в начало скрипта. -e — стоп при ошибке, -u — ошибка при неинициализированной переменной, -o pipefail — ошибка в пайпе не маскируется.


Переменные окружения

Bash
# Установить переменную
export DATABASE_URL="postgresql://user:pass@localhost:5432/mydb"

# Использовать
echo $DATABASE_URL

# Загрузить из .env файла
set -a
source .env
set +a

# Проверить, что переменная задана
if [ -z "${API_KEY:-}" ]; then
    echo "ERROR: API_KEY not set"
    exit 1
fi

cron — расписание задач

Bash
# Открыть crontab
crontab -e

# Формат: минуты часы день месяц день_недели команда
# Бэкап каждый день в 3:00
0 3 * * * /home/ruslan/backup_db.sh >> /var/log/backup.log 2>&1

# ETL каждый час
0 * * * * cd /srv/repos/etl-project && /usr/bin/python3 etl.py >> /var/log/etl.log 2>&1

# Каждые 5 минут
*/5 * * * * /usr/bin/curl -s http://localhost:8080/health > /dev/null

cron vs Airflow

cron — для простых задач (бэкап, мониторинг). Airflow — для сложных пайплайнов с зависимостями, retry и мониторингом. Не запускай ETL через cron, если есть Airflow.


Полезные однострочники для DE

Bash
# Размер директорий
du -sh data/*

# Свободное место на диске
df -h

# Мониторинг процесса
watch -n 5 'docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"'

# Убить зависший процесс
kill -9 $(pgrep -f "python etl.py")

# Скачать файл
wget -O data.csv https://example.com/data.csv
curl -o data.csv https://example.com/data.csv

# Сравнить два файла
diff old_config.yml new_config.yml

Что запомнить

Тема Ключевая мысль
Пайпы cmd1 \| cmd2 \| cmd3 — цепочка обработки
grep Поиск по содержимому: grep -rn "pattern" dir/
jq Парсинг JSON: jq '.field'
Скрипты Всегда set -euo pipefail в начале
cron Простые задачи; для ETL используй Airflow

Проверь себя


Источники