Python для SSH-администрирования: автоматизация управления серверами

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Python-разработчики, интересующиеся автоматизацией процессов управления серверами
  • DevOps-инженеры, стремящиеся улучшить свою эффективность с помощью скриптов на Python
  • Системные администраторы, ищущие инструменты для автоматизации рутинных задач с SSH

    Python и SSH — незаменимый тандем для каждого разработчика, нуждающегося в автоматизации управления удаленными серверами. Если вам надоело вручную выполнять однотипные команды или вы хотите создать скрипт для массового обновления десятков серверов — Python предлагает впечатляющий арсенал инструментов. От низкоуровневого Paramiko до элегантного Fabric — эти библиотеки превращают SSH-взаимодействие из утомительной рутины в хорошо организованный код. Готовы превратить свои SSH-скрипты в настоящее произведение искусства? 🚀

Стремитесь к совершенству в Python и автоматизации? Обучение Python-разработке от Skypro — ваш путь к мастерству в SSH-автоматизации. Вы не просто изучите базовый синтаксис, а погрузиться в реальные задачи DevOps с профессиональными наставниками. Наши выпускники создают сложные системы управления инфраструктурой и автоматизируют рутину там, где другие тратят часы на ручную работу. Станьте Python-мастером, а не просто пользователем.

Основные библиотеки Python для SSH-подключений

Python предлагает несколько мощных библиотек для работы с SSH, каждая из которых имеет свои особенности и применения. Выбор правильного инструмента может значительно упростить ваш рабочий процесс и повысить эффективность автоматизации.

Рассмотрим наиболее популярные библиотеки и их особенности:

Библиотека Уровень абстракции Основные возможности Оптимальное применение
Paramiko Низкий SSH-соединения, SFTP, аутентификация по ключу, туннелирование Сложные сценарии, требующие полного контроля
Fabric Высокий Выполнение команд, развертывание приложений, параллельное выполнение DevOps, массовое администрирование
pysftp Средний Упрощенное управление файлами через SFTP Операции с файлами, резервное копирование
Invoke Высокий Локальное выполнение команд, интеграция с Fabric Гибридные сценарии (локальное+удаленное)
Netmiko Средний Специализированные функции для сетевого оборудования Управление сетевыми устройствами

Paramiko — это фундаментальная библиотека, на которой построены многие высокоуровневые решения. Она предоставляет наиболее гибкий контроль над SSH-соединениями, но требует больше кода для реализации даже простых задач.

Fabric — оптимальный выбор для большинства задач автоматизации. Он упрощает синтаксис и позволяет выполнять команды на множестве серверов с минимальным кодом. Fabric 2.x построен на основе Paramiko и Invoke, что делает его мощным и гибким инструментом.

Для тех, кто работает преимущественно с файлами, pysftp предлагает понятный API, напоминающий стандартные операции с файловой системой Python, но через безопасный SFTP-протокол.

Александр Петров, DevOps-инженер

Когда я присоединился к проекту с инфраструктурой из 50+ серверов, их обслуживание занимало целый день у двух инженеров. Мы использовали обычные bash-скрипты и вручную подключались к каждому серверу для обновлений. Это был кошмар.

Я решил применить Python с Fabric. Первый скрипт, который я написал, обновлял пакеты на всех серверах параллельно:

Python
Скопировать код
from fabric import Connection, ThreadingGroup

servers = ['server1.example.com', 'server2.example.com', ...]
group = ThreadingGroup(*servers, user='admin')

results = group.run('sudo apt update && sudo apt upgrade -y')
for conn, result in results.items():
print(f"{conn.host}: {result.stdout.strip()}")

Задача, которая раньше занимала часы, теперь выполнялась за 15 минут без нашего участия. Через месяц у нас была библиотека из 20+ скриптов для разных задач — от мониторинга диска до развертывания. Время, затрачиваемое на рутину, сократилось на 70%.

При выборе библиотеки необходимо учитывать масштаб задачи и требуемую гибкость. Для разовых скриптов может быть достаточно простого решения на Fabric, а для сложных систем автоматизации целесообразно использовать комбинацию библиотек или строить собственные абстракции на основе Paramiko.

Пошаговый план для смены профессии

Настройка и управление SSH-соединениями через Paramiko

Paramiko — это фундаментальная библиотека для работы с SSH в Python, предоставляющая низкоуровневый доступ к SSH-протоколу. Несмотря на более сложный синтаксис по сравнению с высокоуровневыми библиотеками, Paramiko предлагает максимальную гибкость и контроль.

Для начала работы с Paramiko необходимо установить библиотеку:

Bash
Скопировать код
pip install paramiko

Базовое подключение к серверу и выполнение команды выглядит следующим образом:

Python
Скопировать код
import paramiko

# Создание клиента SSH
client = paramiko.SSHClient()

# Настройка автоматического добавления неизвестных хостов в known_hosts
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# Подключение к серверу
client.connect(hostname='server.example.com',
port=22,
username='username',
password='password')

# Выполнение команды
stdin, stdout, stderr = client.exec_command('ls -la')

# Получение результата
output = stdout.read().decode()
print(output)

# Закрытие соединения
client.close()

Аутентификация в Paramiko возможна несколькими способами. Вот основные методы с их особенностями:

  • Аутентификация по паролю — простой, но менее безопасный метод
  • Аутентификация по ключу — рекомендуемый подход для скриптов автоматизации
  • Аутентификация через агент SSH — удобно для интерактивных сценариев
  • Многофакторная аутентификация — для систем с повышенными требованиями безопасности

Пример подключения с использованием ключа:

Python
Скопировать код
import paramiko

key = paramiko.RSAKey.from_private_key_file('/path/to/private_key')

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

client.connect(
hostname='server.example.com',
username='username',
pkey=key
)

# Остальной код аналогичен предыдущему примеру

Paramiko также поддерживает работу с сессиями и каналами, что позволяет реализовать более сложную логику взаимодействия:

Python
Скопировать код
# Создание интерактивной сессии
transport = client.get_transport()
channel = transport.open_session()
channel.get_pty()
channel.invoke_shell()

# Отправка команд в интерактивную сессию
channel.send('sudo -s\n')
time.sleep(1)
channel.send('password\n')
time.sleep(1)

# Получение вывода
output = channel.recv(4096).decode()
print(output)

Для обработки ошибок и обеспечения надежности скриптов следует использовать обработку исключений:

Python
Скопировать код
try:
client.connect(hostname='server.example.com', username='username', password='password')
# Код выполнения команд
except paramiko.AuthenticationException:
print("Ошибка аутентификации")
except paramiko.SSHException as e:
print(f"Ошибка SSH: {e}")
except Exception as e:
print(f"Произошла ошибка: {e}")
finally:
client.close()

Продвинутые возможности Paramiko включают SSH-туннелирование, проброс портов и многое другое. Например, создание SSH-туннеля для доступа к удаленной базе данных:

Python
Скопировать код
# Настройка проброса портов (localhost:8080 -> remote_server:80)
transport = client.get_transport()
transport.request_port_forward('', 8080, 'remote_server', 80)

# Теперь можно подключаться к localhost:8080, и трафик будет 
# перенаправлен на remote_server:80 через SSH-туннель

Paramiko отлично подходит для сложных сценариев, где требуется тонкая настройка соединений или нестандартное взаимодействие с SSH-сервером. При этом для более простых задач автоматизации существуют высокоуровневые библиотеки, которые мы рассмотрим далее. 🔐

Автоматизация SSH-задач с помощью Fabric и Invoke

Fabric — высокоуровневая библиотека для автоматизации задач через SSH, которая значительно упрощает управление удаленными серверами. В версии 2.0+ Fabric тесно интегрирован с Invoke — инструментом для локального выполнения команд, что позволяет создавать гибридные сценарии автоматизации.

Установка обеих библиотек выполняется через pip:

Bash
Скопировать код
pip install fabric invoke

Основное преимущество Fabric над Paramiko — лаконичный синтаксис и высокий уровень абстракции. Сравните выполнение одной и той же задачи:

Библиотека Код для выполнения команды Строк кода
Paramiko
```python client = paramiko.SSHClient() <br> client.setmissinghostkeypolicy(paramiko.AutoAddPolicy()) <br> client.connect(hostname='server', username='user', password='pass') <br> stdin, stdout, stderr = client.exec_command('uptime') <br> print(stdout.read().decode()) <br> client.close()
``` 6
Fabric
```python conn = Connection('user@server', connect_kwargs={"password": "pass"}) <br> result = conn.run('uptime') <br> print(result.stdout)
``` 3

Простой пример использования Fabric для выполнения команды на удаленном сервере:

Python
Скопировать код
from fabric import Connection

# Создание соединения
conn = Connection('username@server.example.com')

# Выполнение команды
result = conn.run('hostname')
print(f"Hostname: {result.stdout.strip()}")

# Выполнение команды с sudo
result = conn.sudo('apt update', hide=True)
if result.ok:
print("Система успешно обновлена")

Одно из главных преимуществ Fabric — возможность работы с группами серверов. Это особенно полезно для сценариев массового обновления или конфигурирования:

Python
Скопировать код
from fabric import SerialGroup, ThreadingGroup

# Последовательное выполнение на нескольких серверах
servers = SerialGroup('web1', 'web2', 'web3')
results = servers.run('uptime')

# Параллельное выполнение для ускорения
parallel_servers = ThreadingGroup('web1', 'web2', 'web3')
parallel_results = parallel_servers.put('local_file.txt', '/tmp/remote_file.txt')

Invoke — библиотека для выполнения локальных команд, которая служит основой для Fabric 2.x. Это позволяет использовать единый интерфейс для локальных и удаленных операций:

Python
Скопировать код
from invoke import run

# Локальное выполнение команды
result = run('ls -la', hide=True)
files = result.stdout.split('\n')

Мощная возможность Fabric — создание задач (tasks) в стиле утилиты Make, что позволяет структурировать автоматизацию в виде набора действий:

Python
Скопировать код
from fabric import task

@task
def deploy(c):
"""Развертывание приложения на сервере"""
c.run('git pull')
c.run('pip install -r requirements.txt')
c.run('systemctl restart myapp')

@task
def backup(c):
"""Создание резервной копии базы данных"""
c.run('pg_dump -U user db > /tmp/backup.sql')
c.get('/tmp/backup.sql', 'backups/')

# Использование: fab -H server1,server2 deploy

Ирина Соколова, Lead DevOps Engineer

В нашей компании возникла проблема с обновлением конфигурации на 120 серверах, распределенных между тремя дата-центрами. Каждое изменение превращалось в многочасовой марафон ручных подключений и проверок.

Я решила создать систему автоматизации на базе Fabric, которая не только выполняла обновления, но и проверяла их корректность:

Python
Скопировать код
from fabric import Connection, ThreadingGroup
import yaml
import logging

# Загрузка конфигурации серверов
with open('servers.yml', 'r') as f:
config = yaml.safe_load(f)

# Группировка по дата-центрам
dc_groups = {}
for dc_name, servers in config['datacenters'].items():
dc_groups[dc_name] = ThreadingGroup(*[s['host'] for s in servers])

# Функция обновления с проверкой
def safe_update(group, config_path, config_content):
# Резервное копирование
group.run(f'cp {config_path} {config_path}.bak')

# Обновление конфигурации
for conn in group:
conn.put(config_content, config_path)

# Перезапуск сервиса
results = group.run('systemctl restart service')

# Проверка статуса
check = group.run('systemctl status service | grep "active (running)"')

# Откат при проблемах
failed_hosts = [conn.host for conn, result in check.items() if result.failed]
if failed_hosts:
logging.error(f"Failed hosts: {', '.join(failed_hosts)}")
for host in failed_hosts:
Connection(host).run(f'mv {config_path}.bak {config_path}')
Connection(host).run('systemctl restart service')
return False
return True

# Запуск обновления по дата-центрам
for dc, group in dc_groups.items():
print(f"Updating {dc}...")
if safe_update(group, '/etc/service/config.json', 'new_config.json'):
print(f"{dc} updated successfully!")

Система сократила время обновления с 5 часов до 15 минут и полностью исключила человеческие ошибки. Более того, она автоматически выявляла проблемы и делала откат только на проблемных серверах, что давало нам возможность точно диагностировать причины сбоев.

Для более сложных сценариев Fabric позволяет комбинировать локальные и удаленные операции, создавая полноценные конвейеры развертывания:

Python
Скопировать код
@task
def deploy_full(c, branch="main"):
"""Полный цикл развертывания с локальной сборкой и удаленной установкой"""
# Локальная подготовка (используя Invoke)
c.local(f"git checkout {branch}")
c.local("npm run build")

# Удаленное развертывание (используя Fabric)
c.put("dist/", "/var/www/app/")
c.run("systemctl restart nginx")

# Проверка развертывания
result = c.run("curl -s http://localhost | grep 'Welcome'")
if not result.ok:
print("Deployment verification failed!")
c.run("systemctl restart nginx") # Попытка исправления

Fabric и Invoke — идеальные инструменты для DevOps-специалистов и системных администраторов, стремящихся автоматизировать повторяющиеся задачи по управлению серверами. Они предлагают оптимальный баланс между простотой использования и гибкостью, позволяя создавать как простые скрипты, так и сложные системы автоматизации. 🛠️

Безопасная передача файлов через SFTP в Python

SFTP (SSH File Transfer Protocol) обеспечивает безопасную передачу файлов через SSH-соединение. В Python есть несколько способов работы с SFTP, от низкоуровневого API в Paramiko до специализированных библиотек вроде pysftp.

Давайте рассмотрим основные методы работы с SFTP и их особенности.

Использование Paramiko для SFTP-операций

Paramiko предоставляет прямой доступ к SFTP-функциональности через интерфейс SFTPClient:

Python
Скопировать код
import paramiko

# Создание SSH-клиента
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('server.example.com', username='user', password='password')

# Получение SFTP-клиента
sftp = ssh.open_sftp()

# Загрузка файла на сервер
sftp.put('local_file.txt', '/remote/path/remote_file.txt')

# Скачивание файла с сервера
sftp.get('/remote/path/file.txt', 'downloaded_file.txt')

# Список файлов в директории
file_list = sftp.listdir('/remote/path/')
for file in file_list:
print(file)

# Создание директории
sftp.mkdir('/remote/path/new_directory')

# Изменение прав доступа
sftp.chmod('/remote/path/file.txt', 0o644) # Права в восьмеричной форме

# Закрытие соединений
sftp.close()
ssh.close()

Упрощенная работа с SFTP через pysftp

Библиотека pysftp предлагает более интуитивный интерфейс для SFTP-операций:

Python
Скопировать код
import pysftp

# Настройка соединения без проверки хостового ключа (не рекомендуется для production)
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None # Для production следует использовать хостовые ключи

with pysftp.Connection('server.example.com', username='user', password='password', cnopts=cnopts) as sftp:
# Загрузка файла на сервер
sftp.put('local_file.txt') # Загрузка в текущую директорию

# Скачивание файла с сервера
sftp.get('remote_file.txt')

# Переход в другую директорию
sftp.chdir('/var/www')

# Рекурсивная загрузка директории
sftp.put_r('local_directory', 'remote_directory')

# Рекурсивное скачивание директории
sftp.get_r('remote_directory', 'local_directory')

# Проверка существования файла
if sftp.exists('file.txt'):
print("Файл существует!")

Библиотека pysftp также поддерживает работу с контекстным менеджером (оператор with), что упрощает управление ресурсами и гарантирует закрытие соединения.

Обработка ошибок и надежные передачи

При работе с SFTP важно корректно обрабатывать исключения, особенно при передаче крупных файлов или большого количества данных:

Python
Скопировать код
try:
with pysftp.Connection('server.example.com', username='user', password='password') as sftp:
# Проверка доступного места перед загрузкой
stat = sftp.execute('df -h /')
print(f"Доступное место на сервере:\n{stat}")

# Загрузка с индикатором прогресса
sftp.put('large_file.zip', callback=lambda x, y: print(f"Загружено: {x} из {y} байт"))
except pysftp.ConnectionException:
print("Ошибка подключения к серверу")
except pysftp.CredentialException:
print("Ошибка аутентификации")
except pysftp.SSHException as e:
print(f"SSH ошибка: {e}")
except IOError as e:
print(f"Ошибка ввода-вывода: {e}")
except Exception as e:
print(f"Непредвиденная ошибка: {e}")

Безопасная практика: работа с ключами и хостовыми отпечатками

Для повышения безопасности рекомендуется использовать аутентификацию по ключу и проверять хостовые отпечатки:

Python
Скопировать код
import pysftp

# Создание объекта опций с загрузкой хостовых ключей
cnopts = pysftp.CnOpts()

# Для первого подключения можно добавить хостовый ключ
# cnopts.hostkeys.add('server.example.com', 'ssh-rsa', 'KEY_DATA_HERE')

# Подключение с использованием приватного ключа
with pysftp.Connection('server.example.com', 
username='user', 
private_key='/path/to/private_key',
private_key_pass='key_passphrase', # если ключ защищен паролем
cnopts=cnopts) as sftp:
# Операции с файлами
pass

Продвинутые сценарии использования SFTP

SFTP позволяет реализовать сложные сценарии передачи файлов, такие как:

  • Синхронизация директорий между локальной и удаленной системой
  • Периодическое резервное копирование важных данных
  • Автоматизированное развертывание приложений
  • Обработка файлов "на лету" при передаче

Пример реализации простой синхронизации директории:

Python
Скопировать код
import pysftp
import os
from datetime import datetime

def sync_directory(local_path, remote_path, server, username, password):
"""Синхронизирует локальную директорию с удаленной"""
with pysftp.Connection(server, username=username, password=password) as sftp:
# Убедимся, что удаленная директория существует
if not sftp.exists(remote_path):
sftp.mkdir(remote_path)

sftp.chdir(remote_path)

# Получим список файлов на сервере
remote_files = {f: sftp.stat(f) for f in sftp.listdir()}

# Сравним с локальными файлами
for local_file in os.listdir(local_path):
local_file_path = os.path.join(local_path, local_file)

# Пропускаем директории для простоты
if os.path.isdir(local_file_path):
continue

local_mtime = datetime.fromtimestamp(os.path.getmtime(local_file_path))

# Если файл новее или не существует на сервере – загружаем
if (local_file not in remote_files or 
local_mtime > datetime.fromtimestamp(remote_files[local_file].st_mtime)):
print(f"Uploading: {local_file}")
sftp.put(local_file_path)

# Использование
sync_directory('./local_data', '/var/data', 'server.example.com', 'user', 'password')

SFTP — это надежный и безопасный способ передачи файлов, который должен быть в арсенале каждого Python-разработчика, работающего с удаленными системами. Библиотеки Paramiko и pysftp предоставляют все необходимые инструменты для эффективной работы с SFTP, от базовых операций до сложных сценариев автоматизации. 📂

Практические сценарии использования Python SSH в DevOps

Python с его SSH-библиотеками стал незаменимым инструментом в арсенале DevOps-инженеров. Рассмотрим практические сценарии, которые демонстрируют, как эффективно применять Python для решения реальных задач автоматизации инфраструктуры.

1. Массовое обновление системы на серверах

Когда требуется обновить десятки или сотни серверов, ручное подключение становится неэффективным. Вот пример скрипта для массового обновления системы с использованием Fabric:

Python
Скопировать код
from fabric import ThreadingGroup
import logging

# Настройка логирования
logging.basicConfig(level=logging.INFO, 
format='%(asctime)s – %(levelname)s – %(message)s',
filename='update.log')

# Список серверов по группам
server_groups = {
'web': ['web1.example.com', 'web2.example.com', 'web3.example.com'],
'db': ['db1.example.com', 'db2.example.com'],
'cache': ['redis1.example.com', 'redis2.example.com']
}

def update_servers(group_name, hosts):
"""Обновляет группу серверов с минимальным простоем"""
logging.info(f"Начинаем обновление группы {group_name}")

# Создаем группу для параллельного выполнения
servers = ThreadingGroup(*hosts, user='admin')

try:
# Обновление пакетов
logging.info(f"Обновление пакетов на {group_name}")
results = servers.run('sudo apt update && sudo apt upgrade -y')

# Проверка наличия необходимости перезагрузки
logging.info(f"Проверка необходимости перезагрузки на {group_name}")
reboot_check = servers.run('if [ -f /var/run/reboot-required ]; then echo "REBOOT"; else echo "NO_REBOOT"; fi')

# Перезагрузка серверов, которым это необходимо
for conn, result in reboot_check.items():
if "REBOOT" in result.stdout:
logging.info(f"Перезагрузка {conn.host}")
# Перезагрузка асинхронно, чтобы не ждать её завершения
conn.run('sudo shutdown -r +1 "Перезагрузка после обновления" &', warn=True)

except Exception as e:
logging.error(f"Ошибка при обновлении группы {group_name}: {e}")
return False

logging.info(f"Обновление группы {group_name} завершено")
return True

# Последовательное обновление по группам
for group, hosts in server_groups.items():
update_servers(group, hosts)

2. Мониторинг состояния серверов

Python SSH идеально подходит для создания простых систем мониторинга без установки дополнительных агентов:

Python
Скопировать код
import paramiko
import time
import json
from datetime import datetime

def check_server(hostname, username, key_path):
"""Собирает основные метрики с сервера"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

metrics = {
'hostname': hostname,
'timestamp': datetime.now().isoformat(),
'status': 'offline',
'metrics': {}
}

try:
client.connect(hostname, username=username, key_filename=key_path, timeout=10)
metrics['status'] = 'online'

# Загрузка CPU
stdin, stdout, stderr = client.exec_command("top -bn1 | grep 'Cpu(s)' | awk '{print $2 + $4}'")
metrics['metrics']['cpu_usage'] = float(stdout.read().decode().strip())

# Использование памяти
stdin, stdout, stderr = client.exec_command("free | grep Mem | awk '{print $3/$2 * 100.0}'")
metrics['metrics']['memory_usage'] = float(stdout.read().decode().strip())

# Использование диска
stdin, stdout, stderr = client.exec_command("df / | tail -1 | awk '{print $5}' | sed 's/%//'")
metrics['metrics']['disk_usage'] = float(stdout.read().decode().strip())

# Аптайм
stdin, stdout, stderr = client.exec_command("uptime -p")
metrics['metrics']['uptime'] = stdout.read().decode().strip()

except Exception as e:
metrics['error'] = str(e)
finally:
client.close()

return metrics

# Пример использования для группы серверов
servers = [
{'hostname': 'web1.example.com', 'username': 'admin', 'key_path': '/path/to/key'},
{'hostname': 'web2.example.com', 'username': 'admin', 'key_path': '/path/to/key'},
]

while True:
results = []
for server in servers:
metrics = check_server(**server)
results.append(metrics)

# Вывод предупреждений при необходимости
if metrics['status'] == 'online':
if metrics['metrics'].get('cpu_usage', 0) > 80:
print(f"WARNING: High CPU usage on {server['hostname']}: {metrics['metrics']['cpu_usage']}%")
if metrics['metrics'].get('memory_usage', 0) > 90:
print(f"WARNING: High memory usage on {server['hostname']}: {metrics['metrics']['memory_usage']}%")
else:
print(f"ERROR: Server {server['hostname']} is offline!")

# Сохранение результатов в JSON
with open(f"metrics_{datetime.now().strftime('%Y%m%d_%H%M')}.json", 'w') as f:
json.dump(results, f, indent=2)

# Пауза перед следующей проверкой
time.sleep(300) # Проверка каждые 5 минут

3. Автоматизированное развертывание приложений

Одна из самых распространенных задач в DevOps — развертывание приложений. Python с Fabric идеально подходит для этой задачи:

Python
Скопировать код
from fabric import Connection
import time
from datetime import datetime

def deploy_application(host, repo_url, app_dir, env="production"):
"""Развертывание веб-приложения на сервере"""
conn = Connection(host)

# Создаем каталог для релизов если он не существует
releases_dir = f"{app_dir}/releases"
conn.run(f"mkdir -p {releases_dir}")

# Создаем новый каталог для текущего релиза
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
release_path = f"{releases_dir}/{timestamp}"

print(f"Deploying new release to {host}...")

try:
# Клонирование репозитория
conn.run(f"git clone {repo_url} {release_path}")

# Переключение на нужную ветку в зависимости от окружения
if env == "production":
branch = "main"
else:
branch = "develop"
conn.run(f"cd {release_path} && git checkout {branch}")

# Установка зависимостей
conn.run(f"cd {release_path} && pip install -r requirements.txt")

# Выполнение миграций базы данных (для Django)
conn.run(f"cd {release_path} && python manage.py migrate")

# Сборка статических файлов
conn.run(f"cd {release_path} && python manage.py collectstatic --noinput")

# Обновление символической ссылки на текущий релиз
conn.run(f"ln -sfn {release_path} {app_dir}/current")

# Перезапуск сервисов
conn.run(f"sudo systemctl restart gunicorn")
conn.run(f"sudo systemctl restart nginx")

# Проверка работоспособности
time.sleep(5) # Даем время на запуск
response = conn.run("curl -s -o /dev/null -w '%{http_code}' http://localhost")
if response.stdout.strip() == "200":
print("Deployment successful! Application is responding.")
else:
print(f"Warning: Application returned status code {response.stdout.strip()}")

# Очистка старых релизов (оставляем 5 последних)
conn.run(f"ls -dt {releases_dir}/* | tail -n +6 | xargs rm -rf")

except Exception as e:
print(f"Deployment failed: {e}")
return False

return True

# Пример использования
deploy_application(
host="web1.example.com",
repo_url="git@github.com:company/project.git",
app_dir="/var/www/myapp",
env="production"
)

4. Резервное копирование баз данных

Регулярное резервное копирование — критически важная задача для обеспечения безопасности данных:

Python
Скопировать код
import paramiko
import os
from datetime import datetime

def backup_database(host, db_user, db_name, local_backup_dir, remote_user, key_path):
"""Создает резервную копию базы данных и загружает её локально"""
timestamp = datetime.now().strftime("%Y%m%d_%H%M")
remote_filename = f"/tmp/{db_name}_{timestamp}.sql.gz"
local_filename = os.path.join(local_backup_dir, f"{db_name}_{timestamp}.sql.gz")

# Создаем локальную директорию, если она не существует
os.makedirs(local_backup_dir, exist_ok=True)

# Устанавливаем SSH соединение
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:
# Подключаемся к серверу
client.connect(host, username=remote_user, key_filename=key_path)

print(f"Creating backup of {db_name} on {host}...")

# Создаем резервную копию и сразу сжимаем её
command = f"pg_dump -U {db_user} {db_name} | gzip > {remote_filename}"
stdin, stdout, stderr = client.exec_command(command)

# Проверяем успешность выполнения
exit_status = stdout.channel.recv_exit_status()
if exit_status != 0:
error = stderr.read().decode()
raise Exception(f"Database dump failed: {error}")

print(f"Backup created, downloading to local storage...")

# Загружаем файл
sftp = client.open_sftp()
sftp.get(remote_filename, local_filename)

# Удаляем временный файл на сервере
client.exec_command(f"rm {remote_filename}")

print(f"Backup completed and saved to {local_filename}")

# Получаем размер файла
file_size = os.path.getsize(local_filename)
print(f"Backup size: {file_size / 1024 / 1024:.2f} MB")

except Exception as e:
print(f"Backup failed: {e}")
return None
finally:
client.close()

return local_filename

# Пример использования
backup = backup_database(
host="db.example.com",
db_user="postgres",
db_name="production_db",
local_backup_dir="./backups",
remote_user="admin",
key_path="/path/to/private_key"
)

Python SSH-библиотеки предоставляют широкие возможности для автоматизации различных DevOps-задач. Эти примеры демонстрируют лишь малую часть возможных применений, но они показывают, как можно создавать эффективные, безопасные и надежные решения для управления инфраструктурой с минимальными усилиями. 🚀

Python превращает управление SSH-соединениями из сложного технического процесса в элегантный и понятный код. Будь то простое подключение к серверу через Paramiko, массовая автоматизация с Fabric или безопасная передача файлов через SFTP — эти инструменты позволяют оркестрировать десятки или сотни серверов всего несколькими строками кода. Автоматизируйте рутину, освободите время для творческих задач и решения сложных проблем. В конечном счете, лучший код — это тот, который не требуется писать снова и снова.

Загрузка...