"А если сервер упадёт?" — Мониторим сам мониторинг
🤔 Проблема: А кто следит за тем, чтобы сами скрипты мониторинга работали?
✅ Решение: Простые проверки:
⚙️ Проверка, что скрипт запущен (Bash):
Логирование работы скрипта:
👁🗨 Внешний "наблюдатель" (например, UptimeRobot):
➜ Бесплатно мониторит доступность сервера и шлёт SMS/email, если он не отвечает.
👉 Теперь ваш мониторинг действительно надёжен!
🌐 @helcode | #bash #мониторинг
🤔 Проблема: А кто следит за тем, чтобы сами скрипты мониторинга работали?
✅ Решение: Простые проверки:
⚙️ Проверка, что скрипт запущен (Bash):
if ! pgrep -f "monitor_script.sh"; then
/path/to/monitor_script.sh &
echo "Скрипт упал и был перезапущен!" | send_to_telegram
fi
Логирование работы скрипта:
*/5 * * * * /path/to/script.sh >> /var/log/monitoring.log 2>&1
👁🗨 Внешний "наблюдатель" (например, UptimeRobot):
➜ Бесплатно мониторит доступность сервера и шлёт SMS/email, если он не отвечает.
👉 Теперь ваш мониторинг действительно надёжен!
🌐 @helcode | #bash #мониторинг
👍1
Автоматизация мониторинга — зачем она нужна?
Пока вы спите, скрипты работают. Вот почему автоматизация мониторинга критически важна:
●︎ Экономия времени — скрипты не устают и не забывают
●︎ Мгновенные алерты — Telegram-бот предупредит о проблеме раньше пользователей
●︎ Самовосстановление — рестарт служб, очистка диска, блокировка атакующих IP
●︎ Нет человеческого фактора — скрипт не пропустит критическую ошибку
Пример:
Три строки — и сервис всегда работает.
🌐 @helcode | #bash #мониторинг
Пока вы спите, скрипты работают. Вот почему автоматизация мониторинга критически важна:
●︎ Экономия времени — скрипты не устают и не забывают
●︎ Мгновенные алерты — Telegram-бот предупредит о проблеме раньше пользователей
●︎ Самовосстановление — рестарт служб, очистка диска, блокировка атакующих IP
●︎ Нет человеческого фактора — скрипт не пропустит критическую ошибку
Пример:
if service nginx status | grep -q "dead"; then
systemctl restart nginx
fi
Три строки — и сервис всегда работает.
🌐 @helcode | #bash #мониторинг
Знакомство с Nmap
Nmap: швейцарский нож для аудита сетей
Обнаружение хостов — находит все активные устройства в сети.
Сканирование портов — показывает, какие "двери" (порты) открыты на устройствах.
Детекция ОС и сервисов — определяет, что это за устройство и какие сервисы на нём работают.
Движок скриптов (NSE) — самая мощная фича! Целый язык на Lua для автоматизации всего: от поиска уязвимостей до попыток взлома.
Категории скриптов:
...и еще десятки!
Самый частый запрос:
🌐 @helcode | #nmap #nse #порты #сканирование
Nmap: швейцарский нож для аудита сетей
Nmap (Network Mapper) — это фундамент, на котором строится сетевая безопасность. Вот что он умеет:Обнаружение хостов — находит все активные устройства в сети.
nmap -sn 192.168.1.0/24Сканирование портов — показывает, какие "двери" (порты) открыты на устройствах.
nmap -sS -p 1-1000 192.168.1.1Детекция ОС и сервисов — определяет, что это за устройство и какие сервисы на нём работают.
nmap -A 192.168.1.1Движок скриптов (NSE) — самая мощная фича! Целый язык на Lua для автоматизации всего: от поиска уязвимостей до попыток взлома.
Категории скриптов:
auth — проверка логинов vuln — поиск известных уязвимостей (CVE) exploit — попытка эксплуатации discovery — исследование сети ...и еще десятки!
Самый частый запрос:
nmap --script=vuln <цель>🌐 @helcode | #nmap #nse #порты #сканирование
👍6
Настраиваем auditd: правила для мониторинга всего
Как следить за важными действиями?
1. Основные команды:
- Просмотр правил:
- Мониторинг файла (например,
2. Постоянные правила (добавляем в
🦾 Применяем:
🌐 @helcode | #bash #auditd
Как следить за важными действиями?
1. Основные команды:
- Просмотр правил:
sudo auditctl -l
- Мониторинг файла (например,
/etc/passwd): sudo auditctl -w /etc/passwd -p wa -k passwd_changes
2. Постоянные правила (добавляем в
/etc/audit/rules.d/audit.rules): # Ловим использование sudo:
-w /usr/bin/sudo -p x -k sudo_usage
# Мониторим удаление файлов:
-a always,exit -F arch=b64 -S unlink -S unlinkat -k file_deletion
🦾 Применяем:
sudo auditctl -R /etc/audit/rules.d/audit.rules
🌐 @helcode | #bash #auditd
👍2
Как на самом деле работает cron? 🤔
Всё расписание хранится в
Примеры:
⏰
⏰
⏰
⏰
Есть и специальные слова для ленивых (как мы все):
❔Вопрос на засыпку: что выполняется чаще:
✅ Ответ:это одно и то же! Ха-ха-ха)))))))))))))))))
🌐 @helcode | #linux #cron #howto
Cron — это не волшебный черный ящик, а демон (crond), который просыпается каждую минуту и проверяет, не пора ли чего запустить.Всё расписание хранится в
crontab-файлах. Синтаксис строки — это 5 полей:минута час день_месяца месяц день_недели командаПримеры:
⏰
0 * * * * — каждый час в 00 минут. ⏰
0 0 * * 0 — каждое воскресенье в полночь. ⏰
*/15 * * * * — каждые 15 минут. ⏰
0 4 1 * * — первое число месяца в 4 утра.Есть и специальные слова для ленивых (как мы все):
@yearly, @monthly, @weekly, @daily, @hourly, @reboot❔Вопрос на засыпку: что выполняется чаще:
@daily или 0 0 * * *? ✅ Ответ:
🌐 @helcode | #linux #cron #howto
👍1
Анализ логов auditd: находим угрозы
1. Утилиты:
- Поиск по метке:
- Отчёт по файлам:
2. Пример лога:
👉 Что было: пользователь с UID=0 запустил
🌐 @helcode | #bash #логи #автоматизация
1. Утилиты:
- Поиск по метке:
sudo ausearch -k sudo_usage
- Отчёт по файлам:
sudo aureport -f
2. Пример лога:
type=SYSCALL msg=audit(...): uid=0 comm="rm" key="file_deletion"
👉 Что было: пользователь с UID=0 запустил
rm.🌐 @helcode | #bash #логи #автоматизация
Твой Python-скрипт вырос и хочет отдельной команды в терминале. Как ему это организовать? ☕️
Мы все начинаем с простого скрипта
Всё, что нужно, — это
1.
2.
3.
Следующий уровень: после этого можно установить скрипт как пакет через
А какой у вас любимый инструмент для создания CLI? 🤔
🌐 @helcode | #python
Мы все начинаем с простого скрипта
super_script.py. Но потом к нему добавляются аргументы, конфиги, логирование... И вот ты уже не запускаешь скрипт, а выполняешь сложный ритуал: python /path/to/script.py --verbose --output /home/user/data.json. Пора дать ему собственное имя и сделать полноценным CLI-инструментом!Всё, что нужно, — это
argparse из коробки Python. Смотрим, как превратить хаос в элегантную команду:# file: data_processor.py
import argparse
def process_data(input_file, output_file, verbose=False):
# Здесь твоя магия обработки данных
if verbose:
print(f"Обрабатываем {input_file} и сохраняем в {output_file}")
return True
if __name__ == "__main__":
# Создаем парсер
parser = argparse.ArgumentParser(description='Крутой инструмент для обработки данных.')
# Добавляем аргументы
parser.add_argument('input', help='Путь до входного файла')
parser.add_argument('-o', '--output', required=True, help='Путь до выходного файла')
parser.add_argument('-v', '--verbose', action='store_true', help='Вербальный режим')
# Парсим аргументы
args = parser.parse_args()
# Передаем в функцию
process_data(args.input, args.output, args.verbose)
1.
ArgumentParser — это наш главный конструктор команд.2.
add_argument определяет, какие флаги и аргументы мы принимаем. required=True для обязательных, action='store_true' для булевых флагов.3.
parse_args() превращает sys.argv в удобный объект с точками (args.input).Следующий уровень: после этого можно установить скрипт как пакет через
pip install -e . (прописав в setup.py) и твоя команда data_processor будет доступна из любой директории!А какой у вас любимый инструмент для создания CLI? 🤔
P.S. Если твой скрипт после этого начнет требовать зарплату в виде GPU — мы не виноваты.
🌐 @helcode | #python
👍2🤔1
Скрипт для автоматического бэкапа MySQL
✋ Ручные бэкапы — это как ходить по канату без страховки. Автоматизируем!
👩🔬 Решение:
🔧 Дополнения:
- Добавьте
- Используйте
Как вы организуете бэкапы? Храните на облаке или локально?
🌐 @helcode | #bash
✋ Ручные бэкапы — это как ходить по канату без страховки. Автоматизируем!
👩🔬 Решение:
#!/bin/bash
BACKUP_DIR="/backups/mysql"
DATE=$(date +%Y%m%d)
mysqldump -u user -p"password" db_name | gzip > "$BACKUP_DIR/db_name_$DATE.sql.gz"
# Проверяем успешность и шлём алерт
if [ $? -eq 0 ]; then
echo "Backup OK" | sendmail admin@example.com
else
echo "Backup FAILED!" | sendmail admin@example.com
fi
🔧 Дополнения:
- Добавьте
find $BACKUP_DIR -type f -mtime +30 -delete для удаления старых бэкапов. - Используйте
cron для запуска по расписанию. Как вы организуете бэкапы? Храните на облаке или локально?
🌐 @helcode | #bash
👍1
Почему && лучше, чем ;?
🛠 Пример:
❓Где ещё полезно:
-
-
Какие ещё операторы в Bash вы часто используете?
🌐 @helcode | #bash
command1; command2 выполнит обе команды, даже если первая упала. && — только если первая успешна. 🛠 Пример:
cd /nonexistent_dir && rm -rf * # Удаление не сработает (и это хорошо!)
❓Где ещё полезно:
-
make && make test — не запускать тесты, если сборка провалилась. -
git pull && npm install — не ставить зависимости, если обновление репы не удалось. Какие ещё операторы в Bash вы часто используете?
Использовать ; вместо && — это как прыгать с парашютом, не проверив, есть ли он за спиной.
🌐 @helcode | #bash
Как заставить старый скрипт работать в 10 раз быстрее
😴 Ваш скрипт работает так медленно, что пока он выполняется, можно выучить новый язык?
👁🗨 Мы все их видели: скрипты, написанные на коленке, которые со временем стали критически важными. Они работают, но отжирают уйму времени и ресурсов. Часто проблема не в сложности задачи, а в неоптимальных подходах.
👉Взгляните на этот кусок кода. Часто проблема в циклах внутри циклов, где можно применить списковые включения или функции из
Было (медленно):
Стало (быстро):
Списковые включения в Python оптимизированы на уровне C и работают значительно быстрее классических
А вы как ускоряли своих "динозавров"? Поделитесь самым крутым оптимизационным хаком в комментариях!
🌐 @helcode | #python
😴 Ваш скрипт работает так медленно, что пока он выполняется, можно выучить новый язык?
👁🗨 Мы все их видели: скрипты, написанные на коленке, которые со временем стали критически важными. Они работают, но отжирают уйму времени и ресурсов. Часто проблема не в сложности задачи, а в неоптимальных подходах.
👉Взгляните на этот кусок кода. Часто проблема в циклах внутри циклов, где можно применить списковые включения или функции из
itertools.Было (медленно):
results = []
for item in huge_list:
if some_condition(item):
for subitem in item.subitems:
if another_condition(subitem):
results.append(process(subitem))
Стало (быстро):
results = [process(subitem) for item in huge_list if some_condition(item) for subitem in item.subitems if another_condition(subitem)]
# Или еще лучше: использовать генератор для экономии памяти!
results_gen = (process(subitem) for item in huge_list ... )
Списковые включения в Python оптимизированы на уровне C и работают значительно быстрее классических
for`-циклов с .append()`. А использование генераторов (`()`) вместо списков (`[]`) позволяет не загружать все данные в память сразу, что еще ускоряет работу с большими объемами данных.А вы как ускоряли своих "динозавров"? Поделитесь самым крутым оптимизационным хаком в комментариях!
Это как в «Форсаже»: иногда не нужен новый двигатель, а нужно просто правильно настроить карбюратор и сбросить лишний вес.
🌐 @helcode | #python
👍3
Или проголосуйте: что тормозит ваши скрипты чаще всего?
Anonymous Poll
47%
Ввод/вывод (чтение файлов, сетевые запросы)
13%
Нативные Python-циклы
33%
Алгоритмическая сложность (O(n^2) и хуже)
20%
Все сразу
Как автоматически генерировать сложные пароли для всей команды
Ваш пароль "qwerty123" прекрасен... если вы хотите подарить хакеру новый автомобиль. Давайте генерировать лучше!
Слабые пароли - главная дыра в безопасности. А придумывать и хранить десятки сложных паролей для разных сервисов не может даже человек с памятью как у Шерлока. Доверьте это машине.
Однострочник на Python в помощь всей команде:
Мы используем модуль
А как вы управляете паролями в своей команде?
🌐 @helcode | #python
Ваш пароль "qwerty123" прекрасен... если вы хотите подарить хакеру новый автомобиль. Давайте генерировать лучше!
Слабые пароли - главная дыра в безопасности. А придумывать и хранить десятки сложных паролей для разных сервисов не может даже человек с памятью как у Шерлока. Доверьте это машине.
Однострочник на Python в помощь всей команде:
import secrets
import string
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
password = ''.join(secrets.choice(alphabet) for i in range(16))
print(password) # Пример: 'xT5&!k8@qL9#vR2$'
Мы используем модуль
secrets, который криптографически безопасен (в отличие от random). string.ascii_letters + string.digits - это наш алфавит (буквы и цифры). Добавляем спецсимволы для сложности. Длина 16 символов - отличный старт.А как вы управляете паролями в своей команде?
🌐 @helcode | #python
👍2
Автоматизируйте свои чат-боты: хватит отвечать на одни и те же вопросы!
Ваша команда снова спрашивает, «каой пароль от тестовой БД?».
🤖Пора научить бота делать вашу работу за вас.
В любой команде есть рутинные вопросы, которые отвлекают от работы. «Где документация?», «Как запустить проект?», «Кто дежурный?». Вместо того чтобы в сотый раз копировать один и тот же ответ, можно написать простого бота для Telegram или Slack.
Вот пример на Python с библиотекой
Мы используем
Какой самый частый и раздражающий вопрос вы получаете в чате?
🌐 @helcode | #python
Ваша команда снова спрашивает, «каой пароль от тестовой БД?».
🤖Пора научить бота делать вашу работу за вас.
В любой команде есть рутинные вопросы, которые отвлекают от работы. «Где документация?», «Как запустить проект?», «Кто дежурный?». Вместо того чтобы в сотый раз копировать один и тот же ответ, можно написать простого бота для Telegram или Slack.
Вот пример на Python с библиотекой
python-telegram-bot для обработки частого вопроса.from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
# Бот отвечает на сообщение с ключевым словом
await update.message.reply_text(
"Коллега, привет! Вот частые ответы:\n"
"• Пароль от БД: 'supersecret'\n"
"• Документация: https://wiki.our-company.com/\n"
"• Как запустить: см. файл README.md в корне проекта"
)
if __name__ == '__main__':
app = Application.builder().token("YOUR_TOKEN").build()г
app.add_handler(MessageHandler(filters.TEXT & filters.Regex(r'(?i)(пароль|документация|как запустить)'), help_command))
app.run_polling()
Мы используем
MessageHandler с фильтром filters.Regex(). Он ловит любое текстовое сообщение, в котором есть слова «пароль», «документация» или «как запустить» (регистр неважен благодаря `(?i)`), и автоматически отвечает заготовленным текстом.Какой самый частый и раздражающий вопрос вы получаете в чате?
Это как поставить на частый вопрос автоответчик «я в отпуске», только Вы не в отпуске, а просто пьете кофе, пока бот работает.
🌐 @helcode | #python
👍2
Хватит хардкодить пароли в скриптах! Где и как хранить секреты
API-токены, пароли от БД, ключи шифрования. Они не должны лежать в открытом виде в коде, который вы заливаете на GitHub. Но как тогда скрипт получит к ним доступ? Решение есть.
Используем переменные окружения и файлы.
Способ 1: переменные окружения (просто и достаточно для многих случаев)
Задаем переменную в сессии или в файле
И используем в Python-скрипте:
Способ 2: Файлы с секретами (более безопасно)
Создаем файл, который не будет попадать в git:
Читаем его в коде с помощью библиотеки
Немного теории:
- Переменные окружения — это изолированное пространство памяти процесса. Их не видно в списке запущенных процессов (в отличие от аргументов командной строки).
-
Где вы храните свои секреты?
Признавайтесь, мы не осудим
🌐 @helcode | #bash #python
password = "12345" в коде — это как оставить ключи от квартиры в двери. API-токены, пароли от БД, ключи шифрования. Они не должны лежать в открытом виде в коде, который вы заливаете на GitHub. Но как тогда скрипт получит к ним доступ? Решение есть.
Используем переменные окружения и файлы.
Способ 1: переменные окружения (просто и достаточно для многих случаев)
Задаем переменную в сессии или в файле
~/.bashrc / ~/.zshrc:export DB_PASSWORD="my_super_secret_password_123"
И используем в Python-скрипте:
import os
db_pass = os.environ.get('DB_PASSWORD')
if not db_pass:
raise ValueError("Не задан пароль от БД!")
Способ 2: Файлы с секретами (более безопасно)
Создаем файл, который не будет попадать в git:
# .env file (добавляем в .gitignore!)
DB_HOST=localhost
DB_USER=admin
DB_PASSWORD=secret
Читаем его в коде с помощью библиотеки
python-dotenv:
pip install python-dotenv
from dotenv import load_dotenv
load_dotenv() # Загружает переменные из файла .env в os.environ
db_pass = os.getenv('DB_PASSWORD')
Немного теории:
- Переменные окружения — это изолированное пространство памяти процесса. Их не видно в списке запущенных процессов (в отличие от аргументов командной строки).
-
.env файлы — это удобный способ локальной разработки. На продакшене (сервере) эти же переменные задаются через конфигурацию systemd, Docker или панели управления хостингом.Где вы храните свои секреты?
Признавайтесь, мы не осудим
Хардкодить пароль в коде — это как написать пин-код от карты на ней же шариковой ручкой. Удобно, но недальновидно.
🌐 @helcode | #bash #python
👍3🤣1
Автоматическое создание алиасов для часто ошибающихся команд
Наша память избирательна, особенно в 3 часа ночи, когда деплой горит. Постоянно печатать
Просто добавьте эти строки в ваш
Алиасы — это пользовательские сокращения или замены для длинных команд. Shell просто подставляет нужную строку вместо короткого алиаса. Это самый простой способ сэкономить нервы и количество нажатий на клавиатуру.
Какой ваш самый частый ляп в консоли?
🌐 @helcode | #bash
git comit? git pusht? Пора остановить это безумие! Наша память избирательна, особенно в 3 часа ночи, когда деплой горит. Постоянно печатать
git stauts вместо git status - это не про вас, это про всех. Зачем мучиться, если можно научить shell подстраховываться?Просто добавьте эти строки в ваш
~/.bashrc или ~/.zshrc:# Исправляем опечатки в git
alias git='() { if [[ $1 == "comit" ]]; then shift; command git commit "$@"; elif [[ $1 == "pusht" ]]; then shift; command git push "$@"; else command git "$@"; fi; }'
# Или универсальный солдат для частых опечаток:
alias comit='git commit'
alias pusht='git push'
alias gs='git status' # для ленивых, пользуюсь
Алиасы — это пользовательские сокращения или замены для длинных команд. Shell просто подставляет нужную строку вместо короткого алиаса. Это самый простой способ сэкономить нервы и количество нажатий на клавиатуру.
Какой ваш самый частый ляп в консоли?
Это как завести личного ассистента, который поправляет вас, когда вы говорите «симпОтичный». Но только для терминала. И без обид.
🌐 @helcode | #bash
👍1
Как парсить PDF без специализированных библиотек
Парсить PDF на чистом Python — это как есть суп вилкой. Но иногда это бывает нужно...
Многие простые PDF можно "выстрелить" стандартными утилитами и регулярками.
PDF — это сложный формат, но часто текст внутри него хранится в открытом виде. Утилита
🌐 @helcode | #bash
Парсить PDF на чистом Python — это как есть суп вилкой. Но иногда это бывает нужно...
PyPDF2, pdfminer, tabula — все это круто, пока Вам нельзя ставить лишние зависимости в проект или пока вам нужен лишь клочок текста из простого PDF. Иногда задача настолько мала, что тащить за собой библиотеку — это overkill.Многие простые PDF можно "выстрелить" стандартными утилитами и регулярками.
# Используем pdftotext (из пакета poppler-utils)
pdftotext my_document.pdf - | grep -i "искомый текст"
# На Python, читаем PDF как бинарник и ищем строку
import re
with open('file.pdf', 'rb') as f:
pdf_content = f.read()
# Ищем что-то похожее на текст (опасно, но для простых случаев работает)
text_match = re.search(b'(Hello World)', pdf_content)
if text_match:
print(text_match.group(1).decode('utf-8'))
PDF — это сложный формат, но часто текст внутри него хранится в открытом виде. Утилита
pdftotext пытается его извлечь, а дальше мы можем работать с текстом как обычно. Внимание: это хак, а не решение для сложных PDF с таблицами и картинками!Предупреждаю, этот метод такой же надежный, как построить мост из спагетти. Но для быстрого прототипа или личных задач — вполне пригоден!
🌐 @helcode | #bash
👍2🤔2
Ваши скрипты умеют принимать правильные решения? (Просто о условных операторах)
Любой скрипт, который делает что-то полезное, рано или поздно должен уметь выбирать. «Если сервер не ответил, попробовать еще раз», «Если файл большой, сжать его перед отправкой». Без условий код — просто линейный набор команд, как рецепт для робота.
Смотрите, как оживает ваш код с условиями.
Было (скрипт-зомби):
Стало (скрипт-интеллектуал):
Код возврата любой команды (
А вы проверяете успешность команд в своих скриптах?
🌐 @helcode | #bash
if, else, elif... Это не заклинание, это ваши спиннеры для кода! 🧙♂️Любой скрипт, который делает что-то полезное, рано или поздно должен уметь выбирать. «Если сервер не ответил, попробовать еще раз», «Если файл большой, сжать его перед отправкой». Без условий код — просто линейный набор команд, как рецепт для робота.
Смотрите, как оживает ваш код с условиями.
Было (скрипт-зомби):
#!/bin/bash
echo "Начинаем деплой..."
curl http://my-server.com/deploy
echo "Готово." # Всегда "Готово", даже если сервер сгорел
Стало (скрипт-интеллектуал):
#!/bin/bash
echo "Начинаем деплой..."
if curl -f http://my-server.com/deploy; then
echo "✅ Деплой успешен!"
else
echo "❌ Ошибка деплоя! Сервер не ответил."
exit 1
fi
Код возврата любой команды (
0 — успех, не 0 — ошибка) — это ключ к принятию решений. Конструкция if [ условие ]; then... проверяет этот код. Флаг -f у curl как раз заставляет его возвращать ненулевой код при HTTP-ошибке (404, 500 и т.д.).А вы проверяете успешность команд в своих скриптах?
Писать скрипты без условий — это как играть в шахматы, всегда ходя только пешкой на одну клетку. Можно, но зачем?
🌐 @helcode | #bash
👍4
Тайминги и блокировки: как избежать «снежного кома» в cron
🤔 Представьте: задача в
Это классическая проблема наложения задач.
Решения:
1.
2.
Ключ
🌐 @helcode | #linux #cron #automation #performance
🤔 Представьте: задача в
cron -е запускается каждые 5 минут, но иногда выполняется 10. Что будет? Через час у вас будет 12 параллельных процессов, грузящих систему!Это классическая проблема наложения задач.
Решения:
1.
timeout: жестко ограничить время выполнения. * * * * * timeout 300 /path/to/script.sh # Остановить через 5 минут2.
flock: поставить блокировку на файл, чтобы скрипт не запускался, если предыдущий экземпляр еще работает. * * * * * /usr/bin/flock -n /tmp/myscript.lock /path/to/script.shКлюч
-n означает «не ждать». Если скрипт уже работает — новый запуск просто проигнорируется. Идеально для защиты от дублирования!🌐 @helcode | #linux #cron #automation #performance
❤3👎1🤔1
requirements.txt звонит из 2010-го и просит вернуть его. Чем заменить?
Все мы знаем и... немного ненавидим этот файл.
Встречаем
👀 Вот как это выглядит:
*
*
*
Но это еще не всё! Для полного счастья используйте
А что используете вы для управления зависимостями? 🗳
1. Старая гвардия
2.
3.
4. Anaconda (для data science)
5. Свой метод? Делитесь в комментах!
🌐 @helcode | #toml
Все мы знаем и... немного ненавидим этот файл.
requests==2.28.1, pandas~=1.5.0, aiohttp. А потом — «ой, а почему у меня не запускается?». Ручное управление версиями, хаос в зависимостях, вечные конфликты. Это как собирать мебель без инструкции, надеясь, что все винтики подойдут.Встречаем
pyproject.toml — новый стандарт, который заменил всё. Это единый файл конфигурации для сборки, зависимостей и метаданных вашего проекта. Больше никаких setup.py, requirements.txt, setup.cfg и MANIFEST.in!👀 Вот как это выглядит:
# pyproject.toml
[build-system]
requires = ["setuptools>=61.0.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "my_awesome_tool"
version = "0.1.0"
dependencies = [
"requests>=2.28.1",
"pandas~=1.5.0", # Совместимость с версиями 1.5.0+
"aiohttp"
]
[project.optional-dependencies]
dev = ["pytest", "black", "flake8"] # Зависимости для разработки!
*
[build-system]: Говорит pip, как собирать ваш пакет.*
[project]: Основные метаданные и обязательные зависимости.*
[project.optional-dependencies]: Группы зависимостей (например, для тестов, линтинга, docs). Установить их можно так: pip install .[dev]Но это еще не всё! Для полного счастья используйте
poetry или pdm — они не только управляют зависимостями, но и создают виртуальное окружение и блокируют версии в poetry.lock/pdm.lock, гарантируя идентичные окружения у всех разработчиков. Это уровень «профи».А что используете вы для управления зависимостями? 🗳
1. Старая гвардия
requirements.txt (работает и ладно!)2.
pyproject.toml + pip (современно и по стандарту)3.
poetry / pdm (магия и комфорт)4. Anaconda (для data science)
5. Свой метод? Делитесь в комментах!
P.S. Если ваш requirements.txt сейчас плачет в углу — не говорите, что это мы вас надоумили. Просто дайте ему почитать pyproject.toml, пусть постыдится.
🌐 @helcode | #toml
multiprocessing или threading? Вопрос на миллион потоков... и процессов!
Ваш скрипт тормозит и вы хотите распараллелить все на свете.
🤔 Но что выбрать? Потоки? Процессы?
Ответ кроется в трех буквах — GIL (Global Interpreter Lock).
☕️ Это такой злой бариста в кофейне Python, который не дает нескольким потокам одновременно молоть зёрна (выполнять Python-код). Но у каждого процесса своя кофейня (и свой GIL)!
Код-пример (CPU-bound):
Код-пример (I/O-bound):
Выбор зависит от типа задачи. Не используйте потоки для вычислений — вы не получите прироста, а только накладные расходы. Не используйте процессы для простых HTTP-запросов — вы создадите слишком много тяжелых процессов.
А вы чаще сталкиваетесь с I/O или CPU-bound задачами? И какой ваш любимый способ паралеллить?
🌐 @helcode | #python
Ваш скрипт тормозит и вы хотите распараллелить все на свете.
🤔 Но что выбрать? Потоки? Процессы?
Ответ кроется в трех буквах — GIL (Global Interpreter Lock).
☕️ Это такой злой бариста в кофейне Python, который не дает нескольким потокам одновременно молоть зёрна (выполнять Python-код). Но у каждого процесса своя кофейня (и свой GIL)!
Код-пример (CPU-bound):
# Много вычислений -> multiprocessing
import multiprocessing
import math
def calculate_factorial(n):
return math.factorial(n)
if __name__ == '__main__':
numbers = [100000, 200000, 300000] * 5 # Тяжелая работа
with multiprocessing.Pool() as pool:
results = pool.map(calculate_factorial, numbers) # 🚀 Запуск на всех ядрах!
Код-пример (I/O-bound):
# Много ожидания -> threading
import threading
import requests
def check_site(url):
response = requests.get(url)
return response.status_code
urls = ['https://google.com', 'https://yandex.ru', ...] * 10
threads = []
for url in urls:
thread = threading.Thread(target=check_site, args=(url,))
thread.start()
threads.append(thread)
for thread in threads:
thread.join() # 🧵 Ждем все потоки
Выбор зависит от типа задачи. Не используйте потоки для вычислений — вы не получите прироста, а только накладные расходы. Не используйте процессы для простых HTTP-запросов — вы создадите слишком много тяжелых процессов.
А вы чаще сталкиваетесь с I/O или CPU-bound задачами? И какой ваш любимый способ паралеллить?
P.S. GIL — это не баг, это фича, которая не дает твоему коду сломать интерпретатор. Но иногда так хочется его пристрелить... (шучу, не шучу).
🌐 @helcode | #python