Helcode | Хелкод | Скрипты и автоматизация
993 subscribers
52 photos
34 links
☎️ Контакты для связи: @helcodeadm
Download Telegram
PostgreSQL: оптимизация производительности и мониторинг

Цель: повысить производительность PostgreSQL и настроить мониторинг ключевых метрик

Проблема: медленные запросы, блокировки и неоптимальные настройки БД

Решение: комплексная оптимизация и мониторинг

1. Критические настройки postgresql.conf
-- Основные настройки
shared_buffers = '1GB' -- 25% от общей памяти
effective_cache_size = '3GB' -- 75% от общей памяти
work_mem = '64MB' -- Память для операций сортировки
maintenance_work_mem = '256MB' -- Память для обслуживания
max_connections = 200 -- Оптимальное количество подключений

-- Настройки производительности
random_page_cost = 1.1 -- Для SSD дисков
effective_io_concurrency = 200 -- Для SSD дисков
wal_buffers = '16MB'
checkpoint_completion_target = 0.9

-- Логирование медленных запросов
log_min_duration_statement = 1000 -- Запросы дольше 1 секунды


2. Мониторинг ключевых метрик
-- Активные запросы
SELECT
pid,
usename,
application_name,
client_addr,
state,
query,
now() - query_start as duration
FROM pg_stat_activity
WHERE state = 'active'
AND now() - query_start > interval '5 seconds';

-- Статистика по индексам
SELECT
schemaname,
tablename,
indexname,
idx_scan as index_scans,
idx_tup_read as tuples_read,
idx_tup_fetch as tuples_fetched
FROM pg_stat_user_indexes
WHERE idx_scan = 0; -- Неиспользуемые индексы

-- Размеры таблик и индексов
SELECT
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as total_size,
pg_size_pretty(pg_relation_size(schemaname||'.'||tablename)) as table_size,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename) -
pg_relation_size(schemaname||'.'||tablename)) as index_size
FROM pg_tables
WHERE schemaname NOT IN ('information_schema', 'pg_catalog')
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;


3. Оптимизация запросов
-- Поиск медленных запросов
SELECT
query,
calls,
total_time,
mean_time,
rows,
100.0 * shared_blks_hit / nullif(shared_blks_hit + shared_blks_read, 0) AS hit_percent
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;

-- Анализ планов запросов
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM orders WHERE customer_id = 123 AND created_at > NOW() - INTERVAL '30 days';

-- Создание индексов для частых запросов
CREATE INDEX CONCURRENTLY idx_orders_customer_created
ON orders(customer_id, created_at DESC);

CREATE INDEX CONCURRENTLY idx_orders_status_created
ON orders(status, created_at) WHERE status IN ('pending', 'processing');


4. Интеграция с Prometheus
# postgres_exporter configuration
# Запуск экспортера
./postgres_exporter --extend.query-path=queries.yaml

# Пример queries.yaml
pg_stat_database:
query: "SELECT datname, numbackends, xact_commit, xact_rollback, blks_read, blks_hit, tup_returned, tup_fetched, tup_inserted, tup_updated, tup_deleted FROM pg_stat_database"
metrics:
- datname:
usage: "LABEL"
description: "Name of the database"
- numbackends:
usage: "GAUGE"
description: "Number of backends connected to this database"


Рекомендации:
➤ Регулярно проводить VACUUM и ANALYZE
➤ Мониторить соотношение hit/miss в кеше
➤ Настроить логирование медленных запросов
➤ Использовать connection pooling
➤ Регулярно обновлять статистику

🌐 @helcode
👍62🤔1
GitLab CI/CD: создание эффективных пайплайнов

Цель: Настроить автоматизированные пайплайны для тестирования и деплоя

Проблема: Ручные процессы деплоя, отсутствие автоматического тестирования

Решение: Внедрение GitLab CI/CD с многостадийными пайплайнами

1. Базовый .gitlab-ci.yml
# .gitlab-ci.yml
stages:
- test
- build
- security
- deploy

variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2

# Кеширование для ускорения сборок
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .cache/pip/
- vendor/bundle

# Общие настройки для всех job'ов
.default_job: &default_job
image: docker:latest
services:
- docker:dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY


2. Стадия тестирования
unit_tests:
<<: *default_job
stage: test
image: python:3.9
script:
- pip install -r requirements.txt
- pytest tests/unit/ --cov=app --cov-report=xml
artifacts:
reports:
cobertura: coverage.xml
paths:
- coverage/
coverage: '/TOTAL.*\s+(\d+%)$/'

integration_tests:
<<: *default_job
stage: test
script:
- docker-compose -f docker-compose.test.yml up -d
- sleep 30
- ./wait-for-service.sh http://app:8000/health
- pytest tests/integration/
- docker-compose -f docker-compose.test.yml down

e2e_tests:
<<: *default_job
stage: test
image: node:16
script:
- npm install
- npm run test:e2e
artifacts:
paths:
- cypress/screenshots/
- cypress/videos/


3. Стадия сборки и безопасности
build:
<<: *default_job
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
only:
- main
- develop

security_scan:
<<: *default_job
stage: security
image: aquasec/trivy:latest
script:
- trivy image --exit-code 0 --format template --template "@/contrib/html.tpl" -o gl-dependency-scan-report.html $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- trivy image --exit-code 1 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
artifacts:
paths:
- gl-dependency-scan-report.html
allow_failure: true

sast:
stage: security
image:
name: "golang:1.19"
script:
- git clone https://github.com/securego/gosec.git
- cd gosec/cmd/gosec && go install
- gosec ./...


4. Стадия деплоя
deploy_staging:
<<: *default_job
stage: deploy
environment:
name: staging
url: https://staging.example.com
script:
- echo "Deploying to staging..."
- kubectl set image deployment/app app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -n staging
- kubectl rollout status deployment/app -n staging
only:
- develop

deploy_production:
<<: *default_job
stage: deploy
environment:
name: production
url: https://example.com
script:
- echo "Deploying to production..."
- kubectl set image deployment/app app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -n production
- kubectl rollout status deployment/app -n production
when: manual
only:
- main


5. Расширенные возможности
# Параллельное выполнение тестов
parallel_tests:
<<: *default_job
stage: test
parallel: 5
script:
- pytest tests/ -n auto --dist=loadfile

# Кросс-платформенные сборки
multi_arch_build:
<<: *default_job
stage: build
script:
- docker buildx create --use
- docker buildx build --platform linux/amd64,linux/arm64 -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --push .

# Сканирование зависимостей
dependency_scan:
stage: security
image: ruby:3.1
script:
- gem install bundler-audit
- bundle audit check --update


Best Practices:
➤ Использовать кеширование для ускорения
➤ Разделять тесты на unit/integration/e2e
➤ Настраивать артефакты между стадиями
➤ Использовать manual деплой на production
➤ Мониторить производительность пайплайнов

🌐 @helcode
3👍2
Ansible: автоматизация настройки серверов

Цель: Автоматизировать настройку и управление серверной инфраструктурой

Проблема: Ручная настройка серверов, дрейф конфигураций

Решение: Внедрение Ansible для идемпотентного управления конфигурациями

1. Структура проекта Ansible
ansible-project/
├── inventory/
│ ├── production
│ ├── staging
│ └── group_vars/
├── roles/
│ ├── nginx/
│ ├── postgresql/
│ └── app/
├── playbooks/
│ ├── site.yml
│ ├── database.yml
│ └── deploy.yml
└── ansible.cfg


2. Базовый плейбук
# playbooks/site.yml
- name: Configure web servers
hosts: webservers
become: yes
vars:
nginx_worker_processes: 4
app_version: "1.2.3"

roles:
- role: nginx
- role: app

- name: Configure database servers
hosts: dbservers
become: yes
roles:
- role: postgresql


3. Роль для настройки Nginx
# roles/nginx/tasks/main.yml
- name: Install nginx
apt:
name: nginx
state: latest
update_cache: yes

- name: Configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
backup: yes
notify: restart nginx

- name: Enable nginx service
systemd:
name: nginx
enabled: yes
state: started

# roles/nginx/handlers/main.yml
- name: restart nginx
systemd:
name: nginx
state: restarted


4. Шаблоны конфигураций
# roles/nginx/templates/nginx.conf.j2
user www-data;
worker_processes {{ nginx_worker_processes }};
pid /run/nginx.pid;

events {
worker_connections 1024;
use epoll;
}

http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;

include /etc/nginx/mime.types;
default_type application/octet-stream;

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

gzip on;
gzip_types text/plain text/css application/json application/javascript;

server {
listen 80;
server_name {{ inventory_hostname }};

location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}


5. Продвинутые техники
# Динамический inventory для облачных провайдеров
- name: Configure AWS instances
hosts: localhost
gather_facts: false
tasks:
- ec2_instance_info:
region: us-east-1
filters:
"tag:Environment": production
register: ec2_instances

- add_host:
name: "{{ item.public_ip_address }}"
groups: aws_instances
loop: "{{ ec2_instances.instances }}"

# Обработка ошибок и повторные попытки
- name: Deploy application
command: /opt/app/deploy.sh
register: deploy_result
retries: 3
delay: 5
until: deploy_result.rc == 0
ignore_errors: yes

- name: Check deployment status
debug:
msg: "Deployment completed successfully"
when: deploy_result.rc == 0

- name: Handle deployment failure
debug:
msg: "Deployment failed after 3 attempts"
when: deploy_result.rc != 0


6. Использование Vault для секретов
# Шифрование секретов
ansible-vault encrypt_string 's3cr3t-p@ssw0rd' --name 'db_password'

# В плейбуке:
- name: Configure database
hosts: dbservers
vars:
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
3132333435363738393031323334353637383930313233343536373839303132

tasks:
- name: Create database user
postgresql_user:
name: app_user
password: "{{ db_password }}"


Best Practices:
➤ Использовать роли для модульности
➤ Шифровать секреты с помощью ansible-vault
➤ Тестировать плейбуки в staging
➤ Использовать теги для выборочного выполнения
➤ Настраивать правильную обработку ошибок

🌐 @helcode
1
Elastic Stack: централизованное логирование и анализ

Цель: настроить сбор, анализ и визуализацию логов со всей инфраструктуры

Проблема: логи разбросаны по серверам, сложность анализа и поиска проблем

Решение: внедрение Elasticsearch, Logstash и Kibana (ELK Stack)

1. Установка и настройка Elasticsearch
# docker-compose.yml для ELK
version: '3.8'

services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.9.0
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- xpack.security.enabled=false
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
ports:
- "9200:9200"

logstash:
image: docker.elastic.co/logstash/logstash:8.9.0
volumes:
- ./logstash/pipeline:/usr/share/logstash/pipeline
- ./logstash/config:/usr/share/logstash/config
ports:
- "5044:5044"
depends_on:
- elasticsearch

kibana:
image: docker.elastic.co/kibana/kibana:8.9.0
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"
depends_on:
- elasticsearch

volumes:
elasticsearch_data:


2. Конфигурация Logstash
# logstash/pipeline/01-inputs.conf
input {
beats {
port => 5044
}

tcp {
port => 5000
codec => json
}
}

# logstash/pipeline/02-filters.conf
filter {
# Парсинг nginx логов
if [fileset][module] == "nginx" {
grok {
match => { "message" => "%{IPORHOST:remote_ip} - %{DATA:user_name} \[%{HTTPDATE:timestamp}\] \"%{WORD:method} %{DATA:url} HTTP/%{NUMBER:http_version}\" %{NUMBER:response_code} %{NUMBER:body_sent_bytes} \"%{DATA:referrer}\" \"%{DATA:agent}\"" }
}

date {
match => [ "timestamp", "dd/MMM/YYYY:HH:mm:ss Z" ]
}

geoip {
source => "remote_ip"
}
}

# Парсинг application логов
if [logger_name] == "app" {
grok {
match => { "message" => "\[%{TIMESTAMP_ISO8601:timestamp}\] %{LOGLEVEL:level} %{DATA:class} - %{GREEDYDATA:message}" }
}
}
}

# logstash/pipeline/03-outputs.conf
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "logs-%{+YYYY.MM.dd}"
}
}


3. Filebeat для сбора логов
# filebeat.yml
filebeat.inputs:
- type: log
paths:
- /var/log/nginx/access.log
fields:
type: nginx
environment: production

- type: log
paths:
- /var/log/app/app.log
fields:
type: application
environment: production

output.logstash:
hosts: ["logstash:5044"]

setup.template:
name: "logs"
pattern: "logs-*"


4. Kibana дашборды и визуализации
// Пример сохраненного поиска для ошибок
{
"query": {
"bool": {
"must": [
{
"match": {
"level": "ERROR"
}
},
{
"range": {
"@timestamp": {
"gte": "now-1h"
}
}
}
]
}
}
}


5. Мониторинг и алертинг
// Kibana Alert для мониторинга ошибок
{
"name": "High Error Rate",
"schedule": {
"interval": "5m"
},
"conditions": {
"agg_type": "count",
"threshold_comparator": ">",
"threshold": [100]
},
"actions": [
{
"type": "email",
"subject": "High Error Rate Detected",
"to": ["admin@example.com"],
"message": "Error count: {{context.conditions.0.agg_value}}"
}
]
}


🌐 @helcode
👍32
6. Оптимизация производительности
# Индекс-темплейты для оптимизации
PUT _template/logs_template
{
"index_patterns": ["logs-*"],
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "30s"
},
"mappings": {
"properties": {
"@timestamp": {"type": "date"},
"message": {"type": "text"},
"level": {"type": "keyword"},
"remote_ip": {"type": "ip"}
}
}
}

# Политика управления индексами (ILM)
PUT _ilm/policy/logs_policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_size": "50gb",
"max_age": "7d"
}
}
},
"delete": {
"min_age": "30d",
"actions": {
"delete": {}
}
}
}
}
}


Best Practices:
➤ Использовать структурированное логирование
➤ Настраивать ротацию индексов
➤ Мониторить производительность кластера
➤ Использовать index templates для консистентности
➤ Настраивать алертинг на аномалии в логах

🌐 @helcode
👍21
🐳 Kubernetes: Мониторинг и отладка приложений

Цель: настроить эффективный мониторинг и отладку приложений в Kubernetes

Проблема: сложность диагностики проблем в распределенной среде

Решение: комплексный подход к мониторингу и отладке

1. Установка Prometheus Stack
# Добавление репозитория и установка
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# Установка kube-prometheus-stack
helm install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--set grafana.adminPassword=admin \
--set prometheus.service.type=NodePort \
--set alertmanager.service.type=NodePort


2. Конфигурация мониторинга приложений
# ServiceMonitor для кастомного приложения
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: app-monitor
namespace: default
spec:
selector:
matchLabels:
app: my-app
endpoints:
- port: web
path: /metrics
interval: 30s
relabelings:
- sourceLabels: [__meta_kubernetes_pod_name]
targetLabel: pod
- sourceLabels: [__meta_kubernetes_namespace]
targetLabel: namespace


3. Отладка и диагностика
# Просмотр логов нескольких подов
kubectl logs -f deployment/app --all-containers=true --prefix=true --tail=100

# Отладка проблем с сетью
kubectl run debug-pod --image=nicolaka/netshoot --rm -i --tty -- /bin/bash

# Проверка DNS
nslookup kubernetes.default.svc.cluster.local

# Проверка сетевой связности
curl -v http://app-service:8080/health

# Анализ ресурсов
kubectl top pods --containers
kubectl describe pod app-pod-12345
kubectl get events --sort-by=.lastTimestamp


4. Полезные PromQL запросы
# Использование CPU по неймспейсам
sum(rate(container_cpu_usage_seconds_total{namespace="production"}[5m])) by (pod)

# Использование памяти
container_memory_working_set_bytes{container!="", container!="POD"}

# Rate HTTP ошибок
rate(http_requests_total{status=~"5.."}[5m])

# Latency перцентили
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))


5. Расширенная диагностика
# Pod для отладки с полным доступом
apiVersion: v1
kind: Pod
metadata:
name: debug-pod
spec:
hostNetwork: true
hostPID: true
containers:
- name: debug
image: busybox
command: ["sleep", "3600"]
securityContext:
privileged: true
volumeMounts:
- name: host-root
mountPath: /host
volumes:
- name: host-root
hostPath:
path: /


6. Автоматическое масштабирование
# Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60


Best Practices:
➤ Настраивать readiness и liveness пробы
➤ Использовать структурированное логирование
➤ Мониторить бизнес-метрики
➤ Настраивать автоматическое масштабирование
➤ Регулярно проводить chaos testing

🌐 @helcode
Как не сжечь репозиторий и остаться в живых?

Случалось ли Вам делать git commit и тут же понимать, что отправили в историю код, который ломает всё? Или закоммитить файл с паролями, который тут же надо спрятать? Паника? Не надо. У Git есть свои «Машина времени» и «Империус».

Вот три спасательных круга:

➤ Отмена последнего коммита (с сохранением изменений в рабочей директории):
git reset --soft HEAD~1


➤ Полная отмена коммита и всех изменений (опасно!):
git reset --hard HEAD~1


➤ Волшебная палочка для удаления одного файла из коммита (например, config.py с паролями):
git reset HEAD~1 config.py  # Вытаскиваем файл из коммита
git restore config.py # Откатываем его в рабочей директории
git commit --amend # Перезаписываем предыдущий коммит


git reset — это не кнопка удаления, а инструмент перемещения указателя HEAD на другой коммит. Флаг --soft оставляет изменения в индексе, --mixed (по умолчанию) — в рабочей директории, а --hard — безжалостно стирает.

git reset --hard — это как «Авада Кедавра» для кода. Произносить с осторожностью.

🌐 @helcode
👍6
Ветка — не дерево, или Как не заблудиться в трех соснах

Работа в одной ветке main — это как готовить завтрак, обед и ужин на одной сковородке, не помыв ее. Хаос, грязь и все ненавидят друг друга. Ветвление — основа цивилизованной разработки.

Создаем и переключаемся на ветку для новой фичи:
git checkout -b feature/magic-button

Эквивалент новой модной команды:
git switch -c feature/magic-button

Слияние ветки в main (после ПР):
git switch main
git merge feature/magic-button


Ветка в Git — это всего лишь легковесный подвижный указатель на коммит. Когда мы создаем новую ветку, мы не копируем весь код, мы просто создаем новую метку, которая начинает двигаться вперед с коммитами.

Название ветки patch-1 говорит о нашей фантазии так же много, как имя «Кот» для кота.

🌐 @helcode
👍31
Страшная сказка на ночь: мердж-конфликт

Вы с коллегой независимо изменили одну и ту же строку в одном файле. Вы оба делаете git merge и... Внезапно Git снимает с себя ответственность и показывает это душераздирающее сообщение: CONFLICT (content). Знакомо?

Вот как выглядит файл в состоянии конфликта:
print("Hello, World!")
<<<<<<< HEAD
print("Новая крутая фича от меня!")
=======
print("Исправление критического бага от коллеги!")
>>>>>>> branch-hotfix

Решение: необходимо вручную выбрать, что оставить, а что удалить, убрав маркеры <<<<<<<, ======= и >>>>>>>.

Конфликт — это не баг, это фича. Git не может решить, какое изменение более важное — наша новая фича или критический хотфикс коллеги. Он просит нас, как разумного разработчика, принять взвешенное решение.

Опишите в комментарии самый эпичный или смешной мердж-конфликт в своей практике. Кто победил: фича или багфикс?


🌐 @helcode
1
Stash: карманная заглушка для беспорядка

На полпути в грязной работе над фичей, а нам срочно нужно переключиться на другую ветку, чтобы пофиксить баг. Делать коммит с сообщением «wip» (work in progress) — моветон. Что делать?

Волшебная команда, которая прячет все незакоммиченные изменения:
git stash

Вернуть спрятанное обратно:
git stash pop

Посмотреть список своих «заначек»:
git stash list

Спрятать изменения, включая неотслеживаемые файлы:
git stash -u


git stash создает специальный коммит, который не привязан ни к какой ветке, и возвращает нашу рабочую директорию к состоянию последнего коммита. Это временное хранилище для черновиков.

Как часто вы используете stash? Это Ваш ежедневный инструмент или спасательный круг на крайний случай?

git stash — это аналог «быстро зашвырнуть все вещи в шкаф, когда звонит домофон и приехала теща». Главное — не забыть потом pop, иначе будем искать свои носки полгода.

🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥1
.gitignore: искусство прятать концы в воду

Сколько раз Вы видели коммиты с файлами node_modules/, .DS_Store, *.pyc или, не дай бог, .env с продакшн-ключами? Это мусор, который не должен быть в репозитории. Файл .gitignore — наш лучший друг и санитар.

Создаем в корне проекта файл .gitignore и добавляем в него шаблоны:
# Логи и кэш
*.log
.npm/

# Файлы ОС
.DS_Store
Thumbs.db

# Файлы окружения (НЕ КОММИТИТЬ НИКОГДА!)
.env
config.ini

# Зависимости (для Node.js)
node_modules/

# Артефакты сборки (для Python)
__pycache__/
*.pyc


Git проверяет файл .gitignore перед тем, как отслеживать изменения. Если имя файла или папки совпадает с шаблоном внутри — Git делает вид, что этого объекта не существует. Это экономит место, время и нервы.

Поделитесь своим самым ценным или неочевидным правилом в .gitignore! Что такого Вы добавили, о чем другие могут не знать?

Закоммитить node_modules — это как отправить посылку, предварительно наклеив на нее всю пыль и мусор со склада.

🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Rebase vs Merge: холивар, который мы заслужили

Нужно влить свою ветку в main. Два лагеря, две религии. Одни кричат: «Rebase — чистая история!». Другие: «Merge — правдивая история!». Кто прав? Давайте без драки, только хардкор.

Merge (слияние): cоздает коммит с двумя родителями.
git checkout main
git merge feature/branch

История: --o--o--o--m (где m — merge-коммит)

Rebase (перебазирование): перемещает наши коммиты на верхушку main, как будто мы начали работу только что.
git checkout feature/branch
git rebase main

История: --o--o--o--o--o (идеально прямая линия)

➤ Merge сохраняет всю историю разработки, включая факт ветвления. Безопасен для публичных веток.
➤ Rebase переписывает историю, делая ее линейной и чистой. Отлично подходит для локальной чистки перед пулл-реквестом. Опасно использовать на общих ветках.

Ставьте реакцию:

❤️ — за Merge (история должна быть правдой!).

🔥 — за Rebase (чистота и порядок превыше всего!).

Использовать git rebase на общей ветке - это как взять чужой паспорт и начать вклеивать в него новые фотографии.

🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
8🔥4
Git Hooks: Твой личный робот-помощник

Хотите, чтобы код автоматически прогонял тесты перед каждым коммитом? Или чтобы линтер проверял стиль? Или чтобы скрипт развертывания сам запускался после пушa в main? Пора познакомиться с Git Hooks.

Хуки лежат в папке .git/hooks/. Пример пре-коммит хука (.git/hooks/pre-commit), который не даст закоммитить код, не прошедший линтинг:
#!/bin/sh
echo "Запуск линтера..."
if ! eslint --cache --fix .; then
echo "Линтер нашел ошибки! Коммит отменен."
exit 1
fi
git add . # Добавляем исправления, сделанные линтером

Не забудьте дать файлу права на выполнение: chmod +x .git/hooks/pre-commit

Git Hooks — это скрипты, которые Git запускает в ответ на определенные события (commit, push, rebase и т.д.). Они выполняются локально и позволяют автоматизировать рутину и внедрить контроль качества.

Какой самый полезный или безумный Git Hook Вы когда-либо использовали или хотели бы использовать? Поделитесь идеями!

Настроить pre-commit хук — это как нанять очень принципиального секьюрити, который не пустит Вас на работу в пижаме. Иногда раздражает, но в итоге все только выигрывают.

🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍61
Параллельное выполнение задач с xargs

Нужно обработать много файлов или выполнить много команд параллельно?

xargs с параллельным выполнением

# Поиск и удаление старых логов параллельно
find /var/log -name "*.log" -mtime +30 | xargs -P 4 -I {} rm -v {}

# Параллельная загрузка URL из файла
cat urls.txt | xargs -P 8 -I {} curl -O {}

# Массовое конвертирование изображений
find ./images -name "*.jpg" | xargs -P 2 -I {} convert {} -resize 50% resized/{}

# Обработка с пробелами в именах файлов
find . -name "*.txt" -print0 | xargs -0 -P 4 -I {} wc -l {}


Ключевые параметры:
-P N - количество параллельных процессов
-I {} - замена входящих данных
-0 - для работы с именами с пробелами
-n 1 - передавать по одному аргументу

🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👌3👍2
xargs: для тех, кто устал копировать вывод команд

Знакомо: ls | grep .txt показывает файлы, а чтобы удалить их все, приходится либо копировать каждый, либо писать сложную конструкцию? xargs — это мост между stdout одной команды и аргументами другой.

Найдем все .tmp файлы и удалим их одной командой:
find . -name "*.tmp" | xargs rm

Или более безопасный вариант с обработкой пробелов в именах:
find . -name "*.tmp" -print0 | xargs -0 rm


xargs берет поток данных с входа (например, список файлов от find) и превращает его в аргументы для указанной команды (rm). Без xargs команда rm не знала бы, что делать со списком файлов из stdin.

А вы часто используете xargs? Или предпочитаете другие способы (циклы for, -exec в find)?


xargs — это как шеф-повар, который берет ингредиенты (список файлов) и готовит из них блюдо (выполняет команду). Без него пришлось бы все делать вручную.


🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
xargs -I: Когда нужно подставить аргумент именно В ТО САМОЕ МЕСТО

А что если команда ожидает аргумент не в конце, а в середине? Например, нужно переименовать файлы или выполнить сложную операцию? Обычный xargs не справится — тут нужен флаг -I.

Допустим, хотим создать бэкапы всех .py файлов:
find . -name "*.py" | xargs -I {} cp {} {}.backup

Или переименовать файлы, добавив префикс:
ls *.txt | xargs -I FILE mv FILE PREFIX_FILE


Флаг -I позволяет задать placeholder (обычно {}), который будет заменен на каждый элемент входа. Это дает полный контроль над тем, куда подставляются аргументы в команде.

Попробуйте сами! Создайте тестовые файлы и переименуйте их с помощью xargs -I. Какой placeholder Вы используете?
1. {} — классика
2. FILE — для ясности
3. Что-то свое — напишите в комментах!


xargs -I {} — это как заказать бургер "все кроме котлеты" — полный контроль над тем, что и куда попадает.


🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤔1
xargs + parallel: скорость света для массовых операций

Нужно обработать 1000 файлов, но делать это последовательно — слишком долго? xargs может запускать процессы параллельно, используя все ядра процессора!

Скачаем несколько URL параллельно (4 процесса одновременно):
cat urls.txt | xargs -n 1 -P 4 wget


Или обработаем изображения параллельно:
find . -name "*.jpg" | xargs -n 1 -P 8 convert -resize 50%


- -P N — запускает N процессов параллельно
- -n 1 — передает по одному аргументу каждому процессу
Это превращает линейную обработку в конвейерную, ускоряя работу в разы!

А вы используете параллельное выполнение? Поделитесь своими кейсами!

Параллельный xargs — это как нанять бригаду рабочих вместо одного. Главное — не переборщить, а то устроите DDoS самому себе!


🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍81🔥1
xargs в бою: реальные сценарии из жизни DevOps

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

Сценарий 1: массовый деплой на несколько серверов
cat servers.txt | xargs -I SERVER ssh SERVER "cd /app && git pull && systemctl restart myapp"


Сценарий 2: поиск и убийство заблокированных процессов
ps aux | grep "zombie_process" | awk '{print $2}' | xargs kill -9


Сценарий 3: пакетное обновление Docker контейнеров
docker ps -aq | xargs docker stop
docker ps -aq | xargs docker rm


Сила xargs в комбинации с другими утилитами: find, grep, awk, docker. Он становится клеем, который связывает отдельные команды в мощные автоматизированные пайплайны.

Поделитесь своим самым крутым или неочевидным использованием xargs! Какой пайплайн с xargs вы считаете своим козырем?

xargs в руках опытного инженера — это как швейцарский нож: может и консервную банку открыть, и палатку поставить, и даже починить машину в крайнем случае. 🔧


🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍61
Пароли — не главное? Почему двухфакторка важнее сложного пароля

Ставим 20-символьный пароль с иероглифами, но все равно попадаем на фишинговый сайт. Реальность: пароль — самый уязвимый фактор аутентификации. Пора поговорить про 2FA.

Пример настройки 2FA в командной строке Linux (для SSH):
# Устанавливаем Google Authenticator PAM
sudo apt install libpam-google-authenticator

# Настраиваем для пользователя
google-authenticator

Ответь (y - yes):
➤ y — использовать time-based tokens
➤ y — обновлять конфиг
➤ y — разрешить только одно использование кода
➤ y — разрешить 3 попытки за 30 секунд

2FA (Two-Factor Authentication) — это «что-то, что Вы знаете» (пароль) + «что-то, что у Вас есть» (телефон/токен). Даже если украдут пароль, без второго фактора злоумышленник не войдет.

А какой 2FA вы используете?

P.S. Если интересна тема ИБ - сообщайте в комментарии, раскрою всё подробнее!


🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍73🤔1
Шифрование дисков: что будет, если ноутбук украдут в аэропорту?

Представим: Вы работали в кафе, отошли на 5 минут, а ноутбука нет. Без шифрования злоумышленник за 10 минут получит все Ваши данные, пароли и доступ к корпоративной сети.

BitLocker (Windows):
# Проверить статус BitLocker
Manage-bde -status C:

# Включить шифрование
Manage-bde -on C: -RecoveryPassword "Добавить_сюда_ключ"


VeraCrypt (кроссплатформенный аналог):
# Создание зашифрованного контейнера
veracrypt -t -c


Полное шифрование диска преобразует все данные в нечитаемый формат без ключа дешифрования. Даже при физическом доступе к диску данные защищены.

А вы шифруете свои диски? Поделитесь опытом!

Шифрование диска — это как хранить драгоценности в сейфе, а не под подушкой. Вору будет проще унести весь сейф, чем открыть его.


🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
2🤝1🫡1