Bash — автоматизация в терминале¶
Bash — оболочка Linux, в которой живёт инфраструктура дата-инженера: Docker, Airflow, cron, серверы. Умение работать в терминале — не опция, а базовый навык. В этой статье — команды и приёмы, которые ты используешь каждый день.
Навигация и файлы¶
# Где я?
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.
# Найти процессы 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
Перенаправления¶
# Записать вывод в файл (перезаписать)
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 — поиск по содержимому¶
# Найти строку в файле
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 — поиск файлов¶
# Все .sql файлы
find . -name "*.sql"
# Файлы больше 100 МБ
find /data -size +100M
# Файлы изменённые за последний час
find . -mmin -60 -name "*.py"
# Найти и удалить __pycache__
find . -type d -name "__pycache__" -exec rm -rf {} +
awk — обработка колонок¶
# Вывести 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 и конфигами.
# Красивый вывод
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'
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-скрипты¶
Базовая структура¶
#!/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."
Переменные и условия¶
#!/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}..."
Циклы¶
#!/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 — ошибка в пайпе не маскируется.
Переменные окружения¶
# Установить переменную
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 — расписание задач¶
# Открыть 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¶
# Размер директорий
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 |
Проверь себя¶
Источники¶
- GNU Bash Manual — полная документация Bash
- jq Manual — справка по jq
- The Art of Command Line — подборка полезных приёмов