Linux

Базовая теория, синтаксис Bash, а также заметки и примеры по командам для настройки и управления 🐧 Linux.


Linux

Структура каталогов

Системные группы

Загрузка ядра

Процесс загрузки системы:

Системные вызовы

Системные вызовы (Syscall) - это единственный способ для программы в User Space попросить ядро выполнить действие, требующее повышенных привилегий (например, прочитать файл, отправить пакет в сеть или создать новый процесс).

Порядок работы системных вызовов на примере процессов:

Ссылки

ln -s /path/testfile /path/test_soft_link создать символическую (-s) ссылку, которая ссылается на файл testfile
rm test_soft_link при удалении исходного файла у символической ссылки будет ошибка (No such file or directory)

ln /path/testfile /path/test_hard_link создать жестку ссылку, которая указывает на один и тот же inode (адрес на диске)

Inode

Inode (index node) - это служебная структура данных в файловой системе Linux (каждый файл = 1 Inode), которая хранит метаданные о файле (размер, права доступа, UID, GID, временные метки, указатели на блоки данных на диске). Имена файлов хранятся в блоках директории, вместо самой Inode. Директория - это тоже файл, который сопоставляет Имя с номером Inode. При создание 10-ти файлов подряд, их номера Inode могут идти как по порядку (например, 101, 102, 103), так и нет (101, 540, 22), т.к. при удаление файла, его Inode освобождается. Система может отдать этот номер новому файлу.

ls -li /bin отобразить номера inode

stat file наглядно отображает права, UID, GID, временные метки, номер Inode (также номера можно увидеть в ls -li docker) и Links - количество жестких ссылок (Hardlink).

sudo find / -inum 15 найти все жесткие ссылки в системе по номеру inode

Если диск не полный, но файлы не создаются, это значит, что закончились свободные inode, их количество фиксируется при создании файловой системы, в момент форматирования раздела. Можно отобразить доступное и используемое количество inode с помощью команды df -i. Требуется найти директорию и удалить много мелких файлов (например, find / -xdev -type f | cut -d "/" -f 2,3,4 | sort | uniq -c | sort -n) или отформатировать раздел заново с флагом -N (количество inode) или -i (байтов на один inode), например, mkfs.ext4 -N 2000000 /dev/sdb1. В XFS или Btrfs (вместо Ext4) - inode выделяются динамически.

Дескрипторы

Файловый дескриптор (FD) - это неотрицательное целое число (индекс), которое ядро Linux присваивает каждому объекту, открытому процессом. Через это число приложение общается с файлом, сокетом или пайпом. Когда процесс запрашивает открытие файла (через системный вызов open()) или создание сетевого соединения (socket()), ядро выделяет структуру в памяти для управления этим объектом, помещает указатель на эту структуру в таблицу дескрипторов процесса и возвращает процессу наименьшее свободное число (индекс в этой таблице). Например, если на веб-сервер зашло 500 пользователей одновременно, у него будет открыто 500 дескрипторов (по одному на каждое TCP-соединение), помимо этого несколько дескрипторов для загрузки внешних библиотек, а также как минимум 1 дескриптор на чтение конфигурации и еще 1 на запись в лог-файл. При этом, если пользователь хочет загрузить картинку на сайте, сервер открывает этот файл на диске, чтобы прочитать его и отправить в сокет (на время скачивания открывается еще 1 дескриптор).

Дескрипторы ограничиваются лимитами:

В Linux всем процессам при из создание выделяется 3 зарезервированы системой дескриптора для ввода, вывода и ошибок: 0 (stdin), 1 (stdout) и 2 (stderr). Например, команда ls выполняется как ls 1> /dev/stdout 2> /dev/stderr, но можно переопределить направление дескрипторов, например поток ошибок в дескриптор вывода: ls test 2>&1 или передать оба дескриптора в файл: ls test > stdout.txt 2>&1.

exec используется для управления открытя и закрытия дескрипторов для текущего процесса или замещение текущего процесса новым процессом с передачей текущего PID.

# Открываем файл и закрепляем за ним дескриптор №3
exec 3> test.file
echo "Записываем содержимое в файл по номеру дескриптора" >&3

# Мягкая ссылка /proc/self всегда указывает на тот процесс, который к ней обращается
ls -l /proc/self
# Отобразить список используемых дескрипторов для текущего процесса
ls -l /proc/self/fd

# Найти дескрипторы по номеру PID текущего родительского процесса (bash) и отобразить кем он используется
lsof -p $$ 2> /dev/null | grep -E "COMMAND|test.file"
COMMAND     PID     USER  FD   TYPE DEVICE SIZE/OFF   NODE NAME
bash    3296105 lifailon   3w   REG  179,2       48 164078 /home/lifailon/test.file

# Если удалить файл, дескриптор останется висеть в памяти и занимать место в лимите
rm test.file
# Очистить содержимое файла без удаления или изменить размер (работает напрямую с атрибутами на уровне ФС)
truncate -s 0 test.log
# Закрываем дескриптор
exec 3>&-

# Отобразить все дочерние файловые дескрипторы в указанной директории
lsof +D /var/log/
# Отобразить все файловые дескрипторы по названию процесса
lsof -c bash
# Остановить все процессы использующие файлы, для дальнейшего umount /mnt/backup
kill -9 $(lsof -t +D /mnt/backup)
# Отобразить все файлы открытые указанным пользователем (или исключить пользователя)
lsof -u ^root
# Отобразить открытые сокеты по номеру порта
lsof -i:22

Типы файлов в lsof:

Память

free -m

ipcs -lm объем страниц разделяемой памяти (shared memory) для кеширования данных
cat /proc/meminfo | grep -iE "^cache|^buff|^dirty" отобразить объем кеша, буфера и грязных страниц (Dirty) в кеше (еще не записанных на диск)
sync записать все кешированные, но еще не записанные данные на диск (вместо кеша данные будут читаться из диска)
echo 1 > /proc/sys/vm/drop_caches отправить сигнал PageCache на вход drop_caches для очистки страничного кеша (free - buff/cache)
echo 2 > /proc/sys/vm/drop_caches отправить сигнал dentrie для очистки кеша структуры файловой системы inode

filefrag используется для опредиления адресов физических блоков (Physical_offset) на диске (обычно, в неупорядоченном порядке). В процессе дефрагментации ФС, ядро пытается переложить блоки так, чтобы они шли подряд.

filefrag -v /usr/share/pixmaps/fish.png

Filesystem type is: ef53
File size of /usr/share/pixmaps/fish.png is 7254 (2 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..       1:     230327..    230328:      2:             last,eof
/usr/share/pixmaps/fish.png: 1 extent found

Файл размером 7254 байта занимает 2 блока (length) по 4096 байт на диске, потому что ФС не умеет выделять меньше одного блока. Файл не фрагментирован, т.к. соблюдается порядок 230327..230328.

Swap - область на диске, куда ядро вытесняет неиспользуемые страницы памяти (обычно из состояний S и T, и даже R, если эти данные давно не запрашивались), чтобы освободить RAM для активных процессов (R). Swap включается, когда свободная память опускается ниже минимального значения (минимальное количество килобайт, которое ядро обязано держать свободным определяется в файле /proc/sys/vm/min_free_kbytes), ядро приостанавливая выделение памяти процессам и запускает поток kswapd, начиная плавно переносить данные на диск, чтобы система не упала в OOM (Out Of Memory).

Thrashing - критическое состояние, когда RAM кончилась, и система постоянно перекладывает данные из Swap в RAM и обратно (когда CPU загружен на 100%, но us/sy низкие, а iowait зашкаливает). Признак Thrashing, если оба этих числа постоянно высокие (сотни или тысячи КБ/с) одновременно. Это значит, что ядро забирает данные из свопа для одного процесса, и тут же выкидывает данные другого процесса, чтобы освободить место.

OOM Killer

Если память и swap закончились, приходит процесс OOM Killer (Out Of Memory Killer), чтобы система не упала (Kernel Panic), ядро завершает один или несколько процессов.

Ядро не выбирает процесс случайно. Оно начисляет каждому процессу очки (badness score) от 0 до 1000, чем значение больше, тем выше шанс, что процесс будет убит. Значение можно увидеть с помощью cat /proc/[PID]/oom_score. Если в файле процесса /proc/[PID]/oom_score_adj записать -1000, OOM Killer будет игнорировать этот процесс. В логе отображается ядра (dmesg | grep -i oom) отображает какой процесс убит, сколько памяти он занимал и какой у него был oom_score.

Критерии отбора:

Процессы

LA (Load Average) - среднее (avg) количество процессов в состоянии R и D за 1, 5 и 15 минут. Если LA выше количества ядер CPU - система перегружена (присутствует очередь). LA показывает нагрузку не только на CPU, но и на дисковую подсистему (из-за учета процессов в состоянии D). Для опредиления, что LA высокий из-за диска, нужно смотреть wa в top или %iowait в iostat.

top или ps aux/cat /proc/181/status

%Cpu(s): 0.9 us, 0.7 sy, 0.0 ni, 98.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

Сигналы

Программа kill реализует системный вызов kill().

kill -[num] [PID] или pkill [proc_name]

TCP/UDP

Процесс установки TCP-соединения (TCP 3-way Handshake):

SYN (Клиент -> Сервер) => SYN-ACK/Synchronize-Acknowledge (Сервер -> Клиент) => ACK (Клиент -> Сервер)

Статусы установки соединения:

Статусы закрытия соединения (Termination):

Параметр net.ipv4.tcp_orphan_retries определяет, сколько раз ядро будет пытаться отправить FIN (завершающий пакет), если удаленная сторона не отвечает (по умолчанию 8 раз). После этого TCP-соединение принудительно разрывается и удаляется из памяти.

Параметр net.ipv4.tcp_fin_timeout определяет, сколько секунд сокет может находиться в состоянии FIN_WAIT_2, ожидая FIN от удаленной стороны (по умолчанию 60 секунд). Если за это время сервер не прислал свой FIN, ядро убивает сокет.

UDP не подтверждает доставку (отсутствие установки соединения) и не гарантирует порядок пакетов (UDP не будет их пересобирать, за это отвечает приложение). Заголовок содержит 8 байт служебной информации (у TCP минимум 20), соот-но больше полезных данных в пакете. Используется в служебных пакетах (DNS, DHCP), телефонии (VoIP) и стриминге.

Сокеты

ss (Socket Statistics) - консольная утилита для анализа сетевых соединений.

ss -s (summury statistics):

iproute2

ip (пакет iproute2) - это современный стандарт управления сетевым стеком в Linux, который полностью заменяет устаревший net-tools.

Все изменения через ip не сохраняются после перезагрузки системы.

ip -s link выводит подробную статистику всех сетевых интерфейсов для анализа проблема на накальном (L2) уровне.

Маршрутизация - это процесс для определения пути отправки IP-пакетов к адресу назначения. Чем длиннее маска, тем выше приоритет.

ARP таблица используется для сопоставления IP и MAC адресов.

mtr - объединяет функциональность traceroute и ping в одном инструменте сетевой диагностики для каждого узла в трассеровке, который постоянно шлет пакеты и показывает статистику в динамике.

OSI

Сетевая модель OSI - это стандарт, который делит процесс передачи данных от провода до приложения на 7 уровней.

SSL/TLS

SSL (Secure Sockets Layer) - это старая версия протокола TLS, который является более безопасным стандартом, по сути, TLS 1.0, это обновленный проприетарный протокол SSL 3.1. Последняя версия SSL выпущена в 1996 году, в 2014 году была обнаружена критическая уязвимость POODLE, которая позволяла расшифровать данные, поэтому согласно документу RFC 7568 официально SSL 3.0 был признан устаревшим и небезопасным в 2015 году.

Под капотом TLS происходит процесс рукопожатия (Handshake), цель которого договориться о секретном ключе, чтобы никто не подслушал передачу между двумя сторонами. TLS использует MAC (Message Authentication Code), если в процессе передачи зашифрованного пакета изменится хотябы один бит, проверка на второй стороне не пройдет. Для каждой новой сессии создается новый ключ, и даже если кто-то взломает ключ от вчерашней сессии, сегодняшнюю он прочитать не сможет. В TLS сначала используется асимметричное шифрование и сертификаты для проверки подлинности и безопасного обмена общим секретом, после этого общение переходит на быстрое симметричное шифрование с использованием этого секрета. В классическом методе RSA (Rivest-Shamir-Adleman) сервер передает клиенту свой открытый ключ, которым клиент шифрует сгенерированное случайное число (будущий секретный ключ) и отправляет его обратно. Поскольку расшифровать это сообщение может только сервер своим закрытым ключом, обе стороны получают общий секрет, недоступный для перехвата в сети.

Процесс состоит из 4-х шагов:

DHCP

DHCP (Dynamic Host Configuration Protocol) - протокол, который позволяет устройствам автоматически получать IP-адрес и другие настройки сети. Работает по UDP (порты 67 для сервера и 68 для клиента).

Этапы получения адреса (DORA):

Клиентские демоны (например, dhclient или systemd-networkd) пишут этапы DORA в лог: journalctl -u systemd-networkd | grep -i dhcp

Или использовать сниффер: sudo tcpdump -i eth0 -vvv -n port 67 or port 68

Служебные сообщения:

Команды для управления DHCP:

DNS

DNS (Domain Name System) - это сетевой протокол, который отвечает за преобразование доменных имен в IP-адреса, понятные компьютерам. При работе протокола DNS происходит взаимодействие между Прикладным (7) и Транспортным (4) уровнями модели OSI. DNS-запрос спускается с прикладного уровня (где живет сам сервис DNS) на транспортный (4-й), чтобы упаковаться в сегмент UDP (чаще всего) или TCP для передачи по сети через порт 53.

DNS переключается на TCP, когда размер ответа превышает стандартный лимит UDP в 512 байт, например, если у домена много IP-адресов или используются большие записи, а также при использование DNSSEC, где используются цифровые подписи для защиты данных от подмены (сами данные не шифруются и остаются открытыми, но гарантируется их целостность и подлинность).

Порядок преобразования адреса на стороне ОС:

Порядок преобразования адреса на стороне DNS-сервера:

DNS-записи:

Команды для управления DNS:

dig (Domain Information Groper) - консольная утилита для опроса DNS-серверов (альтернатив nslookup).

HTTP/REST

Методы запросов:

Заголовки запросов:

Статусы ответов:

Bash

Переменные

text="ip a"     # передаем текст в переменную
echo $text      # вывести содержимое переменной в stdout
ipaddr=$(ip a)  # передает вывод команды
echo "$ipaddr"  # вывод в двойных скобках передается как есть (сохраняя переносы строк и табуляцию)
echo '$ipaddr'  # в одинарных кавычках не происходит подстановка переменных

# Арифметические операции
echo $((5+5))
# Арифметические операции с поддержкой чисел с плавающей точкой 
echo "scale=2; 10 / 3" | bc

# Ручной ввод переменной
read -p "Enter: " enter
echo $enter
# Экранирование
echo -e "text\ntext"
# Скрыть вывод
read -s -p "Enter password: " pass
echo $pass
# Для ввода пароля
pass=$(systemd-ask-password)

# Коды возврата
true && echo $?   # 0 (успех)
false ; echo $?   # 1 (ошибка)
var 2> /dev/null || echo $? # 127 (command not found)

# Индексы
line="Это длинная строка, которую нужно сократить до 50 символов."
echo "${line:0:50}"

# Экспортируем глобальные переменные и используем их для подстановки в файле
export DOMAIN="mysite.com"
envsubst < nginx.conf.template > nginx.con

Многострочный ввод

Heredoc (Here-document) или EOF (End Of File) - это механизм, который позволяет передавать многострочный текст в команду без использования внешних файлов.

name="srv-01"
ip="192.168.3.100"

cat <<EOF > config.yml
server:
  hostname: $name
  address: $ip
  status: up
EOF

cat <<'EOF'
Здесь переменная окружения $PWD останется просто текстом
EOF

cat <<-EOF
		Удаляет табуляцию
EOF

Срезы

# Объявить срез/список
declare -a array
array=()

array=(1 2 3 4 5)     # создать массив
array=({1..254})      # создать массив от 1 до 254
array=($(ls /))       # передает вывод команды в массив (разделенных через пробел)
array=$(seq 1 5)      # создать массив от 1 до 5

echo ${array[@]}      # отобразить содержимое всего массива
echo ${array[0]}      # отобразить первый индекс в массиве
echo ${array[-1]}     # отобразить последний индекс
echo ${array[@]:1:3}  # вывести 3 элемента (срез c 2-го по 4-й элемент)
echo ${#array[@]}     # отобразить кол-во (#) всех [@] элементов в массиве
echo ${#array[0]}     # отобразить длинну (#) первого [0] элемента в массиве

array+=(4)            # добавить новое значение в массив
array[1]="test"       # изменить значение по номеру индекса
unset arr[1]          # удалить элемент из массива по индексу

for i in ${array[@]} ; do echo $i; done

Карты

# Создать карту
declare -A arr=(
    ["key1"]=1
    ["key2"]="text"
)
echo ${arr[key1]}
echo ${arr[key2]}

# Пример конфигурации в формате ctx=namespace1,namespace2
cat <<EOF > ctx.conf
s1=dev,test
s2=dev,test
EOF

# Создаем карту из context=namespace
declare -A ctxArray
# Создаем срез из context-ов
declare -a ctxList

# Заполняем массив и список с помощью read
while IFS='=' read -r key value; do
    if [[ -n "$key" && ! "$key" =~ ^# ]]; then
        ctxArray["$key"]="$value"
        ctxList+=("$key")
    fi
done < ctx.conf

for CTX in "${ctxList[@]}"; do
    IFS=',' read -r -a nsArr <<< "${ctxArray[$CTX]}"
    for i in "${nsArr[@]}"; do
        echo "Use $i namespace in $CTX context"
    done
done

unset ctxArray
unset ctxList

Циклы

for ((i=1; i <= 10; i++)); do
    echo $i
done

array=($(ls /))
for arr in ${array[@]}; do
    echo $arr
done

array=(1 2 3 4 5)
for var in ${array[@]}; do
    if [ $var -gt 4 ]; then
        # Прерываем цикл
        break
    elif [ $var -gt 3 ]; then
        echo "Last number: $var"
        # Прерывает текущую интерацию в цикле
        continue
    fi
    echo "Number: $var"
done

p=1
while [ $p -le 101 ]; do
    # Eсли условие истинно, выполнять цикл в блоке do, пока не станет ложным
    echo "Значение переменной: $p"
    # ((p++)) # увеличить на 1
    # p=$(($p+10)) # прибавлять 10
    p+=0 # прибавлять текст в конец переменной
done

num=0
ps | sed 1d | while read line; do
    ((num++)) # ((num+=1))
    echo "Line $num : $line"
done

Условия

ОператорОписание
-zстрока пуста
-nстрока не пуста
=, (==)строки равны
!=строки неравны
-eqравно
-neнеравно
-lt, (<)меньше (для арифметических вычислений)
-le, (<=)меньше или равно (для арифметических вычислений)
-gt, (>)больше (для арифметических вычислений)
-ge, (>=)больше или равно (для арифметических вычислений)
!отрицание логического выражения
[-a]/[[&&]]логическое и (первая команда исполняется всегда, вторая - только в случае успешного завершения первой)
[-o]/[[||]]логическое или (первая команда исполняется всегда, вторая - только в случае неудачного завершения первой)
-e fileпроверяет, существует ли файл
-d fileпроверяет, существует ли файл и является ли он директорией
-f fileпроверяет, существует ли файл и является ли он файлом
-r fileпроверяет, существует ли файл и доступен ли он для чтения
-w fileпроверяет, существует ли файл и доступен ли он для записи
-x fileпроверяет, существует ли файл и является ли он исполняемым
-s fileпроверяет, существует ли файл и не является ли он пустым
read key
if [[ -z "$key" ]]; then
    echo "Переменная пустая"
elif [[ "$key" == "true" ]]; then
    echo "Переменная равна true"
else
    echo "Переменная не равна true"
fi

# Получить список директорий и исполняемых файлов в дочерних директориях
path="/etc/*"
for folder in $path; do
    echo "$folder:"
    for file in $folder/*; do
        if [ -x $file ]; then
            echo "- $file"
        fi
    done
done

# Условия типа switch
read -r input
case "$input" in
  "start")
    echo "Запускаю скрипта" ;;
  "stop" | "quit" | "exit")
    echo "Выход из скрипта" ;;
  [0-9])
    echo "Передана одна цифра: $input" ;;
  [A-Z])
    echo "Передана заглавная латинская буква" ;;
  test*)
    echo "Значение начинается на test: $input" ;;
  "")
    echo "Пустое значение" ;;
  *)
    echo "Выполнить условие по умолчанию" ;;
esac

Функции

function calc {
    if [ $2 = "+" ]
        then
        echo $(( $1 + $3 ))
    elif [ $2 = "-" ]
        then
        echo $(( $1 - $3 ))
    fi
}

calc 3 + 2

calc 3 - 2

Опции

getopts - это встроенная в bash команда для разбора аргументов (опций/ключей/флагов) командной строки.

# Принимаем аргументы: -h (без значения) и -f (с обязательным параметром)
while getopts "hf:" opt; do
  case $opt in
    h)
      echo "Это справка: используйте -f [string]"
      exit 0
      ;;
    f)
      # Встроенная переменная со значением после аргумента
      FILE_PATH="$OPTARG"
      echo "Выбран файл: $FILE_PATH"
      ;;
  esac
done

Базовые команды

pwd # узнать путь к текущей директории
ls -lh * # отобразить содержимое каждого подкаталога отдельно
ls -lhaF # отобразить скрытые директории (-a) с точкой и выделит директории (добавляет / в конце наименования)
tree /var/log/ # древовидный просмотр директорий и дочерних файлов
cd $HOME # сменить текущую директорию (перейти в домашний каталог)
cat -n /etc/passwd # просмотр содержимого файла с отображением номеров строк (-n)
mkdir # создать директорию
mktemp # создать временный файл или каталог (-d)
date +%Y%m%d%H%M.%S # получить текущую дату (год месяц день часы минуты секунды)
touch -t 202603242218.56 test.file # создать файл и указать дату создания
cp test.file test.file2 # копировать файла или каталог
mv test.file2 test.file3 # переместить или переименовать файл или каталог
rm -rf test.* # принудительное (-f) и рекурсивное (-r) удаление файлов и каталог

# пути
which top # узнать путь до исполняемого файла
basename $(which top) # top
dirname $(which top) # /usr/bin

# файлы
file /bin/bash # узнать тип файла (например, executable или Unicode text), кодировку (UTF-8 text) и архитектуру
stat /bin/bash # узнать размер файла, количество блоков (сколько 512-байтовых блоков файл занимает на диске), номер Inode, количество жестких ссылок (Links), права доступа и временные метки
# Access - время последнего чтения или выполнения файла
# Modify - модификации содержимого файла
# Change - изменения метаданных (например, прав доступа или владельца)
# Birth  - дата создания файла

# tee (>/>>)
echo "line1" | tee test.txt # перезаписать файл (>)
ls > /dev/null # перенаправить вывод в null
echo "line2" | tee -a test.txt # добавить (>>) текст новой стройокй в конец файла
echo -e "line3\nline4" >> test.txt # добавить две новые строки

# tar (архивирование)
tar -czvf ping.tar.gz -C /bin ping # создать архив в формате gz (-z) из файла или директории
tar -tvf *tar* # отобразить содержимое архива
tar -xzvf ping.tar.gz # разархивировать содержимое

# printf (форматированный вывод)
printf "Arg1: %s\nArg2: %s\n" "10" "20" # принимает и выводит аргументы (%s) в виде строки
printf "%.2f \n" 1.1111 # округлить до 2 символов после запятой
printf "%.0f \n" 1.6 # удалить дробную часть (округлить до 2)

# tac/rev
ls -lh | tac # перевернуть все строки
echo "test" | rev # перевернуть содержимое строк

# head/tail
cat /var/log/syslog | head -n 5 # выводит первые 5 строк файла
cat /var/log/syslog | tail -n 5  # просмотр последних 5 строк файла
tail -f /var/log/syslog # просмотр содержимого файла в реальном времени
watch df -h # выводит на экран и обновляет состояния каждые 2 секунды

# Выравнивание текста по полям
cat /etc/passwd | column -t -s ":"

# wc (Word Count)
ls /home | wc -l # выводит количество строк (--line)
ls /home | wc -w # количество словосочетаний (--words)
ls /home | wc -m # количество символов (--chars)
ls /home | wc -c # количество байт (--bytes)

# sort (сортировка)
cat /etc/passwd | sort -r # отсортировать вывод по алфовиту в обратном порядке (-r)
du -h ~ | sort -n # сортировать по арифметическому значению (-n) размер файлов и директорий
ls -l | sed 1d | sort -nk5 # сортировка по пятой колонке (-k)
cat $tmp | sort -t "." -nk4 # сортировать по четвертой колонке, используя разделитель (-t) точку

# uniq (уникальные значения)
echo -e "1 2\n1 2\n2 1\n1 2" | uniq # удаляет одинаковые строки
echo -e "1 2\n1 2\n2 1\n1 2" | sort | uniq # удалить все дубликаты
echo -e "1 2\n1 2\n2 1\n1 2" | sort | uniq -u # отобразить только уникальные строки (без строк с повторениями)
echo -e "1 2\n1 2\n2 1\n1 2" | sort | uniq -c # добавляет в начало каждой строки кол-во повторений

# tr/translate (like replace/sed)
echo "10 20 100 200" | tr 1 2 # заменяет 1 на 2 для всех подходящих сомволов (10 20 100 200 => 20 20 200 200)
echo "1 2 3" | tr " " "," # заменить пробелы на запятые (1 2 3 => 1,2,3)
echo "1,2,3" | tr -d "," # удалить запятые (1,2,3 => 123)
ls -lh | tr -d '\n' # преобразовать список в одну строку (join method)
echo "ping" | tr "a-z" "A-Z" # поднять регистр (ping => PING)
echo "PING" | tr "A-Z" "a-z" # опустить регистр (PING => ping)

# paste (like join)
cat /etc/passwd | paste -s -d + # объеденить многострочный файл в одну строку, используя указанный delimiter
# Объединяет два файла в один многоколоночный вывод
echo -e "key1\nkey2\nkey3" > 1.txt
echo -e "value1\nvalue2\nvalue3" > 2.txt
paste 1.txt 2.txt -d :

# cut (как awk, но и не инициализирует интерпретатор целого языка и работает быстрее на огромных объемах данных)
# cut не умеет объединять разделители и менять порядок вывода для столбцов (awk по умолчанию считает любое количество пробелов за один разделитель)
echo "1 2 3" | cut -c 1,5 # вывести первый и пятый симов в строке (--characters или -b/--bytes)
echo "1 2 3" | cut -c 1-3 # вывести с первой по третий символ
echo "1 2 3" | cut -c3- # удалить первые два символа (до 3-го)
echo -e "test1,test2,test3\ntest1,test2,test3" | cut -d , -f 2-100 # указать разделитель полей/столбцов (--delimiter) и какие столбцы вывести (--fields) с 2 по 100
echo -e "test1,test2,test3\ntest1,test2,test3" | cut -d , -f 1,3 # вывести 1 и 3 столбцы

# tr + cut + column
ls -lh | tr -s " " | cut -d " " -f 5,9 | column -t # объеденяет последовательность повторяющихся символов в один

# split string
str="sha256:c79464ed2966afa47b2db6a17d0cdc0500ddc6f941992df043304f1f57ade"
# Отрезать все после первого двоеточия (оставить левую часть)
echo "${str%%:*}" 
# Отрезать все до первого двоеточия (оставить правую часть)
echo "${str#*:}"

# split file
split -l 100 input_file.txt output_prefix # разделить файл на части по 100 строк в каждой
split -b 10M input_file.txt output_prefix # разделить файл на части по указанному размеру (например, 10MB)

# diff (сравнение файлов)
echo -e "test1\ntest2" > 1.txt
echo -e "test\ntest2\ntest3" > 2.txt
diff -c 1.txt 2.txt # ! есть изменения, + есть новая строка
diff -yi 1.txt 2.txt # сравнивает в две колонки (| есть изменения, > новая строка справа) и игнорировать регистр (-i)
diff -u 1.txt 2.txt # объеденяет два файла в один (файл слева влить в файл справа) с отображением изменений (+/-)
diff -ibBEt 1.txt 2.txt # не учитывать пробелы (-b) и пустые строки (-B), игнорировать изменения в табуляциях (-E) и заменить табуляции на пробелы в выводе (-t)
diff -c <(echo "$pre") <(echo "$post") # сравнить содержимое переменных

# set (отладка скриптов)
set -x # режим xtrace, печатает каждую команду перед выполнением (подставляя значения переменных, как в bash -x)
set +x # отклачает трассировку вывода команд
set -o pipefail # заставляет конвейер возвращать ошибку, если упала любая команда в цепочке (по умолчанию, Bash берет статус только последней команды)
set -e # падать при любой ошибки (аналогично set -o errexit), без учета конвееров
set -u # запрет на пустые переменные (set -o nounset, например, опечатка в имени переменной, Bash выдаст ошибку и остановится, а не подставит пустоту)

Базовые пакеты

# Обновление всех установленных в систему пакетов
sudo apt update && sudo apt full-upgrade -y

# Установка пакетов
sudo apt install curl git jq fzf micro gdu bat fd-find ripgrep -y

# Установка пакетов из PPA
sudo add-apt-repository ppa:rmescandon/yq -y
sudo apt update
sudo apt install yq -y

# Интерактивный поиск по истории команд
history | fzf
# Выполнить выбранную команду из списка
eval $(history | fzf | awk '{print $2}')

# Интерактивный интерфейс для навигации по историю команд
curl -sSL https://hishtory.dev/install.py | python3 -

# Анализ занятого дискового пространства с навигацией по каталогам
gdu
# Поиск файлов с предпросмотром и подсветкой синтаксиса
fzf --preview "batcat --color=always {}"
# Поиск всех файлов с расширением yml/yaml в системе
find / -name *.y*ml | fzf
fdfind "\.ya?ml$" / | fzf

# Поиск в файлах по их содержимому
curl -sSL https://github.com/phiresky/ripgrep-all/releases/download/v0.10.10/ripgrep_all-v0.10.10-x86_64-unknown-linux-musl.tar.gz -o ripgrep.tar.gz
tar -xzf ripgrep.tar.gz
cp ripgrep_all-*/rga ripgrep_all-*/rga-fzf /usr/local/bin/
rm -rf ripgrep*
rga "fatal" /var/log/syslog*
rga-fzf

# Текстовый редактор в стиле IDE с поддержкой выделения, управления мышью, подсветки синтаксиса и файловым менеджером
curl https://raw.githubusercontent.com/sinelaw/fresh/refs/heads/master/scripts/install.sh | sh

Профиль

nano ~/.bashrc

# Определить переменную окружения, доступную для дочерних процессов, запущенных в текущей сессии
# Игнорировать запись в историю команд, которые начинаются с пробела
export HISTCONTROL=ignorespace

# Добавить фильтрацию по введеному тексту в истории команд при испоьзовании стрелочек вверх и вниз
if [[ "$-" == *i* ]]; then
    bind '"\e[A": history-search-backward'
    bind '"\e[B": history-search-forward'
fi

# Псевдонимы для команды или набора команд с флагами для сокращения ввода 
alias tspin=tailspin
alias ts=tailspin

# Забиндить очистку ввода на Ctrl+L
bind '"\C-l": "^\C-u\C-mclear\C-m"'

source ~/.bashrc применить политики (перечитать профиль)

oh-my-bash - используется для управления оформлением ввода (промпта) в терминале.

При установки oh-my-bash, обновляется профиль bashrc, делая рядом резервную копию старого файла в .bashrc.omb-TIMESTAMP:

bash -c "$(curl -fsSL https://raw.githubusercontent.com/ohmybash/oh-my-bash/master/tools/install.sh)"
# Вывести список доступных тем
ls ~/.oh-my-bash/themes/
# Изменить тему
sed -iE "s/^OSH_THEME=.*/OSH_THEME=powerline/" ~/.bashrc && source $HOME/.bashrc

fzf over bash complete - реализует автодополнения опций для команд в интерфейсе fzf.

git clone https://github.com/rockandska/fzf-obc $HOME/.local/opt/fzf-obc
echo "source $HOME/.local/opt/fzf-obc/bin/fzf-obc.bash" >> $HOME/.bashrc

compgen

compgen - это встроенная команда оболочки Bash, которая генерирует список возможных вариантов автодополнения (используется под капотом системы при нажатии клавиши Tab) в терминале, чтобы оболочка выводила список доступных команд, опций, файлов или переменных.

compgen -c выводит все команды, доступные в текущей оболочке
compgen -a выводит все алиасы, определенные в текущей оболочке
compgen -b выводит все встроенные команды Bash
compgen -k выводит все зарезервированные слова Bash
compgen -v выводит все переменные, определенные в текущей оболочке
compgen -A export выводит все экспортированные переменные
compgen -A function выводит все функции, определенные в текущей оболочке
compgen -A arrayvar выводит все массивы, определенные в текущей оболочке (echo ${BASH_ALIASES[@]})
compgen -A hostname выводит все известные хосты
compgen -A job выводит все активные фоновые задания (запускаемые через &)
compgen -A service выводит все службы (для систем, поддерживающих службы, например, через systemd)
compgen -d выводит все директории в текущем каталоге
compgen -f выводит все файлы и директории в текущем каталоге
compgen -u выводит всех пользователей системы
compgen -g выводит все группы системы
compgen -W "start stop status restart" st выводит список слов из wordlist, которые начинаются с префикса st

jobs

(ping google.com > icmp.log 2>&1) & запустить задачу в фоне (отображается [номер задачи] и PID дочернего процесса)
jobs отобразить список фоновых задач (+ задача активна)
fg 1 открыть задачу по номеру (вернуть stdin и tty)
bg %1 - продолжить выполнение задачи в фоне, если она была остановлена (Ctrl+Z)
kill %1 завершить последнию запущенную задачу
disown %1 завершить последнию (если она первая) запущенную задачу
disown завершить все фоновые задачи (очистить всю очередь заданий)

wait встает на паузу и ждет завершения указанной или всех фоновых задач.

ping -c 5 google.com &
PID=$!
wait $PID
# wait %1
echo "Процесс $PID завершился с кодом $?"

for url in google.com github.com ; do
    ping -c 5 "$url" > "$url.log" 2>&1 &
done
wait

nohup ping google.com > icmp.log 2>&1 & используется для запуска процессов в фоне (защита от SIGHUP сигналов)
ps -ef | grep "ping google.com" найти процесс
kill $(pgrep ping) завершить процесс

(ping google.com > icmp.log 2>&1 &) запустить скрипт в subshell (создает процесс bash, рядом запускает отдельный процесс ping и потом завершает процесс bash)
(exec ping google.com > icmp.log 2>&1 &) сразу заменяет процесс bash в subshell на ping (забирает его PID) с помощью exec
pstree -a -p $USER

echo {1..10} | xargs -n 1 -P 4 bash -c 'echo Start task $1 && sleep $1 && echo Complate task $1' _ принимает 1 аргумент и запускат до 4-х потоков за раз
echo "google.com 4 github.com 4" | xargs -n 2 -P 2 sh -c 'ping -c $2 $1' -- принимает 2 аргумента

echo "google.com github.com" | xargs -n 1 -P 2 ping -c 5

GNU Parallel - инструмент командной оболочки для параллельного выполнения задач на одном или нескольких компьютерах (ожидает завершения работы без вывода прцоесса в фон).

sudo apt install parallel

printf "%s\n" google.com github.com | parallel -j 2 ping -c 5 {}

GPU Task Spooler - система буферизации задач, которая упрощает управление задачами (как jobs в PowerShell).

sudo apt install task-spooler

tsp ping google.com -c 5 создать задачу
tsp -l отобразить список задач
tsp -s 0 отобразить статус задачи
tsp -s 0 отобразить PID задачи
tsp -o 0 отобразить путь к tmp файлу с выводом
tsp -t 0 вывести вывод работы задачи в режиме tail во время выполнения
tsp -k 0 остановить процесс (отправить сигнал SIGTERM)
tsp -C очистить все выполненные (со статусом finished) задачи

cron

ls /etc/cron.d/ директория хранения задач различных пакетов (atop, sysstat)

Директории для скриптов, которые надо выполнять раз в час, день, неделю и месяц: ls -l /etc/cron.hourly
ls -l /etc/cron.daily
ls -l /etc/cron.weekly
ls -l /etc/cron.monthly

crontab -l просмотр задач
crontab -l | grep -Pv "^$|^#" отобразить только активные задания
crontab -e создать задачу от текущего пользователя
crontab -u lifailon -l отобразить задачи пользователя lifailon
sudo crontab -u root -e создать задачу от пользователя root
crontab -r удалить все задачи

cat /etc/crontab

#### # .---------------- минута (0 - 59)
#### # |  .------------- час (0 - 23)
#### # |  |  .---------- мень месяца (1 - 31)
#### # |  |  |  .------- месяц (1 - 12) или jan,feb,mar,apr...
#### # |  |  |  |  .---- день недели (0 - 6) (Воскресень 0 или 7) или sun,mon,tue,wed,thu,fri,sat
#### # |  |  |  |  |
#### # *  *  *  *  * user-name command to be executed
####  17  *  *  *  *   root    cd / && run-parts --report /etc/cron.hourly
####  25  6  *  *  *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
####  47  6  *  *  7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
####  52  6  1  *  *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

0,14,29,44 * * * * каждые 15 минут
*/15 * * * * каждые 15 минут

00 23 * * * systemctl restart zabbix-agent && echo $(date): Reboot Zabbix Agent use cron >> /var/log/reboot.log

00 03 * * 6 echo $(date): Reboot Operating System use cron >> /var/log/reboot.log && /sbin/reboot

@reboot date >> ~/date-reboot.log

journalctl -eu cron || cat /var/log/syslog | grep -i cron

addr="google.com"
path="/var/log/metrics/icmp-test.log"
date=$(date | awk '{print $3,$2,$4}')
loss=$(ping -c 2 $addr | grep -Ewo "[0-9]+%")
if [ $loss = "100%" ]; then
    echo "$date $addr : unavailable" >> $path
else
    echo "$date $addr : available" >> $path
    tail -n 1 $path
fi

echo "*/1 * * * * bash /root/google-icmp-test.sh" >> /var/spool/cron/crontabs/root добавить задачу в планироващик на выполнение скрипта каждую минуту

cp /etc/hosts /etc/hosts.bak backup файла
echo "11.11.11.11 google.com" >> /etc/hosts изменить адрес для недоступности хоста
cp /etc/hosts.bak /etc/hosts восстановить файл
cat /var/log/icmp-test.log | grep unavailable отфильтровать лог по unavailable

grep

Описание ключей для grep и ripgrep:

КлючОписаниеПример
-EРасширенные регулярки (поддержка +, {}, (), ?, |)rg "error|crit"
-PРегулярные выражения Perlrg -P "(?<=id=)\d+"
-iПоиск без учета регистра (заглавных/строчных букв)rg -i "user"
-vИнверсия (показать все, кроме подходящих строк)rg -v "^#"
-wИщет точное совпадение целого словаrg -w "bin"
-oВыводит только найденный текст, вместо всей строкиrg -o "127\..*"
-nПоказывает номер найденных строк в файлеrg -n "auth"
-cВыводит количество найденных строкrg -c "login"
-lВыводит только имена файлов с совпадениямиrg -l "TODO"
-rРекурсивный поиск (искать во всех подпапках)rg "config"
-A nAfter. Показать n строк после найденнойrg -A 2 "Error"
-B nBefore. Показать n строк до найденнойrg -B 2 "Error"
-C nContext. Показать по n строк до и после найденнойrg -C 1 "Error"
-m nКоличество строк вывода после n совпадений в одном файле.rg -m 1 "root"
-qВернуть только код возврата 0 (найдено) или 1 (не найдено).rg -q "ok" && echo 1
-FОтключить регулярные выраженияrg -F "1.2.3.4"

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

cat /var/log/auth.log | grep sshd отфильтровать логи всех SSH-подключений
cat /etc/passwd | grep -w sys поиск целого слова, окруженное пробелами (-w) или знаками пунктуации (например, (/) или :)
cat /etc/ssh/sshd_config | grep -win port не учитывать регистр (-i) и отобразить номера строк (-n)
ss -n | grep -E ":22|:80|:443|:8080" использовать Regex (-E) для поиска нескольким шаблонам через pipe (|)
ss -n | grep -Ec ":22|:80|:443|:8080" вывести кол-во (--count) совпадений
ss -n | grep "192.168.3\....:" поиск любых трех символов (.) после точки (точка экранируется)
ss -n | grep "192.168.3\..+:" поиск любого кол-во (*/+) любых символов (.) после точки и до символа :
cat /etc/ssh/sshd_config | grep -v "^#" вывести значения, не подходящие под критерии поиска (-v), которые начинаются (якорь ^) с символа #
cat /etc/ssh/sshd_config | grep -Ev "^$|^#" удалить пустые строки ^$ (якори начала и конца строки) и комментарии (^#)
cat /etc/ssh/sshd_config | grep -E "0{2,}" найти символ 0, который повторяется 2 или более (,) раз подряд
cat /etc/zabbix/zabbix_agentd.conf | grep "=$" найти строки, которые кончаются ($) на символ = (получить все параметры без значений)
echo -e "Test-one\ntest-two\ntest-three" | grep -E "^[a-zA-Z\-]+$" искать только текст, где есть буквы и тире (без цифр)
echo 'test<version>1.2.3</version>test' | grep -P "(?<=<version>).*(?=</version>)" группировка (-P) для поиска значения между известным набором символов слева (?<=) и справа (?=)
echo "test<version>3.6.4</version>test" | grep -Eo '[0-9.]+' вывести только (-o) цифры и точки (повторяются любое кол-во раз подряд)
zabbix_path=$(systemctl status zabbix-agent | grep -Po "(?<=-c ).*(?=.conf)" | sed "s/$/.conf/") забрать путь до конфигурационного файла zabbix-агента
cat $zabbix_path | grep -Po "(?<=^Server=).+" найти и вывести только имя сервера
resolvectl | grep "DNS Servers" -m 1 напечатать только первое совпадение (-m int)
networkctl status | grep -A 3 "DNS:" найти строку и напечатать три строки после нее (-A)
networkctl status | grep -B 3 "DNS:" найти строку и напечатать три строки до нее (-B)
networkctl status | grep -C 1 "DNS:" найти строку и напечатать одну строки до нее и одну после (-C)
grep -H "Error" /var/log/* поиск в нескольких файлах (выводит название файла в начале строки)
grep -L "DNS" /etc/systemd/*.conf поиск в файлах, в которых нет совпадения (-L)
if echo "GET" | grep -Eq "^GET"; then echo da; else echo net; fi подавлять вывод (-q) для проверки в условиях

ripgrep (rg) - это более быстрая замена grep написанная на языке Rust, с схожим синтаксисом и дополнительными функциями.

Уникальные ключи ripgrep:

КлючОписаниеПример
-zИскать внутри сжатых файлов (gz, bz2)rg -z "err" logs.gz
-tИскать только в типах файлов (py, js, conf, log)rg "port" -t conf
-TИсключить тип файлов из поискаrg "error" -T log
-uИскать везде, включая .gitignorerg -u "secret"
-uuИскать везде, включая скрытые файлы (.file)rg -uu ".env"

sed

Описание ключей:

КлючОписаниеПример
-nПодавить автоматический вывод (использовать с p)sed -n '5p' file.txt
-iРедактировать файл на местеsed -i 's/old/new/' file.txt
-EРегулярные выражения (поддержка +, {}, ())sed -E 's/(a|b)/c/'
-eВыполнение нескольких команд в одном вызовеsed -e 's/a/b/' -e 's/c/d/'
pТолько вывести найденные строки (использовать с -n)sed -n '/pattern/p'
sПоиск и заменаsed 's/найти/заменить/'
gГлобальная замена (все совпадения в строке)sed 's/a/b/g'
dУдалить строку по номеруsed '3d' file.txt
aДобавить текст после строкиsed '2a New line' file.txt
iВставить текст перед строкойsed '2i New line' file.txt
cЗаменить всю строку целикомsed '1c Header' file.txt
rЧтение и вставка содержимого из другого файлаsed '3r other.txt' main.txt
wЗапись результата (только совпадений) в файлsed 's/a/b/w res.txt'
yПосимвольная замена (транслитерация)sed 'y/abc/ABC/'
!Инверсия команды (выполнить, если не совпало)sed '/#/!d' file.txt
&Подставить весь найденный текст в заменуsed 's/[0-9]/(&)/g'
\1, \2Обратные ссылки на группы ()sed -E 's/(.*):(.*)/\2:\1/'
IФлаг игнорирования регистраsed 's/admin/root/Ig'

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

cat /etc/passwd | sed -n "1,5p" отобразить с первой по пятую строку (p)
cat /etc/passwd | sed "$ d" удалить (d) последнюю строку
cat /etc/passwd | sed "1,3d" удалить c первой по третью строку (2,3d)
echo "One 1" | sed "s/One/Two/; s/1/2/" заменить One на Two и 1 на 2
cat /etc/zabbix/zabbix_agentd.conf | sed "s/127.0.0.1/192.168.3.102/" заменить (s) ip-адрес
cat /etc/ssh/sshd_config | sed "/^#\|^$/d" удалить пустые строки ^$ и комментарии ^#
timedatectl | grep zone | sed -E "s/.+zone: //" удалить любое кол-во лимволов до слова zone: включительно, используя Regex (-E/-r)
echo "test<version>3.6.4</version>test" | sed -E 's/[^<]*<(.*)>.*/\1/;s/<.*//;s/.*>//' использовать regex для удаления текста до и после искомого значения
echo -e "test\ntest" | sed "2s/test/test2/" заменить во второй строке (2s)
echo -e "test\ntest\ntest\ntest" | sed "2,3s/test/test2/" заменить во второй и третей строке (2,3s)
echo -e "test\ntest\ntest\ntest" | sed "2c test2" заменить текст целиком во второй строке (2c)
echo "The test and test" | sed "s/test/test2/g" заменить для каждого совпадения (/g - global)
echo "The test and test" | sed "s/test/test2/2" заменить для второго совпадения (/2)
echo "line2" | sed "i\line1" добавить строку в начало (i)
echo "line1" | sed "a\line2" добавить строку в конец (a) или в после указанной строки (2a)
echo "11 22 33 34" | sed "y/123/234/" заменить 1 на 2, 2 на 3 и 3 на 4 (y)

awk

GAWK/GNU AWK - это скриптовый язык программирования и утилита командной строки, предназначенная для построчной обработки текста, структурированного по столбцам.

Описание ключей:

КлючОписаниеПример
-FУказать разделитель полей (по умолчанию space/tab)awk -F: '{print $1}' /etc/passwd
-vПередать внешнюю переменную из оболочки в скрипт awkawk -v a=$VAR '{print $1, a}'
-fПрочитать программу awk из указанного файлаawk -f script.awk data.txt
$0Обращение ко всей текущей строке целикомawk '{print $0}' file.txt
$nОбращение к конкретному полю по номеру ($1, $2…)awk '{print $1, $3}' file.txt
NFОбращение к последнему полюawk '{print $NF}'
NRВывести строку по номеру (Number of Record)awk 'NR==5 {print $0}' file.txt
RSРазделитель входных записей (по умолчанию новая строка)awk 'BEGIN{RS=""} {print $1}'
OFSРазделитель полей при выводе (Output Field Separator)awk 'BEGIN{OFS=","} {print $1,$2}'
ORSРазделитель записей при выводе (Output Record Separator)awk 'BEGIN{ORS="\n\n"} {print $0}'
BEGINБлок команд, выполняемый ОДИН раз до начала чтения файлаawk 'BEGIN{print "START"} {print $0}'
ENDБлок команд, выполняемый ОДИН раз после обработки файлаawk '{s+=$1} END{print s}'
~Оператор соответствия регулярному выражениюawk '$1 ~ /root/ {print $3}'
!~Оператор НЕсоответствия регулярному выражениюawk '$1 !~ /#/' file.txt
ifУсловный оператор внутри тела awkawk '{if($3>100) print $1}'
lengthФункция подсчета количества символов в строке/полеawk 'length($0) > 80'
1Краткая форма команды {print $0} (всегда истина)awk '/pattern/ {print "found"}; 1'
subЗамена первого вхождения в поле или строкеawk '{sub(/old/, "new", $1); print}'
gsubГлобальная замена всех вхождений (Global Substitute)awk '{gsub(/a/, "b"); print}'
splitРазбить строку в массив по разделителюawk '{split($1, a, "."); print a[1]}'

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

cat /etc/passwd | awk -F: '{print "name: " $1 " \t Dir: " $NF}' вывести содержимое первого и последнего $NF элемента в строке, используя разделитель : и табуляцию (\t)
echo 'one two three four' | awk '{print $(NF-1)}' вывести содержимое преподследнего элемента
echo 'one two three four five' | awk '{print $((NF/2)+1)}' вывести содержимое из середины
echo "One Two Three" | awk '{$3="Four"; print $0}' заменить третье значение/переменную в строке
cat /etc/passwd | awk 'BEGIN{FS=":"; OFS=" - "} {print $1,$7}' указать разделитель послей (элементов) на вход (FS) и заменить его на выходе (OFS)
uptime | awk 'BEGIN{RS=" "; ORS="\n"} {print $0}' указать разделитель записей (строк) на входе (RS) и заменить его на выходе (ORS)
echo -e "12345\n54321" | awk 'BEGIN{FIELDWIDTHS="2 3"}{print $1,$2}' указать фиксированное кол-во символов для разделения
lsof | awk '{if($7=="REG")print $0}' условие для выборки по столбцу
cat /etc/ssh/sshd_config | awk '/Port / {print $2}' условие поиска для вывода
cat /etc/ssh/sshd_config | awk 'length $0 > 1' вывести строки, которые длиннее, чем 1 символ (удалить пустые строки)
cat /var/log/syslog | grep "$date" | awk '{print length($6)}' вывести длинну значения
awk 'BEGIN{x = "low"; print toupper(x)}' использовать функцию для перевода в вверхний регистр
awk 'BEGIN{x = "LOW"; print tolower(x)}' использовать функцию для перевода в нижний регистр
echo "1 2 3 4:5:6" | awk '{item=$4; split(item,array,":"); print array[2]}' разбить 4 значение на массив (используя функцию split) и забрать значение по 2-му индексу
free | awk '{if (NR == 2) print $0}' вывести только вторую строку
free | awk '{if (NR >= 2) print $0}' вывести втроую и последующие строки
free | awk '{if (NF >= 5) print $0}' вывести строки, где 5 или больше значений
cat /etc/passwd | awk '{ if (NR >= 10 && NR <= 20) print $0}' вывести с 10 по 20 строки
last | sed -n 1p | awk '$2=" ",$4=" "{print $0}' вывести все, кроме 2 и 4 значения (заменить)
ps -A | awk '{sum=""; for(i=1;i<=NF;i++) { if (i != 2) {sum=sum" "$i} } print sum}' вывести все, кроме 2-го значения

perl

Perl - это интерпретируемый язык программирования, который может использоваться для написания программ с C-подобным синтаксисом, так и в однострочных конструкциях для обработки текста в Bash-скриптах.

КлючОписаниеПример PerlАналог (grep/sed/awk)
-neПоиск и печать нужных строк (как grep)ls -lh / | perl -ne 'print if /root/'ls -lh / | grep root
-peЗамена текста во всем файле (как sed)ls -lh / | perl -pe 's/root/admin/g'ls -lh / | sed 's/root/admin/g'
-aneРазбить строку на массив (как awk)ls -lh / | perl -ane 'print "$F[8] $F[4]\n"'ls -lh / | awk '{print $9,$5}'
-F:Указать разделитель полейcat /etc/passwd | perl -ane 'print "$F[8] $F[4]\n"' -F:cat /etc/passwd | awk -F: '{print $2,$1}'
..Диапазон строкcat /etc/passwd | perl -ne 'print if 1..5'sed -n '1,5p' или awk 'NR==1, NR==5'
nextОтрицание (пропуск строк)cat /etc/ssh/sshd_config | perl -ne 'next if /^#/; print'grep -Ev "^$|^#" или sed "/^#|^$/d"
BEGIN/ENDПодсчет количества строкls -lh | perl -ne '$s++; END{print $s}'ls -lh | awk '{s++} END{print s}'

Пример доступа к структуре данных в формате json:

docker inspect lifailon/docker-socket-proxy:arm64 | perl -MJSON::PP -0 -e 'print decode_json(<>)->[0]{Config}{Image}'

curl

curl ifconfig.me узнать внешний ip
curl -v telnet://192.168.3.100:22 проверить доступность порта с помощью протокола telnet
echo -e "Subject: Test\n\nThis is test body" | curl smtp://localhost:2525 --mail-from admin@docker.local --mail-rcpt admin@docker.local --user admin:admin -T - проверить отправку почты с помощью протокола smtp
curl -sS https://httpbingo.org/headers подавить вывод статистики/загрузки (--silent) и отображать только вывод ошибок (--show-error)
curl -sSI https://raw.githubusercontent.com/Lifailon/lazyjournal/main/scripts/install.sh отправить запрос HEAD (--head) вместо GET для отображения статуса и заголовков ответа (не возвращяет тело ответа)
curl -sSi https://httpbingo.org/headers вернуть заголовки и тело ответа
curl -s -o /dev/null -w "%{http_code}\n" https://httpbingo.org/basic-auth/username/password вернуть только статус ответа (например, 401 - ошибка авторизации)
curl -sSf https://httpbingo.org/post выйти с ошибкой (--fail), если код не равен ОК 200 (например, 405 - метод не поддерживается)
curl -sSf -X POST https://httpbingo.org/post изменить метод запроса на POST
curl -sSLI https://github.com/Lifailon/lazyjournal/releases/download/0.8.6/lazyjournal-0.8.6-linux-arm64 переходить по редиректах (--location) и узнать размер файла в content-length curl -sSO --limit-rate 5m https://raw.githubusercontent.com/Lifailon/hwstat/rsa/hwstat.sh скачать файл, используя оригинальное название (--remote-name) и ограничив загрузку в 5 МБайт
curl -sSL https://raw.githubusercontent.com/Lifailon/hwstat/rsa/hwstat.sh -o hwstat.sh указать название файла (--output)
curl -sS --unix-socket /var/run/docker.sock http://localhost/version отправить запрос на локальный UNIX socket
curl -sSLk $url игнорировать ошибку самоподписанного сертификата SSL (--insecure)
curl -sSLk $url --cert client.crt --key client.key --cacert ca.pem использовать сертификаты для запроса curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0" https://httpbingo.org/headers подменить заголовок запроса User-Agent
curl -H "Authorization: Bearer token" https://httpbin.org/bearer передать токен в заголовке запроса для авторизации (--header)
curl -u username:password https://httpbingo.org/basic-auth/username/password авторизация (--user)
curl -H "Authorization: Basic $(echo -n username:password | base64)" https://httpbingo.org/basic-auth/username/password авторизация с помощью заголовка запроса
curl -x "http://user:pass@192.168.3.100:9090" "https://kinozal.tv/rss.xml" использовать proxy-сервер
curl -s "http://qbit:8888/api/v2/auth/login" --max-time 1 -c cookies.file -H "Referer: $QB_ADDR" -d "username=$QB_USER&password=$QB_PASS" 1> /dev/null передать данные авторизации в теле запроса (--data) и сохранить файл cookie для последующего использования в запросах
curl -s "http://qbit:8888/api/v2/app/version" -b cookies.file использовать файл cookie
curl --data-binary @config.conf https://httpbingo.org передать файл в исходном виде с переносом строк (байт в байт)

Пример отправки данных в базу временных рядов InfluxDB:

ip="192.168.3.104"
db="dbash"
table="icmp_metrics_table"
server="google.com"
host=$(hostname)

while true; do
    date=$(echo $EPOCHREALTIME | sed -E "s/\..+//")"000000000"
    ping=$(ping $server -c 2)
    loss=$(printf "%s\n" "${ping[@]}" | grep -Eo "[0-9]+%" | sed "s/%//")
    if (( $(echo "$loss != 100" | bc) )); then
        status="true"
        rtt=$(printf "%s\n" "${ping[@]}" | grep rtt | awk -F"/" '{print $5}')
    else
        status="false"
        rtt="0"
    fi
    #                                                            Table  Tag (string/int)          Field (double/int)      TIMESTAMP
    curl -i -XPOST "http://$ip:8086/write?db=$db" --data-binary "$table,host=$host,server=$server status=$status,rtt=$rtt $date"
    sleep 5
done

netcat

nc -zv 192.168.3.100 5985 проверить порт без попытки соединения (-z) в подробном режиме (-v)
nc -zvn 192.168.3.100 1-1000 2>&1 | grep succeeded сканирование TCP-портов, не используя преобразование DNS (-n)
nc -zvnu 192.168.3.100 5550-5560 сканирование UDP-портов (-u)
nc -lp 8081 создать сокет (чат сервер) в режиме прослушивания (listen) с указанием номера порта (-p)
nc 192.168.3.101 8081 подключиться к сокету (чат-клиент)
nc -lp 8081 > out.txt все поступившие данные на сокет записываются в файл (вместо вывода в консоль)
cat /etc/passwd | nc -N 192.168.3.101 8081 передать содержимое файла на удаленный сокет принимающей стороны (содержимое /etc/passwd запишется в out.txt) и закрыть удаленный сокет (-N)
nc -w 5 -Uvl server.sock > out.txt создать UNIX-сокет и передать вывод в файл, сокет закроется через 5 секунд (-w 5) или если будет задан параметр -N на стороне клиента
lsblk | nc -Uv server.sock подключиться к локальному сокету с второго терминала и отправить вывод команды в файл сокета приема \

Пример API сервера:

PORT=8085

# Добавить обработку сигналов kill -2 (ctrl+c) и kill -15
trap 'fuser -k -15 $PORT/tcp; break' SIGINT SIGTERM

while true; do
    request=$(nc -l -w 1 -p $PORT)
    request=$(echo "$request" | head -n 1)
    method=$(echo "$request" | cut -d " " -f 1 | tr '[:lower:]' '[:upper:]')
    endpoint=$(echo "$request" | cut -d " " -f 2)
    if [[ $method != "GET" ]]; then
        response="HTTP/1.1 405 Method Not Allowed\n\nMethod $method not supported on $endpoint\n"
    elif [[ $endpoint == "/api/date" ]]; then
        response="HTTP/1.1 200 OK\nContent-Type: text/plain\n\n$(date)"
    elif [[ $endpoint == "/api/disk" ]]; then
        response="HTTP/1.1 200 OK\nContent-Type: application/json\n\n$(lsblk -e7 --json)"
    elif [[ $endpoint == "/api/systemd/analyze" ]]; then
        response="HTTP/1.1 200 OK\nContent-Type: image/svg+xml\n\n$(systemd-analyze plot)"
    else
        response="HTTP/1.1 404 Not Found\n\n404 Not Found\n"
    fi
    echo -ne "$response" | nc -l -w 1 -p $PORT
done

curl -s http://localhost:8085/api/date

curl -s http://localhost:8085/api/disk | jq .blockdevices[]

Пример отправки метрик в базу данных временных рядов Graphite с помощью протокола UDP:

# StatsD (UDP)
# Формат: метрика:значение|type
# g (gauge) - запоминает последнее число
# c (counter) - счетчик, которй суммирует значение
# ms (timer) - считает среднее или перцентили
# s (set) - считает количество уникальных записей
# Хранятся в stats и stats_counts по указанном пути через точку

while true; do
  echo "test.dev.random:$(($RANDOM % 100))|c" | nc -u 127.0.0.1 8125
  sleep 1
done

Пример отправки метрик с помощью протокола TCP:

# Carbon (TCP)
# Формат: метрика значение timestamp

while true; do
  echo "test.dev.random $(($RANDOM % 100)) $(date +%s)" | nc -w 1 127.0.0.1 2003
  sleep 1
done

Пример проброса порта (L4 Reverse Proxy) сервера (переадресует локальный порт 2222 на 22 удаленной машины):

ncat -l 2222 -k --sh-exec "ncat 192.168.3.101 22"
socat TCP-LISTEN:2222,fork,reuseaddr TCP:192.168.3.101:22

Froxy - классический прямой и обратный прокси-сервер:

sudo apt-get install -y dotnet-runtime-8.0
arch="x64" # или "arm64"
sudo curl -s -L "https://github.com/Lifailon/froxy/releases/download/0.4.0/froxy-0.4.0-linux-$arch" -o /usr/local/bin/froxy
sudo chmod +x /usr/local/bin/froxy

froxy --socks 1080 запустить SOCKS прокси-сервер на порту 1080
froxy --forward 8080 запустить HTTP/HTTPS прокси на порту 1080
froxy --forward 8080 >> froxy.log & запустить фоновый процесс и передать вывод логов в файл
froxy --local 5514 --remote 192.168.3.100:514 запустить обратный прокси сервер на порту 5514, который перенаправляет на хост 192.168.3.100 и порт 514 (syslog)
froxy --local 192.168.3.100:2121 --remote 192.168.3.101:21 TCP туннелирование для RDP
froxy --local 127.0.0.1:8443 --remote https://example.com принимать HTTPS трафик на порту 8443 и переадресовать на указанный URL (поддерживаются GET и POST запросы с передачей заголовков и тела запроса от клиента, для использования API запросы и прохождения авторизации на сайтах используя cookie)
froxy --local *:8443 --remote https://example.com --user admin --pass admin слушать на всех интерфейсах и использовать авторизацию

jq

jq - это язык запросов для работы с JSON.

apt install jq

nodes=$(curl -s -H "Accept: application/json" https://check-host.net/nodes/ips) получить список node
echo $nodes | jq обработка входных данных командой jq (вывод отображается в правильно структурированном формате, а все элементы подсвечиваются соответствующим цветом)
echo $nodes | jq '.nodes | length' количество дочерних объектов в блоке node[]
echo $nodes | jq -r .nodes[1] получить значение второго объекта массива в формате raw string вместо JSON
echo $nodes | jq -r .nodes[-1] получить значение последнего объекта массива
hosts=$(curl -s -H "Accept: application/json" https://check-host.net/nodes/hosts) получить список всех хостов
echo $hosts | jq -r '.nodes | to_entries[].key' получить список всех вложенных ключей (адреса хостов) из объека (не является массивом)
echo $hosts | jq -r '.nodes | to_entries[].value' получить только значения всех вложанных ключей
echo $hosts | jq '.nodes."bg1.node.check-host.net"' получить значение дочернего ключа nodes по имени
echo $hosts | jq '.nodes | [.[]] | last' преобразовать отдельные объекты внутри nodes в массив, и передать полученный вывод в функцию last для получения значений последнего объекта
echo $hosts | jq '.nodes | to_entries[].value.location[0] == "ru"' проверить каждый элемент объекта в условии на true/false (вернет массив)
echo $hosts | jq '.nodes | to_entries[] | {Host: .key, Country: .value.location[1], City: .value.location[2]}' получить данные key-value из объекта nodes и пересобрать массив с новыми значениями ключей
echo $hosts | jq -r '.nodes | to_entries[] | "\(.key) (\(.value.location[1]), \(.value.location[2]))"' собрать массив строки из содержимого ключей
var="-" && echo $hosts | jq --arg v "$var" -r '.nodes | to_entries[] | "\(.key) \($v) \(.value.location[1]) \($v) \(.value.location[2])"' передать внешнюю переменную, которая будет использоваться внутри запроса
echo $hosts | jq -r '.nodes | to_entries[] | select(.value.location[0] == "ru") | .key' произвести фильтрацию с помощью функции select(), чтобы получить только нужные объекты
echo $hosts | jq '.nodes | to_entries[] | select(.value.location[0] != "ru") | .key' вывести объекты, которые не равны значению
echo $hosts | jq '.nodes | length' вывести общее количество объектов
echo $hosts | jq '.nodes | to_entries | map(select(.value.location[0] != "ru")) | length' создать массив функцией map() (объеденяет отдельные объекты {}{} группируются в один массив [{},{}]) только из тех объектов, которые соответствуют условию select() и вывести количество найденных объектов
echo $hosts | jq -r '.nodes | to_entries[] | select(.value.location[0] == "ru" or .value.location[0] == "tr") | .key' проверить два условия через or или and (для проверяемого типа данных int кавычки не используются)
echo $hosts | jq -r '.nodes | to_entries[] | select(.key | index("jp")) | .key' вывести список хостов региона Japan, которые в названии ключа содержат ключевое слово jp (частичное совпадение в значении)
echo '{"iso": [{"name": "Ubuntu", "size": 4253212899}, {"name": "Debian", "size": 3221225472}]}' | jq '.iso[] | {name: .name, size: (.size / 1024 / 1024 / 1024 | tonumber * 100 | floor / 100 | tostring + " GB")}' получить ГБ из байт и округлить вывод до 2 символом после запятой
echo '{"iso": [{"name": "Ubuntu", "progress": 0.333}]}' | jq '.iso[] | {name: .name, progress: (.progress * 100 | floor / 100 * 100 | tostring + " %")}' получить процент из дробной части (33%)
echo '[{"name": "Ubuntu", "added_on": 1625072400}, {"name": "Debian", "added_on": 1625158800}]' | jq '.[] | {name: .name, date: (.added_on + 3 * 3600 | strftime("%H:%M:%S %d.%m.%Y"))}' получить дату

jc

jc - инструмент для преобразования вывода популярных инструментов командной строки в JSON, YAML или словари Python, что позволяет передавать вывод в такие инструменты, как jq.

apt install jc

dig google.com | jc --dig
dig example.com | jc --dig | jq -r '.[].answer[].data'
jc --pretty /proc/meminfo
systemctl list-units --all --plain --no-legend --no-pager | jc --systemctl -p

yq

yq - это язык запросов для YAML, JSON, XML, CSV, TOML, INI и HCL.

snap install yq

cat /etc/netplan/*.yaml | yq .network.ethernets список адаптеров в конфигурации netplan
cat /etc/netplan/*.yaml | yq .network.ethernets.eth0.nameservers.addresses[] вывести массив dns адресов, настроенные на адаптере
curl -s https://kinozal.tv/rss.xml -x kinozal:proxy@192.168.3.100:9090 | yq -p xml .rss.channel.item[1].link вывести ссылку из первого элемента
curl -s https://raw.githubusercontent.com/JingWangTW/dark-theme-editor/main/hugo.toml | yq -p toml .params.footer.socialLink прочитать конфигурацию Hugo

xq

xq - это инструмент командной строки для запросов к XML и HTML в стиле jq.

apt-get install xq || brew install xq

curl -s https://kinozal.tv/rss.xml -x kinozal:proxy@192.168.3.100:9090 | xq -nx /rss/channel/item вывод содержимого дочерних элементов с тегами
curl -s https://kinozal.tv/rss.xml -x kinozal:proxy@192.168.3.100:9090 | xq -x /rss/channel/item/link вывести только содержимое (массив ссылок)
curl -s https://kinozal.tv -x kinozal:proxy@192.168.3.100:9090 | xq -nq "head" вывести блок head целиком (с тегами)
curl -s https://kinozal.tv -x kinozal:proxy@192.168.3.100:9090 | xq -q "head" вывести только текст из дочерних элементов выбранного тега (содержимое title)
curl -s https://kinozal.tv/browse.php?s=the+rookie -x kinozal:proxy@192.168.3.100:9090 | xq -nq "body > div > div > div > div > table > tbody > tr > td"
curl -s -X POST -u "Login:Password" "http://localhost:9091/transmission/rpc" | xq -q a -a href забрать X-Transmission-Session-Id для дальнейших запросов к API (обратиться к тэгу a и атрибуту href)

htmlq

htmlq - это язык запросов для HTML в стиле jq.

brew install htmlq

curl -s https://kinozal.tv/browse.php?s=the+rookie -x kinozal:proxy@192.168.3.100:9090 | htmlq table tr td a -t получить содержимое таблицы (вывести только текст содержимого)
curl -s https://kinozal.tv/browse.php?s=the+rookie -x kinozal:proxy@192.168.3.100:9090 | htmlq table tr td a -a href получить только ссылки
curl -s -X POST -u "Login:Password" "http://localhost:9091/transmission/rpc" | htmlq a -a href забрать X-Transmission-Session-Id для дальнейших запросов к API (обратиться к тэгу a и атрибуту href)

dasel

dasel - это инструмент для обработки JSON, YAML, TOML, XML и CSV c поддержкой конвертации между форматами.

brew install dasel

echo '{"name": "Tom"}' | dasel -r json 'name'
echo '{"name": "Tom"}' | dasel -r json -w yaml конвертировать json в yaml
echo '{"name": "Tom"}' | dasel -r json -w xml конвертировать json в xml
echo '{"name": "Tom"}' | dasel put -r json -t string -v 'contact@tomwright.me' 'email' добавить свойство
echo '{"email": "contact@tomwright.me","name": "Tom"}' | dasel delete -r json '.email' удалить свойство

tee users.json <<EOF
{
    "users": [
      {
        "name": "Иван Иванов",
        "email": "ivan.ivanov@example.com"
      },
      {
        "name": "Мария Петрова",
        "email": "maria.petrova@example.com"
      }
    ]
}
EOF

dasel -f users.json -r json ".users.[0].email"

tee users.yaml <<EOF
users:
  - name: Иван Иванов
    email: ivan.ivanov@example.com
  - name: Мария Петрова
    email: maria.petrova@example.com
EOF

dasel -f users.yaml -r yaml ".users.[1].email"

tee users.toml <<EOF
[[users]]
name = "Иван Иванов"
email = "ivan.ivanov@example.com"
[[users]]
name = "Мария Петрова"
email = "maria.petrova@example.com"
EOF

dasel -f users.toml -r toml ".users.[1].email"

tee users.xml <<EOF
<users>
  <user>
    <name>Иван Иванов</name>
    <email>ivan.ivanov@example.com</email>
  </user>
  <user>
    <name>Мария Петрова</name>
    <email>maria.petrova@example.com</email>
  </user>
</users>
EOF

dasel -f users.xml -r xml ".users.user.[0].email"

Системная информация

КомандаОписание
cat /etc/hostnameИмя хоста
cat /etc/hostsЛокальная таблица преобразовани ip в имя
cat /etc/hosts.{allow,deny}Белый список адресов и ограничение доступа к внешним сервисам (echo "in.telnetd: 192.168.3., .domain.ru" >> /etc/hosts.allow)
cat /proc/net/arpЛокальная таблица сопоставления ip c MAC-адресом
hostnamectlПодробная информация о системе (Operating System, Kernel, Architecture)
lsb_release -aВерсия дистрибутива
cat /etc/os-releaseОписание дистрибутива и версия ОС в формате ключ=значение
cat /proc/versionВерсия ядра и дистрибутива
uname или archВыводит архитектуру процессора формате x86_64 или aarch64
dpkg --print-architectureВыводит архитектуру процессора формате amd64 или arm64
lscpuПодробная информация о процессоре в yaml формате
nprocКол-во ядер
cat /proc/cpuinfoИнформация по ядрам процессора
uptimeВыводит время работы системы, кол-во залогиненных пользователей и LA - средняя загрузка системы за последние 1, 5 и 15 минут на 1 ядро
cat /proc/loadavgВыводит LA, 4-е значение - это кол-во процессов выполняемых в данный момент/общее количество процессов в системе и последнее значение, это PID последнего созданного процесса
cat /proc/cmdlineСодержит имя файла образа ядра и его параметры запуска, которые были указаны в приглашении загрузчика GRUB
cat /proc/statВыводит общую статистику работы CPU с момента последней загрузки (user/nice/system/idle/iowait/irq/softirq/steal_time/guest/guest_nice)
dmidecode -t biosИнформация о системе (system/baseboard/processor/memory) или использовать bios-vendor
dmidecode -t baseboardВерсия материнской платы, Video, Sound и их статус
lsusb -vtИнформация о USB устойствах (Bluetooth адаптер, мышка, клавиатура, принтеры)
lspciИнформация о PCI устройствах (подключенные к материнской плате компьютера по шине PCIe)
lshw -shortИнформацию по каждому PCI устройству
lshw -class busМатеринская плана и USB устройства, а также display (VGA controller), ё и disk
cat /proc/partitionsВыводит таблицу со списком всех блочных устройств (дисков) и их разделов, которые ядро распознало в системе на данный момент
cat /proc/asound/cardsВыводит список всех звуковых карт и аудиоинтерфейсов, которые распознало ядро через систему ALSA
ls /sys/class/netСписок сетевых интерфейсов
cat /proc/net/devСписок сетевых интерфейсов и их статистика (bytes, packets, errs, drop) для Receive (приема) и Transmit (передачи)
ethtool -S ens33Статистика сетевого интерфейса (ip down для сброса статистики и выгрузить модуль ядра с драйверов modprobe -r module и ip up)
ethtool -i ens33Драйвер сетевой карты
ethtool ens33 -p 60Включить светодиод на сетевой карте на 60 секунд
lsmodВыводит информацию из файла /proc/modules, какие дополнительные драйверы и функции сейчас загружены
modinfo ip_tablesВыводит информацию о конкретном модуле
cat /sys/block/sda/statСтатистика диска sda (аналогично stat -f /dev/sda)
ls /etc/*modprobe*Содержит конфигурационные файлы со списками модулей ядра
cat /etc/servicesСписок всех сервисов и сопоставленных с ними портов в системе (`cat /etc/services
cat /etc/mime.typesСписок сопосталвения файлов и их программ (`cat /etc/mime.types
ls -l /dev | grep sdСписок всех дисков и разделов в файловой системе
cat /proc/diskstatsСтатистика дисков
cat /proc/buddyinfoИнформация о фрагментации памяти в ядре Linux, спользуется для диагностики проблем с фрагментацией памяти
cat /proc/cgroupsОтображает информацию о текущих контрольных группах (cgroups), которые ядро использует для ограничения и изоляции ресурсов (CPU, память, ввод-вывод) для процессов
who -HaВыводит список пользователей, вошедших в систему в данный момент из системного файла /etc/utmp
who -bВыводит дату и время последней загрузки операционной системы
lastВыводит историю перезагрузок (-n 5 reboo), выключений (shutdown) и авторизации (требуется пакет wtmpdb, который хранит данные в SQLite)
historyВыводит историю выполняемых команд
history -aДобавить историю команд текущей сессии в файл ~/.bash_history, не дожидаясь завершения сессии
history -cОчистить текущую историю в оперативной памяти
history -rПеречитать файл истории заново

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

curl -s https://raw.githubusercontent.com/dylanaraps/neofetch/refs/heads/master/neofetch | bash
curl -s https://raw.githubusercontent.com/dylanaraps/pfetch/refs/heads/master/pfetch | bash
curl -s https://raw.githubusercontent.com/KittyKatt/screenFetch/refs/heads/master/screenfetch-dev | bash
curl -s https://raw.githubusercontent.com/ThatOneCalculator/NerdFetch/refs/heads/main/nerdfetch | bash
curl -s https://raw.githubusercontent.com/m0zgen/system-checks/master/system-check.sh | sudo bash
curl -s https://raw.githubusercontent.com/Lifailon/hwstat/refs/heads/rsa/hwstat.sh | bash

curl -s -L "https://github.com/fastfetch-cli/fastfetch/releases/download/2.40.1/fastfetch-linux-amd64.deb" -o /tmp/fastfetch.deb
sudo dpkg -i /tmp/fastfetch.deb && rm /tmp/fastfetch.deb
fastfetch

Системные настройки

sysctl -a отобразить все настройки ядра Linux, где представленны все параметры в виде переменных, имена переменных соответствуют пути файла в директории /proc/sys (вместо слеша в переменной используется точка)
sysctl net.ipv6.conf.all отобразить сетевые настройки для протокола IPv6
sysctl -w net.ipv6.conf.all.disable_ipv6=1 отключить протокол IPv6 до перезагрузки системы (аналогично echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6)
sysctl -w net.ipv6.conf.ens33.disable_ipv6=1 для интерфейса ens33
sysctl --system обновление информации из файлов/вернуть значения переменных до состояния сохраненного в файлах (удалить временные изменения с помощью команды sysctl)
sysctl -p /etc/sysctl.d/system-custom-tuning.conf загрузить настройки из указанного файла

# Количество выделенных файловых дескрипторов (сколько файлов открыто в системе на текущий момент), неиспользуемых дескрипторов и максимальное количество (определяется в file-max)
sysctl fs.file-nr
# Количество открытых дескрипторов у процессора PID 1
ls /proc/1/fd/ | wc -l
# Текущее количество активных асинхронных операций ввода-вывода (I/O) к диску
sysctl fs.aio-nr

Настройки в файле /etc/sysctl.d/system-custom-tuning.conf

# Разрешает выполнение 32 битных программ в 64 битной системе
abi.vsyscall32=1

# Максимальное количество файловых дескрипторов, которые могут быть открыты в файловой системе всеми процессами на уровне ядра ОС
fs.file-max=9223372036854775807
# Максимальное количество файловых дескрипторов для каждого отдельного процесса
fs.nr_open=1073741816
# Максимальное количество асинхронных операций ввода-вывода (I/O) к диску
fs.aio-max-nr=65536

# Минимальный размер свободной оперативной памяти который необходимо поддерживать
vm.min_free_kbytes=45056
# Процент свободной опретивной памяти, по достижении которого, данные (неиспользуемые процессами страницы памяти) начинают переноситься на SWAP раздел
vm.swappiness=60
# Скорость удаления dentry (имена папок и файлов) и inode (информация о правах, размере и расположении на диске) из кеша
vm.vfs_cache_pressure=100
# Процент от общей оперативной памяти который может быть заполнен страничным кешем, по достижении которой демон pdflush (dirty page flush) начинает сбрасывать данные из кеша оперативной памяти на диск
vm.dirty_background_ratio=10
# Предел объема оперативной памяти в процентах от free Available который может быть выделен под PageCache до их записи на диск
# На этом уровне все новые операции ввода-вывода приостанавливаются до тех пор, пока на диск не будут записаны грязные (Dirty) страницы (значение должно быть выше, чем dirty_background_ratio)
vm.dirty_ratio=20
# Время хранения Dirty-страниц в кеше в сотых долях секунд (3000 = 30 секунд) перед их записью на диск
vm.dirty_expire_centisecs=3000
# Интервал процесса проверки данных, которые подлежат записи на диск (500 - 5 секунд)
vm.dirty_writeback_centisecs=500

# Значение продолжительности жизни пакета (Time To Live) для исходящих пакетов (когда пакет попадает на роутер при маршрутизации, величина TTL в пакете уменьшается на 1)
net.ipv4.ip_default_ttl=64
# Выключение обнаружения максимального размера пакета (Path MTU Discovery) на пути следования
net.ipv4.ip_no_pmtu_disc=0
# Количество оперативной памяти (в страницах), которое суммарно может использовать стек TCP на все нужды
net.ipv4.tcp_mem= 93579 124775 187158
# Если включено, ядро будет игнорировать все icmp запросы (рекомендуется для защиты от DoS-атак)
net.ipv4.icmp_echo_ignore_all=0
# Игнорировать запросы ICMP ECHO, переданные широковещательными пакетами
net.ipv4.icmp_echo_ignore_broadcasts=1
# Игнорировать ошибочные ICMP запросы
net.ipv4.icmp_ignore_bogus_error_responses=1
# Запретить принимать и отправлять ICMP-пакеты перенаправления
net.ipv4.conf.all.accept_redirects=0
# Разрешает (1) или запрещает (0) маршрутизацию пакетов через текущий хост
net.ipv4.ip_forward=1
# Включить форвардинг пакетов (разрешить ядру операционной системы осуществлять проброс трафика с одного интерфейса на другой)
net.ipv4.conf.default.forwarding=1
# Диапазон локальных портов, доступных для установки исходящих подключений (создания локальных клиентских сокетов)
net.ipv4.ip_local_port_range=32768 60999
# Максимальное количество сокетов, находящихся в состоянии TIME-WAIT одновременно, для предотвращения простых DoS-атак
net.ipv4.tcp_max_tw_buckets=32768
# Максимальное количество осиротевших TCP сокетов (не связанных каким-либо идентификатором пользовательского файла) для броса соединения
net.ipv4.tcp_max_orphans=32768
# Количество попыток закрыть соединение, которое закрыто на локальной стороне сервера, перед тем, как оно будет принудительно разорвано и удалено ().
net.ipv4.tcp_orphan_retries=0
# Задает максимальное время пребывания сокета в состоянии FIN-WAIT-2 и используется, если другая сторона не закрыла соединение со своей стороны (для избежания утечки памяти)
net.ipv4.tcp_fin_timeout=60
# Срабатывает при достижение значения tcp_max_syn_backlog и помогает защититься от SYN-flood атак (ядро отвечает на каждый SYN-пакет, как обычно SYN/ACK)
net.ipv4.tcp_syncookies=1
# Помогает уменьшить задержки в сети, позволяя начать передачу данных сразу при отправке клиентом первого TCP-SYN (3 - включает для входящих и исходящих пакетов)
net.ipv4.tcp_fastopen=1
# Размер очереди запоминаемых запросов на попытку установки TCP-соединения (SYN-пакета в состоянии Waiting Acknowledgment) при отправки клиентом TCP-SYN пакета, для которых не было получено сервером подтверждения от клиента (полуоткрытых соединений)
net.ipv4.tcp_max_syn_backlog=512
# Размер очереди полуоткрытых соединений (открытых сокетов) ожидающих установки соединения. Если в ответ на SYN-пакета (synchronize) клиентом был получен от сервера пакет SYN-ACK (acknowledges), сервер ожидает от клиента отправки ACK-пакета, после чего соединение считается установленным
net.core.somaxconn=4096
# Количество попыток передачи SYN-пакета при установлении нового соединения, на каждую попытку отводится примерно 30-40 секунд (6 = 180 секунд)
net.ipv4.tcp_syn_retries=6
# Количество попыток передачи SYN-ACK-пакета в ответ на SYN-запрос для установки пассивного TCP-соединение, инициированное другим хостом
net.ipv4.tcp_synack_retries=5
# Регулирует размер очереди пакетов между сетевой картой и ядром, если ядро не успевает обрабатывать пакеты и очередь переполняется, то новые пакеты отбрасываются
net.core.netdev_max_backlog=1000

Лимиты

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

cat /etc/security/limits.conf | grep -Ev "^$|^#"

<user/@group>  <soft/hard>  <core/rss/as/nproc/cpu>  <value>
@zabbix           soft              nofile          65535     # установить soft ограничение на кол-во открытых файлов (nofile) для группы zabbix (можно менять в любую сторону, пока оно не превышает hard)
@zabbix           hard              nofile          65535     # ограничение hard можно менять только в меньшую сторону от имени обычного пользователя
*                 soft              nofile          2048      # ограничение для всех пользователей (-n)
*                 hard              nofile          8192
zabbix            soft              as              100       # максимальное кол-во оперативной памяти в КБ (-m)
zabbix            hard              as              100
*                 soft              msgqueue        unlimited # снятие ограничения очереди сообщений памяти (-q)
*                 hard              msgqueue        unlimited
*                 soft              nproc           unlimited # ограничение на количество процессов для всех пользователей (-u)
*                 hard              nproc           unlimited
user              hard              maxlogins       1         # ограничить количество SSH-соединений/сессий для конкретного пользователя (максимальное количество сеансов SSH под одним и тем же пользователем)
*                 hard              maxsyslogins    1         # ограничить общее количество сеансов/активных соединений SSH (за исключением root)

ulimit -a отобразить список ограничений

core file size              (blocks, -c) 0
data seg size               (kbytes, -d) unlimited
scheduling priority                 (-e) 0
file size                   (blocks, -f) unlimited
pending signals                     (-i) 15052
max locked memory           (kbytes, -l) 496180
max memory size             (kbytes, -m) unlimited
open files                          (-n) 1024
pipe size                (512 bytes, -p) 8
POSIX message queues         (bytes, -q) 819200
real-time priority                  (-r) 0
stack size                  (kbytes, -s) 8192
cpu time                   (seconds, -t) unlimited
max user processes                  (-u) 15052
virtual memory              (kbytes, -v) unlimited
file locks                          (-x) unlimited

ulimit -Sn отобразить значение текущего Soft (-S) ограничения для nofile (-n)
ulimit -Hn отобразить Hard (-H) ограничение
ulimit -n 3000 изменить ограничение количества открытых файлов для одного процесса (до перезагрузки)
ulimit -Sm 1500000 изменить soft (-S) ограничение оперативной памяти (-m) в 1500 Мб для пользователя
ulimit -u 5000 ограничение максимального количества запущенных пользовательских процессов (-u)
ulimit -s ограничение места для размера аргументов (stack size) команды/скрипта (bash: /usr/bin/diff: Argument list too long)
ulimit -m максимальный объем оперативной памяти
ulimit -v максимальный объем виртуальной памяти
ulimit -f максимальный размер создаваемых файлов
ulimit -t максимальное количество процессорного времени

systemctl edit rsyslog ограничения на уровне Unit для конкретного сервиса

[Service]
LimitNOFILE=1617596
LimitNOFILESoft=1617596

systemctl restart rsyslog
pid=$(ps -A | grep rsyslogd | awk '{print $1}') получить pid процесса
cat /proc/$pid/limits проверить применение ограничений после перезапуска сервиса

Квоты

Quotas - это ограничения на использование дискового пространства.

nano /etc/fstab примонтировать раздел на который необходимо установить квоту с указанными опциями

/dev/sda  /  ext4  defaults,usrquota,grpquota  0 0

mount -o remount,rw / перемонтировать файловую систему в режиме чтения (read) и записи (write)
mount | grep quota вывести список примонтированных устройств с фильтрацией по настройкам квот
quotacheck -favugm выполнить проверку наличия служебных файлов aquota.user и aquota.group (если их нет, команда создаст файлы автоматически)
quotaon -avug включить квоту
edquota -u lifailon создать квоту для пользователя или для группы (-g) на размер данных и кол-во файлов

Disk quotas for user lifailon (uid 1000):
  Filesystem                            blocks       soft       hard     inodes     soft     hard
  /dev/mapper/ubuntu--vg-ubuntu--lv     397112       400M       500M      3004       0        0

edquota -p lifailon user скопировать квоту на другого пользователя
edquota -t изменить период отсрочки soft квоты до момента, когда она станет hard (по умолчанию 7 дней)
quota lifailon -s отобразить квоты для пользователя
repquota -us / просканировать файловую систему и увидеть, кто из пользователей (-u) или групп (-g) потребляет больше всего места

#                Space limits               File limits
#                used     soft     hard     used     soft   hard
lifailon  --     388M     400M     500M     3004     0      0

# +- достигнут space limits 
# -+ достигнут file limits

su lifailon
# Создать файл размером 400MB
dd if=/dev/zero of=/tmp/test.file bs=1024000 count=400
dd: error writing '/tmp/test.file': Disk quota exceeded
117645312 bytes (118 MB, 112 MiB) copied, 0.158031 s, 744 MB/s

Systemd

Hostnamed

systemctl status systemd-hostnamed статус работы сервиса управления сетевым именем
hostnamectl выводит краткую сводку о системе
hostnamectl set-hostname srv-01.docker.local изменить имя сервера с сохранением в файле /etc/hostname при перезагрузке системы

Resolved

systemd-resolved - это локальный DNS-резолвер (заглушка stub resolver на локальном адресе 127.0.0.53), которая кеширует DNS-запросы и обеспечивает шифрование (DoT). Она перезаписывает файл /etc/resolv.conf при каждой загрузки системы и является символической ссылкой на файл-заглушку /run/systemd/resolve/stub-resolv.conf.

systemctl status systemd-resolved статус работы сервиса
journalctl -u systemd-resolved логи работы и кеша DNS

resolvectl status вывести список DNS-настроек для всех интерфейсов
resolvectl status | grep "Current DNS"
resolvectl dns wlan0 1.1.1.1 временно сменить DNS адрес на адаптере
resolvectl query google.com проверить резолвинг (покажет, через какой протокол UDP или TCP и какой сервер прошел запрос)

resolvectl monitor выводит статистику запросов на сервере в реальном времени
resolvectl statistics отобразить статистику кеша и количество транзакций (внешние запросы для резолвинга имени)
resolvectl show-cache вывести содержимое кеша
resolvectl flush-caches очистить локальный кеш DNS

Настройка конфигурации в файле /etc/systemd/resolved.conf

[Resolve]
DNS=8.8.8.8 1.1.1.1
# Включаем кеширование
Cache=yes

# Настройки подключения к домену
# DNS=192.168.3.101 8.8.8.8
# Domains=docker.local

/etc/resolv.conf - главный конфигурационный файл в системе, для настройки внешних DNS-резолверов.

# nameserver 127.0.0.53
nameserver 8.8.8.8
nameserver 1.1.1.1

# Настройки подключения к домену
# nameserver 192.168.3.233
# domain docker.local
# search docker.local

Чтобы изменения в файле не перезатирались после перезагрузки системы, нужно отключить службу systemd-resolved и удалить симлинк rm /etc/resolv.conf && touch /etc/resolv.conf.

Timedated

timedatectl - это клиент системной службы systemd-timedated.service, предназначенный для управления системным временем и даты.

timedatectl текущее время
timedatectl list-timezones список часовых поясов
timedatectl set-timezone 'Europe/Moscow' изменить временную зону на MSK, +0300 (изменится Local time)
timedatectl set-ntp no отключить NTP-синхронизацию
timedatectl set-time "13:00:00" указать время вручную, после отключения NTP
timedatectl set-ntp yes включить NTP service

Настройка синхронизации в файле /etc/systemd/timesyncd.conf

[Time]
# Основные сервера
NTP=ntp.msk-ix.ru 0.ru.pool.ntp.org
# Резервный сервер
FallbackNTP=ntp.ubuntu.com

Применить настройки и отобразить статус:

systemctl status systemd-timesyncd
systemctl restart systemd-timesyncd
timedatectl timesync-status
journalctl -u systemd-timesyncd

Analyze

systemd-analyze отображает статистику времени загрузки ядра и userspace (пользовательского пространства)
systemd-analyze time суммарное время на запуск системы
systemd-analyze blame --no-pager отобразить все процессы и отсортировать по времени загрузки
systemd-analyze plot > systemd-analyze.svg создать векторный отчет в формате Scalable Vector Graphics

Cgroups

systemd-cgtop аналог top для cgroups (Control Groups), который выводит, сколько ресурсов (CPU и RAM) потребляет конкретный сервис, а не просто процесс
systemd-cgtop -d 5 -m обновлять вывод каждые 5 секунд и сортировать по памяти (--order=memory)
systemd-cgtop -n 1 -P вывести 1 раз и cчитать только процессы пользователей (игнорировать потоки ядра)

systemd-cgls (Control Group List) - выводит дерево всех запущенных процессов, сгруппированных по их принадлежности к конкретным сервисам в cgroups.

systemd-path выводит стандартные пути в системе (где лежат конфиги, логи и т.д.)
systemd-delta находит различия между дефолтными конфигами и правками в /etc

systemd-sysusers декларативный процесс создания УЗ (ищет файлы .conf в директориях /usr/lib/sysusers.d/ и /etc/sysusers.d/). Если в конфиге указан пользователь, которого еще нет в /etc/passwd, создаст его.

echo "password" | sudo systemd-creds encrypt - pass.cred сохранить пароль в файл с использованием TPM2 (Trusted Platform Module), который использует ключ внутри микросхемы на материнской плате для шифрования
systemd-creds decrypt pass.cred при переносе диска на другую систему, расшифровать файл будет невозможно, потому что на новой плате другой TPM чип с другим ключом

Systemctl

systemctl reload ssh отправка сигнала SIGHUP (-1) для обновления конфигурации сервиса из /etc/ssh/sshd_config без разрыва текущих соединений (если у юнита поддерживается эта функция)
systemctl status ssh отображает путь к юниту, статус его работы, автозагрузки, потребление ресурсов, CGroup и лог

systemctl restart ssh/systemctl start ssh запуск или перезапуск юнита (до перезагрузки)
systemctl stop ssh остановка юнита (до перезагрузки)

При остановки процесса используется сигнал SIGTERM (-15) или любой другой, который будет указан в параметре KillSignal (например, прерывание KillSignal=SIGINT, который используется при нажатии Ctrl+C) для процесса, который указан параметр KillMode. По умолчанию используется KillMode=control-group, который завершает главный и все созданные им дочерние процессы (одновременно всей группе), или только родительский процесс (Main PID), используя KillMode=process, что бы сохранить установленные соединения, созданные дочерними процессами.

По умолчанию systemd ждет 90 секунд (указывается в параметре юнита TimeoutStopSec или глобально с помощью DefaultTimeoutStopSec в файле /etc/systemd/system.conf), если сервис за это время не ответит, systemd посылает сигнал SIGKILL (-9), при котором ядро сразу убивает процесс.

systemctl enable ssh добавить в автозагрузку, на основе группы в секции [Install] создает симлинк на реальный файл сервиса в системе (Created symlink '/etc/systemd/system/multi-user.target.wants/ssh.service' → '/usr/lib/systemd/system/ssh.service')
systemctl disable ssh удалить из автозагрузки

systemctl mask ssh выключить юнит, который нельзя будет запустить вручную или разбудить другим сервисом как зависимость (создает симлинк на /dev/null)
systemctl unmask ssh включить юнит (удалить симлинк)

systemctl cat ssh отобразить путь и содержимое unit-файла
systemctl edit --full ssh открыть юнит-файл для редактирования
systemctl daemon-reload перечитать все файлы юнитов с диска и перестроить дерево зависимостей

systemctl list-dependencies ssh отобразить дерево зависимостей для запуска указанного юнита (например, сначала должен быть запущен ssh.socket)
systemctl list-dependencies ssh --reverse отобращить сервисы, зависящие от указанного юнита

systemctl list-units --all --no-pager --type service отображение статуса всех сервисов
systemctl list-units --all --no-pager --type service --state=active вывести список только работающих сервисов
systemctl list-units --all --no-pager --user --type service список пользовательских сервисов (--user)

systemctl list-unit-files список всех юнит-файлов на диске с их текущим статусом работы при загрузке системы (STATE) и по умолчанию (PRESET) сразу после установки пакета
systemctl list-unit-files --all --no-pager --type=service,timer отфильтровать по сервисам и таймерам
systemctl list-unit-files --all --no-pager --type=service --state=enabled вывести список сервисов, которые добавлены в автозагрузку
systemctl preset ssh.service привести STATE к состоянию, указанному в PRESET

Scope

systemd-run превращает скрипт в временный изолированном сервис (scope) для ограничения ресурсов
systemd-run --scope -p MemoryMax=500M bash ./script.sh запустит скрипт с выводов в терминал
systemd-run --scope -p CPUQuota=20% stress --cpu 4 лимит на процессорное время в процентах
systemd-run --unit=backup bash ./backup.sh запускает сервис в фоне с возможность просмотра логов и будет удален после его завершения
journalctl -u backup

Unit

cat /etc/systemd/system.conf глобальные настройки юнитов, которые будут использоваться по умолчанию

Разбор юнита ssh.service:

[Unit]
# Название сервиса (отображается в systemctl status)
Description=OpenBSD Secure Shell server
# Ссылки на документацию (man-страницы)
Documentation=man:sshd(8) man:sshd_config(5)
# Порядок запуска (текущий сервис будет запущен только после службы сети, системы поиска имен и аудита)
After=network.target nss-user-lookup.target auditd.service
# Проверка, если файл указанный существует, сервис не запустится (защита от автозапуска)
# Позволяет убрать из автозагрузки с помощью touch /etc/ssh/sshd_not_to_be_run
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
# Читать переменные окружения из файла, которые доступны только этому процессу
# Символ "-" означает не выводить ошибку, если файла отсутствует
EnvironmentFile=-/etc/default/ssh
# Проверка конфигурации на валидность перед запуском (в случае ошибки сервис не поднимется)
ExecStartPre=/usr/sbin/sshd -t
# Основная команда запуска (-D не уходить в фон и используем переменную, полученную из файла EnvironmentFile)
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
# Проверка конфигурации перед мягкой перезагрузкой (reload)
ExecReload=/usr/sbin/sshd -t
# Команда перезагрузки - посылает сигнал SIGHUP основному процессу (не разрывает текущие сессии)
ExecReload=/bin/kill -HUP $MAINPID
# При остановке убивать только основной процесс, не трогая дочерние (это сохранит работу текущих SSH-сессий)
KillMode=process
# Автоматический перезапуск сервиса, если код завершения не равен 0
Restart=on-failure
# Код выхода, при котором systemd не будет перезапускать сервис
RestartPreventExitStatus=255
# Тип запуска сервиса (сервис сам сообщит о готовности, когда полностью инициализируется)
# Например, в bash используется команда systemd-notify --ready "Config loaded"
Type=notify
# Создать временную идректорию /run/sshd (нужна для работы демона)
RuntimeDirectory=sshd
# Права доступа на временную идректорию
RuntimeDirectoryMode=0755

[Install]
# При включение автозагрузки (systemctl enable), сервис добавится в многопользовательский режим
WantedBy=multi-user.target
# Позволяет обращаться к сервису по короткому имени sshd вместо ssh при включение в автозагрузку
Alias=sshd.service

Создание юнита для проверки интернета: /root/scripts/icmp-check.sh

#!/bin/bash

ADDRESS="${1:-google.com}"
TIMEOUT="${2:-30}"

host "$ADDRESS" > /dev/null || { echo "DNS ERROR"; exit 1; }
systemd-notify --ready --status="DNS OK"

while true; do
    date=$(date '+%Y.%m.%d %H:%M')
    loss=$(ping -c 2 $ADDRESS | grep -Ewo "[0-9]+%")
    if [ $loss = "100%" ]; then
        echo "$date: $ADDRESS - unavailable"
    else
        echo "$date: $ADDRESS - available"
    fi
    sleep $TIMEOUT
done

Создание сервиса для скрипта: /etc/systemd/system/icmp-check.service

[Unit]
Description=ICMP/ping checker
After=network.target

[Service]
ExecStart=/root/scripts/icmp-check.sh google.com 5
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
# Type=simple
# Проверяем статус
Type=notify
# Время ожидания проверки
TimeoutStartSec=10
# Запись в файл
# StandardOutput=append:/var/log/icmp.log
# StandardError=inherit

[Install]
WantedBy=multi-user.target
Alias=icmpd.service

Запуск сервиса:

chmod +x /root/scripts/icmp-check.sh
systemctl daemon-reload
systemctl enable icmp-check.service
systemctl start icmp-check
systemctl status icmp-check
journalctl -u icmp-check.service --since "today" -f

Timer

Timer - это современная замена cron, которая отправляет по расписанию команду start сервисам.

Создаем юнит для обновления пакетов: /etc/systemd/system/apt-upgrade-daily.service

[Unit]
Description=Update and upgrade system packages
# Запустить только после того, как отработает указанный сервис (будет получен IP-адрес)
After=network-online.target
# Попытаться запустить сервис, если он остановлен
Wants=network-online.target
# Жесткая зависимость (если сервис упал, этот сервис тоже будет остановлен)
Requires=network-online.target

[Service]
# Ожидание выполнения ExecStart до его завершения, преред тем как вернуть статус
Type=oneshot
# Сначала запустить обновление списка и потом обновлять пакеты
ExecStartPre=/usr/bin/apt-get update
# Игнорировать ошибки с помощью "-"
ExecStart=-/usr/bin/apt-get upgrade -y
# Выполнение после успешного завершения
ExecStartPost=/bin/sh -c 'echo "System packages updated successfully" | systemd-cat -t apt-upgrade-daily -p info'
# Сколько ждать выполнения задания до принудительной остановки
TimeoutStopSec=10min

User=root
Group=root
WorkingDirectory=/tmp
Restart=no
MemoryMax=1G
CPUQuota=50%

[Install]
WantedBy=multi-user.target

Создаем таймер для автоматизации запуска: /etc/systemd/system/apt-upgrade-daily.timer

[Unit]
Description=Update and upgrade system packages by daily timer

[Timer]
# Раз в месяц (1-го числа в 00:00)
#OnCalendar=monthly
# Раз в неделю (в понедельник)
#OnCalendar=weekly
# Запустить через 15 минут после включения системы
#OnBootSec=15min
# Каждый час после предыдущего запуска (создает цикл)
#OnUnitActiveSec=1h
# Каждые 30 минут
#OnCalendar=*-*-* *:0/30:00
# Сб и вс в 6 утра
#OnCalendar=Sat,Sun *-*-* 06:00:00
# По будням
#OnCalendar=Mon..Fri 06:00:00
# Каждый день в 6:00 и 18:00
#OnCalendar=*-*-* 06,18:00:00
OnCalendar=*-*-* 06:00:00
# Запускает таймер, если система была выключена и в это время был пропущен запуск
Persistent=true

[Install]
WantedBy=timers.target

systemctl list-timers --all отображает расписание всех таймеров

systemctl daemon-reload
# Добавить таймер в автозагрузку (добавляет в расписание) и сразу включить его (--now как systemctl start)
systemctl enable --now apt-upgrade-daily.timer
systemctl status apt-upgrade-daily.timer
# Запустить сервис вручную (не дожидаясь срабатывания таймера) 
systemctl start apt-upgrade-daily.service
# Вывести лог запуска самого таймера
journalctl -u apt-upgrade-daily.timer -f
# Вывести лог работы сервиса (срабатывания и stdout приложений)
journalctl -u apt-upgrade-daily.service -f
# Вывести лог приложения из ExecStartPost по тегу
journalctl -t apt-upgrade-daily -f
# Отключить таймер (удалить из списка расписания)
# systemctl disable apt-upgrade-daily.timer

Path

Path следит за изменениями в указанном файле и запускает указанный юнит на выполнение, после чего засыпает до следующего изменения.

Создаем юнит для бэкапов: /etc/systemd/system/homepage-backup.service

[Unit]
Description=Backup homepage config

[Service]
Type=oneshot
ExecStart=/usr/bin/cp -r /home/lifailon/docker/homepage/homepage_config /tmp/homepage_backup

[Install]
WantedBy=multi-user.target

Создаем юнит для отслеживания изменений: /etc/systemd/system/homepage-monitor.path

[Unit]
Description=Monitor homepage config and backup files

[Path]
PathChanged=/home/lifailon/docker/homepage/homepage_config/services.yaml
Unit=homepage-backup.service

[Install]
WantedBy=multi-user.target

Включаем:

systemctl daemon-reload
systemctl enable --now homepage-monitor.path
systemctl list-unit-files --type=path
journalctl -u homepage-backup.service -f

Mount

systemd-mount /dev/sdb1 /mnt/data монтирование дисков через systemd (создает временный .mount юнит)
systemctl status mnt-data.mount
systemd-umount /mnt/data

У юнитов монтирования есть жесткое правило именования, которое должно в точности повторять путь до директории монтирования, заменяя / на -.

/etc/systemd/system/mnt-backup.mount

[Unit]
Description=Mount remote SMB share
After=network-online.target
Wants=network-online.target

[Mount]
What=//192.168.3.100/Backup
Where=/mnt/backup
Type=cifs
Options=credentials=/etc/samba/creds,iocharset=utf8,rw,file_mode=0777,dir_mode=0777

[Install]
WantedBy=multi-user.target

systemctl enable --now mnt-backup.mount

Если в момент загрузки системы SMB-сервер недоступен или потеряно соединение, монтирование не произойдет или директория будет отмантирована и необходимо будет монтировать вручную systemctl start mnt-backup.mount.

Используя automount, монтирование производится в момент обращения к папке.

/etc/systemd/system/mnt-backup.automount

[Unit]
Description=Mount remote SMB share

[Automount]
Where=/mnt/backup
# Размонтировать через 5 минут бездействия (опционально)
TimeoutIdleSec=300

[Install]
WantedBy=multi-user.target

systemctl enable --now mnt-backup.automount

journald

journald - это служба, которая собирает и хранит логи в бинарном формате, которые можно читать и фильтровать с помощью утилиты journalctl.

Запись

systemd-cat - перехватывает STDOUT и отправляет его демону systemd-journald

# Определить tag и уровень логирования
echo "test from terminal" | systemd-cat -t script -p info

journalctl -t script
Mar 31 12:01:15 rpi-105 script[3729952]: test from terminal

Фильтрация

journalctl --system отобразить системный журнал
journalctl --user отобразить пользовательский журнал для текущего пользователя
journalctl -em отобразить записи из всех доступных журналов (--merge) с конци (--pager-end)
journalctl -ek отобразить только сообщения ядра (--dmesg) для текущей загрузки
journalctl -et systemd фильтрация по тегу

journalctl -ep 3 фильтрация по уровню логирования - 0 (emerg), 1 (alert), 2 (crit), 3 (err), 4 (warning), 5 (notice), 6 (info), 7 (debug)

journalctl -S "2023-09-01 12:00:00" -U "2023-09-01 15:00:00" фильтрация по времени с (--since) 1 сентября 12:00:00 по (--until) 15:00:00
journalctl --since today отобразить сообщения за сегодня

journalctl --list-boots вывести список сохраненных загрузок системы
journalctl -b отобразить сообщения с момента последней загрузки системы (--boot)
journalctl -b ba6b2292a0e84d83a81cedfaa221926f показать сообщения с момента конкретной загрузки системы

systemctl --type=help вывести список доступных типов юнитов
systemctl list-units --all --no-legend --no-pager --type=service,timer --output=json | jq -r .[].unit вывести список имет всех юнитов с фильтрацией по типу юнитов
journalctl -eu ssh фильтрация журнала по названию юнита (--unit)

Ротация

journalctl -n 1 --no-pager --output=json-pretty вывод всех доступных полей для последнего значения в формате JSON
journalctl --fields вывести список всех используемых полей по которым возможна фильтрация вывода в системе (SYSLOG_IDENTIFIER, UNIT, USER_UNIT, _UID, _PID, _COMM, _EXE, _CMDLINE и т.д.)
journalctl --field SYSLOG_IDENTIFIER вывести список доступных значений для фильтрации
journalctl SYSLOG_IDENTIFIER=dockerd фильтрация вывода по полю
journalctl -e _PID=3972315 фильтраци по PID процесса
journalctl -e _EXE=/usr/sbin/cron фильтраци по исполняемому файлу

journalctl --disk-usage вывести общее использование диска всеми файлами журнала (Archived and active journals take up 2.8G in the file system)
journalctl --flush сбросить логи из оперативной памяти (/run) на диск (/var)
journalctl --relinquish-var прекратить запись в /var/log/journal и переключиться обратно на хранение в оперативной памяти (/run/log/journal), например, при выключение системы
journalctl --verify проверить целостность файла журнала
journalctl --vacuum-time=1month удалить файлы журнала, старше указанного времени (1-го месяца)
journalctl --vacuum-size=100M очистить логи, чтобы размер хранилища соответствовал указанному размеру
journalctl --vacuum-files=100 оставить только указанное количество файлов журнала
journalctl --rotate запустить немедленную ротацию файлов журнала
journalctl --sync синхронизировать незаписанные сообщения журнала на диск

journalctl --header вывести список журналов на диске

Конфигурация

Настройка логирования в файле /etc/systemd/journald.conf

[Journal]
# Журналы сохраняются на диске или в памяти, при недостатке места на диске
Storage=auto
# Журналы всегда сохраняются на диске (/var/log/journal)
# Storage=persistent
# Журналы хранятся только в памяти (/run/log/journal) и не сохраняются на диск
# Storage=volatile
# Журналы не сохраняются
# Storage=none

# Сжимает данные внутри файлов журнала
Compress=yes
# Добавляет цифровую подпись в журналы, чтобы защитить их от изменений
Seal=yes
# Для каждого пользователя создается свой файл логов (обычный юзер не сможет прочитать логи другого юзера в /var/log/journal)
SplitMode=uid
# Интервал между синхронизациями журнала с диском (5 минут)
SyncIntervalSec=5m

# Временной интервал, в течение которого будет ограничено количество записей журнала, если они приходят слишком часто
RateLimitIntervalSec=30s
# Максимальное количество записей, которое можно сделать в журнал за интервал RateLimitIntervalSec
RateLimitBurst=10000

# Ограничивает максимальное количество дискового пространства, которое могут занимать системные журналы (если пространство превышает этот лимит, старые журналы будут удаляться)
SystemMaxUse=3G
# Минимальное количество свободного места на диске, которое должно оставаться для других системных задач (если места на диске становится меньше, система начнет удалять старые журналы)
SystemKeepFree=1G
# Ограничивает размер одного файла журнала на диске. Если файл превышает этот размер, он будет разделен (по умолчанию 1/8 от SystemMaxUse)
SystemMaxFileSize=15%
# Максимальное количество файлов журнала, которые могут быть созданы (старые файлы будут удаляться)
SystemMaxFiles=100
# Сколько памяти в ОЗУ можно отдать под логи
RuntimeMaxUse=
# Сколько ОЗУ оставить свободной, прежде чем начать удалять старые логи из памяти
RuntimeKeepFree=
# Максимальный размер одного файла лога в ОЗУ
RuntimeMaxFileSize=
# Сколько отдельных файлов логов может плодиться в памяти
RuntimeMaxFiles=100
# Максимальный срок хранения журналов (например, журналы будут храниться не более месяца)
MaxRetentionSec=1month
# Принудительная ротация, даже если файл не заполнился до лимита SystemMaxFileSize, через месяц он будет закрыт, и начнется новый
MaxFileSec=1month

# Должны ли записи журнала перенаправляться в системный журнал (syslog), например для rsyslog
ForwardToSyslog=yes
# Должны ли записи журнала перенаправляться в буфер ядра (KMsg)
ForwardToKMsg=no
# Должны ли записи журнала отображаться на консоли работающего в системе через TTY (не в терминал других пользователей)
ForwardToConsole=no
# Должны ли записи журнала отображаться всем пользователям, работающим в системе (уведомления будут выводиться всем пользователям через команду wall)
ForwardToWall=yes
# Указывает, на какой терминал выводить логи, если включен параметр ForwardToConsole=yes
TTYPath=/dev/console

# Максимальный уровень журналируемых записей, которые будут сохраняться
MaxLevelStore=debug
# Максимальный уровень журналируемых записей, которые будут отправляться в syslog
MaxLevelSyslog=debug
# Лимит для пересылки в буфер ядра
MaxLevelKMsg=notice
# Лимит для вывода на физический монитор (HDMI)
MaxLevelConsole=info
# Максимальный уровень журналируемых записей, которые будут выводиться всем пользователям через команду wall
MaxLevelWall=emerg
# Включить возможность слушать логи через сокеты
MaxLevelSocket=debug
# Максимальный размер строки, которая может быть записана в журнал
LineMax=48K
# Заставляет journald забирать все, что пишет само ядро Linux (сообщения драйверов, ошибки железа)
ReadKMsg=yes

# Журналировать события аудита (например, вход в систему, попытки доступа к файлам, изменения прав на файл, запуск и завершение процессов и т.п.)
Audit=yes

sudo systemctl restart systemd-journald

journalctl _TRANSPORT=audit просмотр журнала аудита после включения в конфигурации (из файла /var/log/audit/audit.log)

auditd

auditd (Linux Audit Daemon) - нативный инструмент мониторинга событий операционной системы и записи их в журналы событий от компании RedHat, который наблюдает за системными вызовами и может записывать события чтения, записи, выполнения и изменение прав.

apt install auditd

sudo auditctl -w /etc/hosts -p rwa -k hosts_access создаем правило мониторинга для файла /etc/hosts
sudo auditctl -a always,exit -F path=/etc/hosts -F perm=rwa -k hosts_access отслеживать системные вызовы (syscall) относящиеся к файлу (работает быстрее)

r    read        Чтение файла
w    write       Запись / изменение содержимого
x    execute     Исполнение файла (программы)
a    attribute   Изменение атрибутов (chmod, chown и т.п.)

auditctl -l вывести список всех правил
auditctl -D удаляет все активные правила аудита

ausearch -k hosts_access --format text вывести лог событий

At 19:03:07 04/01/26 system, acting as root, successfully opened-file /etc/hosts using /usr/bin/ping

ausearch -k hosts_access --format interpret подробный вывод лога

type=PROCTITLE msg=audit(04/01/26 19:10:34.221:638) : proctitle=ping -c 2 google.com
type=PATH msg=audit(04/01/26 19:10:34.221:638) : item=0 name=/etc/hosts inode=739 dev=b3:02 mode=file,644 ouid=root ogid=root rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(04/01/26 19:10:34.221:638) : cwd=/
type=SYSCALL msg=audit(04/01/26 19:10:34.221:638) : arch=aarch64 syscall=openat success=yes exit=5 a0=AT_FDCWD a1=0xffffb0f6fd40 a2=O_RDONLY|O_CLOEXEC a3=0x0 items=1 ppid=4018 pid=4019 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=ping exe=/usr/bin/ping subj=unconfined key=hosts_access

type=PROCTITLE msg=audit(04/01/26 19:40:46.511:1273) : proctitle=cat /etc/hosts
type=PATH msg=audit(04/01/26 19:40:46.511:1273) : item=0 name=/etc/hosts inode=739 dev=b3:02 mode=file,644 ouid=root ogid=root rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(04/01/26 19:40:46.511:1273) : cwd=/home/lifailon
type=SYSCALL msg=audit(04/01/26 19:40:46.511:1273) : arch=aarch64 syscall=openat success=yes exit=3 a0=AT_FDCWD a1=0xffffd3b616c2 a2=O_RDONLY a3=0x0 items=1 ppid=2279 pid=12227 auid=lifailon uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts0 ses=3191 comm=cat exe=/usr/bin/cat subj=unconfined key=hosts_access

aureport вывести отчет

# Мониторинг отказа доступа (permission denied) к файлам во всей систем
sudo auditctl -a always,exit -F arch=b64 -S open,openat -F exit=-EACCES -k access-denied
# Ошибки типа operation not permitted
sudo auditctl -a always,exit -F arch=b64 -S open,openat -F exit=-EPERM -k access-denied

# Мониторинг использования sudo (x)
sudo auditctl -a always,exit -F path=/usr/bin/sudo -F perm=x -F 'auid>=1000' -F 'auid!=4294967295' -k sudo-command

# Мониторинг добавления/изменения/удаления пользователей
sudo auditctl -w /usr/sbin/useradd -p x -k useradd
sudo auditctl -w /usr/sbin/userdel -p x -k userdel
sudo auditctl -w /usr/sbin/usermod -p x -k usermod

# Мониторинг изменений (wa) системных настроек (файлы конфигурации)
sudo auditctl -w /etc/passwd -p wa -k passwd-changes
sudo auditctl -w /etc/shadow -p wa -k shadow-changes
sudo auditctl -w /etc/group -p wa -k group-changes
sudo auditctl -w /etc/sudoers -p wa -k sudoers-changes

dmesg

dmesg -Tx прочитать логи буфера сообщений ядра из /var/log/dmesg (используется для записи во время загрузки системы пока сервис Syslog еще не запущен)
dmesg -Tx -l crit,err отфильтровать вывод
dmesg -E включить логирование ядра в консоль (--console-on)
dmesg -D отключить (--console-off)
dmesg -n 1 изменить уровень логирования для печати в консоль
dmesg -u отображать вывод из программ окружения пользователя
dmesg -w выводить журнал в реальном времени

rsyslog

systemctl status rsyslog

Настройка сервера (listener) в файле /etc/rsyslog.conf

# provides UDP syslog reception (input module udp)
module(load="imudp")
input(type="imudp" port="514")
# provides TCP syslog reception
#module(load="imtcp")
#input(type="imtcp" port="514")
# Включить фильтрацию одинаковых сообщений
$RepeatedMsgReduction off
# Шаблон создания директории на основе IP адреса клиента и сбор всех логов в один файл
$template RemoteLogs,"/var/log/remote/%fromhost-ip%/syslog.log"
# Шаблон создания директории на основе имени клиента и лог-файлов по имени программы:
# $template RemoteLogs,"/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log"
# Сохранять сообщения от любого источника (*) с любым приоритетом (*) в файл, заданный шаблоном (RemoteLogs)
*.* ?RemoteLogs

systemctl restart rsyslog

Настройка клиента в файле /etc/rsyslog.d/all.conf

# UDP:
*.* @192.168.3.101:514
# TCP:
# *.* @@192.168.3.101:514
# Фильтрация по категории и уровню важности
# auth.* @@192.168.3.101:514
# *.err @@192.168.3.101:514

logrotate

systemctl status logrotate.timer

Настройка глобальных параметров ротации в файле /etc/logrotate.conf

# Ротация файлов журнала еженедельно
weekly
# По умолчанию используется группа adm, которая является владельцем группы (ls -ld /var/log/syslog)
su root adm
# Количество файлов или недель (если ротация настроена еженедельно) хранения журналов
rotate 4
# Создавать новые пустые файлы журналов после ротации старых
create
# Использовать дату в качестве суффикса ротируемого файла
dateext
# Сжимать лог-файлы
compress
# Включить дочерние конфигурации
include /etc/logrotate.d

Ротация файлов в конфигурации /etc/logrotate.d/logrotate_remote.conf

/var/log/remote/*/*.log {
  su root root
  daily
  copytruncate
  size 10M
  rotate 3
  compress
  dateext
}

Условия запуска:

Условия хранения:

logrotate -d /etc/logrotate.d/logrotate_remote.conf проверить ротацию (--debug)
logrotate -fv /etc/logrotate.d/logrotate_remote.conf запустить ротацию сейчас (--force) с подробным выводом (--verbose)
cat /etc/cron.daily/logrotate задание запуска создается автоматически, который читает конфигурационный файл ротации /etc/logrotate.conf (в нем указана директрия: include /etc/logrotate.d в которой лежат файлы ротации)

Менеджеры пакетов

apt

ls -l /var/lib/apt/periodic/update-success-stamp дата последнего выполнения apt update
ls -lh /var/cache/apt местоположение кеша пакетов apt
history | grep "apt update" история запуска команды обновления

apt list --installed список установленных пакетов
apt-mark showauto список автоматически установленных пакетов
apt-mark showmanual список пакетов, установленных вручную
echo $(($(apt-mark showauto | wc -l) + $(apt-mark showmanual | wc -l))) количество всех установленных пакетов

apt update обновить список всех установленных пакетов из источников, указанных в файле конфигурации /etc/apt/sources.list
apt list --upgradable отобразить список, для каких пакетов доступны обновления
apt install --only-upgrade powershell обновить один выбранный пакет
apt --fix-broken install исправить проблемы и ошибки с зависимостями
apt full-upgrade обновляет все пакеты, которые уже установлены в системе (доставляет новые пакеты зависимости и удаляет пакеты, которые устанавливались в систему и уже не используются)

apt install net-tools установить пакет
apt download net-tools скачать пакет без установки
apt install net-tools --reinstall переустановить пакет
apt remove net-tools удалить пакет (конфигурационные файлы, которые были изменены в системе удалены не будут)
apt purge net-tools полностью удалить пакет, вместе со всеми его конфигурационными файлами
apt policy net-tools отобразить какая версия установленна и какие доступны
apt install net-tools=number ver установить конкретную версию
apt autoremove очистить ненужные пакеты, которые система не использует
apt autoclean очистить кеш пакетов

dpkg

dpkg -i spark.deb установить указанный пакет
dpkg -l отобразить список установленных deb-пакетов
dpkg -l | wc -l количество установленных пакетов
dpkg -l spark проверить, установлен ли пакет в системе и его версию
dpkg -s spark проверить статус пакета
dpkg -r spark удалить deb-пакет
dpkg -P spark удалить пакет вместе с фаилами конфигурации
dpkg -L spark отобразить путь, куда установлен пакет

snap

ls /snap директория пакетов
ls /var/lib/snapd/snaps расположение загруженных пакетов в формате snap
snap install snap-store установка магазина приложений
snap find nmap поиск приложения в магазине snap
snap info nmap информация о пакете (его наличии, версия, дата релиза и размер)
snap list список установленных в системе пакетов
snap list --all nmap отобразить все доступные версии для указанного пакета
snap install nmap --stable установить конкретную версию пакета
snap refresh nmap обновить пакет до последней версии
snap revert nmap откатить версию до предыдущей
snap connections nmap посмотреть доступность приложения к интерфейсам системы
snap remove nmap удалить пакет

Учетные записи

Авторизация

sudo -u www-data выполнить команду от имени другого пользователя
su root войти под пользователем root
sudo su переключиться на root (используется .bashrc текущего пользователя)
sudo -i переключиться в консоль от имени root (будет выполнен его .bashrc и .profile)

/etc/passwd - содержит список всех пользователей зарегистрированных в системе

/etc/group содержит список всех групп пользователей

/etc/shadow хранит пароли пользователей в зашифрованном виде (если * или !, пользователь не сможет войти в систему с использованием аутентификации по паролю, другие методы входа, например, на основе ssh-ключей или переключение на пользователя разрешены).

Синтаксис shadow: логин:пароль:дата последней смены пароля:минимальный срок действия пароля:максимальный срок действия пароля:период предупреждения:период бездействия:срок хранения.

/etc/login.defs" - настройка поведения утилиты управления пользователями и параметрами входа в систему (настройки минимального и максимального id для выдачи новому пользователю и группе, количество попыток входа, таймау, что делать с директорий пользователя при создании или удалении и т.п.)

cat /etc/login.defs | grep -Pv "^$|^#"

Управление паролями

passwd - используется пользователями для изменения своего пароля и администраторами для блокировки или разблокировки.

passwd lifailon смена пароля для указанного пользователя
passwd -S lifailon статус пароля для указанной УЗ
passwd -d lifailon удалить пароль
passwd -l lifailon заблокировать УЗ
passwd -u lifailon разблокировать УЗ
passwd -x 90 lifailon максимальный срок жизни пароя в днях
passwd -n 30 lifailon смена пароля разрешена не чаще 1 раза в 30 дней
passwd -w 5 lifailon установить количество дней предупреждения об истечении срока действия пароля до его окончания

chage (change age) - инструмент для настройки политик безопасности.

Получить информацию о последней смене пароля и срок его действия:

chage -l lifailon

# Последняя смена пароля: 15 апреля 2025 г.
# Срок действия пароля истекает: никогда
# Пароль неактивен: никогда
# Срок действия учетной записи истекает: никогда
# Минимальное количество дней между сменами пароля: 0
# Максимальное количество дней между сменами пароля: 99999
# Количество дней предупреждения до истечения срока действия пароля: 7

chage -E lifailon установить дату истечения срока действия пользовательской учетной записи

chage lifailon -M 30 установки минимального (-m) и максимального (-M) срока действия пароля

Создание УЗ (useradd)

adduser username интерактивное создание пользователя, по умолчанию будет создан домашний каталог (/home/username), можно указать данные о пользователе и задать пароль
deluser username удалить пользователя (каталог не удаляется)

useradd -D отобразить параметры, которые будут применены для пользователя по умолчанию

useradd -o -u 0 -g 0 -s /bin/bash root2 создать нового пользователя с правами root

userdel -r root2 удалить пользователя и его домашний каталог (-r)

useradd -G adm,wheel -p password -s /bin/bash logger разрешить пользователю читать логи и пользоваться sudo

-o разрешить создание пользователя с неуникальными идентификаторами
-u указать идентификатор для пользователя
-g указать идентификатор группы
-p задать пароль пользователя
-G добавить пользователя в дополнительные группы
-N не создавать группу с именем пользователя
-s указать командную оболочку для пользователя (по умолчанию /bin/sh, можно указать /bin/bash)
-b указать базовый каталог для размещения домашнего каталога пользователя (по умолчанию в /home)
-d домашний каталог, в котором будут размещаться файлы пользователя
-m создавать домашний каталог пользователя, если он не существует
-c комментарий к учетной записи
-l не сохранять информацию о входах пользователя в lastlog и faillog

Управление УЗ (usermod)

id lifailon узнать UID и GID и в каких группах состоит пользователь
usermod -u 1022 kup изменить UID
groupmod -g 1022 kup изменить GID

usermod -L lifailon заблокировать вход по паролю (перед паролем пользователя в файле /etc/shadow добавляется !)
usermod --expiredate 1 -L lifailon заблокировать пользователя (не будет возможности авторизоваться через su - Authentication failure)
usermod --expiredate 2023-10-25 lifailon задать дату блокировки
usermod --expiredate "" -U lifailon разблокировать пользователя

usermod --password "NewPassword" lifailon изменить пароль
usermod -l lifailon failon изменить имя пользователя (-l)
usermod -d /root lifailon изменить домашнюю директорию пользователя (-d)
usermod -m -d /root lifailon переместить домашнюю директорию сохранив все содержимое (-m)
usermod -s /usr/bin/dash lifailon изменить оболочку по умолчанию (-s)

Управление группами

groups lifailon отобразить в каких группах находится указанный пользователь

usermod -g root lifailon изменить основную группу пользователя, изменяя GID (Primary Group ID)

usermod -aG plugdev lifailon добавить пользователя в дополнительную группу (-G) с доступом монтирования ФС без прав sudo (нужно использовать вместе с флагом -a, чтобы не перезатирать текущие группы)

gpasswd -a lifailon plugdev добавить пользователя в группу
gpasswd -d lifailon plugdev удалить пользователя из группы
gpasswd -A lifailon plugdev сделать пользователя администратором группы (позволяет управлять группой без использования sudo)

groupadd test создать группу
delgroup test удалить группу, если ошибка 'test' still has test as their primary group! предварительно исключить из группы всех пользователей

Смена владельца (chown)

chown lifailon tmp изменить владельца на пользователя lifailon для директории tmp
chown lifailon:lifailon tmp изменить владельца и группу
chown -R lifailon:lifailon tmp применить изменения ко всем подкаталогам (-R)
chown --from=root:root lifailon:lifailon -R ./ изменить владельца и группу только для тех каталогов и файлов, у которых владелец и группа root в текущем каталоге

Права доступа (chmod)

Формат в выводе команды ls -l:

    -                    ---                          ---         ---
    |                     |                            |           |
тип файла   права доступа пользователя (владельца)   группы   всех остальных

Права:

Владельцы:

Формат:

Управление:

chmod u+x filename разрешить выполнение (x) для владельца (u)
chmod ugo+x filename разрешить выполнение (x) для всех (ugo)
chmod ug+r filename разрешить чтение (r) для владельца (u) и группы (g)
chmod o-w filename запретить запись (w) для всех остальных пользователей (o)
chmod -R g+rwx dir дать полный доступ (rwx) группе (g) на директорию и всем файлам в ней (-R)

Права доступа в восьмеричной системе (полностью переписывают текущие права новыми):

0 никаких прав
1 только выполнение
2 только запись
3 выполнение и запись
4 только чтение
5 чтение и выполнение
6 чтение и запись
7 чтение, запись и выполнение

chmod 744 filename разрешить полные права для владельца, а остальным только чтение
chmod 664 filename чтение и запись для владельца и группы, только чтение для остальных

Суперпользователь (sudo)

sudoers - конфигурационный файл (/etc/sudoers) для настройки прав доступа утилиты sudo

visudo открыть sudoers для редариктория

Defaults env_reset, timestamp_timeout=10 задать ограничение времени для sudo на 10 минут

Создать конфигурацию пользователя для использования sudo без пароля:

# Разрешить перезапуск определенного сервиса, обновление списка пакетов и установку обновлений системы
# lifailon ALL=NOPASSWD: /usr/bin/service memcahched restart, /usr/bin/apt-get update, /usr/bin/apt-get upgrade
# Доступ для группы
# %powerusers ALL=NOPASSWD: /usr/bin/service memcahched restart

echo "lifailon ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/lifailon
chmod 644 /etc/sudoers.d/lifailon

visudo --check проверка синтаксиса и всех прав доступа (0440)

sudo -l вывести список команд, которые текущий пользователь может выполнять с использованием sudo

Профили

Процессы

strace

strace (system call trace) - это инструмент трассировки системных вызово при работе процессов в Linux, которое выводит каждое обращение программы к ядру Linux, например, для чтение или запись в файлы.

strace -c top -n 1 > /dev/null показывает статистику (-c) всех используемых системных вызовов при запуске программы (% time - процент от общего времени выполнения)

strace -e trace=openat uptime > /dev/null вывести подробный вывод с путями к файлам и фильтрацией доступа по O_RDONLY (= 3 - это номер файлового дескриптора внутри процесса)

strace -f -p $(pgrep -o sshd) -o ~/passwd.txt -v -e trace=write -s 64 процесс сниффинга (перехвата паролей), который следим за всеми процессами sshd (-f), ищем все PID для sshd процессов (-p), триггер только на запись данных (-e) в указанный файл и ограничиваем вывод 64 байтами

lsof

lsof (list open files) - утилита для доступа к таблице файловых дескрипторов, которая выводит список всех открытых в данный момент файлов и процессов, которые их используют (файловые дискрипторы), включая сетевые сокеты (открытые порты и соединения), pipes, FIFO, символьные и блочные устройства (терминалы, диски, /dev/null).

КлючОписаниеПример
-iСписок активных сетевых соединений (LISTEN и ESTABLISHED для TCP)lsof -i
-nНе преобразовывать IP в доменные именаlsof -ni
-PНе преобразовывать порты в названия протоколовlsof -nPi
-i :nПоказать процессы, использующие конкретный портlsof -i :443
-i@ipПоказать соединения с определенным IP-адресомlsof -i@1.1.1.1
-UСписок только UNIX-сокетовlsof -U
-p pidСписок файлов, открытых конкретным процессом по его PIDlsof -p 1
-c procСписок файлов, открытые процессом по его имени (команде)lsof -c ssh
-u userСписок файлов, открытых конкретным пользователемlsof -u root
+D pathРекурсивный поиск открытых файлов внутри директорииlsof +D /var/log
-tВыводит только PID процессов для killlsof -t -i :80
-aЛогическое И для объединения с другими ключамиlsof -a -c docker-pr -i
+LПоказать открытые удаленные файлы (deleted), которые занимают местоlsof +L1

fincore

util-linux-extra - пакет, который содрежит дополнительные утилиты из состава util-linux, которые не включены в базовый пакет для экономии места.

sudo apt install util-linux-extra

fincore /var/log/* отобразить все файлы, которые находятся в кеше страниц оперативной памяти (page cache)
fincore /var/log/syslog отображает данные файла, хранящиеся в памяти, кол-во страниц хранящиеся в памяти page cache и размер самого файла
fincore /var/log/syslog -J вывод в формате json

Скрипт рекурсивно выводит список всех файлов, которые сейчас находится в оперативной памяти:

fc=$(du -a $1 2> /dev/null | awk '{print $2}' | xargs fincore 2> /dev/null)
echo -e "PAGE\tSIZE\tPATH"
echo -e "----\t----\t----"
printf "%s\n" "${fc[@]}" | grep -wvE "0B|SIZE" | awk 'BEGIN {OFS="\t"}; {print $1,$3,$4}'

vmstat

vmstat (virtual memory statistics) - утилита командной строки для мониторинга количества активных и ожидающих процессов, использование физической и виртуальной памяти, буферов и кеша, интенсивности обмена данными с диском (подкачка страниц), количество блоков считанных или записанных на диск.

КлючОписаниеПример
-aАктивная/неактивная память (вместо буферов/кэша)vmstat -a
-fПоказать количество форков (процессов) с момента загрузки системыvmstat -f
-mВывод использования динамической памяти ядра (Slab allocator)vmstat -m
-sВывести таблицу счетчиков событий и статистики памятиvmstat -s
-dВывести подробную статистику активности дисковvmstat -d
-pСтатистика конкретного раздела дискаvmstat -p /dev/sda1
-DСуммарная статистика по дисковой подсистемеvmstat -D
-S unitEдиниц измерения (k, K, m, M)vmstat -S M
-tДобавить timestamp к каждой и зациклить выводvmstat -t
n mОбновлять каждые n секунд, m разvmstat -t 1 5
vmstat -t -S M

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- -----timestamp-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st                 UTC
 0  0     38    197    110   1277    0    0     2    27    3    0  1  1 98  0  0 2026-04-06 14:16:37

ps

ps (process status) - это стандартная утилита командной строки, предназначенная для получения моментального снимка о текущих работающих процессах в системе.

КлючОписаниеПример
-eПоказать все процессы в системеps -e
auxВсе процессы всех пользователей с %CPU и %MEM в стиле BSDps aux
-fВывод с дополнительными полям (UID, PPID, C и STIME)ps -ef
-FДобавляет к выводу поля памяти (SZ, RSS и PSR)ps -eF
-eФильтрация вывода по указанным полямps -eo pid,%cpu,rss,etime,args
--sortСортировка по полю (префикс - для обратной сортировки)ps -eo pid,%cpu --sort=-%cpu
-u userСписок процессов конкретного пользователя (по имени или ID)ps -Fu root
-p pidПоказать процесс по его PIDps -Fp 1
-C procПоиск процесса по имени исполняемого файлаps -FC dockerd
-LПоказать потоки (threads) процессовps -eFL
-HОтображает дерево процессов c отступамиps -eFH
axjfВывод в виде дерева с отображением связей (родитель/потомок)ps axjf

top

КлючОписаниеПример
-d nИнтервал обновления экрана в секундахtop -d 1
-n nЗавершить работу после указанного кол-ва циклов обновленияtop -n 1
-bРежим записи в файл для обработки скриптами (batch mode)top -b -n 1 > top.log
-cCommand. Показывает полный путь к исполняемому файлу и аргументыtop -c
-iIdle. Не показывать S (Sleeping) и Z (Zombie) процессыtop -i
-HПоказывает все потоки (threads) процессовtop -H
-u userПоказать процессы конкретного пользователяtop -u root
-p pidМониторинг указанных PID через запятуюtop -p 1,123
-o fieldСортировка по выбранному полю (например, %CPU или RES)top -o %MEM

htop

КлавишаОписаниеДействие
F1HelpОткрыть справку по всем клавишам и функциям
F2/SSetupМеню настроек (цвета, колонки, вид графиков в шапке)
F3//SearchПоиск процесса по названию (подсветка совпадений)
F4/\FilterФильтрация списка (выводит только подходящие строки)
F5TreeПереключить режим отображения: список или дерево (аналогично ps -eFH или ps axjf)
F6SortОткрыть меню выбора поля для сортировки
F7Nice -Увеличить приоритет процесса (в диапазоне от -20 до 19, требует root при значение nice ниже 0)
F8Nice +Уменьшить приоритет процесса (увеличить значение nice)
F9KillОткрыть меню выбора все доступных системных сигналов для отправки процессу (например, 9 SIGKILL)
SPACESelectПометить (Tag) процесс для групповых действий (например, kill нескольких процессов)
UUntagСнять теги выделения со всех процессов
llsofВывести список файлов, которые используют процессы (файловые дискрипторы с номерами inode)
sstraceТрассировка системных вызовов (syscalls) процесса в реальном времени
LltraceТрассировка вызовов библиотечных функций процесса
eEnvironПоказать переменные окружения процесса (аналогично команде cat /proc/<PID>/environ)
uuserФильтр процессов из меню списка пользователей
MMEM sortСортировать по использованию оперативной памяти
PCPU sortСортировать по нагрузке на процессор
TTime sortСортировать по времени работы процесса
IInvertИнвертировать текущий порядок сортировки
iIO PriorИзменить приоритет ввода-вывода (ionice) для выбранного процесса
KKernelСкрыть/показать потоки ядра (kernel threads)
HThreadsСкрыть/показать пользовательские потоки (user threads)
pPathsПоказать полный путь к исполняемому файлу
ZPauseПриостановить/возобновить обновление экрана

iotop

iotop - это top для отображения операциий ввода-вывода (I/O) процессов к дисковой подсистеме.

apt install iotop

КлючОписаниеПример
-oПоказывает процессы, которые реально совершают ввод-выводiotop -o
-aСохраняет и накапливает метрики I/O с момента запускаiotop -ao
-d nИнтервал обновления экрана в секундах niotop -d 5
-n nКоличество итераций перед выходом (используется с -b)iotop -on 1
-bНеинтерактивный режим для логирования в файл (batch mode)iotop -obn 1 > io.log
-tДобавить метку времени (timestamp) для каждой строкиiotop -obt
-qCкрыть заголовки и общую сводку для логированияiotop -obtqqq
-p pidМониторинг ввода-вывода только конкретных PIDiotop -p 123,456
-u userПоказать активность диска только для конкретного пользователяiotop -u mysql
-PПоказать только процессы и скрыть потоки (threads)iotop -P

sysstat

sysstat - это пакет инструментов для мониторинга ресурсов Linux.

apt install sysstat

Состав утилит:

iostat

КлючОписаниеПример
-hВывод в формате перевода байт в МБ и ГБiostat -h
-cПоказать только отчет об использовании процессора (CPU)iostat -c
-dПоказать только отчет об использовании дисков (Device)iostat -d
-xПоказать расширенную статистику (util, await, svctm)iostat -x
-pПоказать статистику для конкретного устройства и его разделовiostat -p sda
-oВывод в формате JSONiostat -p /dev/sda3 -o JSON
-tДобавить метку времени (timestamp) для каждого отчетаiostat -t
-yПропустить первую строку (статистика с момента загрузки ОС)iostat -y 1 5
-zСкрыть устройства, у которых нет активности (нулевые значения)iostat -z
-NПоказать имена LVM групп вместо имен сопоставленных устройствiostat -N
n mОбновлять каждые n секунд, m разiostat 1 10

mpstat

mpstat (multiprocessor statistics) - это утилита для мониторинга равномерного распредиления нагрузки на каждое ядро, для поиска, кто тормозит - пользовательское приложение (%usr), операционная система (%sys), ожидание диска (%iowait) или аппаратные прерывания (%irq или %soft), что может указывать на проблемы с сетевой картой или драйверами.

КлючОписаниеПример
-P ALLПоказать статистику по каждому ядру процессора отдельноmpstat -P ALL
-P nПоказать статистику только для конкретного ядра nmpstat -P 0
-uПоказать только статистику использования (CPU utilization)mpstat -u
-I CPUПоказать количество прерываний на каждое ядроmpstat -I CPU
-I SUMПоказать общее количество прерываний на системуmpstat -I SUM
-AЭквивалент -I ALL -u -P ALLmpstat -A

stress

stress - это утилита за утилизации основных системных ресурсов (процессора, оперативной память и дискового ввода-вывода) с целью проверки стабильности системы под нагрузкой.

sudo apt install stress

КлючОписаниеПример
-c nCPU. Запустить n воркеров, загружающих процессор (sqrt)stress -c 4
-i nIO. Запустить n воркеров, нагружающих ввод-вывод (sync)stress -i 2
-m nMEM. Запустить n воркеров, выделяющих память (malloc)stress -m 2
--vm-bytesОбъем памяти, выделяемый каждым воркером (по умолчанию 256M)stress -m 1 --vm-bytes 1G
-d nDisk. Запустить n воркеров, активно пишущих файлыstress -d 1
--hdd-bytesРазмер временных файлов для воркеров дискаstress -d 1 --hdd-bytes 5G
-t nАвтоматически завершить работу через n секунд (--timeout)stress -c 1 -t 60
-qQuiet. Тихий режим (минимум вывода в консоль)stress -q -c 2
-vVerbose. Подробный вывод о работе каждого воркераstress -v -c 1

stress-ng

stress-ng - современная версия утилиты stress, содержащая сотни специализированных тестов для глубокого стресс-тестирования практически каждого компонента системы (от кэша процессора и сетевых протоколов до специфических системных вызовов ядра).

apt-get install stress-ng

КлючОписаниеПример
-c nCPU. Запустить n воркеров для нагрузки процессораstress-ng -c 4
--cpu-methodВыбор алгоритма нагрузки (matrix, fft, jmp, all)stress-ng -c 1 --cpu-method fft
-m nVM. Запустить n воркеров для нагрузки оперативной памятиstress-ng -m 2 --vm-bytes 1G
-d nHDD. Запустить n воркеров для нагрузки на запись/чтениеstress-ng -d 2 --hdd-bytes 5G
-i nIO. Нагрузка на системные вызовы ввода-выводаstress-ng -i 4
--net nNetwork. Нагрузка на сетевой стек (отправка пакетов)stress-ng --net 2
--matrix nMatrix. Стресс-тест процессора через матричные вычисленияstress-ng --matrix 1
--switch nContext Switch. Нагрузка на переключение контекстаstress-ng --switch 4
--timeout nАвтоматическая остановка теста через n секунд (или m, h)stress-ng -c 4 -t 60s
--temp-pathУказать путь для временных файлов (например, на RAM)stress-ng -d 1 --temp-path /dev/shm
--class cЗапустить все стрессоры для cpu, os или iostress-ng --class cpu --sequential 4
--sequential nЗапускать стрессоры по очереди (вместо параллельного)stress-ng --sequential 2
--metrics-briefВывести краткую статистику производительности (bogo-ops)stress-ng -c 2 -t 10s --metrics-brief
-vVerbose. Подробный лог того, что делает утилитаstress-ng -v -c 1

smartmontools

Smartmontools - это набор из консольной утилиты smartctl и демона smartd для мониторинга состояния жестких дисков (HDD) и твердотельных накопителей (SSD) через технологию S.M.A.R.T..

apt install smartmontools

КлючОписаниеПример
-iInfo. Показать общую информацию о диске (модель, серийник, S.M.A.R.T. статус)smartctl -i /dev/sda
-HHealth. Быстрая проверка: прошел диск внутренний тест здоровья или нетsmartctl -H /dev/nvme0
-aAll. Вывести всю доступную информацию, атрибуты и результаты тестовsmartctl -a /dev/sda
-xeXtended. Максимально подробный отчет, включая лог ошибок и статистикуsmartctl -x /dev/sdb
-AAttributes. Показать только таблицу S.M.A.R.T. атрибутов для HDDsmartctl -A /dev/sda
-l errorError log. Показать список последних зарегистрированных ошибок дискаsmartctl -l error /dev/sda
-l selftestTest log. Показать результаты ранее запущенных тестовsmartctl -l selftest /dev/sda
-t shortShort test. Запустить короткую проверкуsmartctl -t short /dev/sda
-t longLong test. Запустить полное сканирование поверхности дискаsmartctl -t long /dev/sda
-XAbort. Прервать выполнение запущенного тестаsmartctl -X /dev/sda
-cCapabilities. Показать возможности S.M.A.R.T. и примерное время тестовsmartctl -c /dev/sda
-d typeDevice type. Указать тип контроллера (ata, scsi, nvme, sat)smartctl -d sat -a /dev/sda
-s onEnable. Включить поддержку S.M.A.R.T. на диске, если она выключенаsmartctl -s on /dev/sda

lm-sensors

lm-sensors (Linux monitoring sensors) - это пакет для систем на базе Linux, который позволяет считывать данные с аппаратных датчиков материнской платы и процессора.

apt install lm-sensors

sensors-detect сканировать датчики температуры
sensors отобразить датчики

Файловая система

find

find - утилита командной строки для поиска файлов и каталогов в файловой системе по различным критериям (имени, размеру, времени изменения, правам доступа, владельцу и другим параметрам).

Описание ключей:

КлючОписаниеПример
-nameПоиск по имени (с учетом регистра)find . -name "file.txt"
-inameПоиск по имени (без учета регистра)find . -iname "FILE.txt"
-typeТип объекта: f (файл), d (папка), l (ссылка)find /etc -type f
-sizeПоиск по размеру (+ больше, - меньше, k, M, G)find . -size +100M
-mtimeИзменен n дней назад (- меньше или + больше)find /var/log -mtime -2
-atimeВремя последнего доступа (в днях)find . -atime +30
-userПоиск файлов, принадлежащих пользователюfind /home -user root
-permПоиск по правам доступаfind . -perm 644
-maxdepthОграничить глубину поиска по директориямfind . -maxdepth 2
-emptyНайти только пустые файлы или директорииfind . -type d -empty
-notИнвертировать условие (или использовать !)find . -not -name "*.log"
-execВыполнить команду для каждого файла (конец {} \;)find . -name "*.sh" -exec chmod +x {} \;
-deleteУдалить найденные объектыfind /tmp -mtime +7 -delete

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

find / -name "*.sql" найти файлы, начать поиск с корня (/)
find / -iname "mysql" найти файлы не учитывая регистр (-i)
find ~ -name "test.*" -not -name "*.conf" найти все файлы с наименование test, которые имеют любое расширение, за исключением (-not) расширения .conf
find ~ -amin -10 поиск файлов по дате последнего чтения (-amin) которые просматривались за последние 10 минут (например, с помощью cat)
find ~ -type f -mmin -10 искать только файлы (-type f), которые были модифицированны за последние 10 минут (-nmin)
find ~ -type f -mtime +1 -mtime -7 найти все файлы, измененные в промежутке от 1 до 7 дней назад
find ~ -size +50M -size -100M поиск файлов по их размеру (от 50 до 100 Мбайт)
find / -perm 444 поиск файлов по режиму доступа (только чтение для всех)
find /home/lifailon/ -user root поиск файлов по владельцу
find /home/lifailon/ -group root поиск по группе
find /root/ -empty поиск пустых файлов или директорий

touch -t 202306222200.15 /tmp/test.txt создать файл с указанной датой создания
find /tmp -type f -mtime +30 -exec rm -f {} \; удалить все файлы, котоыре не изменялись больше 30 дней
find /tmp -type f -name "*.txt" -exec rm -f {} \; удалить все текстовые файлы в директории tmp
dd if=/dev/zero of=/var/log/test.log count=11 bs=1M создать файл заполненный нулями указанного размера (11 Мбайт)
find /var/log -type f -name "*.log" -size +10M -exec rm -f {} \; удалить все лог-файлы, объемом больше 10 Мбайт

fd

fd - быстрая альтернатива find на Rust

apt install fd-find установить

Описание ключей:

Ключ fdКлюч findОписаниеПример
-e-name "*.ext"Поиск по расширению файла (extension)fdfind -e jpg
-H-Включить в поиск скрытые файлы и папки (hidden)fdfind -H config
-I-Игнорировать правила .gitignorefdfind -I secret
-t-typeТип объекта: f (файл), d (дир), l (ссылка), x (исп)fdfind -t d backup
-x-exec {} \;Выполнить команду для каждого результата (exec)fdfind -e txt -x rm или fd -e txt | xargs rm
-X-exec {} +Выполнить команду один раз, передав все файлы как аргументыfdfind -e txt -X tar -cvf texts.tar
-g-nameИспользовать подстановочные знаки (glob) вместо регулярокfdfind -g "*.log"
-i-inameИгнорировать регистрfdfind -i "Data"
-p-pathИскать совпадение во всем пути, а не только в имени файлаfdfind -p "src/main"
-d-maxdepthОграничить глубину поиска (max-depth)fdfind -d 2 "node"
-S-sizeПоиск по размеру файла (+ больше, - меньше)fdfind -S +1G
-c-Цветовой вывод (always, auto, never)fdfind -c always
-a-Показать абсолютный путь вместо относительногоfdfind -a "script.sh"
-L-LСледовать по символическим ссылкам (follow)fdfind -L "link_name"

Поиск в интерфейсе fzf с помощью fd:

# fdfind over fzf
if command -v fzf > /dev/null; then
    function fd-fzf(){
        if [ -z "$1" ]; then
            # Current path by default
            fdfind . ${pwd} | fzf
        else
            # Specified path
            fdfind . $1 | fzf
        fi
    }
    # Alt+F for fd-fzf
    bind '"\ef": "fd-fzf\n"'
    # Alt+Shift+F for rga-fzf
    if command -v rga-fzf > /dev/null; then
        bind '"\eF": "rga-fzf\n"'
    fi
fi

locate

plocate - альтернатива стандартного mlocate с более быстрым по скорости поиском файлов и меньшим по размеру базой данных для хранения индексов (как Everything в Windows).

apt install plocate

updatedb обновить индексы базы данных
ls -lh /var/lib/[mp]locate/*.db проверить размер базы данных
locate .torrent найти по частичному совпадению в имени или расширению
locate -c .torrent отображает количество найденных результатов
locate -n 10 .torrent вывести 10 результатов
locate -i Kinozal-Bot игнорировать регистр
locate -r "\.log$" использовать регулярные выражения при поиске

du/df/lsblk

du -h /home отображает общий размер указанной директории и подкаталогов внутри директории
du -ah /home отобразить общий размер всех дочерних директорий и файлов (-a) в директориях
du -sh /home отобразить общий размер только указанной директории (-s)
tree -h --du /home

df (disk free) - работает на уровне файловых систем и отображает общий объем (Size), занятого (Used) и свободно (Avail) пространства только для примонтированных разделов
df -h -T отобразить Type файловой системы (ext4/cifs)

lsblk (list block) - отображает список всех подключенных блочных устройств из директории /dev (devices), которые имеют файловую систему или могут ее содержать, а также их размер, тип (disk/part/lvm) и точку монтирования (MOUNTPOINTS) в системе.

lsblk -a вывести список всех блочных устройств
lsblk -f отображает используемую файловую систему (FSTYPE), версию, UUID, а также FSAVAIL - сколько свободно на диске и FSUSE - сколько занято на диске в процентах
lsblk -e7 вывод без loop устройств
lsblk -o NAME,SIZE --nodeps -e7 фильтровать вывод и вывести без структуры разделов (--nodeps)
lsblk -Jbe7 выводить SIZE в байтах (--bytes) и формате JSON (--json)
lsblk -S вывести информацию о SCSI-устройствах (--scsi)
lsblk -m вывести информацию о правах доступа

mount | grep /dev/ отобразить все примонтированные файловые системы

findmnt отобразить список смонтированных файловых систем в древовидном формате

e2label /dev/sda3 узнать метку диска

blkid отобразить список подключенных дисков, их UUID и TYPE

lsscsi отобразить параметры SCSI устройств подключенных к системе

dust

dust - альтернатива du на Rust для визуализации и анализа занятого пространства.

snap install dust

dust $HOME                # выводит график используемого пространства по директориям и файлам
dust -s                   # показывает размер файла, а не объем используемого им дискового пространства
dust -n 30                # выводит 30 каталогов (по умолчанию - высота терминала)
dust -d 3                 # показывает 3 уровня подкаталогов
dust -D                   # отобразить только директории
dust -F                   # отобразить только файлы
dust -f                   # считайте файлы вместо дискового пространства
dust -i                   # не показывать скрытые файлы
dust -z 10M               # минимальный размер (включать только файлы размером более 10 МБ)
dust -z 40000/30MB/20kib  # исключить выходные файлы/каталоги размером менее 40 000 байт/30 МБ/20 КБ
dust -o mb                # формат вывода (si/b/kb/kib/mb/mib/gb/gib)
dust -e "\.png$"          # включать только те файлы, которые соответствуют регулярному выражению (например, только файлы png)
dust -v "\.png$"          # регулярное выражение для игнорирования файлов с разрешением png
dust -j  | jq             # вывод в формате JSON
dust -P                   # отключить индикатор прогресса

gdu

gdu - анализатор использования диска, написанный на Go с поддержкой навигации по директориям.

curl -sSL https://github.com/dundee/gdu/releases/latest/download/gdu_linux_$(dpkg --print-architecture).tgz -o gdu | tar xz
chmod +x gdu_linux_* && mv gdu_linux_* /usr/bin/gdu

gdu                                   # анализировать текущий каталог
gdu <путь_к_каталогу>                 # анализировать указанный каталог
gdu -a                                # показывать видимый размер вместо использования диска
gdu --no-delete                       # запретить операции записи (удаление)
gdu --no-view-file                    # запретить просмотр содержимого файлов
gdu -d                                # показать все смонтированные диски
gdu -i /sys,/proc /                   # игнорировать указанные пути
gdu -I '.*[abc]+'                     # игнорировать пути по регулярному выражению
gdu -c /                              # использовать только ч/б цвета (белый/серый/черный)
gdu / > file                          # записать статистику в файл без запуска интерфейса
gdu -n /                              # только вывести статистику, не запуская интерактивный режим
gdu -p /                              # не показывать прогресс (полезно для использования в скриптах)
gdu -ps /путь/к/папке                 # показать только общий объем для указанного каталога
gdu -t 10 /                           # показать топ-10 самых больших файлов
gdu --reverse-sort -n /               # сортировка от меньшего к большему в неинтерактивном режиме
gdu -o- / | gzip -c > report.json.gz  # сохранить данные в JSON для последующего анализа
zcat report.json.gz | gdu -f-         # прочитать данные анализа из файла

dd

dd if=/dev/sr0 of=/tmp/cd.iso bs=2048 сохранить образ диска (if=источник) в файл (of=назначение) с указанием кол-ва байт для чтения и записи за один раз (2 МБайт), по умолчанию используется размер блока 512 байт (2b блока = 1024 байт, 1k = 1 КБайт/1024 байт, 1kB = 1000 байт, 1M = 1024 КБайт/1 МБайт)
dd if=/dev/mem bs=2048 count=100 вывести содержимое оперативной памяти на экран (не использовать файл)
dd if=/dev/zero of=/tmp/md-01 bs=4M count=256 создать файл заполненный нулями (из /dev/zero) размером 1 ГБ с указанием кол-во копируемых блоков (bs*count) или очистить диск
dd if=/dev/random of=/tmp/md-02 bs=4M count=256 создать файл размером 1 ГБ заполненный рандомными цифрами
dd if=/dev/sda of=/tmp/mbr.img bs=1b count=1 скопировать в файл первые 512 байт диска содержащие таблицу разделов MBR
dd if=/dev/sda of=/tmp/sda.img создать образ жесткого диска, используетася для полного backup системы (копирование раздела на двоичном уровне,включая таблицу MBR и всю пустую область диска и разделов)

Backup системного диска:

Backup через nc (netcat):

nc -lp 5000 | sudo dd of=/backup/sda.img.gz сохранение сжатого файла образа жесткого диска sdb на удаленном сервере (принимающая сторона)
dd if=/dev/sda | gzip -c | nc 192.168.21.121 5000 на узле, у которого установлен жесткий диск (передающая сторона)
nc -lp 5000 | gunzip -c | sudo dd of=/dev/sdb восстановление содержимого жесткого диска из сжатого образа (записывать не на системный диск), сохраненного на удаленном сервере на локальном узле (принимающая сторона)
cat /backup/sda.img.gz | nc my_local_host.com 5000 на удаленном сервере, на котором сохранен файл образа жесткого диска (передающая сторона)

Создание ISO образа:

dd if=/dev/sda3 status=progress of=/mnt/disk_b/disk.iso bs=5M создать iso-образ (сохранить образ раздел)
dd if=путь/к/образу.iso of=/dev/sdb1 записать ISO-образ ОС на внешнее устройство
sync завершить запись этой командой (чтобы при извлечении не потерять часть данных)
mount -o loop /mnt/disk_b/disk.iso /mnt/iso примонтировать файл образа только для чтения (iso - это директория, которую предварительно нужно создать), подключается как /dev/loop6
umount /mnt/iso отмонтировать

parted

parted (Partition Editor) - современный инструмент командной строки для управления таблицами разделов и самими разделами на жестких дисках, с поддержкой таблиц GPT (больше 2 ТБ) и динамическим изменением размера.

parted -l отобразить список всех разделов на дисках
parted -l | grep -i model
dd if=/dev/zero of=/tmp/disk.img count=1000 bs=1M создать образ диска заполненный нулями размером 1 Гб
parted /tmp/disk.img передать управление в parted созданный файл образа диска для управления ФС
parted /dev/sdc передать parted физический диск
mktable gpt создать таблицу разделов GPT
print отобразить тип таблицы (Partition Table: GPT) и список разделов на устройстве, если они были созданы
print free отобразить свободное место и все разделы
mkpart primary ext4 0 500M создать первичный (primary) /dev/sdc1 раздел с ФС ext4 размером 500 Мб.
mkpart primary ext4 500 1000M создать второй раздел /dev/sdc2 (указать начало и конец)
resizepart 2 600M уменьшить 2-й раздел на 100 МБ (указывается end-конец)
resizepart 2 100% увеличить до всего свободного размера
rm 2 удалить раздел
resize2fs /dev/sdc2 расширить файловую систему ext4 на всё доступное пространство раздела /dev/sdc2

fdisk

fdisk (fixed disk) - классическая утилита командной строки для работы с разделами диска.

fdisk -l отображает список всех подключенных устройств построчно с размером секторов для каждого раздела
fdisk -x подробный вывод (узнать UUID разделов)
fdisk /dev/sdc
m список команд
p отобразить размер диска и список разделов (/dev/sdc1)
n создать новый раздел (p), указать номер раздела partition number (от 4 до 128, по умолчанию 4), начало и конце сектора (enter - оставить по умолчанию)
i информация о выбранном разделе разделе (начало, конец, общий размер сектора и размер диска)
t задать тип раздела - 30/8E (Linux LVM) или 20/83 (Linux filesystem)
l отобразить список всех типов
w сохранить
q выход
partprobe /dev/sdc информирует ядро ОС об изменениях таблицы разделов, запрашивая у системы, чтобы она перечитала таблицу разделов

sfdisk

sfdisk (scriptable fdisk) - это инструмент, созданный специально для работы с fdisk внутри скриптов для автоматизации (без интерактивного режима).

sfdisk -d /dev/sdc > sdc.partition.table.txt создать backup для разметки таблицы GPT или MBR (аналогично dump cfdisk)
sfdisk -f /dev/sdc < sdc.partition.table.txt восстановить из backup

sfdisk -d /dev/sda | sfdisk -f /dev/sdd для восстановления RAID1 в MD при замене диска вышедшего из строя (sda в sdd)
mdadm --manage /dev/md1 --add /dev/sdd1 восстановление копирования в RAID-массиве
watch cat /proc/mdstat отображать прогресс синхронизации

ls /dev/sd* отобразить все диски в файловой системе
fdisk -l отобразить все диски через fdisk
cfdisk /dev/sda разметка диска на разделы (новый вариант)
cfdisk /dev/sdb инициализировать новый диск и выбрать таблицу разделов gpt
new - sda4 создать новый раздел sda4 или sdb1
Free space - Partition size: 100G
write - yes
pvcreate /dev/sda4 создать физический виртуальный том из раздела
vgextend ubuntu-vg /dev/sda4 добавить новый раздел в группу
lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv добавить свободное место в группе для логического раздела ubuntu-lv
lsblk
df -h система будет видеть старый объем диска, необходимо выполнить команду по изменению размера файловой системы
df -T -h отобразить тип ФС
resize2fs -f /dev/ubuntu-vg/ubuntu-lv для ext*
btrfs filesystem resize +100g / для btrfs

cfdisk /dev/sdс создать раздел с помощь cfdisk или в fdisk/parted
mkfs.ext4 /dev/sdc1 форматировать раздел
mkdir /mnt/sdc1 && mount /dev/sdc1 /mnt/sdc1 примонтировать раздел
df -h && lsblk раздел нового диска должен быть в статусе Mounted on или MOUNTPOINTS
chmod 0777 /mnt/sdc1 разрешить всем пользователям доступ к диску
df -h -T отображает тип файловой системы примонтированных разделов
echo "/dev/sdc1 /mnt/sdc1 ext4 rw,relatime 0 0" >> /etc/fstab сохранить монтирование после перезагрузкиы (добавить по наименованию или UUID устройства)
umount /dev/sdc1 отмонтировать раздел

hdparm

hdparm (Hard disk parameters) - это утилита командной строки для просмотра и настройки низкоуровневых параметров жестких дисков (ATA/SATA/SAS) и SSD.

КлючОписаниеПример
-iПоказать краткую информацию о диске из ядраhdparm -i /dev/sda
-IПоказать детальную информацию напрямую от диска (идентификация)hdparm -I /dev/sda
-tТест скорости чтения из буферизованного диска (дисковый ввод)hdparm -t /dev/sda
-TТест скорости чтения из кэша системы (производительность RAM)hdparm -T /dev/sda
-gПоказать геометрию диска (цилиндры, головки, сектора)hdparm -g /dev/sda
-W nУправление кэшированием записи (0 - выкл, 1 - вкл)hdparm -W 1 /dev/sda
-S nУстановка тайм-аута ожидания перед сном (spindown)hdparm -S 120 /dev/sda
-yНемедленно перевести диск в режим ожидания (Standby)hdparm -y /dev/sda
-YПеревести диск в режим глубокого сна (Sleep)hdparm -Y /dev/sda
-CПроверить текущий статус питания (active/idle/standby)hdparm -C /dev/sda
-B nУстановка APM (Advanced Power Management) от 1 до 255hdparm -B 127 /dev/sda
-M nУправление шумом (AAM) от 128 (тихо) до 254 (быстро)hdparm -M 128 /dev/sda
-r nУстановить флаг read only (1 - вкл, 0 - выкл)hdparm -r 1 /dev/sda
-zЗаставить ядро перечитать таблицу разделов дискаhdparm -z /dev/sda

SWAP

fallocate -l 4G /swapfile.img создать файл-образ для swap
dd if=/dev/zero of=/swapfile.img count=1024 bs=1M создать файл для swap указанного размера
chmod 600 /swapfile.img дать права
mkswap /swapfile.img создать swap-пространство из файла или использовать весь объем раздела (mkswap /dev/sda4)
swapon /swapfile.img активировать swap-пространство
echo "/swapfile.img none swap sw 0 0" | sudo tee -a /etc/fstab примонтировать
free -m отобразить объем
swapoff -a отключить
rm /swapfile.img удалить файл

LVM

LVM (Logical Volume Management) - это система для управления логическими томами, которая создает дополнительный слой абстракции от железа, позволяющий собрать несколько разных дисков в один, и затем разбить его на группы и разделы. Позволяет использовать программный RAID 0 и 1 (зеркалирование) с управляемым пространством, снапшотами и импортированием томов в другую систему.

pvs отображает список всех PV в системе
pvdisplay подробная информация
pvcreate /dev/sdb инициализировать физический диск в LVM как физический том

vgs отображает список всех VG
vgdisplay подробная информация
vgcreate vg21 /dev/sdb создать группу томов с добавлением физического тома на диске sdb
vgextend vg21 /dev/sdc добавить новый PV в VG

lvs отображает список LV и их объем
lvdisplay подробная информация
lvcreate -n boot -L 1G vg21 создать первый логический раздел с наименованием boot размером 1 Gb в группе vg21
lvcreate -n home -L 9G vg21 создать второй логический раздел с наименованием home размером 9 Gb в группе vg21
lvcreate -n lv21 -l+100%FREE vg21 создать один логический раздел lv21 для группы томов vg21 и назначить ему весь объем диска
mkfs -t ext4 /dev/vg21/lv21 назначить файловую систем ext4
mkdir /mnt/lv21 создать директорию для монтирования
mount /dev/vg21/lv21 /mnt/lv21 примонтировать раздел к созданной директории
echo "/dev/vg21/lv21 /mnt/lv21 ext4 defaults 0 0" >> /etc/fstab добавить монтирование в автозагруку

Расширение физического раздела можно сделать за счет добавление нового диска путем добавления в группу или увеличением имеющегося виртуального диска.

pvcreate /dev/sdc добавляем новый диск и инициализируем (минус: если один из дисков выходит из строя, данные будут не доступны, аналогично работе RAID 0)
pvresize /dev/sdb увеличиваем объем дискового пространства виртуального диска PV (resize измекняет размер физического тома)
vgextend vg21 /dev/sdc рашширяем группу vg21 за счет добавленного диска sdc
vgs отобразит у какой из групп всего памяти VSize и сколько доступно памяти VFree для распредиления логическим разделам LV
lvextend -l +100%FREE /dev/vg21/lv21 добавить все свободное простраство логическому разделу LV
vgs VFree будет 0 а в lsblk объем раздела увеличится
lvextend -L+1G /dev/vg21/lv21 добавить 1 Гб от группы томов vg21 разделу lv21
lvextend -L500G /dev/vg21/lv21 добавить да указанного размера диска 500Гб
lvs проверить
df -T отобразить используемую ФС
resize2fs /dev/vg01/lv01 изменить размер для файловой системы ext4

e2fsck -fy /dev/vg21/lv21 проверка диска
resize2fs /dev/vg21/lv21 500M уменьшить размер ФС на 500 Мбайт
lvreduce -L-500 /dev/vg21/lv21 уменьшить размер логического тома на 500 Мбайт
vgs в VFree добавится 500m для распределения другой логической группе
resize2fs /dev/ubuntu-vg/ubuntu-lv 1G применить изменения в ФС (уменьшить размер на 500 Мбайт)

umount /dev/vg21/lv21 предварительно отмонтировать LV
lvremove /dev/vg21/lv21 удалить логический том LV
lvs нет групп
vgs для VSize и VFree объем будет совпадает
vgremove vg21 удалить группу томов VG
pvremove /dev/sdb удалить диск sdb из PV

Новый диск sdc разбить на 2 раздела (основной sdc1, немного больше чем у целевого зеркалируемого раздела lv21 и sdc2 оставшийся объем для ведения файла журнала)

pvcreate /dev/sdc1 /dev/sdc2 добавить оба раздела в LVM
vgextend vg21 /dev/sdc1 /dev/sdc2 добавить в имеющиюся группу vg21 (расширить группу vg21)
vgs у группы vg21 VFree увеличится объем добавленных томов-разделов
lvconvert -m1 /dev/vg21/lv21 /dev/sdb /dev/sdc1 /dev/sdc2 конвертируем логический том lv21, входящий в состав группы vg21 в зеркалируемый том (-m1), зеркалируется /dev/sdb (где находится lv21) на sdс1, а /dev/sdс2 используется для ведения файла журнала.

lvs -a -o +devices раздел lv21 пишет на 2 устройства:

[lv21_rimage_0] /dev/sdb(0)  # основной том
[lv21_rimage_1] /dev/sdc1(1) # зеркало

lsblk

sdb                     8:16    0    4G  0 disk
+-vg21-lv21_rmeta_0    253:0    0    4M  0 lvm
¦ L-vg21-lv21          253:4    0    2G  0 lvm
L-vg21-lv21_rimage_0   253:1    0    2G  0 lvm
  L-vg21-lv21          253:4    0    2G  0 lvm
sdc                     8:32    0    4G  0 disk
+-sdc1                  8:33    0    3G  0 part
¦ +-vg21-lv21_rmeta_1  253:2    0    4M  0 lvm
¦ ¦ L-vg21-lv21        253:4    0    2G  0 lvm
¦ L-vg21-lv21_rimage_1 253:3    0    2G  0 lvm
¦   L-vg21-lv21        253:4    0    2G  0 lvm

Извлекаем (удаляем) sdb (оригинальный диск) и lsblk отображает только два раздела (part) sdc1 и sdc2 зеркального диска без LVM, т.к. группа не активна

Командой lvs выводим состояние группы vg21 и ошибки:

WARNING: Couldn't find device with uuid stBI99-6Qs3-B8lr-Ekaw-ahnD-oxPc-LsayLR.
WARNING: VG vg21 is missing PV stBI99-6Qs3-B8lr-Ekaw-ahnD-oxPc-LsayLR (last written to /dev/sdb).

vgchange -ay vg21 активировать группу
mount /dev/vg21/lv21 /mnt/lv21 примонтировать группу lv21

lvs
lvcreate -L 1G -s -n snap-1 /dev/ubuntu-vg/ubuntu-lv предварительно нужно добавить VFree в Volume Group (Logical volume “snap-1” created)
lvcreate -L 1G -s -n snap-1 /dev/vg21/lv21 параметр -s помечает, что 1Гб дискового пространства из группы vg21 будет использоваться для snapshot lv21
lvs Origin - к какому логическому тому (lv) относиться snapshot, Data% - процент исползованного объема от выделенного
lsblk отображает изменения в томах разделов
mount /dev/vg21/snap-1 /mnt/snap содержимое снапшота можно смонтировать как обычный раздел, если отредактивароть снапшот и откатиться к нему, мы получим те данные, которые отредактировали
lvconvert --merge /dev/vg21/snap-1 откатиться к снапшоту snap-1, понадобится перезагрузка ОС (даже если это не основной диск)

umount /dev/vg21/lv21 отмонтировать
vgchange -an vg21 деактивировать группу томов (0 logical volume в volume group “vg21”)
vgexport vg21 экспортировать группу (successfully exported)
pvdisplay список групп (VG Name vg21 (exported)) \

Переносим диск на новый компьютер:

pvscan сканировать группы на новой системе (PV /dev/sdb is in exported VG vg21)
vgimport vg21 импортировать в систему (successfully imported)
vgs и lvs проверить группы
vgchange -ay vg21 активировать группу (1+ lg в vg “vg21”)
lsblk проверить подключение LVM

RAID

MD (Multiple Devices) - это SOFT RAID, который позволяет объединять несколько отдельных дисков (или разделов) в одно виртуальное устройство (RAID-массив).

mdadm --zero-superblock --force /dev/sd{b,c} занулить все суперблоки на дисках, которые будут добавлены в RAID-массив, т.к. диски могут содержать служебную информацию о других RAID (вывод: unrecognised md component device - ни один из дисков ранее не был добавлен в массив)
mdadm --create --verbose /dev/md0 -l 1 -n 2 /dev/sd{b,c} создать зеркальный RAID1 (-l/--leve 1) и указать кол-во дисков (-n/--raid-devices)
mkfs.ext4 /dev/md0 форматировать в ext4
mkdir /md0-sdb-sdc-raid1 создать директорию для монтирования
mount /dev/md0 /md0-sdb-sdc-raid1 примонтировать вручную
lsblk -o NAME,UUID | grep md* отобразить UUID устройства
echo "UUID=20482c47-fa11-462d-b7b8-93a342a7edf8 /md0-sdb-sdc-raid1 ext4 defaults 1 2" >> /etc/fstab добавить в автозагрузку по UUID, т.к. после перезагрузки ОС номер может измениться (например, на md127)
mount -a примонтировать все файловые системы из fstab
cat /proc/mdstat проверить состояние всех доступных RAID-массивов: md127 : active raid1 sdc[1] sdb[0]
mdadm -D /dev/md127 подробное (--detail) состояние массива. State: cleane - проблем нет, degraded - диск неисправен/поврежден, Active/Working/Failed/Spare Devices - количество активных (в работе), рабочих, нерабочих или запасных дисков в массиве. Consistency Policy - тип синхронизации после сбоя в массиве (resync - полная синхронизация после восстановления массива)
mdadm /dev/md127 --add /dev/sdd добавить запасной диск (в Spare Device) для горчей замены (Hot-Spare), в статусе списка дисков будет указан какой диск (spare /dev/sdd)
mdadm -G /dev/md127 -raid-devices=3 расширить массив до трех дисков (добавится из запасных дисков в активный в массив)
mdadm /dev/md127 --fail /dev/sdb пометить рабочий диск как нерабочий (перевести диск в Failed Device) для замены на запасной из Spare Device, который начнет автоматическую синхронизацию для ввода в массив (Rebuild Status : 50% complete)
mdadm /dev/md127 --remove /dev/sdb удалить нерабочий диск из массива
mdadm --stop /dev/md127 остановить/разобрать массив (предварительно umount /md0-sdb-sdc-raid1). В случае, если один из двух дисков был извлечен и не было запасных дисков, массив будет остановлен автоматически (State: inactive)
mdadm --assemble --scan --verbose команда просканирует все диски на наличие разобранного/развалившегося RAID-массива и самостоятельно (автоматически) попытается восстановить из них массив с изначальным именем (mdadm -D /dev/md0)
mdadm --stop /dev/md127 && mdadm --assemble --scan && mount -a && mdadm -D /dev/md0 если в системе остался один диск (второй извлечен), RAID-массив будет востановлен (пересобран) автоматически из одного диска с статусом: clean, degraded, можно сразу добавить новый диск для автоматической синхронизации данных
mdadm --assemble /dev/md127 /dev/sdb /dev/sdc указать вручную из каких дисков пересобрать массив
echo 'check' > /sys/block/md127/md/sync_action проверять целостность данных в массиве (mdadm -D /dev/md0 - Check Status : 80% complete)
cat /sys/block/md127/md/mismatch_cnt вывод файла (0 - все впорядке)
echo 'idle' > /sys/block/md127/md/sync_action остановить проверку

iSCSI

iSCSI (Internet Small Computer System Interface) - это протокол, который позволяет передавать команды для работы с дисками SCSI через сеть Ethernet/IP.

Портал (серверная часть) содержит цели (Target), каждая из которых предоставляет инициатору (клиенту) доступ к своим блочным устройствам.

apt install tgt

dd if=/dev/zero of=/storage/disk1.img bs=1 count=0 seek=200G создание динамического диска (разреженный файл) с максимальным размером 200 ГБ, где вместо последовательности нулей на диске хранят информацию об этих последовательностях в специальной таблице
dd if=/dev/zero of=/storage/disk1.img bs=1M count=2048 создание фиксированного размера диск
cp --sparse=always filename newfilename преобразование обычного файла в разреженный

Файлы конфигурации таргета: /etc/tgt/targets.conf или /etc/tgt/conf.d/disk-1.conf

<target iqn.2023-10.local.domain:ubuntu-target> 
   backing-store /storage/disk1.img 
   initiator-address 192.168.3.101
   incominguser admin PasswordAdmin
</target>

systemctl restart tgt
tgtadm --mode target --op show отобразит все подключенные цели и предоставляемые ими блочные устройства

apt install open-iscsi установка клиентской части

# Опросить сервер, какие имеются диски (сервер должен вернуть строку подключения IQN)
iscsiadm -m discovery -t st -p 192.168.3.101

# Авторизация
iscsiadm -m node -T iqn.2023-10.local.domain:ubuntu-target -o update -n node.session.auth.authmethod -v CHAP
iscsiadm -m node -T iqn.2023-10.local.domain:ubuntu-target -o update -n node.session.auth.username -v user
iscsiadm -m node -T iqn.2023-10.local.domain:ubuntu-target -o update -n node.session.auth.password -v password1212

# Подключение
iscsiadm -m node -T iqn.2023-10.local.domain:ubuntu-target --login
lsblk

SMB Server

Samba - пакет, которые позволяют обращаться к удаленным сетевым дискам по протоколу SMB/CIFS.

apt install samba
systemctl status smbd

useradd smb1 # создать пользователя в системе
passwd smb1 # задать пароль для пользователя
smbpasswd -a smb1 # создать пользователя для Samba

mkdir -p /public/share
chmod 777 /public/share

iptables -I INPUT -p tcp --dport 445 -j ACCEPT
iptables -I INPUT -p tcp --dport 137 -j ACCEPT
iptables -I INPUT -p tcp --dport 139 -j ACCEPT
iptables -I INPUT -p udp --dport 137:138 -j ACCEPT
iptables -L

/etc/samba/smb.conf

[global]
workgroup = WORKGROUP

[share1]
    path = /public/share
    public = yes
    writable = yes
    read only = no
    guest ok = yes
    create mask = 0777
    directory mask = 0777
    force create mode = 0777
    force directory mode = 0777
    valid users = smb1
    write list = smb1
    vfs objects = recycle
    recycle:repository = .recycle/%U
    recycle:keeptree = Yes
    recycle:touch = Yes
    recycle:versions = Yes
    recycle:maxsize = 0
    recycle:exclude = *.tmp
    recycle:exclude_dir = /tmp

systemctl restart smbd применить настройки

SMB Client

apt install cifs-utils

cat <<EOF > /root/.smbclient
username=lifailon
password=password
# domain=docker.local
EOF

mkdir -p /mnt/backup
echo "//192.168.3.100/Backup /smb/backup cifs user,rw,credentials=/root/.smbclient 0 0" >> /etc/fstab
mount -a
df -h

apt update && apt install -y smbclient
BACKUP_DIR="/backup/homepage"
SMB_PATH=//192.168.3.100/Backup
SMB_USER=Lifailon
SMB_PASS=password
smbclient "$SMB_PATH" -U "$SMB_USER%$SMB_PASS" -c "ls"
smbclient "$SMB_PATH" -U "$SMB_USER%$SMB_PASS" -c "put /tmp/backup.tar.gz backup-$(date +%d.%m.%Y-%H-%M).tar.gz"
smbclient "$SMB_PATH" -U "$SMB_USER%$SMB_PASS" -c "del $FILE_NAME"

NFS Server

apt install nfs-kernel-server установить сервер, с помощью которого будет выполнено открытие шары. Сервис NFS слушает соединения для TCP и UDP на порту 2049

rpcbind - это демон в системах, который преобразует номера программ RPC (Remote Procedure Call) в универсальные сетевые адреса (порт 111), позволяя клиентам находить порты, на которых работают эти службы. Без него удаленные вызовы процедур не функционируют (замена portmap), по этому он необходим для работы сетевых файловых систем (NFS v2 и v3), так как они зависят от RPC.

apt install rpcbind
rpcinfo -p | grep nfs проверить, слушается ли порт NFS-сервер

cat /proc/filesystems | grep nfs проверить, поддерживается ли NFS на уровне ядра (вывод: nodev nfsd)
modprobe nfs вручную загрузить модуль ядра nfs
systemctl status nfs-server служба сервера
ufw allow 111,2049 && ufw reload
mkdir /nfs/share создать папку для шары
adduser nfs-user создать пользователя для подключения
chown nfs-user:nfs-user /nfs/share изменить владельца шары
chmod 775 /nfs/share дать полный доступ владульцу и группе
echo "/nfs/share 192.168.3.0/24(rw,sync,no_subtree_check)" >> /etc/exports шарим директорию в подсети
exportfs -a применить настройки (обновить таблицу экспорта для NFS-сервера)

Опции:

Работает стандартная система доступа UNIX, поэтому, если нужно чтобы пользователь подключивший шару мог получить доступ к дочерним директориям, то на клиентской стороне должен существовать пользователь с таким же UID (именем и ID), а на сервере для расшаренной директории должна принадлежать такому же пользователю или группе в которой он состоит (GID). Или дать полный доступ для всех пользователей (chmod 777), тогда все созданные файлы будут от имени: nobody nogroup

# Изменить UID
usermod -u 1020 nfs-user
# Изменить GID
groupmod -g 1020 nfs-user-02
# Проверяем ID
id nfs-user-02
# Предоставить полный доступ ко всем файлам расшаренной директории
# Анонимному пользователю присваивается UID 1020
echo "/nfs-folder 192.168.3.0/24(rw,sync,all_squash,anonuid=1020,anongid=1020)" > /etc/exports

NFS Client

NFS-common - это пакет, который используется для подключения к NFS-серверу например, nfs-kernel-server. В пакет включены программы: lockd, statd, showmount, nfsstat, gssd и idmapd.

apt install nfs-common

# Отобразить список всех доступных ресурсов
showmount -e 192.168.3.101

# Монтируем директорию
mkdir -p /mnt/nfs
mount 192.168.3.101:/nfs/share/ /mnt/nfs
# 192.168.3.104:/nfs-folder  48G  20G  27G  43%  /mnt/nfs-folder)

umount /mnt/nfs

FTP Server

vsftpd (Very Secure File Transfer Protocol Daemon) - это FTP-сервер для Linux/UNIX-систем, распространяемый под лицензией GPL и является стандартом для многих дистрибутивов (Ubuntu, CentOS, RHEL) благодаря высокой производительности, поддержке SSL/TLS для шифрования и возможности настройки виртуальных пользователей.

apt install vsftpd
systemctl status vsftpd
ufw allow 20:21/tcp
ufw allow 30000:31000/tcp
cp /etc/vsftpd.conf /etc/vsftpd.conf.bak

/etc/vsftpd.conf

listen=YES
listen_ipv6=NO
# отключить ананимный вход
anonymous_enable=NO
# Разрешить использовать имена локальных пользователей сервера для входа
local_enable=YES
# Разрешить для авторизованных пользователей управлять файловой системой (по умолчанию возможно только скачивание).
write_enable=YES
# Когда установлено в YES, ограничивает пользователей их домашними каталогами для предотвращения доступа к остальной части файловой системы
chroot_local_user=NO
# Задать список пользователей, которые будут или не будут ограничены своими домашними каталогами в зависимости от chroot_local_user
chroot_list_enable=YES
# Путь к файлу, который содержит список пользователей для chroot-ограничения
chroot_list_file=/etc/vsftpd.chroot_list
user_sub_token=$USER
# Указать для всех пользователей по умолчанию домашний каталог при подключении
local_root=/home/$USER/ftp
# Включает использование списка пользователей, которые могут (или не могут) входить на сервер
userlist_enable=YES
# Указывает путь к файлу со списком пользователей, которые разрешены или запрещены
userlist_file=/etc/vsftpd.user_list
# Определяет поведение списка пользователей (когда установлено в NO, только пользователи из списка userlist_file могут входить на сервер и наоборот)
userlist_deny=NO
# Использовать 20-й порт для передачи данных вместо случайного (нужно для стабильной работы firewall)
connect_from_port_20=YES
# Записывать в лог файл все транзакции
xferlog_enable = YES

systemctl restart vsftpd
ss -ln | grep -w "21" проверить, что 21 порт слушает (LISTEN)
ss -tn | grep -w "21" проверить установленные соединения на 21 порту (ESTAB)
cat /var/log/vsftpd.log лог работы (CONNECT/LOGIN/UPLOAD/DOWNLOAD/RENAME/DELETE)

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/vsftpd.key -out /etc/ssl/certs/vsftpd.crt сгенерировать самозаверяющий SSL-сертификат и закрытый ключ

/etc/vsftpd.conf

ssl_enable=YES
rsa_cert_file=/etc/ssl/certs/vsftpd.crt
rsa_private_key_file=/etc/ssl/private/vsftpd.key
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
require_ssl_reuse=NO
ssl_ciphers=HIGH

useradd -m -s /bin/bash ftpuser пользователь с домашним именным каталогом и оболочкой bash
passwd ftpuser задать пароль пользователю
echo "ftpuser" | tee -a /etc/vsftpd.chroot_list добавить пользователя в список ограниченных домашним каталогом
echo "ftpuser" | tee -a /etc/vsftpd.user_list добавить пользователя в список разрешенных для подключения
mkdir /home/ftpuser/ftp создать домашнию директорию
chown ftpuser:ftpuser ftp назначить владельца и группу для директории
chmod 555 ftp ограничить доступ только на чтение и выполнение
mkdir /home/ftpuser/ftp/upload создать директорию для загруки (с возможностью записи)
chown ftpuser:ftpuser upload
chmod 775 upload полный доступ для владельца и группы

FTP Client

ftp 192.168.3.101 доступен только без использования SSL
230 Login successful вход в систему успешен
ls отобразить все файлы в текущей директории на удаленном компьютере
get test.json скачать файл на локальный компьютер
put out.txt загрузить файл на удаленный сервер
bye закрыть соединение

Rsync

rsync -options SRC DST

-a режим архивирования, когда сохраняются все исходные атрибуты оригинальных файлов (дата изменения и создания)
-b создание резервной копии
-c проверка контрольных сумм для файлов
-e использовать другой транспорт (например ssh)
-h выводит цифры в формате, нормальном для чтения
-l копировать символьные ссылки
-L копировать содержимое ссылок
-p сохранять права для файлов
-q минимум информации
-u не перезаписывать более новые файлы
-v выводить подробную информацию о процессе копирования
-w выполнить полное копирование без синхронизации
-z сжимать файлы перед передачей
--delete удалять остальные файлы у получателя, которых нет в источнике отправителя
--progress выводить прогресс передачи файла (в %)
--stat показать статистику передачи

rsync -zvh /home/lifailon /backup копирование и синхронизация только файлов (skipping directory) указанной директории (в пределах одной локальной машины, например на внешний носитель). При редактировании файлов в исходной папке и повторном копирование заменит все содержимое (без синхронизации).

Конфигурация сервера в /etc/rsyncd.conf:

pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsync.log
[share]
path = /backup/
hosts allow = 192.168.3.105
hosts deny = *
list = true
uid = lifailon
gid = lifailon
read only = false

chown kup:kup backup сменить владельца и группу директории
chmod ug+rwx backup выдать им полные права (для удаленного пользователя)
systemctl start rsync запустить сервер

Синхронизация на удаленной машине (192.168.3.105) авторизованным под пользователем, указанным в конфигурации:

rsync -avzh /backup/ kup@192.168.3.105:/tmp/backup/ скопировать содержимое локальной папки backup (включая директории) на удаленный сервер. По умолчанию Rsync использует транспорт SSH (шифрованный) с запросом пароля (если не используется ключ).
rsync -avzhe "ssh -p 2121" /tmp/backup/ kup@192.168.21.121:/tmp/backup/ указать нестандартный порт для ssh (можно добавить в планировщик Cron)
rsync -avzh /tmp/backup/ rsync://192.168.21.121:/share явно задать использование транспорта Rsync
rsync -avzh kup@192.168.3.105:/tmp/backup /tmp/backup/ скопировать данные с удаленного сервера на локальный компьютер

GPG

GPG (GNU Privacy Guard) - это инструмент, который используется алгоритм RSA или Ed25519 для шифрования и цифровой подписи.

gpg -c filename зашифровать данные
gpg filename.gpg расшифровать данные
gpg --gen-key создавать пару ключей (публичный и приватный ключи)
gpg --export -a 'User Name' > publickey.asc экспорт публичного ключа
gpg --import publickey.asc импорт на второй стороне
gpg --encrypt --recipient 'Recipient Name' filename зашифровать данные с использованием публичного ключа получателя (только владелец приватного ключа сможет расшифровать)
gpg --decrypt encryptedfile.gpg расшифровать данные с помощью приватного ключа
gpg --sign filename подписывать данные с использованием приватного ключа для подтверждения их подлинности и целостности (без шифрования)
gpg --verify signedfile.gpg проверка подписи с использованием публичного ключа отправителя

Сети

SSH

w отобразить все активные сессии (TTY с экраном, FROM с ip)
who отобразить активные сессии, время/дата входа и ip с которого подключен пользователь
last -a история всех последних входов пользователей в систему
lastlog дата последнего входа каждого пользователя в систему
last reboot история перезагрузки
id -G получить список id крупп в которых состоит текущий пользователь

Конфигурация /etc/ssh/sshd_config

# Изменить порт
Port 2121
# Отключить аудентификацию по паролю
PasswordAuthentication no
# Включить X11
X11Forwarding yes
# Включить возможность подключения под пользователем root
PermitRootLogin yes
# Сколько времени сервер будет держать соединение открытым, для возможности ввод пароля
LoginGraceTime 2m
# Лимит попыток ввода пароля за одну сессию
MaxAuthTries 6
# Проверка прав доступа к ключам (запрет на chmod 777 ~/.ssh/authorized_keys)
StrictModes yes
# Ограничивает количество полуоткрытых соединений для защиты от Brute Force (подбора паролей) и SYN-flood атак
# Свыше 10 соединений отбрасывает 30% новых запросов на соединение и при 100 отбрасывает всех
MaxStartups 10:30:100

# Проверка активности соединения (отправка пустых keep-alive пакетов для сохранения активного соединения)
TCPKeepAlive no
# Задать интервал ожидания в секундах, через который sshd запросит ответ от клиента
ClientAliveInterval 60
# Количество запросов без ответа до завешрения сеанса (ClientAliveInterval * ClientAliveCountMax = 180 секунд)
ClientAliveCountMax 3

systemctl restart sshd
systemctl status sshd

ssh-keygen -t rsa -b 4096 сгенерировать пару ключей
id_rsa приватный (закрытый) ключ хранится на клиенте (от кого происходит подключение) для подключения без ввода пароля
~/.ssh/id_rsa.pub публичный (открытый) ключ используется для передачи на сервер, куда будем подключаться

sshpass - это утилита командной строки, предназначенная для автоматизации SSH-подключений путем неинтерактивной передачи пароля.

sudo apt install sshpass

hosts=(192.168.3.101 192.168.3.102 192.168.3.103 192.168.3.104)
username="lifailon"
port=2121
read -s -p "Введите пароль пользователя $username: " password
echo
for host in ${hosts[@]}; do
    sshpass -p $password ssh -p $port $username@$host "echo $(uname -n) $(free -m | grep Mem: | awk '{print $3"/"$2}')"
done

SCP

ssh-copy-id root@192.168.3.105 -p 2121 скопировать публичный ключ на удаленный сервер (добавить новой строкой), утилита будет искать в директории текущего локального пользователя файл публичного ключа и скопирует его содержимое (~/.ssh/id_rsa.pub) указанному при подключение пользователю на удаленный компьютер в файл ~/.ssh/authorized_keys

scp -P 2121 /home/lifailon/files/* lifailon@192.168.3.105:/home/lifailon/downaload/ скопировать содержимое каталога files на удаленный компьютер в директорию downaload

scp -P 2121 -r kup@192.168.3.105:/home/lifailon/downaload /home/lifailon/files/ скачать (-r) данные с удаленного сервера на локальный

Wi-Fi Tools

iw - системная утилита для управления и настройки Wi-Fi в Linux (замена устаревшего пакета wireless-tools, в который входила команда iwconfig).

sudo apt install iw

iw dev wlan0 info общая информация об интерфейсе
iw dev wlan0 scan поиск доступных Wi-Fi сетей
iw dev wlan0 link информация о текущем Wi-Fi подключение
iw dev wlan0 station dump статистика передачи данных для текущего подключения (количество переданных байт, ошибки, текущий битрейт)
sudo ip link set wlan0 down выключить интерфейс
sudo iw wlan0 set monitor control переводит карту в режим захвата пакетов из обычного режима type managed
ip link set wlan0 up включить интерфейс

Получить подробную информацию о Wi-Fi адаптера с помощью команды iw list. Если присутствует AP (Access Point) в списке Supported interface modes, значит поддерживается режим точки доступа.

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

apt install wavemon
wavemon

impala - TUI интерфейс для управления подключениями к Wi-Fi сетям.

apt update
apt install iwd
systemctl enable --now iwd
curl -sSL https://github.com/pythops/impala/releases/download/v0.7.4/impala-$(uname -m)-unknown-linux-musl -o $HOME/.local/bin/impala
chmod +x $HOME/.local/bin/impala
impala

linux-wifi-hotspot - позволяет поднять точку доступа, используя одновременно Wi-Fi подключение к основной точки доступа на роутере, с поддержкой подключения к VPN-тунелю.

add-apt-repository ppa:lakinduakash/lwh
apt update
apt install linux-wifi-hotspot

Network Manager

Network Manager - это системна для автоматического обнаружения и настройки сетевых соединений, обеспечивая автоматическое переключение на наиболее быстрое или доступное соединение с поддержкой управления с помощью графического интерфейса.

apt install network-manager
systemctl status NetworkManager

nmcli device status состояние интерфейсов - название адаптера, тип (wifi/ethernet), состоянием подключения и названием сети
nmcli general status подробное состояние интерфейсов с текущими настройками

sudo nmcli device wifi hotspot ssid failon.vpn password 12345678 создать точку доступа
sudo nmcli connection modify failon.vpn 802-11-wireless.band a изменить диапазон частоты работы на 5 ГГц
sudo nmcli connection up failon.vpn включить или отключить (down) точку доступа

echo "127.0.1.1 $(hostname)" | sudo tee -a /etc/hosts добавить имя хоста в файл /etc/hosts
nmcli device wifi rescan пересканировать все доступные поблизости Wi-Fi сети
nmcli device wifi list вывести список всех доступных Wi-Fi сетей
nmcli device wifi connect "TP-Link" password 12345678 name "TP-Link Wifi" подключиться к Wi-Fi сети

nmcli radio wifi текущее состояние работы Wi-Fi интерфейса
nmcli radio wifi on включить или выключить (off) Wi-Fi интерфейс

nmcli connection show список уже настроенных и сохраненных соединений (ethernet, vpn или wifi)
nmcli connection show failon.net подробная информация с настройками указанного подключения по его SSID
nmcli -f ipv4 connection show failon.net отфильтровать вывод настроек
nmcli connection up failon.net подключиться
nmcli connection down failon.net отключиться

nmcli connection add con-name "eth-dhcp" type ethernet ifname ens33 создать проводное подключение (ethernet) для сетевого интерфейса ens33
nmcli connection modify "eth-dhcp" ipv4.dns 8.8.8.8 изменить настройки подключения
nmcli connection up eth-dhcp применить настройки
nmcli connection show eth-dhcp вывести все настройки указанного соединения
nmcli connection modify "eth-dhcp" ipv4.method manual ipv4.addresses 192.168.3.106/24 ipv4.gateway 192.168.3.1 настроить статический IP-адрес

Networkd

systemd-networkd - это современный системный сервис и серверный стандарт, который управляет сетевыми конфигурациями, пришедший на смену старым скриптам /etc/network/interfaces (networking) и тяжелому Network Manager.

systemctl status systemd-networkd статус работы сервиса
journalctl -u systemd-networkd отобразить лог сервиса

networkctl list список всех адаптеров (configured используемый активный профиль)
networkctl status статус службы, Address и Gateway адаптера, DNS-адреса и лог systemd-networkd
networkctl status ens33 характеристики адаптера (Network File, Driver, Vendor, Model, MTU, Speed)

Netplan

netplan - это универсальный менеджер управления сетью для NetworkManager или networkd, который определяет настройки с помощью yaml файлов и создает конфигурации в директории /run/systemd/network/.

netplan status получить статус по всем интерфейсам
netplan get прочитать конфигурацию
netplan --debug generate проверка конфигурации на ошибки
netplan try применить изменения на 120 секунд с выводов лога (полезно для отладки)
netplan apply применить изменения (перезапускает сеть)

nano /etc/netplan/*.yaml

network:
  version: 2
  ethernets:
    ens33:
      dhcp4: yes
    ens36:
      dhcp4: yes
network:
  version: 2
  renderer: networkd
  ethernets:
    ens33:
      dhcp4: no
      addresses: [192.168.3.105/24]
      routes:
        - to: default
          via: 192.168.3.1
      nameservers:
        addresses: [192.168.3.101, 8.8.8.8, 1.1.1.1]
        search: [docker.local]

renderer указывает, кому передать управление сетью - networkd или NetworkManager (в средах с графическим интерфейсом)

network:
  ethernets:
    ens33:
      dhcp4: no
      match:
        macaddress: 54:43:32:21:10:09
        mtu: 1500
network:
  version: 2
  wifis:
    wlp33:
      dhcp4: yes
      dhcp6: no
      nameservers:
        addresses: [8.8.8.8]
      access-points:
        "wifi-ssid":
          password: "12345678"
network:
  version: 2
  ethernets:
    ens33: {}
    ens36: {}
  bonds:
    bond0:
      dhcp4: no
        interfaces:
          - ens33
          - ens36
          parameters:
            mode: active-backup # используется только один интерфейс, второй активируется в случае неработоспособности первого
            mode: broadcast     # используется оба интерфейса одновременно, пакеты передают все интерфейсы
            mode: balance-rr    # используется оба интерфейса по очереди с распределением пакетов
            mode: balance-tlb   # используется оба интерфейса по очереди, пакеты распределяются в соответствии с текущей нагрузкой
            mode: balance-xor   # используется оба интерфейса по очереди, распределение пакетов на основе политики хеширования
          addresses:
            - 192.168.1.150/24
          gateway4: 192.168.1.1
          mtu: 1500
          nameservers:
            addresses:
              - 8.8.8.8

Realmd

realmd - это системная служба, которая упрощает процесс настройки аутентификации в сетевых доменах (например, Active Directory или FreeIPA), где нужно выполнять процедуру join (создание учетной записи на компьютере в домене и обмен ключами Kerberos)

apt -y install realmd libnss-sss libpam-sss sssd sssd-tools adcli samba-common-bin oddjob oddjob-mkhomedir packagekit установка зависимостей

Настроить атрибуты хоста в файле /etc/realmd.conf, которые будут сохранены в учетной записи компьютера в AD (атрибуты operatingSystem и operatingSystemVersion)

[active-directory]
os-name = Ubuntu Server
os-version = 20.04

realm discover docker.local --verbose возвращает полную конфигурацию домена и список пакетов, которые должны быть установлены для регистрации системы в домене
realm join --help | grep pass
realm join -U lifailon docker.local --one-time-password добавить УЗ lifailon в домен
realm list проверить статус после подключения (server-software: active-directory)
id lifailon@docker.local получить сведения о УЗ домена (список групп из Active Directory)

SSSD

SSSD (System Security Services Daemon) - это связующее звено между системой под управлением Linux и удаленным сервером аутентификации (Active Directory, FreeIPA или LDAP для сопоставления прав доступа и других параметров), с поддержкой Kerberos для проверки пароля и кешированием (на случай, если доступ к контроллеру домена будет потерян).

# Запретить доступ всем остальным пользователям (очищает список simple_allow_* в файле sssd.conf)
realm deny --all

# Добавит доменную группу в систему 
# echo "simple_allow_groups = ssh-connect-domain" >> /etc/sssd/sssd.conf
realm permit -g 'ssh-connect-domain'

# Добавит доменного пользователя для авторизации в системе
# echo "simple_allow_users = lifailon" >> /etc/sssd/sssd.conf
realm permit lifailon@docker.local

systemctl restart sssd

Создавать домашний каталог для нового доменного пользователя в файле /usr/share/pam-configs/mkhomedir

Name: activate mkhomedir
Default: yes
Priority: 900
Session-Type: Additional
Session:
required pam_mkhomedir.so umask=0022 skel=/etc/skel

pam-auth-update обновить конфигурацию и выбрать созданную activate mkhomedir

Предоставить права sudo в файле /etc/sudoers.d/domain_admins

lifailon@docker.local               ALL=(ALL)       ALL
%ssh-connect-domain@docker.local    ALL=(ALL)       ALL

ssh lifailon@docker.local@hostname

nmap

nmap (Network Mapper) - это утилита командной строки для обнаружения активных хостов, открытых портов и определения запущенных сервисов.

snap install nmap

КлючОписаниеПример
-sSscan TCP SYN. Не завершает соединение (SYN - SYN-ACK - RST)nmap -sS 192.168.3.101
-sTscan TCP Connect. Полное TCP-соединение (SYN - SYN-ACK - ACK)nmap -sT 192.168.3.101
-sAscan TCP ACK. Обнаружить фильтрацию пакетов (ACK - RST или drop = filtered)nmap -sA 192.168.3.101
-sUscan UDP. Поиск открытых UDP-портов (DNS, DHCP, SNMP)nmap -sU 192.168.3.101
-snscan ICMP. Определение активных хостов с помощью ARP запросовnmap -sn 192.168.1.0/24
-PnNo ICMP. Пропускает стадию обнаружения с помощью ping (если хост блокирует ICMP)nmap -Pn 192.168.1.0/24
-nNo DNS. Отключает обратное разрешение имен для ускоренияnmap -n 192.168.3.101
-SSpoofing. Подмена исходящего адреса без ping (т.к. ответ уйдет на поддельный IP)nmap -S 192.168.3.1 -e eth0 -Pn 192.168.3.191
-vVerbose. Увеличивает детализацию вывода в консолиnmap -v 192.168.3.101
-pPorts. Сканирование конкретных портов или их диапазоновnmap -p 22,80,443 или nmap -p 0-1023
-p-All ports. Сканирует все 65535 возможных TCP-портовnmap -p- 192.168.3.101
-FFast scan. Сканирует только 100 наиболее распространенных портовnmap -F 192.168.3.101
-OOS detection. Попытка определить операционную систему хостаnmap -O 192.168.3.101
-sVService detection. Определение версий ПО на открытых портахnmap -sV 192.168.3.101
-AAggressive. Включает -O, -sV, скрипты -sC и traceroutenmap -A 192.168.3.101
-sCDefault scripts. Использование стандартного набора Lua-скриптов NSEnmap -sC 192.168.3.101
-T<0-5>Timing. Установка скорости (0 - скрытный, 5 - агрессивный)nmap -T5 1.1.1.1
-oNNormal output. Сохранение результата в текстовый файлnmap -oN scan.txt
-iLInput list. Чтение списка целевых IP-адресов из файлаnmap -iL list.txt

tcpdump

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

Описание ключей:

КлючОписаниеПример
-DПоказать список доступных интерфейсовtcpdump -D
-iВыбор сетевого интерфейса (например, eth0 или ens33)tcpdump -i eth0
-nНе преобразовывать IP-адреса в доменные именаtcpdump -n
-nnНе преобразовывать порты в названия протоколов (80 -> http)tcpdump -nn
-vПодробный вывод ( -vv или -vvv для максимума)tcpdump -v
-qКраткий вывод (меньше протокольной информации)tcpdump -q
-AВыводить содержимое пакета в формате ASCII (текст)tcpdump -A
-XВыводить содержимое пакета в HEX и ASCIItcpdump -X
-c nЗахватить только n пакетов и завершить работуtcpdump -c 100
-wЗаписать сырой трафик в файл формата .pcaptcpdump -w file.pcap
-rПрочитать пакеты из сохраненного .pcap файлаtcpdump -r file.pcap
-s 0Захват пакета целиком (0 = без ограничений)tcpdump -s 0
-eВыводить заголовки канального уровня (MAC-адреса)tcpdump -e
-lИспользовать буферизацию строк (удобно в pipe)tcpdump -l | grep "GET"
-FЧитать фильтры (BPF) из указанного файлаtcpdump -F filter.txt

Примеры фильтров:

ФильтрОписаниеПример
hostФильтр по IP-адресу (источник или назначение)tcpdump host 8.8.8.8
srcФильтр только по IP отправителя (source)tcpdump src 192.168.3.100
dstФильтр только по IP получателя (destination)tcpdump dst 192.168.3.101
netФильтр по подсети (CIDR)tcpdump net 192.168.3.0/24
portФильтр по номеру порта (TCP или UDP)tcpdump port 80
src portФильтр по номеру порта отправителяtcpdump src port 53
dst portФильтр по номеру порта получателяtcpdump src port 80
portrangeФильтр по диапазону портовtcpdump portrange 1-1024
protoФильтр по протоколу (tcp, udp, icmp, arp)tcpdump icmp
andЛогическое И (объединение условий)tcpdump "host 1.1.1.1 and port 80"
orЛогическое ИЛИ (одно из условий)tcpdump "port 80 or port 443"
notЛогическое НЕ (исключение)tcpdump "not port 22"
lessПакеты длиной меньше или равной N байтtcpdump less 64
greaterПакеты длиной больше или равной N байтtcpdump greater 1024
broadcastЗахват только широковещательных пакетовtcpdump broadcast
multicastЗахват только мультикаст-трафикаtcpdump multicast
tcp[]Фильтр по флагам TCP (syn, ack, psh, rst, fin)tcpdump "tcp[tcpflags] & tcp-syn != 0"

Разбор пакета: 12:43:35.049609 IP 192.168.3.101.22 > 192.168.3.100.24527: Flags [P.], seq 18468:19808, ack 793, win 592, length 1340

tshark

tshark - это консольный анализатор сетевых протоколов (сниффер), работает на движке Wireshark без графического интерфейса, который позволяет захватывать, фильтровать и анализировать трафик в реальном времени или читать дампы в формате .pcap. Как и tcpdump использует библиотеку захвата трафика libpcap, поэтому базовые ключи и синтаксис фильтров захвата у них идентичны.

apt install tshark

КлючОписаниеПример
-DПоказать список доступных интерфейсовtshark -D
-iВыбор интерфейса (номер из списка или название)tshark -i eth0
-nОтключить разрешение имен (IP/порты/MAC)tshark -n
-fФильтр захвата (BPF синтаксис, как в tcpdump)tshark -f "tcp port 80"
-YФильтр отображения (Display Filter, синтаксис Wireshark)tshark -Y "http.request"
-wЗапись трафика в файл .pcapngtshark -w capture.pcap
-rЧтение и анализ готового файла захватаtshark -r file.pcap
-VDetailed. Полный разбор всех протоколов (дерево пакета)tshark -V -r file.pcap
-OВывести детали только для конкретного протоколаtshark -O http
-TФормат вывода (fields, json, text, pdml, psml)tshark -T json
-eВывод конкретного поля (используется только с -T fields)tshark -T fields -e ip.src
-EНастройка формата вывода (header=y, separator=,)tshark -E header=y
-c nОстановить захват после n пакетовtshark -c 100
-aУсловие автостопа (duration:сек, filesize:КБ, files:кол-во)tshark -a duration:60
-bRing buffer. Создание нескольких файлов по кругуtshark -b filesize:1024
-zСтатистика (подсчет пакетов, HTTP запросов, экспертный лог)tshark -z http,tree
-pНе использовать «промискуитетный» режимtshark -p
-sSnaplen. Размер захватываемой части пакета (байты)tshark -s 64
-xДобавить HEX и ASCII дамп к выводуtshark -x

tshark -D список интерфейсов
tshark -i 1
disown
tshark -i 1 -Y "syslog" захват пакетов syslog (udp.port == 514)
tshark -i 1 host 192.168.3.104 захват пакетов для конкретного IP-адреса
tshark -i 1 net 192.168.3.0/24 захват пакетов указанной подсети
tshark -i 1 src host 192.168.3.104 захват исходящих пакетов
tshark -i 1 dst host 192.168.3.104 захват входящих пакетов
tshark -i 1 dst host 192.168.3.104 and port 8086 отфильтровать по входящему хосту и порту
tshark -i 1 dst host 192.168.3.104 and port 8086 and src host 192.168.3.99 отфильтровать по исходящему хосту
tshark -i 1 -x dst host 192.168.3.104 and port 8086 and src host 192.168.3.101 прочитать пакеты в шестнадцатеричном формате (-x)
tshark -i 1 -O TCP dst host 192.168.3.104 and port 8086 and src host 192.168.3.101 прочитать TCP-заголовки
tshark -i 1 -a duration:10 -w ~/192.168.3.0.pcap сохранить захват в файл
tshark -Y 'ip.addr == 192.168.3.106' -r ~/192.168.3.0.pcap прочитать файл захвата с использованием фильтра
tshark -Y "(ip.addr == 192.168.3.106) or (ip.addr == 192.168.3.107)" -r ~/192.168.3.0.pcap отфильтровать по двум адресам (или)
tshark -Y "(ip.addr == 192.168.3.104) and (tcp.port == 8086)" -r ~/192.168.3.0.pcap отфильтровать по двум параметрам (и)
tshark -Y "!(ip.addr == 192.168.3.104)" -r ~/192.168.3.0.pcap исключить
tshark -Y "not arp and not (udp.port == 53)" -r ~/192.168.3.0.pcap отобразить весь udp-трафик, исключив ping и dns пакеты

Termshark - терминальный пользовательский интерфейс (TUI) для tshark, созданный по образцу Wireshark.

apt install termshark

ufw

ufw (Uncomplicated Firewall) - это простой и удобный инструмент командной строки для управления брандмауэром в Linux, используемый по умолчанию в Debian и Ubuntu (является стандартом с версии 8.04 LTS). Он упрощает настройку сложных правил iptables или nftables, обеспечивая базовую защиту от атак, ограничение доступа к портам и управление входящим/исходящим трафиком.

systemctl status ufw

ufw status статус работы (включена или отключена фильтрация)
ufw enable включить ufw
ufw disable отключить
ufw reload перезапустить/применить настройки
ufw reset сбросить настройки (отключить ufw и удалить все правила)
ufw show listening список всех портов, которые в данный момент слушают входящие соединения, и сопоставляет их с действующими правилами фаервола
ufw default deny incoming отклонять все входящие пакеты (политика по умолчанию, какие действия будут применяться к пакетам, если они не подпадают под созданные правила)
ufw default allow outgoing все исходящие разрешать
ufw allow in 22 разрешить входящий трафик на порт 22
ufw allow out 22 разрешить исходящий трафик на порт 22
ufw deny in 80/tcp запретить входящий TCP-трафик на 80 порт
ufw delete deny in 80/tcp удалить правило
ufw allow 161,10050,10051/tcp открыть несколько портов
ufw allow 25/tcp открыть для всех направлений 25 порт
ufw limit ssh лимт подключений к определенному порту с одного IP-адреса (для защиты от перебора), по умолчанию подключения блокируются, если пользователь пытается создать шесть и больше подключений за 30 секунд (настроить время и количество запросов можно только через iptables)

ufw logging on включить логирование
ufw logging medium выбрать уровень логирования (low/medium/high)
cat /var/log/ufw директория хранения логов.

Синтаксис лога: [UFW ALLOW/BLOCK/AUDIT] IN=интерфейс OUT=итерфейс SRC=ip_источника DST=ip_назначения LEN=размер_пакета TOS=0x10 PREC=0x00 TTL=64 ID=728 DF PROTO=протокол SPT=порт_источника DPT=порт назначения LEN=размер_пакета

ufw show raw все активные правила в формате iptables
ufw show added недавно добавленные правила
ufw show builtins правила, добавленные по умолчанию
ufw show user-rules правила, добавленные пользователем
ufw show before-rules правила, которые выполняются перед принятием пакета
ufw show after-rules правила, которые выполняются после принятия пакета
ufw show logging-rules правила логгирования пакетов

firewalld

Firewalld - . Изначально он создавался как более мощная и гибкая альтернатива старым скриптам настройки фаервола. Firewalld - это динамический менеджер брандмауэра (файрвола) для Linux, который работает как удобный интерфейс для системы фильтрации пакетов nftables.

Firewalld - это динамический менеджер брандмауэра для Linux, который служит современным интерфейсом (фронтендом) для подсистем ядра nftables или iptables, разработаный сообществом Fedora при поддержке Red Hat.

apt install firewalld
systemctl status firewalld статус работы

firewall-cmd --state статус работы
firewall-cmd --reload применить настройки (перечитать)

firewall-cmd --list-all список созданных правил (для services и ports)
firewall-cmd --list-port вывести список только открытых портов
firewall-cmd --list-service вывести список открытых сервисов
firewall-cmd --list-all-zones отобразить список всех зон
firewall-cmd --get-active-zones список используемых зон
firewall-cmd --list-rich-rules список правил с условиями
firewall-cmd --list-all --zone=public информация о конкретной зоне

firewall-cmd --permanent --add-port=22/tcp открыть 22 порт
firewall-cmd --permanent --add-port=8000-8080/udp открыть диапазон портов
firewall-cmd --permanent --add-service=ssh разрешить порты для сервиса ssh
firewall-cmd --permanent --new-service=speedtest добавить службу
firewall-cmd --permanent --service=speedtest --add-port=80/tcp добавить порт к службе
firewall-cmd --info-service=speedtest информация о службе
firewall-cmd --permanent --add-rich-rule 'rule family="ipv4" source address="192.168.3.0/24" service name="speedtest" accept' открыть доступ для подсети
firewall-cmd --permanent --add-rich-rule 'rule family="ipv4" source address="192.168.3.0/24" port port="22" protocol="tcp" accept'
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.21.0/24' reject" закрыть доступ для подсети
firewall-cmd --permanent --remove-port=22/tcp удалить правило

nftables

nftables - это современная подсистема ядра Linux, которая отвечает за фильтрацию пакетов, классификацию трафика и NAT, пришедший за смену iptables.

nft -a list ruleset вывести список существующих правил
nft flush ruleset очистить все правила
nft list tables вывести список существующих таблиц
nft add table inet filter создать таблицу filter
nft add chain inet filter input { type filter hook input priority 0\; } добавить цепочку input (будут проверять каждый входящий пакет из сети до того, как он попадет в систему)
nft add rule inet filter input ct state related,established counter accept разрешает ответы на все новые открываемые клиентом и уже открытые соединения
nft add rule inet filter input iifname "lo" counter accept разрешает программам внутри системы общаться друг с другом через локальную петлю (localhost)
nft add rule inet filter input ip protocol icmp counter accept разрешить icmp
nft add rule inet filter input tcp dport {80, 443} counter accept открыть порты
nft add rule inet filter input ip saddr { 192.168.100.0/24, 1.1.1.1/32 } tcp dport 22 counter accept открыть 22 порт для подсетей
nft chain inet filter input { policy drop \; } остальное блокировать
nft delete rule inet filter input handle 5 удалить правило по номеру в # handle NUMBER
nft add rule inet filter input position 5 tcp dport 22 counter accept добавить правило в конкретное место с номером в списке

fail2ban

Fail2Ban - демон для блокировки хостов, вызывающие множественные ошибки аутентификации.

sudo apt install -y fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Создаем базовую конфигурацию для shh в файле /etc/fail2ban/jail.local

[sshd]
enabled         = true
port            = 2121
logpath         = /var/log/auth.log
maxretry        = 3
findtime        = 10m
bantime         = 6h

Применяем настройки и проверяем статус:

fail2ban-client reload

fail2ban-client status
fail2ban-client status sshd

Status for the jail: sshd
|- Filter
|  |- Currently failed: 3     # в логах зафиксировано 3 неудачные попытки входа (которые еще не привели к бану) за время, указанное в findtime
|  |- Total failed:     4251  # общее количество совпадений в лог-файле
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 0     # количество адресов в черном списке
   |- Total banned:     278   # общее количество IP-адресов, которые были заблокированы за все время работы службы
   `- Banned IP list:

# Удалить адрес из бана
# fail2ban-client set sshd unbanip 81.200.53.25

Создаем фильтр поиска событий для блокировки попыток доступа к панели управления 3x-ui в файле /etc/fail2ban/filter.d/3x-ui.conf

[Definition]
failregex = ^.*wrong username:.*IP: "<HOST>".*$

# Пример ожидаемого события:
# Apr 01 19:02:09 yieldingturquoi.aeza.network 3x[148991]: WARNING - wrong username: "test", password: "test", IP: "81.200.53.25"

Добавляем новое правило:

[3x-ui]
enabled         = true
port            = 20533
filter          = 3x-ui
backend         = systemd
journalmatch    = SYSLOG_IDENTIFIER=3x
maxretry        = 3
findtime        = 10m
bantime         = 1h

Фильтр для доступа mixed proxy:

[Definition]
failregex = ^.*from (?:tcp|udp):<HOST>:\d+ rejected.*proxy/socks.*invalid username or password.*$

# Пример ожидаемого события:
# 2026/04/01 22:25:00.444801 from tcp:81.200.53.25:27840 rejected  proxy/socks: invalid username or password

Добавляем новое правило:

[3x-proxy]
enabled         = true
port            = 12537
filter          = 3x-proxy
logpath         = /root/docker/3x/3x_logs/access.log
maxretry        = 3
findtime        = 10m
bantime         = 1h
action          = iptables-allports[name=3x-proxy, chain=DOCKER-USER]

Apache

apt install apache2
sed -r "s/^Listen.+/Listen 8443/" -i /etc/apache2/ports.conf
systemctl restart apache2
systemctl status apache2
ss -lpn | grep apache
echo "<H1>$(hostname)</H1>" > /var/www/html/index.html

Создаем скрипт для API сервера: /var/www/api/api.sh

#!/bin/bash

if [ "$REQUEST_METHOD" != "GET" ]; then
    echo "Content-type: text/plain"
    echo
    echo "Request method not supported"
elif [ "$REQUEST_URI" == "/api/status" ]; then
    echo "Content-type: application/json"
    echo
    echo '{"status": "true"}'
else
    echo "Content-type: application/json"
    echo
    echo '{"status": "false"}'
fi

Создаем VirtualHost для обработки запросов сервера в файле /etc/apache2/sites-available/api.conf

<VirtualHost *:8443>
    DocumentRoot /var/www/html
    # Связать endpoint (включая все дочернии в пути) с исполняемым файлом
    ScriptAlias /api /var/www/api/api.sh
    # Все опции, вложенные внутрь секции Directory, применяются к указанной директории
    <Directory "/var/www/api">
        # Разрешить выполнение CGI-скриптов
        Options +ExecCGI
        # Обрабатывать все файлы с расширение sh как CGI-скрипт
        AddHandler cgi-script .sh
        AllowOverride None
        Require all granted
    </Directory>
    # Добавить авторизацию для endpoint
    <Location "/api">
        AuthType Basic
        AuthName "Restricted Area"
        AuthUserFile /etc/apache2/.htpasswd
        Require valid-user
        SetHandler cgi-script
        Options +ExecCGI
    </Location>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Настраиваем модули:

# Активируем модули для базовой аутентификации
a2enmod auth_basic
# Создать пользователя rest с паролем api
htpasswd -b -c /etc/apache2/.htpasswd rest api

# Активируем модуль CGI
a2enmod cgi
# Выдаем права скрипту на выполнение
chmod +x /var/www/api/api.sh

# Активируем конфигурацию сервера (VirtualHost)
a2ensite api.conf

systemctl restart apache2
tail -f /var/log/apache2/error.log
tail -f /var/log/apache2/access.log

Примеры отправки запросов:

curl -s -X GET http://127.0.0.1:8443/api -u rest:api | jq .status
curl -s -X GET http://127.0.0.1:8443/api/status -u rest:api | jq .status
curl -s -X GET http://127.0.0.1:8443/api/status -u rest:api -X POST

Доступные переменные внутри скрипта:

Server-status- это модуль mod_status, предоставляющий HTML-страницу с подробной статистикой работы веб-сервера в реальном времени.

Настройка статистики в файле /etc/apache2/mods-available/status.conf

# Проверить, что подключен модуль статистики
apachectl -M | grep status_module
# Проверить синтаксис
apachectl -t

# Активировать модуль (Module status already enabled)
a2enmod status
systemctl restart apache2
netstat -tulpan | grep apache2

curl http://127.0.0.1:8443/server-status?auto

/etc/apache2/ports.conf

Listen 8443
Listen 2024

Создаем каталог, к которому будет доступ через WebDAV и предоставить доступ к нему для www-data:

mkdir /var/www/webdav
chown www-data:www-data /var/www/webdav

Создаем конфигурацию в файле /etc/apache2/sites-available/webdav.conf

<VirtualHost *:2024>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/webdav
    Alias /webdav /var/www/webdav
    <Directory /var/www/webdav>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
        Dav On
        AuthType Basic
        AuthName "WebDAV"
        AuthUserFile /etc/apache2/.htpasswd
        Require valid-user
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/webdav_error.log
    CustomLog ${APACHE_LOG_DIR}/webdav_access.log combined
</VirtualHost>

Настраиваем модули:

a2enmod dav
a2enmod dav_fs
a2enmod auth_digest
a2enmod authn_core
a2enmod authn_file
a2enmod authz_core
a2enmod authz_user

# Создать пользователя admin
htpasswd /etc/apache2/.htpasswd admin
# Активировать конфигурацию сайта (VirtualHost)
a2ensite webdav

systemctl restart apache2