Bash Советы
1.86K subscribers
54 photos
8 videos
4 links
🚀 Секреты и советы по Bash

🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!

💻 Прокачивай терминал вместе с нами! 👇
Download Telegram
Основы работы с терминалом и BASH

Основные команды терминала. Первый скрипт на BASH.
Основы BASH | Условия
Основы Bash | Циклы
Основы BASH | for, let, trap
Основы BASH | Функции, рекурсия, модули, массивы
Основы терминала | GNU awk
Основы BASH | expect, who, mesg, autoexpect

🖤 Автор: bugsandfeatures

👉@bash_srv
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👩‍💻 Считаем количество файлов в указанной директории


#!/usr/bin/env bash

# Script Name: count_files.sh
# Description: Counts the number of directories, files, and total count in a specified directory,
# with options to filter by extension and set traversal depth.
# Usage: count_files.sh [--directory <dir>] [--depth <depth>] [--extension <ext>] [--help]
# --directory <dir> (optional) - the directory to count files in (default: current directory)
# --depth <depth> (optional) - the maximum depth of directory traversal (default: unlimited)
# --extension <ext> (optional) - only count files with the specified extension
# --help (optional) - display this help message
# Example:
# ./count_files.sh
# ./count_files.sh --directory /path/to/dir --depth 2 --extension txt

set -euo pipefail

show_help() {
cat << EOF
Usage: $0 [OPTIONS]

Options:
-d, --directory DIR The directory to count files in (default: current directory)
-p, --depth DEPTH The maximum depth of directory traversal (default: unlimited)
-e, --extension EXT Only count files with the specified extension
-h, --help Display this help message

Examples:
$0
$0 --directory /path/to/dir --depth 2 --extension txt
EOF
exit 0
}

count_files() {
local dir="$1"
local depth="$2"
local extension="$3"

if [[ ! -d "$dir" ]]; then
echo "Error: Directory '$dir' does not exist."
exit 1
fi

echo -e "\nCounting files in directory: $dir"
[[ -n "$depth" ]] && echo "Depth: $depth"
[[ -n "$extension" ]] && echo "Filtering by extension: .$extension"

local find_cmd=(find "$dir")
[[ -n "$depth" ]] && find_cmd+=(-maxdepth "$depth")
[[ -n "$extension" ]] && find_cmd+=(-name "*.$extension")
find_cmd+=(-type f)

local num_files
num_files=$( "${find_cmd[@]}" | wc -l )

local num_dirs
num_dirs=$( find "$dir" ${depth:+-maxdepth "$depth"} -type d | wc -l )

local total_count=$((num_dirs + num_files))

echo "Number of directories: $num_dirs"
echo "Number of files: $num_files"
echo "Total count: $total_count"
}

main() {
local dir="$(pwd)"
local depth=""
local extension=""

# Parse options
options=$(getopt -o d:p:e:h --long directory:,depth:,extension:,help -n "$0" -- "$@")
eval set -- "$options"

while true; do
case "$1" in
-d|--directory)
dir="$2"
shift 2
;;
-p|--depth)
depth="$2"
shift 2
;;
-e|--extension)
extension="$2"
shift 2
;;
-h|--help)
show_help
;;
--)
shift
break
;;
*)
echo "Invalid option: $1"
show_help
;;
esac
done

count_files "$dir" "$depth" "$extension"
}

main "$@"


👉@bash_srv
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 Bash-совет дня: Как быстро найти и удалить пустые директории

Иногда в системах с большим количеством файлов и директорий накапливаются пустые папки. Вот простой способ найти и удалить их одним махом:


find /path/to/search -type d -empty -delete


🔍 Разбор:
- /path/to/search — укажи директорию, где искать.
- -type d — ищем только директории.
- -empty — фильтруем только пустые.
- -delete — удаляем найденные.

🛡 Важно:
Перед удалением рекомендую посмотреть, что именно будет удалено:


find /path/to/search -type d -empty


Так ты убедишься, что ничего лишнего не затронешь 😉

👉@bash_srv
📁Как отрезать расширение у файла в Bash


filename="example.txt"
name="${filename%.*}"
echo "$name"


📌 Что тут происходит:

- ${filename%.*} — удаляет последнюю точку и всё после неё, то есть расширение.

👀 Примеры:


filename="backup.tar.gz"
name="${filename%.*}" # Результат: backup.tar


Если хочешь убрать все расширения (в т.ч. .tar.gz), можно использовать вот так:


filename="backup.tar.gz"
name="${filename%%.*}" # Результат: backup


🧠 Под капотом:
- %.* — удаляет самую правую точку и всё после.
- %%.* — удаляет самую левую точку и всё после.

Мощно и без внешних команд! 🚀

👉@bash_srv
🛡 Проверка SSL-сертификатов с помощью Bash

Иногда нужно быстро проверить срок действия SSL-сертификата удалённого сайта. Вот удобный однострочник на Bash, который покажет дату окончания действия сертификата:


echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
| openssl x509 -noout -dates | grep notAfter


📆 Чтобы получить только оставшиеся дни до окончания:


end_date=$(echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2)

end_ts=$(date -d "$end_date" +%s)
now_ts=$(date +%s)
echo "Осталось дней: $(( (end_ts - now_ts) / 86400 ))"


🔒 Полезно для автоматического мониторинга или проверки перед продлением сертификатов!

👉@bash_srv
🚀 Утилита timeout: автоматическое завершение зависших команд

Когда ты запускаешь какую-то команду, и она может зависнуть — это беда. Особенно в скриптах. На помощь приходит утилита timeout из пакета coreutils.

🛠 Пример использования:

timeout 30s ./backup.sh

Эта команда завершит ./backup.sh, если она не завершится за 30 секунд.

📌 Можно задать время в секундах (s), минутах (m), часах (h) и даже днях (d).

🔄 Что произойдёт при превышении тайм-аута?
По умолчанию timeout отправляет сигнал SIGTERM, а через 5 секунд — SIGKILL, если процесс всё ещё жив.

☠️ Изменение сигнала:

timeout -s SIGINT 10s ./script.sh


📋 Проверка кода возврата:

if timeout 5s ./some_command; then
echo "Успешно"
else
echo "Команда завершена по таймауту или с ошибкой"
fi


👉@bash_srv
🧯Как отключить историю Bash — навсегда и без следов

Иногда не хочется, чтобы команды сохранялись в истории (~/.bash_history). Особенно при работе с конфиденциальными данными.



🔒 Отключение истории в текущей сессии

Просто обнуляем переменные истории:


unset HISTFILE
export HISTSIZE=0
export HISTFILESIZE=0


💥 После этого Bash не будет сохранять историю вообще. Даже после выхода из сессии.



🧼 Стереть историю прямо сейчас


history -c # очистить историю из памяти
> ~/.bash_history # стереть файл истории




🔁 Отключить навсегда (для пользователя)

Добавь в ~/.bashrc или ~/.bash_profile:


export HISTFILE=
export HISTSIZE=0
export HISTFILESIZE=0


📌 После перезапуска оболочки история вестись не будет.



🧙 Дополнительно (опционально)

Чтобы Bash не пытался писать историю на выходе:


unset HISTFILE
trap "" EXIT


🛑 Будь осторожен! Без истории сложнее откатить действия. Но иногда это нужно: безопасность превыше всего 🔐

👉@bash_srv
🔥 Убиваем процесс по порту в один клик

Когда нужно быстро освободить занятый порт, но неохота копаться в lsof и kill, вот простой и мощный однострочник:


fport() { fuser -k "$1"/tcp; }


Теперь можно просто вызвать:


fport 8080


💡 Этот алиас использует fuser, чтобы найти и завершить все процессы, прослушивающие указанный TCP-порт.

⚠️ Убедись, что fuser установлен (обычно он входит в пакет psmisc):

sudo apt install psmisc # для Debian/Ubuntu
sudo yum install psmisc # для RHEL/CentOS


🚀 Удобно для Dev-серверов, где постоянно перезапускаешь сервисы и ловишь ошибку "Address already in use".

👉@bash_srv
📌 Регулярки — Ищем email-адреса в тексте

Надо быстро вытащить email-адреса из логов или текстов? Лови универсальное регулярное выражение:


grep -Eo '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'


📦 Примеры использования:

cat файл.txt | grep -Eo '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'


🎯 Оно находит валидные email'ы вроде:
- support@domain.com
- test.user+admin@sub.domain.co

⚙️ Флаг -o в grep выводит только совпадения, без строк целиком.

📥 Используй для анализа логов, дампов или выгрузок из баз.

👉@bash_srv
🧠 Логи — Самые частые IP-адреса в access.log

Когда нужно быстро понять, кто чаще всего лупит по серверу — вот простой однострочник:


awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head


🔍 Что делает:
1. awk '{print $1}' — вытаскивает IP из первой колонки.
2. sort и uniq -c — считает повторы.
3. sort -nr | head — выводит топ-10 по частоте.

📊 Вывод будет примерно такой:

152 192.168.1.10
103 203.0.113.45
87 172.16.0.5


🔥 Подходит для NGINX, Apache и других web-логов с классическим форматом.

👉@bash_srv
🚀 Полезный Bash-скрипт: Уведомление о перезагрузке сервера 🔔

Иногда нужно предупредить пользователей, что сервер будет перезагружен, особенно если они работают в терминале. Ниже скрипт, который отправит им сообщение и задаст таймер на перезагрузку:


#!/bin/bash

TIMEOUT=5 # Через сколько минут будет перезагрузка
MESSAGE="⚠️ Внимание! Сервер будет перезагружен через $TIMEOUT минут. Пожалуйста, сохраните свою работу."

# Оповестим всех пользователей
wall "$MESSAGE"

# Поставим таймер на перезагрузку
shutdown -r +$TIMEOUT "Плановая перезагрузка сервера через $TIMEOUT минут"


📌 wall рассылает сообщение всем, у кого открыт терминал, а shutdown -r запланирует перезагрузку. Всё просто и эффективно.

💡Можно обернуть это в cron или systemd-таймер — и будет готовый инструмент для автоматических уведомлений и перезагрузок.

👉@bash_srv
🚀 Полезный Bash-скрипт: Очистка кэша пакетного менеджера APT 🧹

Иногда кэш пакетов APT разрастается и занимает лишнее место. Ниже написал простой скрипт, который поможет автоматизировать очистку и освободить дисковое пространство 💾


#!/bin/bash

# Очищаем кэш APT
echo "🧼 Очистка кэша APT..."
sudo apt clean
sudo apt autoclean

# Удаляем неиспользуемые пакеты
echo "🗑 Удаление неиспользуемых пакетов..."
sudo apt autoremove -y

# Отчёт о свободном месте
echo "📊 Свободное место после очистки:"
df -h /


📌 Как использовать:
1. Сохрани как clean_apt.sh
2. Сделай исполняемым: chmod +x clean_apt.sh
3. Запускай по необходимости или добавь в cron

Полезно для серверов с ограниченным дисковым пространством или если хочется держать систему в чистоте 😎

👉@bash_srv
🚀 Bash-совет дня: Быстрый мониторинг TCP/UDP портов

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


sudo ss -tunlp


📌 Пояснение ключей:
- -t — TCP
- -u — UDP
- -n — не разрешать имена хостов и портов (быстрее)
- -l — только слушающие сокеты
- -p — показать PID и имя процесса

🔍 Хочешь отсортировать по порту или найти конкретный? Добавь grep:

sudo ss -tunlp | grep 8080


🎯 Альтернатива на случай, если нет ss:

sudo netstat -tunlp


Полезно для отладки фаервола, проверки работы сервисов или просто для уверенности, что сервер не слушает ничего лишнего 😉

👉@bash_srv
🧹 Автоматическая очистка логов старше N дней

Если логи разрастаются, а места становится всё меньше — пора автоматизировать их очистку! Вот простой способ удалить файлы старше, скажем, 14 дней:


find /var/log -type f -name "*.log" -mtime +14 -exec rm -f {} \;


🔧 Объяснение:
- /var/log — каталог с логами (можно заменить на нужный путь);
- -type f — только файлы;
- -name "*.log" — ищем только .log-файлы;
- -mtime +14 — которым больше 14 дней;
- -exec rm -f {} — удаляем.

🛡️ Сухой запуск перед удалением:

find /var/log -type f -name "*.log" -mtime +14

Так ты увидишь, что будет удалено, прежде чем запускать rm.

📌 Добавь в cron, чтобы забыть о рутине навсегда.

👉@bash_srv
В чем разница между объявлением переменной export VAR="VALUE" и VAR="VALUE" в bash?

В bash (и других оболочках Unix) разница между командами export VAR="VALUE" и VAR="VALUE" связана с областью видимости переменной:

1. VAR="VALUE":
- Это обычное объявление переменной в текущей оболочке (сессии).
- Переменная VAR будет доступна только внутри текущей сессии, и не будет передаваться дочерним процессам, запущенным этой сессией.
- Например, если вы запустите новую команду или скрипт из текущей оболочки, VAR не будет доступна в этом дочернем процессе.

2. export VAR="VALUE":
- Команда export делает переменную VAR доступной для всех дочерних процессов текущей оболочки.
- То есть, VAR будет установлена и доступна не только в текущей сессии, но и во всех процессах, запущенных из этой сессии.
- Это полезно, когда необходимо передать значение переменной в другие программы или скрипты, запущенные из текущей оболочки.

Для примера


# Присвоение переменной без export
VAR="Hello"
bash -c 'echo $VAR' # Ничего не выведет, так как VAR не экспортирована

# Присвоение переменной с export
export VAR="Hello"
bash -c 'echo $VAR' # Выведет "Hello", так как VAR экспортирована


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

👉@bash_srv
🖥 Bash скрипт перекодировки всех файлов в директории


#!/bin/bash
#=====================================
# скрипт изменения кодировки файлов.
#=====================================
# суть для одного файла: iconv -f Исходная_кодировка -t В_какую_кодировку > выходной_файл
# CONFIG:
TYPES="*.txt"; # на случай поиска по расширению. напр. "*.log"
FROM='cp1251'; # из какой кодировки.
TO='utf8'; # в какую кодировку.
FILEPREFIX='.utf8'; # к названию перекодированного файла добавится.

# START:
if [ -z $1 ]
then
echo "Encoding all $TYPES in directory From $FROM To $TO";
echo "use $0 /Path_to_recoding_directory/"; echo;
exit 1;
else
echo "Encoding all $TYPES in directory $1 From $FROM To $TO";
echo;
find $1 -name "$TYPES" -type f -print0|while read -d '' SOURCE; do
echo "========== SOURCE: $SOURCE FROM: $FROM TO: $TO ==========";
cat "$SOURCE"|iconv -f $FROM -t $TO > "$SOURCE$FILEPREFIX";
wait;
done;
exit 0;
fi
# end


👉@bash_srv
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Bash скрипт проверки существования файла, каталога, пользователя


Проверка существования файла:


?
if ! [ -f /path/to/file ]; then
echo 'No file'
fi


Проверка существования директории:


if ! [ -d /path/directory/ ]; then
echo 'No directory'
fi


Проверка существования пользователя:


grep "username:" /etc/passwd >/dev/null
if [ $? -ne 0 ]; then
echo 'No username found'
fi


👉@bash_srv
Please open Telegram to view this post
VIEW IN TELEGRAM