Linux для чайника
20K subscribers
87 photos
4 files
78 links
Linux
- Разбор утилит / инструментов
- Новости / факты
- Опросы для проверки знаний, навыков
и многое другое.

Только по вопросам сотрудничества: @altmainf

Регистрация в перечне РКН https://clck.ru/3EpL9L
Download Telegram
Каждый раз, когда вы будете устанавливать программы с помощью aptitude, будет загружаться DЕВ-архив и помещаться в папку /var/cache/apt/archives.

Скорее всего, там уже есть файлы:
ls /var/cache/apt/archives/

Для освобождения места на диске, можно применить:
sudo aptitude clean

Повторное выполнение команды ls покажет, что все пакеты удалены, но если у вас слабый интернет и вам необходима неделя, чтобы загрузить последние версии программных пакетов (что очень мало вероятно, сейчас уже ..), то следует подумать дважды, прежде чем выполнять действия, описанные выше, либо воспользоваться
sudo aptitude autoclean

который удалит только устаревшие пакеты.
Если диск заполняется и нужно знать, где находятся все занимающие место медиафайлы, поможет команд du.

Без аргументов она выводит использование диска для каждого каталога в иерархии каталогов, начиная с текущего рабочего каталога. (Это может быть длинный список, для примера просто запусти команду du в ( / ), чтобы понять, о чем речь. Когда надоест смотреть, нажимай Ctrl+C)

Команда du -s включает режим общего подсчета для вывода только итоговой суммы.

Чтобы оценить все файлы и подкаталоги в определенном каталоге, перейди в него и запусти команду du -s *, но имей в виду, что могут существовать каталоги с точкой, которые эта команда не увидит.

В посте ранее приводился список аргументов команды.
Замена традиционной команды ls

exa - замена для команды ls, написанная на Rust, используется для отображения списка файлов и каталогов. Призвана предоставлять более удобные по умолчанию форматирование и цвета, а также дополнительные функции, такие как дерево каталогов.

Примеры:
Отобразить список файлов с подробной информацией:
exa -l

Отобразить список файлов, включая скрытые, с подробной информацией:
exa -la

Показать древовидный вывод содержимого каталога:
exa --tree

Показать древовидный вывод содержимого каталога с указанием уровня вложенности:
exa --tree --level=2

Отобразить файлы с информацией о Git-статусе:
exa -l --git

Установка exa зависит от вашего дистрибутива Linux. Например, для дистрибутивов на основе Debian:
sudo apt install exa
Модули ядра Linux

Ядро Linux — является монолитным ядром. 
Это значит, что весь исполняемый код сосредоточен в одном файле. Такая архитектура имеет некоторые недостатки, например, невозможность установки новых драйверов без пересборки ядра. Но разработчики нашли решение и этой проблеме, добавив систему модулей.

Модули ядра Linux собираются только под определенную версию ядра и находятся в папке /lib/modules/.

Основные команды для управления модулями.
 ⁃ lsmod - посмотреть загруженные модули
 ⁃ modinfo - информация о модуле
 ⁃ insmod - загрузить модуль
 ⁃ rmmod - удалить модуль

Чтобы посмотреть все установленные модули ядра Linux в системе:
dpkg -S *.ko | grep /lib/modules
Файловую систему необходимо смонтировать до того, как она станет видимой для процессов.

Точкой монтирования для ФС может быть любой каталог.

Например, команда
sudo mount /dev/sda1 /mnt/temp

монтирует ФС в разделе, представленном файлом устройства /dev/sda1 в каталоге /mnt, который является традиционным для временных точек монтирования.

Размер файловой системы можно проверить с помощью команды df. Например:
df -h /mnt/web1 

В приведенном примере флаг -h используется для выдачи результатов в понятном для человека виде.
Поиск введенных ранее команд в командной строке можно организовать по префиксу. То есть набираем "cd " и при нажатии вверх-вниз видим только команды начинающейся с "cd ".

Для такой возможности - открываем на редактирование файл ~/.inputrc и записываем туда:

"\e[A": history-search-backward
"\e[B": history-search-forward

Сохраняем. Готово.
Отобразить список открытых файлов и псевдофайлов, в том числе и сокетов, как локальных, так и протоколов TCP и UDP, можно с помощью команды lsof

К примеру, показать все TCP и UDP сокеты
lsof -i

Показать все TCP и UDP сокеты, связанные с адресом 192.168.1.5.
lsof -i@192.168.1.5

Тоже самое, но при отображении не преобразовывать адреса хостов и номера портов в доменные имена и названия сервисов.
lsof -i@192.168.1.5 -n -P

Показать все TCP сокеты; при отображении не преобразовывать адреса хостов и номера портов.
lsof -i TCP -n -P

Показать все UDP сокеты, связанные с адресом 192.168.1.5; при отображении не преобразовывать адреса хостов и номера портов.
lsof -i UDP@192.168.1.5 -n -P
Системному администратору или DevOps-инженеру часто требуется быстро собрать информацию о сервере: версия ОС, ресурсы, нагрузка, сеть, установленные пакеты и т.д.
Обычно это делается набором команд вроде lscpu, free -h, df -h, ip a, uptime и многих других.

Но что если всё это можно объединить в один универсальный отчёт, создаваемый по расписанию и сохраняемый в файл?
Для этого идеально подойдёт небольшой Bash-скрипт, который собирает ключевые метрики и формирует системный отчёт.

#!/bin/bash
# sysreport.sh — генерация системного отчёта для Linux

REPORT="$HOME/sysreport_$(hostname)_$(date +%F_%H-%M).txt"

{
echo "======================================"
echo "🖥 СИСТЕМНЫЙ ОТЧЁТ ($(hostname))"
echo "======================================"
echo "Дата: $(date)"
echo "Пользователь: $USER"
echo "--------------------------------------"

echo ""
echo "=== ОС и ядро ==="
lsb_release -a 2>/dev/null || cat /etc/os-release
uname -a

echo ""
echo "=== Аппаратные данные ==="
echo "CPU:"
lscpu | grep -E 'Model name|CPU\(s\)|Thread|Core'
echo ""
echo "Память:"
free -h
echo ""
echo "Диски:"
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT
echo ""
echo "Файловые системы:"
df -hT | grep -v tmpfs

echo ""
echo "=== Сеть ==="
ip -brief address
echo ""
echo "Маршруты:"
ip route show
echo ""
echo "DNS-серверы:"
grep "nameserver" /etc/resolv.conf

echo ""
echo "=== Нагрузка и процессы ==="
echo "Uptime: $(uptime -p)"
echo "Средняя загрузка: $(uptime | awk -F'load average:' '{print $2}')"
echo "Топ-5 по CPU:"
ps -eo pid,comm,%cpu --sort=-%cpu | head -6
echo ""
echo "Топ-5 по памяти:"
ps -eo pid,comm,%mem --sort=-%mem | head -6

echo ""
echo "=== Активные подключения ==="
sudo netstat -tulnp 2>/dev/null | head -10 || ss -tulnp | head -10

echo ""
echo "=== Последние входы пользователей ==="
last -n 5

echo ""
echo "=== Обновления системы ==="
if command -v apt &>/dev/null; then
apt list --upgradable 2>/dev/null | grep -v "Listing" || echo "Все пакеты обновлены."
elif command -v dnf &>/dev/null; then
dnf check-update || echo "Все пакеты обновлены."
fi

} > "$REPORT"

echo " Отчёт сохранён в: $REPORT"


Для запуска:
chmod +x sysreport.sh
./sysreport.sh


Создаётся файл вроде:
/home/admin/sysreport_server01_2025-11-12_14-05.txt
Встроенная команда : — «делай ничего, но успешно»

Команда : есть в POSIX, но почти никто не использует её в реальных скриптах.
Она ничего не делает, ничего не выводит и всегда возвращает 0.

Примеры:

• Проверка обязательных переменных
: "${DB_HOST:?Переменная DB_HOST обязательна}"
Если переменной нет — Bash мгновенно завершит скрипт с ошибкой.

«Пустое» вычисление
i=0
: $((i++))
echo "$i" # 1

Строка выглядит как no-op, но выполняет арифметику.

Бесконечный цикл
while :; do
echo "Работаю..."
sleep 1
done

Лучше, чем while true, потому что не вызывает внешнюю команду
$PIPESTATUS — статусы всех команд в pipeline

Обычное поведение Bash:
cmd1 | cmd2 | cmd3
echo $? # ← статус *последней* команды

Но если cmd1 сломалась — вы не узнаете.

Пример:
grep ERROR log.txt | sort | uniq
echo "${PIPESTATUS[@]}"

Выход, например: 1 0 0

Практическая польза:
Проверка pipeline, который не должен молча ломаться:
grep "$pattern" logfile |
awk '{print $2}' |
sort -u

if (( PIPESTATUS[0] != 0 )); then
echo "Ошибка: grep ничего не нашёл"
fi
Магические модификаторы строк ${var@Q}, ${var@U}, ${var@L}

Пример:
v="Hello World"
echo "${v@Q}" # 'Hello World'
echo "${v@U}" # HELLO WORLD
echo "${v@L}" # hello world


Практическое применение:
${var@Q} — идеально подходит для безопасной сериализации аргументов в логи:
echo "Запускаю с аргументом: ${user_input@Q}"
Файловые дескрипторы в Bash

Когда мы пишем Bash-скрипты, большинство операций с файлами выглядит максимально просто:
cmd < input.txt
cmd > output.txt
cmd >> output.txt

Но за этими короткими операторами скрывается мощная система: файловые дескрипторы (FD).

А знание о них открывает возможности, которые обычное перенаправление не покрывает в принципе: работа с несколькими файлами, сложные пайплайны, межпроцессное взаимодействие и даже работа с потоками как с объектами.

Что такое файловые дескрипторы?
У каждого процесса в Linux есть три стандартных канала:
FD Назначение
0 stdin (ввод)
1 stdout (вывод)
2 stderr (ошибки)

Но процесс может иметь дополнительные дескрипторы:
3, 4, 5 … — хоть до сотен.

Это такие же каналы ввода-вывода, как и 0–2, только вы сами решаете, куда они ведут.

Зачем нужны дополнительные FD?
Обычное перенаправление < file может быть применено только один раз.
То есть вы не можете «последовательно читать два файла» в одном цикле:
while read line; do …; done < file1 < file2 # так не работает
Более того, невозможно одновременно читать из одного файла и писать в другой ― в рамках одного while read.

Файловые дескрипторы это исправляют.

• Открываем файл на чтение в FD 3
exec 3< file.txt
Теперь файл открыт и доступен по номеру FD 3.
Читаем:
read line <&3
echo "$line"

Закрываем: exec 3<&-

• Открываем файл на запись в FD 4
exec 4> output.log
echo "Hello" >&4
exec 4>&-


Пример: одновременно читать один файл и писать в другой
exec3< input.txt
exec 4> output.txt

while read -r line <&3; do
echo "[LOG] $line" >&4
done

exec 3<&-
exec 4>&-


Пример: два входных файла одновременно
exec 3< fileA.txt
exec 4< fileB.txt

read A <&3
read B <&4

echo "A: $A"
echo "B: $B"

exec 3<&-
exec 4<&-


• Подводный камень: FD могут конфликтовать
Большая проблема классического подхода:
- вы вручную выбираете номер,
- FD может быть занят библиотекой или другим скриптом,
- при вложенных bash-функциях конфликт становится реальным.

Например, если вы выбрали FD 3, а ваш скрипт был вызван другой программой, которая тоже использует FD 3 ― поведение будет непредсказуемым.

Решение существует, и оно элегантно.
Оно появилось в современных версиях Bash, но о нём почти никто не знает.

Это — динамические файловые дескрипторы через {fd}.
Динамические файловые дескрипторы в Bash: скрытая фича, которая всё меняет

Bash давно умеет сам выбирать безопасные свободные FD, и делает это удивительно удобно.

Этот пост — о малоизвестном синтаксисе {fd} и реальных кейсах его применения.

• Что такое динамические файловые дескрипторы?
Синтаксис: exec {fd}< file.txt
Смысл:
- Bash находит свободный номер FD, например 11.
- Открывает файл file.txt для чтения.
- Записывает номер (11) в переменную fd.
Проверка:
echo "$fd" # например 11
Теперь файл привязан к FD 11, и вы работаете с переменной $fd.

• Почему это важно?
- не нужно угадывать свободный номер FD
- нет конфликтов с библиотеками
- можно открывать десятки файлов подряд
- можно работать с каналами процессов и /dev/fd/*
- проще читать и писать разные потоки одновременно

• Простейший пример:
exec {fd}< file.txt

while read -r line <&$fd; do
echo "$line"
done

exec {fd}<&-

FD создаётся динамически, закрывается безопасно.

• Два файла одновременно (без конфликтов)
exec {a}< fileA.txt
exec {b}< fileB.txt

read A <&$a
read B <&$b

echo "A: $A"
echo "B: $B"

exec {a}<&-
exec {b}<&-

Не нужно думать про FD 3, 4, 5…

• Чтение + запись одновременно
exec {in}< data.txt
exec {out}> log.txt

while read -r line <&$in; do
echo "line: $line" >&$out
done

exec {in}<&-
exec {out}>&-


• Работа с потоками процессов: <( … )
Динамические FD работают не только с файлами:
exec {tmpfd}<(sed 's/foo/bar/g' data.txt)
cat <&$tmpfd
exec {tmpfd}<&-

<(...) создаёт временный поток (/dev/fd/…), а {tmpfd} превращает его в аккуратный FD.

Реальный практический пример:

Задача:
— читать лог,
— писать его полностью в один файл,
— строки с ERROR писать отдельно,
— считать WARNING.


Решение:
exec {in}< log.txt
exec {all}> all.log
exec {err}> errors.log

warnings=0

while read -r line <&$in; do
echo "$line" >&$all

if [[ $line == *ERROR* ]]; then
echo "$line" >&$err
fi

[[ $line == *WARNING* ]] && ((warnings++))
done

exec {in}<&-
exec {all}>&-
exec {err}>&-

echo "Warnings: $warnings"

С классическими FD 3, 4, 5 такой код был бы более рискованным — конфликты гарантированы.

• Как увидеть, что FD создан?
ls -l /proc/$$/fd
После: exec {fd}< file
увидите: 11 -> file
Инструмент сетевой диагностики MTR

MTR (My Traceroute) — инструмент для сетевой диагностики в Linux. Он сочетает функциональность traceroute и ping, предоставляя реал-тайм мониторинг пути пакетов от вашего компьютера до целевого хоста.

MTR работает в интерактивном режиме и может генерировать отчеты. Он часто используется сетевыми администраторами, разработчиками и пользователями для диагностики интернет-соединений.

Установка MTR
MTR обычно предустановлен в большинстве дистрибутивов Linux, но если нет, установите его через менеджер пакетов:
Ubuntu/Debian:
sudo apt update && sudo apt install mtr
После установки проверьте версию: mtr --version.

Основные команды и опции
Запуск MTR прост: mtr [опции] <цель>, где <цель> — IP-адрес или домен (например, google.com).

Ключевые опции:
-r (report mode): Генерирует статический отчет вместо интерактивного режима. Полезно для скриптов или логов.
-c <число>: Количество пакетов для отправки (по умолчанию 10 в report mode).
-i <секунды>: Интервал между пакетами (по умолчанию 1 секунда).
-n: Не разрешать имена хостов (показывать только IP).
-w: Широкий вывод (больше столбцов).
-p: Режим ping (только ping без traceroute).
-T: Использовать TCP вместо ICMP (полезно для обхода фаерволов).
-U: Использовать UDP вместо ICMP.
--no-dns: Отключить разрешение DNS.
-h: Справка по всем опциям.

В интерактивном режиме (без -r) MTR показывает динамическую таблицу. Используйте клавиши:

q — выход.
d — переключить режим отображения (статистика/график).
j — перейти к следующему узлу.
k — перейти к предыдущему узлу.
? — справка по клавишам.

Примеры использования
• Базовый интерактивный запуск: mtr google.com
Это откроет интерактивное окно с таблицей: столбцы показывают хоп (узел), потерю пакетов, среднюю задержку, лучший/худший/последний пинг и jitter (колебания).

• Генерация отчета: mtr -r -c 10 google.com
Выводит текстовый отчет, который можно сохранить: mtr -r -c 10 google.com > report.txt.

• Тестирование с TCP (для обхода ICMP-блокировок): mtr -T google.com
Полезно, если ICMP заблокирован фаерволами.

• Мониторинг с интервалом 0.5 секунды: mtr -i 0.5 -c 20 example.com

• Проверка локальной сети: mtr 192.168.1.1
(Замените IP на ваш роутер или сервер.)

Интерпретация результатов
Loss %: Процент потерянных пакетов. Высокий (более 5%) указывает на проблемы.
Snt: Отправлено пакетов.
Last: Последняя задержка.
Avg: Средняя задержка.
Best/Wrst: Лучшая/худшая задержка.
StDev: Стандартное отклонение (jitter) — показывает стабильность.
Предположим, что вам нужно запустить приложение с графическим интерфейсом gedit с помощью соответствующей команды и закрыть окно эмулятора терминала без завершения работы этого приложения.

В этом случае сначала следует запустить его в фоновом режиме:
gedit &

В результате вы увидите окно приложения, а в окне терминала будет выведен идентификатор соответствующей задачи, например:
[1] 14191

Теперь следует удалить задачу с известным идентификатором из таблицы задач командной оболочки:
disown 14191

После этого вы можете закрыть окно эмулятора терминала. Приложение с графическим интерфейсом будет работать как ни в чем ни бывало.
globstar и рекурсивный **

Включаем:

shopt -s globstar

Используем:

echo **/*.py
Полный обход директорий — без find.

Пример реального скрипта:
for f in **/*.md; do
pandoc "$f" -o "${f%.md}.html"
done
Несколько распространённых и полезных идиом Bash

1. Проверка существования файла или директории
if [ -f "$file" ]; then
echo "Файл существует"
fi

Используется для проверки файлов (-f), директорий (-d), исполняемых файлов (-x) и т.д. Полезно перед операциями, чтобы избежать ошибок.

2. Условное присваивание переменной (с дефолтным значением)
name=${NAME:-"Гость"}
Если переменная NAME пустая или не установлена, присваивает "Гость". Аналогично ${VAR:=value} для установки.

3. Цикл по файлам в директории
for file in *.txt; do
echo "Обрабатываю $file"
done

Простой способ итерации по файлам. Осторожно с пробелами в именах — используй for file in *; do и кавычки.

4. Чтение строк из файла с циклом while
while IFS= read -r line; do
echo "Строка: $line"
done < input.txt

Безопасное чтение файла построчно, без потери пробелов. IFS= отключает разделение, -r сохраняет бэкслеши.

5. Проверка успешности команды
if command; then
echo "Команда прошла успешно"
else
echo "Ошибка"
fi

Bash возвращает код выхода (0 — успех). Это основа для обработки ошибок.

6. Here-документ для многострочного ввода
cat << EOF
Это многострочный текст.
EOF

Полезно для создания конфигов или скриптов на лету. << — heredoc, EOF — маркер конца.

7. Trap для очистки при выходе
trap 'rm -f /tmp/tempfile' EXIT
Автоматическая очистка временных файлов при завершении скрипта. Можно ловить сигналы вроде INT (Ctrl+C).

8. Set -e для строгого режима
set -e
# Теперь скрипт выходит при первой ошибке

Делает скрипт "строгим" — он прерывается на первой неудачной команде. Комбинируй с set -u (ошибка на неустановленных переменных) и set -o pipefail (для пайпов).
Встроенные команды календарей

cal: Простой календарь на текущий месяц. cal покажет календарь, cal 2025 — на год, cal -3 — на три месяца. (ncal для альтернативного вида).

calendar: Утилита из пакета bsdmainutils (sudo apt install bsdmainutils для Ubuntu).
Создайте файл ~/.calendar с событиями в формате "MM/DD/YYYY описание". Команда calendar покажет предстоящие события.

at и cron: Для напоминаний.
at — одноразовые: echo "notify-send 'Время встречи'" | at 14:00 tomorrow.
cron — повторяющиеся: crontab -e и добавьте 0 9 * * 1-5 notify-send "Еженедельный отчет". (Установите at через пакетный менеджер, если нужно).
Проверка, выполняется ли скрипт в interactive shell

[[ $- == *i* ]]

В переменной $- содержатся флаги текущего shell, и если там есть буква i, то оболочка интерактивная.

Допустим, у нас есть скрипт, который выводит приветствие только если его запустили интерактивно (например, вручную), но молчит, когда его запускает cron, systemd, ssh-скрипты и т.п.


#!/usr/bin/env bash

# Идиома: определение интерактивности оболочки
if [[ $- == *i* ]]; then
echo "Добро пожаловать! Скрипт запущен интерактивно."
echo "Можно показывать красивые подсказки, приглашения, меню…"
else
# Ничего не выводим или выводим очень лаконично
echo "non-interactive mode"
fi

echo "Основная работа скрипта продолжается..."


Cпецпеременная Bash ($-) — список текущих shell-опций.
Например: himBH Где: i → interactive (если есть — оболочка интерактивная). Остальные буквы — разные режимы (h, m, B и т.д.)

Примеры запуска:

Интерактивно (пишем в терминале)
$ ./script.sh
Добро пожаловать! Скрипт запущен интерактивно.
Можно показывать красивые подсказки, приглашения, меню…
Основная работа скрипта продолжается...


Неинтерактивно (через pipe)
$ echo | bash script.sh
non-interactive mode
Основная работа скрипта продолжается...


Через cron (эффект аналогичный)
non-interactive mode
Основная работа скрипта продолжается...
Старший и младший номера устройств

Как мы помним, в UNIX — все есть файл, поэтому каждому устройству в системе соответствует имя этого устройства в каталоге /dev. 

Каждое именованное устройство в Linux однозначно характеризуется двумя (байтовыми: 0...255) номерами: старшим номером (major) — номером отвечающим за отдельный класс устройств, и младшим номером (minor) — номером конкретного устройства внутри своего класса

Если вы введёте команду ls -l, то увидите два числа (разделённые запятой) в каждой записи файла устройства перед датой последней модификации файла, где обычно показывается длина. Эти цифры являются старшим и младшим номером устройства для каждого из них (старшие номера: 1, 4, 7 и 10, а младшие: 1, 3, 5, 64, 65 и 129).
Удаление дубликатов файлов по хэшу

#!/bin/bash

# -------------------------------------------
# Скрипт проходит по всем файлам в указанной
# директории, вычисляет их хэши и удаляет
# дубликаты (спрашивая подтверждение).
# -------------------------------------------

# Директория для сканирования.
# Если пользователь не передал путь, используется текущая.
dir="${1:-.}"

# Хэш-алгоритм. Можно заменить на:
# md5sum — быстрее, но менее надёжно
# sha1sum — средне
# sha256sum — медленнее, но максимально надёжно
algo="sha256sum"

# Ассоциативный массив "хэш → путь к оригиналу".
# В нём сохраняются хэши всех уже встреченных файлов.
declare -A seen

echo "-------------------------------------------"
echo " Сканирование директории: $dir"
echo " Алгоритм хеширования: $algo"
echo "-------------------------------------------"
echo

# Используем find для обхода ВСЕХ файлов.
# -type f — только обычные файлы.
# -print0 — вывод с нулевым разделителем, чтобы корректно
# обрабатывать имена с пробелами и спецсимволами.
while IFS= read -r -d '' file; do

# Вычисляем хэш файла. Команда вида:
# sha256sum file | awk '{print $1}'
# выводит только сам хэш без имени.
hash=$($algo "$file" | awk '{print $1}')

# Если этот хэш уже есть в массиве,
# значит, файл-дубликат найден.
if [[ ${seen[$hash]} ]]; then
echo "🔁 Найден дубликат:"
echo " Оригинал: ${seen[$hash]}"
echo " Дубликат: $file"
echo

# Запрашиваем подтверждение удаления.
read -p "Удалить дубликат? [y/N]: " answer

# Удаление только если ответ 'y' или 'Y'
if [[ "$answer" =~ ^[Yy]$ ]]; then
rm -v "$file" # -v — verbose, показывает что удалено
else
echo "Пропуск."
fi

echo

else
# Если хэша нет — запоминаем файл как оригинал.
seen[$hash]="$file"
fi

# Этот синтаксис < <(...) позволяет передавать результат find
# прямо в цикл while (без создания временных файлов).
done < <(find "$dir" -type f -print0)

echo "Готово!"