Управление очередями фоновых задач в Bash с помощью функций и переменных
При работе с большими скриптами в Linux нередко требуется запускать задачи в фоновом режиме. Но чтобы всё работало корректно, нужно уметь управлять очередями задач. Сейчас разберемся, как организовать очередь фоновых задач с использованием функций и переменных, чтобы избежать перегрузки системы.
🛠 Что нужно знать о фоновых задачах?
В Bash можно запускать процессы в фоне, добавляя & в конце команды. Но если одновременно запущено слишком много процессов, система может потерять стабильность. Управление очередью фоновых задач позволяет:
Реализация очереди задач
1. Пример базового скрипта с ограничением задач. Этот скрипт запускает фоновые задачи, ограничивая их количество:
Вывод:
При выполнении скрипта можно увидеть, что одновременно запускается не более четырёх задач:
2. Улучшение с приоритетами и динамическим управлением
Добавление приоритетов. Мы можем использовать массивы для хранения задач с разным приоритетом.
Задачи с приоритетом выполняются в первую очередь, вывод:
3. Дополнительные трюки: управление через переменные
Динамическое добавление задач в очередь. Очередь можно заполнять динамически, используя массив:
✅ Преимущества такого подхода:
BashTex📱 #bash #utils
При работе с большими скриптами в Linux нередко требуется запускать задачи в фоновом режиме. Но чтобы всё работало корректно, нужно уметь управлять очередями задач. Сейчас разберемся, как организовать очередь фоновых задач с использованием функций и переменных, чтобы избежать перегрузки системы.
В Bash можно запускать процессы в фоне, добавляя & в конце команды. Но если одновременно запущено слишком много процессов, система может потерять стабильность. Управление очередью фоновых задач позволяет:
Ограничить количество одновременно выполняемых задач.
Следить за состоянием задач.
Организовать приоритет выполнения.
Реализация очереди задач
1. Пример базового скрипта с ограничением задач. Этот скрипт запускает фоновые задачи, ограничивая их количество:
#!/bin/bash
# Максимальное количество фоновых задач
MAX_JOBS=4
# Функция для ожидания завершения задач
wait_for_jobs() {
while (( $(jobs -r | wc -l) >= MAX_JOBS )); do
sleep 1
done
}
# Функция, которая будет выполняться в фоне
task() {
local id=$1
echo "Task $id started"
sleep $((RANDOM % 5 + 1)) # Имитация выполнения
echo "Task $id completed"
}
# Основной цикл
for i in {1..10}; do
wait_for_jobs # Ожидание освобождения очереди
task "$i" & # Запуск задачи в фоне
done
# Ожидание завершения всех задач
wait
echo "All tasks completed!"
Вывод:
Task 1 started
Task 2 started
Task 3 started
Task 4 started
Task 1 completed
Task 5 started
Task 2 completed
Task 6 started
...
All tasks completed!
При выполнении скрипта можно увидеть, что одновременно запускается не более четырёх задач:
2. Улучшение с приоритетами и динамическим управлением
Добавление приоритетов. Мы можем использовать массивы для хранения задач с разным приоритетом.
#!/bin/bash
MAX_JOBS=3
PRIORITY_TASKS=("High1" "High2")
NORMAL_TASKS=("Normal1" "Normal2" "Normal3")
wait_for_jobs() {
while (( $(jobs -r | wc -l) >= MAX_JOBS )); do
sleep 1
done
}
task() {
local name=$1
echo "Task $name started"
sleep $((RANDOM % 5 + 2))
echo "Task $name completed"
}
# Выполнение задач с приоритетом
for task_name in "${PRIORITY_TASKS[@]}" "${NORMAL_TASKS[@]}"; do
wait_for_jobs
task "$task_name" &
done
wait
echo "All prioritized tasks completed!"
Задачи с приоритетом выполняются в первую очередь, вывод:
Task High1 started
Task High2 started
Task Normal1 started
Task High1 completed
Task Normal2 started
...
All prioritized tasks completed!
3. Дополнительные трюки: управление через переменные
Динамическое добавление задач в очередь. Очередь можно заполнять динамически, используя массив:
#!/bin/bash
MAX_JOBS=4
TASK_QUEUE=()
# Функция добавления задач в очередь
add_task() {
TASK_QUEUE+=("$1")
}
# Функция выполнения задач из очереди
process_queue() {
for task_name in "${TASK_QUEUE[@]}"; do
wait_for_jobs
task "$task_name" &
done
}
# Добавляем задачи в очередь
add_task "Task1"
add_task "Task2"
add_task "Task3"
add_task "Task4"
add_task "Task5"
# Обрабатываем очередь
process_queue
wait
echo "Dynamic queue processing completed!"
Контроль над нагрузкой на систему.
Возможность задания приоритетов выполнения.
Легкость добавления задач в реальном времени.
Масштабируемость для больших скриптов.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥3
Динамическое распределение нагрузки между серверами на основе сетевого трафика
⚙️ Как это работает?
Балансировщики нагрузки анализируют входящий трафик, измеряют метрики серверов (задержки, использование ресурсов) и динамически перенаправляют запросы к менее загруженным узлам.
Основные механизмы:
Инструменты для реализации
1. HAProxy. HAProxy - высокопроизводительный балансировщик нагрузки. Он поддерживает динамическое распределение на основе метрик.
Настройка:
Фрагмент конфигурации
Здесь запросы направляются серверу с наименьшим числом соединений (leastconn).
2. NGINX. NGINX также можно использовать как балансировщик. Он поддерживает модули для анализа времени отклика.
Пример конфигурации:
Дополнительный модуль
3. Traefik. Современное решение для балансировки в облачных и контейнерных средах. Traefik автоматически подхватывает информацию о серверах из Docker или Kubernetes.
BashTex📱 #linux #utils
Балансировщики нагрузки анализируют входящий трафик, измеряют метрики серверов (задержки, использование ресурсов) и динамически перенаправляют запросы к менее загруженным узлам.
Основные механизмы:
Текущий сетевой трафик: оценивается объём данных, проходящих через сервер.
Задержка отклика: запросы направляются к серверу с минимальной задержкой.
Уровень нагрузки CPU/RAM: запросы равномерно распределяются между серверами, исходя из их состояния.
Инструменты для реализации
1. HAProxy. HAProxy - высокопроизводительный балансировщик нагрузки. Он поддерживает динамическое распределение на основе метрик.
Настройка:
sudo apt update && sudo apt install haproxy
Фрагмент конфигурации
/etc/haproxy/haproxy.cfg:
frontend http_front
bind *:80
default_backend servers
backend servers
balance leastconn
server srv1 192.168.1.101:80 check
server srv2 192.168.1.102:80 check
Здесь запросы направляются серверу с наименьшим числом соединений (leastconn).
2. NGINX. NGINX также можно использовать как балансировщик. Он поддерживает модули для анализа времени отклика.
Пример конфигурации:
upstream backend {
server 192.168.1.101 max_fails=3 fail_timeout=30s;
server 192.168.1.102 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
Дополнительный модуль
ngx_http_healthcheck_module позволяет учитывать время отклика серверов.3. Traefik. Современное решение для балансировки в облачных и контейнерных средах. Traefik автоматически подхватывает информацию о серверах из Docker или Kubernetes.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥2
Прерывание работы скрипта с сохранением прогресса
При выполнении долгих скриптов (например, обработки данных или резервного копирования) важно предусмотреть механизм безопасного прерывания с возможностью продолжения с того места, где процесс остановился. Сегодня про то, как можно организовать такую систему в Bash с использованием файлов-снапшотов.
Файл-снапшот хранит состояние выполнения скрипта. При запуске скрипт проверяет наличие этого файла, чтобы понять, нужно ли продолжить работу или начать заново.
💡 Реализация
Предположим, у нас есть список файлов для обработки. Скрипт будет:
Примеры вывода
Первый запуск:
Если прервать выполнение, то прогресс сохранится в progress.snapshot.
Повторный запуск:
🔎 Обработка ошибок
Чтобы обеспечить надежность:
🔗 Расширенная версия: поддержка нескольких процессов
Для обработки в несколько потоков можно использовать отдельные снапшоты для каждой задачи. Например:
Файлы-снапшоты - простой, но важный инструмент для повышения надежности скриптов. Они позволяют безопасно прерывать и продолжать выполнение, экономя ваше время.
BashTex📱 #bash #utils
При выполнении долгих скриптов (например, обработки данных или резервного копирования) важно предусмотреть механизм безопасного прерывания с возможностью продолжения с того места, где процесс остановился. Сегодня про то, как можно организовать такую систему в Bash с использованием файлов-снапшотов.
Файл-снапшот хранит состояние выполнения скрипта. При запуске скрипт проверяет наличие этого файла, чтобы понять, нужно ли продолжить работу или начать заново.
Предположим, у нас есть список файлов для обработки. Скрипт будет:
Чтить файл-снапшот, чтобы определить, с какого места продолжить.
Обрабатывать файлы по одному.
Обновлять прогресс в snap-файле.
#!/bin/bash
# Имя файла-снапшота
SNAPSHOT_FILE="progress.snapshot"
# Список задач (например, файлы для обработки)
FILES=("file1.txt" "file2.txt" "file3.txt" "file4.txt" "file5.txt")
# Чтение текущего прогресса из снапшота
CURRENT_INDEX=0
if [[ -f $SNAPSHOT_FILE ]]; then
CURRENT_INDEX=$(<"$SNAPSHOT_FILE")
echo "Прогресс найден: начнем с файла ${FILES[$CURRENT_INDEX]}"
else
echo "Снапшот не найден: начнем сначала"
fi
# Обработка файлов
for ((i=CURRENT_INDEX; i<${#FILES[@]}; i++)); do
echo "Обрабатываю ${FILES[$i]}..."
# Имитация долгой обработки
sleep 2
echo "Файл ${FILES[$i]} обработан!"
# Обновление прогресса в файле-снапшоте
echo $((i + 1)) > "$SNAPSHOT_FILE"
done
# Удаление снапшота после завершения работы
rm -f "$SNAPSHOT_FILE"
echo "Все файлы обработаны, прогресс очищен!"
Примеры вывода
Первый запуск:
Снапшот не найден: начнем сначала
Обрабатываю file1.txt...
Файл file1.txt обработан!
Обрабатываю file2.txt...
Файл file2.txt обработан!
...
Если прервать выполнение, то прогресс сохранится в progress.snapshot.
Повторный запуск:
Прогресс найден: начнем с файла file3.txt
Обрабатываю file3.txt...
Файл file3.txt обработан!
...
Чтобы обеспечить надежность:
Проверяйте, существует ли файл перед обработкой.
Используйте команды trap для удаления временных файлов при непредвиденных ошибках.
Логируйте результаты обработки.
trap 'rm -f $SNAPSHOT_FILE; echo "Ошибка! Прогресс сохранен.";' SIGINT SIGTERM
Для обработки в несколько потоков можно использовать отдельные снапшоты для каждой задачи. Например:
for file in "${FILES[@]}"; do
{
if [[ ! -f "${file}.done" ]]; then
echo "Обрабатываю $file..."
sleep 2 # Имитация обработки
echo "Файл $file обработан!"
touch "${file}.done"
fi
} &
done
wait
Файлы-снапшоты - простой, но важный инструмент для повышения надежности скриптов. Они позволяют безопасно прерывать и продолжать выполнение, экономя ваше время.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥2
Please open Telegram to view this post
VIEW IN TELEGRAM
😁26
LS как инструмент для сортировки и поиска
Обычно ls используют просто для вывода списка файлов, но на самом деле эта команда умеет больше - она может сортировать, фильтровать и даже помогать в поиске нужных данных. Разберем варианты использования.
1. Сортировка файлов по размеру. Хотите быстро найти самый тяжелый файл в каталоге? Используйте:
Если хотите отсортировать в обратном порядке (от меньшего к большему), добавьте -r:
2. Сортировка по времени изменения. Чтобы узнать, какие файлы менялись последними, используйте:
-t - сортировка по времени изменения
Если хотите узнать, какие файлы были доступны (прочитаны) последними:
А для сортировки по времени создания (если поддерживается файловой системой):
3. Поиск файлов с определенными характеристиками
По расширению. Найти все .log файлы:
По размеру (совместно с grep). Например, найти все файлы больше 100MB:
Фильтрация директорий. Только каталоги (без файлов):
4. Использование цветных фильтров. Хочется визуально выделять файлы по типу? Используйте:
Для более детальной настройки цветов можно изменить переменную LS_COLORS:
5. Совместное использование с другими командами. Команда ls хорошо сочетается с head, tail и sort:
Найти самый старый файл
Отобразить файлы, отсортированные по имени без учета регистра
BashTex📱 #linux #utils
Обычно ls используют просто для вывода списка файлов, но на самом деле эта команда умеет больше - она может сортировать, фильтровать и даже помогать в поиске нужных данных. Разберем варианты использования.
1. Сортировка файлов по размеру. Хотите быстро найти самый тяжелый файл в каталоге? Используйте:
ls -lhS
-l - детальный вывод (размер, права, дата)
-h - удобный человекочитаемый формат (KB, MB, GB)
-S - сортировка по размеру (от большего к меньшему)
Если хотите отсортировать в обратном порядке (от меньшего к большему), добавьте -r:
ls -lhSr
2. Сортировка по времени изменения. Чтобы узнать, какие файлы менялись последними, используйте:
ls -lt
-t - сортировка по времени изменения
Если хотите узнать, какие файлы были доступны (прочитаны) последними:
ls -lu
А для сортировки по времени создания (если поддерживается файловой системой):
ls -lU
3. Поиск файлов с определенными характеристиками
По расширению. Найти все .log файлы:
ls *.log
По размеру (совместно с grep). Например, найти все файлы больше 100MB:
ls -lhS | grep '[0-9][0-9][0-9]M'
Фильтрация директорий. Только каталоги (без файлов):
ls -d */
4. Использование цветных фильтров. Хочется визуально выделять файлы по типу? Используйте:
ls --color=auto
Для более детальной настройки цветов можно изменить переменную LS_COLORS:
export LS_COLORS="di=34;1:fi=0:ln=36;1:ex=32;1"
di=34;1 - каталоги (синий)
ln=36;1 - символические ссылки (голубой)
ex=32;1 - исполняемые файлы (зеленый)
5. Совместное использование с другими командами. Команда ls хорошо сочетается с head, tail и sort:
Найти самый старый файл
ls -lt | tail -n 1
Отобразить файлы, отсортированные по имени без учета регистра
ls -l | sort -f
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19
Автономное восстановление сетевого соединения при сбоях
Что делать, если сервер внезапно теряет соединение? Вручную перезапускать сетевой интерфейс? Можно автоматизировать этот процесс.
1. Простая проверка доступности сети. Начнем с базового скрипта, который проверяет соединение и перезапускает сеть, если пинг не проходит.
🔗 Как работает:
Пингует 8.8.8.8 (можно заменить на свой сервер).
Если нет ответа, записывает событие в лог и перезапускает сетевой интерфейс.
Если сеть работает, просто пишет статус в лог.
Автозапуск каждые 5 минут: Добавьте в crontab:
2. Авто-переключение на резервный интерфейс. Если ваш сервер поддерживает несколько сетевых интерфейсов (например, eth0 и eth1), можно автоматически переключаться на резервный:
🔗 Как работает:
Если основной интерфейс не отвечает, переключается на резервный.
Изменяет маршрут по умолчанию на резервное подключение.
3. Авто-переключение на резервный VPN. Если ваш сервер использует VPN, можно автоматически переключаться между провайдерами:
🔗 Как работает:
Проверяет доступность VPN (например, 10.8.0.1).
Если основной VPN не отвечает, переключается на резервный сервер.
BashTex📱 #bash
Что делать, если сервер внезапно теряет соединение? Вручную перезапускать сетевой интерфейс? Можно автоматизировать этот процесс.
1. Простая проверка доступности сети. Начнем с базового скрипта, который проверяет соединение и перезапускает сеть, если пинг не проходит.
#!/bin/bash
TARGET="8.8.8.8" # IP-адрес для проверки (Google DNS)
INTERFACE="eth0" # Ваш сетевой интерфейс
if ! ping -c 4 $TARGET &> /dev/null; then
echo "$(date) - Потеряно соединение! Перезапускаю сеть..." >> /var/log/network_recovery.log
systemctl restart networking
systemctl restart NetworkManager # Для дистрибутивов с NetworkManager
ip link set $INTERFACE down && sleep 2 && ip link set $INTERFACE up
else
echo "$(date) - Сеть работает нормально" >> /var/log/network_recovery.log
fi
Пингует 8.8.8.8 (можно заменить на свой сервер).
Если нет ответа, записывает событие в лог и перезапускает сетевой интерфейс.
Если сеть работает, просто пишет статус в лог.
Автозапуск каждые 5 минут: Добавьте в crontab:
*/5 * * * * /path/to/network_check.sh
2. Авто-переключение на резервный интерфейс. Если ваш сервер поддерживает несколько сетевых интерфейсов (например, eth0 и eth1), можно автоматически переключаться на резервный:
#!/bin/bash
TARGET="8.8.8.8"
PRIMARY_IF="eth0"
SECONDARY_IF="eth1"
if ! ping -c 4 $TARGET &> /dev/null; then
echo "$(date) - Основной интерфейс $PRIMARY_IF не отвечает, переключаюсь на $SECONDARY_IF" >> /var/log/network_recovery.log
ip route del default
ip route add default via 192.168.1.2 dev $SECONDARY_IF
else
echo "$(date) - Основной интерфейс $PRIMARY_IF работает" >> /var/log/network_recovery.log
fi
Если основной интерфейс не отвечает, переключается на резервный.
Изменяет маршрут по умолчанию на резервное подключение.
3. Авто-переключение на резервный VPN. Если ваш сервер использует VPN, можно автоматически переключаться между провайдерами:
#!/bin/bash
VPN_PRIMARY="vpn1"
VPN_SECONDARY="vpn2"
if ! ping -c 4 10.8.0.1 &> /dev/null; then
echo "$(date) - Основной VPN не отвечает, переключаюсь на резервный $VPN_SECONDARY" >> /var/log/network_recovery.log
systemctl restart openvpn@$VPN_SECONDARY
else
echo "$(date) - VPN работает стабильно" >> /var/log/network_recovery.log
fi
Проверяет доступность VPN (например, 10.8.0.1).
Если основной VPN не отвечает, переключается на резервный сервер.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥2🎅1
Динамическая замена строк в переменных без внешних утилит
В Bash многие привыкли использовать
1. Простая замена в строке. Стандартная конструкция:
Вывод:
Здесь world заменяется на Bash.
2. Замена всех вхождений. Если слово встречается несколько раз, можно заменить все его появления:
Вывод:
Обратите внимание на // — оно заменяет все вхождения.
3. Удаление подстроки. Чтобы удалить слово из строки, просто оставьте замену пустой:
Вывод:
4. Замена только в начале или конце строки.
Замена в начале строки:
Вывод:
Замена в конце строки:
Вывод:
5. Динамическая замена значений в переменных. Допустим, у нас есть путь, и мы хотим заменить часть его на другую:
Вывод:
6. Усложненный пример: замена динамических данных. Предположим, у нас есть строка с датой, и мы хотим заменить год на текущий:
Вывод (если 2025 год):
BashTex📱 #linux #utils
В Bash многие привыкли использовать
sed, awk или tr для замены текста, но можно обойтись без них, используя встроенные механизмы обработки строк1. Простая замена в строке. Стандартная конструкция:
text="Hello, world!"
echo "${text/world/Bash}"
Вывод:
Hello, Bash!Здесь world заменяется на Bash.
2. Замена всех вхождений. Если слово встречается несколько раз, можно заменить все его появления:
text="apple banana apple orange"
echo "${text//apple/grape}"
Вывод:
grape banana grape orangeОбратите внимание на // — оно заменяет все вхождения.
3. Удаление подстроки. Чтобы удалить слово из строки, просто оставьте замену пустой:
text="error: file not found"
echo "${text/error: /}"
Вывод:
file not found4. Замена только в начале или конце строки.
Замена в начале строки:
text="error_log_123"
echo "${text/#error_/warn_}"
Вывод:
warn_log_123Замена в конце строки:
text="backup_20240101.tar"
echo "${text/%tar/gz}"
Вывод:
backup_20240101.gz5. Динамическая замена значений в переменных. Допустим, у нас есть путь, и мы хотим заменить часть его на другую:
path="/home/user/project/file.txt"
new_path="${path/user/admin}"
echo "$new_path"
Вывод:
/home/admin/project/file.txt6. Усложненный пример: замена динамических данных. Предположим, у нас есть строка с датой, и мы хотим заменить год на текущий:
text="Backup from 2023-05-01"
current_year=$(date +%Y)
echo "${text/2023/$current_year}"
Вывод (если 2025 год):
Backup from 2025-05-01BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥2
Быстрая настройка GitLab CI/CD для проектов
Автоматизация сборки, тестирования и развертывания - важный шаг в DevOps. GitLab CI/CD позволяет быстро организовать процесс CI/CD с минимальными затратами.
1. Подготовка GitLab Runner. Перед запуском CI/CD необходимо настроить GitLab Runner — агент, выполняющий задачи в пайплайне.
Установка и регистрация GitLab Runner:
Токен можно найти в разделе Settings → CI/CD → Runners в GitLab.
2. Создание
🔗 Что тут происходит?
build - сборка проекта
test - запуск тестов
deploy - деплой на сервер (например, с помощью
3. Запуск и отладка. После коммита .gitlab-ci.yml в репозиторий GitLab автоматически запустит пайплайн.
Просмотр логов сборки: Перейдите в "CI/CD → Pipelines", выберите нужный пайплайн и смотрите логи выполнения.
Отладка вручную: Можно запустить локальный Runner для проверки:
BashTex📱 #utils
Автоматизация сборки, тестирования и развертывания - важный шаг в DevOps. GitLab CI/CD позволяет быстро организовать процесс CI/CD с минимальными затратами.
1. Подготовка GitLab Runner. Перед запуском CI/CD необходимо настроить GitLab Runner — агент, выполняющий задачи в пайплайне.
Установка и регистрация GitLab Runner:
# Устанавливаем GitLab Runner
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/noscript.deb.sh | sudo bash
sudo apt install gitlab-runner -y
# Регистрируем Runner в GitLab
sudo gitlab-runner register \
--url "https://gitlab.com/" \
--registration-token "ВАШ_ТОКЕН" \
--executor "docker" \
--docker-image "alpine:latest"
Токен можно найти в разделе Settings → CI/CD → Runners в GitLab.
2. Создание
.gitlab-ci.yml. Файл .gitlab-ci.yml описывает все стадии CI/CD. Простейший вариант:
stages:
- build
- test
- deploy
build:
stage: build
noscript:
- echo "Сборка проекта..."
- make build # Команда сборки
test:
stage: test
noscript:
- echo "Запуск тестов..."
- make test # Запуск тестов
deploy:
stage: deploy
noscript:
- echo "Деплой на сервер..."
- rsync -avz ./project user@server:/var/www/project
only:
- main # Деплой только из ветки main
build - сборка проекта
test - запуск тестов
deploy - деплой на сервер (например, с помощью
rsync)3. Запуск и отладка. После коммита .gitlab-ci.yml в репозиторий GitLab автоматически запустит пайплайн.
Просмотр логов сборки: Перейдите в "CI/CD → Pipelines", выберите нужный пайплайн и смотрите логи выполнения.
Отладка вручную: Можно запустить локальный Runner для проверки:
gitlab-runner exec shell test
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Циклы с подсчётом времени выполнения: оптимизация итераций
При написании Bash-скриптов важно не только выполнять задачи, но и делать это максимально эффективно. Разберемся, как можно замерять время выполнения циклов и оптимизировать их.
1. Измерение времени выполнения. Для базового замера используем команду time.
Пример простого for-цикла:
real - общее время выполнения
user - время, потраченное процессором на выполнение кода
sys - время, потраченное на системные вызовы
2. Оптимизация цикла. Допустим, у нас есть for-цикл, выполняющий сложные вычисления:
Но можно ускорить этот процесс!
Оптимизация с seq и awk:
Результат: Использование awk снижает нагрузку на bash, так как он быстрее работает с числами.
3. Запуск в параллельном режиме. Для ещё большего ускорения используем xargs -P:
-P 4 запускает 4 параллельных процесса, ускоряя обработку данных.
BashTex📱 #bash #utils
При написании Bash-скриптов важно не только выполнять задачи, но и делать это максимально эффективно. Разберемся, как можно замерять время выполнения циклов и оптимизировать их.
1. Измерение времени выполнения. Для базового замера используем команду time.
Пример простого for-цикла:
time for i in {1..10000}; do echo -n; done
real 0m0.245s
user 0m0.190s
sys 0m0.055s
real - общее время выполнения
user - время, потраченное процессором на выполнение кода
sys - время, потраченное на системные вызовы
2. Оптимизация цикла. Допустим, у нас есть for-цикл, выполняющий сложные вычисления:
start=$(date +%s) # Засекаем время начала
for i in {1..1000}; do
echo $((i * i)) > /dev/null # Квадрат числа
done
end=$(date +%s) # Засекаем время окончания
echo "Время выполнения: $((end - start)) секунд"
Но можно ускорить этот процесс!
Оптимизация с seq и awk:
time seq 1 1000 | awk '{print $1 * $1}' > /dev/null
Результат: Использование awk снижает нагрузку на bash, так как он быстрее работает с числами.
3. Запуск в параллельном режиме. Для ещё большего ускорения используем xargs -P:
time seq 1 1000 | xargs -P 4 -I {} bash -c 'echo $(( {} * {} ))' > /dev/null
-P 4 запускает 4 параллельных процесса, ускоряя обработку данных.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Please open Telegram to view this post
VIEW IN TELEGRAM
😁13👍4
basename и dirname: неочевидные сценарии работы с путями
Команды basename и dirname - инструменты для работы с файловыми путями в Bash. Они часто используются в скриптах, но не все знают о неочевидных возможностях. Разбираемся!
1️⃣ Быстрая обработка путей
🔹 basename извлекает имя файла
🔹 dirname оставляет только путь к каталогу
2️⃣ Работа с расширениями. Можно удалить расширение файла с помощью basename:
📌 Это полезно, например, при генерации логов:
💡 Здесь $0 - имя запущенного скрипта.
3️⃣ Разбор путей без / в конце. Если путь оканчивается на /, dirname может вернуть неожиданный результат:
📌 Чтобы избежать проблем, лучше заранее удалять слеши:
4️⃣ Разделение относительных и абсолютных путей. Хотим понять, абсолютный ли путь передан в скрипт?
5️⃣ Комбинируем с find и xargs. Переименовываем все .txt файлы в .bak, сохраняя имена:
📌 Здесь basename убирает .txt, а dirname сохраняет путь.
BashTex📱 #linux #utils
Команды basename и dirname - инструменты для работы с файловыми путями в Bash. Они часто используются в скриптах, но не все знают о неочевидных возможностях. Разбираемся!
file_path="/var/log/nginx/access.log"
echo "Файл: $(basename "$file_path")" # access.log
echo "Каталог: $(dirname "$file_path")" # /var/log/nginx
basename "/home/user/noscript.sh" .sh # Выведет: noscript
log_file="$(basename "$0" .sh).log"
echo "Логи пишем в $log_file"
dirname "/etc/nginx/" # Выведет: /etc
dirname "/etc/nginx" # Выведет: /etc
path="/etc/nginx/"
dirname "${path%/}" # /etc/nginx
path="./noscript.sh"
if [[ "$(dirname "$path")" == "." ]]; then
echo "Это относительный путь"
else
echo "Это абсолютный путь"
fi
find /path/to/files -name "*.txt" | while read file; do
mv "$file" "$(dirname "$file")/$(basename "$file" .txt).bak"
done
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Обработка многомерных массивов и ассоциативных списков в Bash
Bash не поддерживает многомерные массивы на уровне языка, но это не мешает нам создавать их с помощью ассоциативных массивов или хитрых обходных путей. Сегодня про то, как это сделать.
1️⃣ Ассоциативные массивы как таблицы. С Bash 4+ появились ассоциативные массивы (declare -A), что позволяет организовать данные в виде таблицы:
📌 Мы используем ключи вида userX,property, чтобы эмулировать двумерную структуру.
2️⃣ Многомерные массивы через вложенные списки. Если нужно хранить массив внутри массива, можно использовать строки с разделителем:
📌 Здесь IFS=":" read -r ... разбивает строку на переменные.
3️⃣ Итерация по многомерной структуре. Перебираем всех пользователей и их данные:
📌 !users[@] возвращает список всех ключей.
4️⃣ JSON-подход с jq. Если сложность растет, лучше работать с JSON:
BashTex📱 #linux #utils
Bash не поддерживает многомерные массивы на уровне языка, но это не мешает нам создавать их с помощью ассоциативных массивов или хитрых обходных путей. Сегодня про то, как это сделать.
declare -A users
users["user1,name"]="Egor"
users["user1,age"]=25
users["user2,name"]="Ivan"
users["user2,age"]=30
echo "Имя user1: ${users["user1,name"]}" # Egor
echo "Возраст user2: ${users["user2,age"]}" # 30
declare -A servers
servers["db"]="192.168.1.10:5432:PostgreSQL"
servers["web"]="192.168.1.20:80:Nginx"
IFS=":" read -r ip port service <<< "${servers["db"]}"
echo "Сервер базы: IP=$ip, Порт=$port, Сервис=$service"
for key in "${!users[@]}"; do
echo "$key -> ${users[$key]}"
done
json='{"user1": {"name": "Egor", "age": 25}, "user2": {"name": "Ivan", "age": 30}}'
echo "$json" | jq '.user1.name' # Egor
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
Проверка архивов на целостность: избегаем битых бэкапов
Создавать бэкапы - хорошая практика. Но что, если архив оказался битым в самый нужный момент?😱 Разберемся, как проверять целостность архивов, чтобы не потерять важные данные.
1️⃣ Проверка tar-архива. Если архив создавался с помощью tar, его можно проверить без распаковки:
Если файл поврежден, команда выдаст ошибку:
🧑💻 Автоматическая проверка в скрипте:
2️⃣ Проверка архивов .zip. Для .zip можно использовать встроенную проверку:
Если файл битый, команда выдаст ошибки.
🧑💻 Автоматическая проверка в скрипте:
3️⃣ Проверка и автоматическое исправление rar. Если архив в формате .rar, его можно проверить так:
Если архив поврежден, rar может попытаться его восстановить:
4️⃣ Защита от битых архивов при создании
📁 Контрольные суммы. Считаем SHA256-хеш перед передачей или копированием:
А потом проверяем:
📦 Двойная упаковка с тестированием
📌 Здесь tee дублирует поток, а gzip -t сразу проверяет целостность.
BashTex📱 #linux #utils
Создавать бэкапы - хорошая практика. Но что, если архив оказался битым в самый нужный момент?
tar -tvf backup.tar.gz
Если файл поврежден, команда выдаст ошибку:
gzip: stdin: unexpected end of file
tar: Child returned status 1
tar: Error is not recoverable: exiting now
if tar -tzf backup.tar.gz &>/dev/null; then
echo "Архив исправен"
else
echo "Архив поврежден!"
fi
unzip -t backup.zip
Если файл битый, команда выдаст ошибки.
if unzip -t backup.zip | grep -q "No errors detected"; then
echo "Архив исправен"
else
echo "Архив поврежден!"
fi
rar t backup.rar
Если архив поврежден, rar может попытаться его восстановить:
rar r backup.rar
sha256sum backup.tar.gz > backup.sha256
А потом проверяем:
sha256sum -c backup.sha256
tar -cvf - logs/ | gzip | tee backup.tar.gz | gzip -t
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Скрытая мощь { } и (( )) в Bash: работа с диапазонами и числами
В Bash есть два механизма - фигурные скобки { } для работы с диапазонами и двойные круглые скобки (( )) для арифметики. Как их использовать эффективно?
1️⃣ Диапазоны и генерация последовательностей с { }. Фигурные скобки позволяют быстро создавать списки значений.
ℹ️ Простая генерация чисел:
ℹ️ Шаг в последовательности:
ℹ️ Генерация букв:
ℹ️ Использование в for-циклах:
ℹ️ Создание файлов за раз:
Создаст file_1.txt, file_2.txt, file_3.txt.
2️⃣ Арифметика с (( )) - быстрее и лаконичнее. (( )) используется для работы с числами без expr или let.
ℹ️ Базовые операции:
ℹ️ Инкремент и декремент:
ℹ️ Проверка условий без if:
ℹ️ Битовые операции:
3️⃣ Сочетание { } и (( ))
ℹ️ Сумма чисел от 1 до 10 с for:
ℹ️ Выбор только чётных чисел:
BashTex📱 #bash #utils
В Bash есть два механизма - фигурные скобки { } для работы с диапазонами и двойные круглые скобки (( )) для арифметики. Как их использовать эффективно?
echo {1..5}
1 2 3 4 5
echo {0..10..2}
0 2 4 6 8 10
echo {a..e}
a b c d e
for i in {1..3}; do
echo "Файл_$i.txt"
done
Файл_1.txt
Файл_2.txt
Файл_3.txt
touch file_{1..3}.txt
Создаст file_1.txt, file_2.txt, file_3.txt.
((sum = 5 + 3))
echo $sum
8
x=10
((x++)) # Увеличить на 1
((x--)) # Уменьшить на 1
echo $x
x=5
(( x > 3 )) && echo "x больше 3"
x больше 3
((x = 5 & 3)) # Побитовое И
echo $x
1
sum=0
for i in {1..10}; do
((sum += i))
done
echo "Сумма: $sum"
Сумма: 55
for i in {1..10}; do
((i % 2 == 0)) && echo "$i — чётное"
done
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14👍5
Please open Telegram to view this post
VIEW IN TELEGRAM
😁24👍4🔥2🫡1
Создание временных файлов и директорий
Временные файлы часто нужны в скриптах, но их создание вручную может привести к конфликтам имен или уязвимостям.
1️⃣ Создание временного файла
Файл создается с правами 600 (только владелец может читать и записывать).
2️⃣ Создание временного файла с заданным шаблоном
XXXXXX заменяется случайными символами, исключая конфликты имен.
3️⃣ Создание временной директории
⚠️ Удаление временных файлов:
Или используем trap, чтобы удалить временные файлы при завершении скрипта:
BashTex📱 #linux #utils
Временные файлы часто нужны в скриптах, но их создание вручную может привести к конфликтам имен или уязвимостям.
mktemp решает эту проблему, создавая уникальные файлы и директории с безопасными правами доступа.
tmpfile=$(mktemp)
echo "Временный файл: $tmpfile"
Временный файл: /tmp/tmp.BX9G7f9a6Z
Файл создается с правами 600 (только владелец может читать и записывать).
mktemp /tmp/mytemp.XXXXXX
XXXXXX заменяется случайными символами, исключая конфликты имен.
tmpdir=$(mktemp -d)
echo "Временная директория: $tmpdir"
Временная директория: /tmp/tmp.P8Z3K1qGfJ
rm -f "$tmpfile"
rm -rf "$tmpdir"
Или используем trap, чтобы удалить временные файлы при завершении скрипта:
trap 'rm -f "$tmpfile"' EXIT
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16
mtr vs traceroute: анализ сетевых маршрутов
Когда нужно диагностировать сетевые проблемы, чаще всего используют
▪️ traceroute - классический анализ маршрута
traceroute показывает последовательность узлов, через которые проходит пакет до цели.
📌 Показывает только один запуск, без динамики.
▪️ mtr - интерактивный анализ сети
mtr комбинирует traceroute и ping, предоставляя динамическое обновление маршрута.
📌 Отличия от traceroute:
Постоянно обновляет данные (динамический анализ).
Показывает потерю пакетов (Loss%), среднее и максимальное время отклика (Avg, Wrst).
Удобно для выявления нестабильных узлов.
💡 Когда использовать?
traceroute - если нужен единоразовый снимок маршрута.
mtr - если важно видеть динамику и выявить нестабильные узлы.
BashTex📱 #linux #networks
Когда нужно диагностировать сетевые проблемы, чаще всего используют
traceroute или mtr. Оба инструмента помогают определить путь пакетов до целевого хоста, но mtr значительно превосходит traceroute по функциональности. Разберем различия.traceroute показывает последовательность узлов, через которые проходит пакет до цели.
traceroute bashtex.com
1 192.168.1.1 (192.168.1.1) 1.234 ms 1.567 ms 1.678 ms
2 10.0.0.1 (10.0.0.1) 2.345 ms 2.678 ms 2.789 ms
3 203.0.113.1 (203.0.113.1) 10.345 ms 11.456 ms 12.567 ms
mtr комбинирует traceroute и ping, предоставляя динамическое обновление маршрута.
mtr bashtex.com
HOST: myhost Loss% Snt Last Avg Best Wrst StDev
1.|-- 192.168.1.1 0.0% 10 1.2 1.3 1.0 1.5 0.2
2.|-- 10.0.0.1 0.0% 10 2.4 2.5 2.2 3.0 0.3
3.|-- 203.0.113.1 10.0% 10 10.4 11.2 10.0 13.5 1.2
Постоянно обновляет данные (динамический анализ).
Показывает потерю пакетов (Loss%), среднее и максимальное время отклика (Avg, Wrst).
Удобно для выявления нестабильных узлов.
traceroute - если нужен единоразовый снимок маршрута.
mtr - если важно видеть динамику и выявить нестабильные узлы.
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Please open Telegram to view this post
VIEW IN TELEGRAM
😁19🫡7👍1🔥1
Масштабируемое развертывание приложений с Bash и Docker
😎 Основная идея:
Проверять текущую загрузку CPU/памяти
Автоматически запускать дополнительные контейнеры при высокой нагрузке
Останавливать лишние контейнеры при снижении нагрузки
▪️ Bash-скрипт для масштабирования
⚙️ Как использовать?
1. Сохраните скрипт, например, как
2. Сделайте его исполняемым:
3. Настройте запуск через cron (например, каждые 5 минут):
Добавьте строку:
🏳️ Что получаем:
При нагрузке выше 70% добавляются контейнеры
При снижении нагрузки контейнеры удаляются
Управление происходит автоматически
BashTex📱 #bash
Проверять текущую загрузку CPU/памяти
Автоматически запускать дополнительные контейнеры при высокой нагрузке
Останавливать лишние контейнеры при снижении нагрузки
#!/bin/bash
APP_NAME="myapp"
IMAGE="myapp_image"
LIMIT=70 # Порог загрузки CPU в процентах
MAX_CONTAINERS=5
# Получаем текущую загрузку CPU
CPU_LOAD=$(awk '{print $1}' <(grep 'cpu ' /proc/stat | awk '{print ($2+$4)*100/($2+$4+$5)}'))
# Получаем текущее количество запущенных контейнеров
RUNNING_CONTAINERS=$(docker ps -q -f "name=$APP_NAME" | wc -l)
if (( $(echo "$CPU_LOAD > $LIMIT" | bc -l) )); then
if (( RUNNING_CONTAINERS < MAX_CONTAINERS )); then
echo "Высокая нагрузка ($CPU_LOAD%). Запускаем новый контейнер..."
docker run -d --name "$APP_NAME-$RUNNING_CONTAINERS" $IMAGE
else
echo "Достигнут лимит контейнеров ($MAX_CONTAINERS)."
fi
else
if (( RUNNING_CONTAINERS > 1 )); then
STOP_CONTAINER=$(docker ps -q -f "name=$APP_NAME" | tail -n 1)
echo "Нагрузка низкая ($CPU_LOAD%). Останавливаем контейнер $STOP_CONTAINER..."
docker stop $STOP_CONTAINER && docker rm $STOP_CONTAINER
fi
fi
1. Сохраните скрипт, например, как
autoscale.sh2. Сделайте его исполняемым:
chmod +x autoscale.sh
3. Настройте запуск через cron (например, каждые 5 минут):
crontab -e
Добавьте строку:
*/5 * * * * /path/to/autoscale.sh >> /var/log/autoscale.log 2>&1
При нагрузке выше 70% добавляются контейнеры
При снижении нагрузки контейнеры удаляются
Управление происходит автоматически
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🫡1
Автоматическое монтирование сетевых папок при загрузке системы
Если вам нужно подключать сетевые папки автоматически при старте системы, лучше всего использовать /etc/fstab или systemd automount. Разберем оба способа.
1️⃣ Использование /etc/fstab. Добавьте строку в
⚠️ После изменения /etc/fstab примените команду:
2️⃣ Автоматическое монтирование через systemd. Создайте юнит
Затем включите монтирование:
💡 Какой способ выбрать?
fstab - если подключение постоянно и предсказуемо
systemd - если нужна гибкость и управление через systemctl
BashTex📱 #linux #utils
Если вам нужно подключать сетевые папки автоматически при старте системы, лучше всего использовать /etc/fstab или systemd automount. Разберем оба способа.
/etc/fstab, чтобы система монтировала папку при загрузке:
//192.168.1.100/share /mnt/share cifs username=user,password=pass,iocharset=utf8,_netdev 0 0
//192.168.1.100/share - путь к папке на сервере
/mnt/share - локальная точка монтирования
cifs - используемый протокол (для Windows/Samba)
_netdev - монтирование после установки сети
mount -a
/etc/systemd/system/mnt-share.mount:
[Unit]
Denoscription=Автоматическое монтирование сетевой папки
After=network-online.target
[Mount]
What=//192.168.1.100/share
Where=/mnt/share
Type=cifs
Options=username=user,password=pass,iocharset=utf8
[Install]
WantedBy=multi-user.target
Затем включите монтирование:
systemctl daemon-reload
systemctl enable --now mnt-share.mount
fstab - если подключение постоянно и предсказуемо
systemd - если нужна гибкость и управление через systemctl
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥1
Создание зашифрованных контейнеров с cryptsetup и LUKS
LUKS (Linux Unified Key Setup) + cryptsetup позволяют создавать зашифрованные контейнеры, доступ к которым можно получить только после ввода пароля.
📦 Что можно хранить в зашифрованном контейнере?
🔹 Личные файлы и документы
🔹 Бэкапы с конфиденциальными данными
🔹 Временные файлы, которые нужно удалять без следов
🧑💻 Создание зашифрованного контейнера
1️⃣ Создаем файл-контейнер. Допустим, нам нужен контейнер размером 1 ГБ:
2️⃣ Настраиваем LUKS-шифрование
⚠️ Важно: Этот шаг удалит все данные в файле!
При появлении запроса укажите сложный пароль для доступа к контейнеру.
3️⃣ Открываем зашифрованный контейнер
Теперь в системе появился виртуальный шифрованный диск
4️⃣ Форматируем в файловую систему
5️⃣ Монтируем и используем
Теперь файлы, скопированные в
🚫 Отключение контейнера. Чтобы отключить зашифрованный диск:
🏠 Автоматическое подключение по паролю. Можно хранить ключ для автоматического подключения в файле:
Теперь можно открыть контейнер без ввода пароля:
BashTex📱 #linux #security
LUKS (Linux Unified Key Setup) + cryptsetup позволяют создавать зашифрованные контейнеры, доступ к которым можно получить только после ввода пароля.
dd if=/dev/zero of=secure.img bs=1M count=1024
cryptsetup luksFormat secure.img
При появлении запроса укажите сложный пароль для доступа к контейнеру.
cryptsetup luksOpen secure.img secure_container
Теперь в системе появился виртуальный шифрованный диск
/dev/mapper/secure_container.
mkfs.ext4 /dev/mapper/secure_container
mkdir /mnt/secure
mount /dev/mapper/secure_container /mnt/secure
Теперь файлы, скопированные в
/mnt/secure, будут автоматически зашифрованы.
umount /mnt/secure
cryptsetup luksClose secure_container
dd if=/dev/random of=/root/luks.key bs=1 count=256
chmod 600 /root/luks.key
cryptsetup luksAddKey secure.img /root/luks.key
Теперь можно открыть контейнер без ввода пароля:
cryptsetup luksOpen secure.img secure_container --key-file /root/luks.key
BashTex
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍5