Added about Linux
This commit is contained in:
parent
920b20081b
commit
01f899d831
25 changed files with 4414 additions and 7 deletions
|
|
@ -24,7 +24,7 @@
|
||||||
**Требования:** Go 1.21+
|
**Требования:** Go 1.21+
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://gitverse.ru/magnusroot/rubric
|
git clone https://github.com/user/rubric
|
||||||
cd rubric
|
cd rubric
|
||||||
go build -o rubric .
|
go build -o rubric .
|
||||||
```
|
```
|
||||||
|
|
@ -32,7 +32,7 @@ go build -o rubric .
|
||||||
Или сразу установить глобально:
|
Или сразу установить глобально:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go install gitverse.ru/magnusroot/rubric@latest
|
go install github.com/user/rubric@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ type Book struct {
|
||||||
// All — список всех справочников
|
// All — список всех справочников
|
||||||
var All = []Book{
|
var All = []Book{
|
||||||
GoBook,
|
GoBook,
|
||||||
// LinuxBook — будет добавлен позже
|
LinuxBook,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find ищет книгу по ключу или алиасу
|
// Find ищет книгу по ключу или алиасу
|
||||||
|
|
|
||||||
115
catalog/linuxbook.go
Normal file
115
catalog/linuxbook.go
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
package catalog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"rubric/modules/linuxmodules"
|
||||||
|
"rubric/utils"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LinuxBook — запись справочника Linux в главном меню
|
||||||
|
var LinuxBook = Book{
|
||||||
|
Key: "linux",
|
||||||
|
Aliases: []string{"l", "lnx"},
|
||||||
|
Title: "Справочник по GNU/Linux",
|
||||||
|
Description: "Основы GNU/Linux: файлы, процессы, сети, systemd, bash-скрипты и многое другое",
|
||||||
|
Run: runLinuxBook,
|
||||||
|
}
|
||||||
|
|
||||||
|
func runLinuxBook(scanner *bufio.Scanner) {
|
||||||
|
for {
|
||||||
|
showLinuxMenu()
|
||||||
|
|
||||||
|
input, ok := ReadLine(scanner)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if input == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if IsQuit(input) {
|
||||||
|
fmt.Printf("\n %s%sДо свидания!%s\n\n",
|
||||||
|
utils.ColorBold, utils.ColorCyan, utils.ColorReset)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if IsBack(input) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// По номеру
|
||||||
|
if n, err := strconv.Atoi(input); err == nil {
|
||||||
|
if n >= 1 && n <= len(linuxmodules.All) {
|
||||||
|
linuxmodules.All[n-1].Run()
|
||||||
|
waitLinuxBack(scanner)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("\n %s%sНомер %d вне диапазона (1–%d)%s\n",
|
||||||
|
utils.ColorBold, utils.ColorRed, n, len(linuxmodules.All), utils.ColorReset)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// По ключу
|
||||||
|
if m, ok := linuxmodules.Find(input); ok {
|
||||||
|
m.Run()
|
||||||
|
waitLinuxBack(scanner)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\n %s%sНе понял '%s'. Номер, ключ раздела, b — назад.%s\n",
|
||||||
|
utils.ColorBold, utils.ColorRed, input, utils.ColorReset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func showLinuxMenu() {
|
||||||
|
utils.Header("Справочник GNU/Linux")
|
||||||
|
|
||||||
|
fmt.Printf(" %s%sРазделы:%s\n\n",
|
||||||
|
utils.ColorBold, utils.ColorWhite, utils.ColorReset)
|
||||||
|
|
||||||
|
for i, m := range linuxmodules.All {
|
||||||
|
aliases := ""
|
||||||
|
if len(m.Aliases) > 0 {
|
||||||
|
aliases = fmt.Sprintf("%s [%s]%s",
|
||||||
|
utils.ColorDim, strings.Join(m.Aliases, ", "), utils.ColorReset)
|
||||||
|
}
|
||||||
|
fmt.Printf(" %s%s %2d.%s %s%-12s%s %s%-30s%s%s\n",
|
||||||
|
utils.ColorBold, utils.ColorCyan, i+1, utils.ColorReset,
|
||||||
|
utils.ColorYellow+utils.ColorBold, m.Key, utils.ColorReset,
|
||||||
|
utils.ColorWhite, m.Title, utils.ColorReset,
|
||||||
|
aliases,
|
||||||
|
)
|
||||||
|
fmt.Printf(" %s%s%s\n\n",
|
||||||
|
utils.ColorDim, m.Description, utils.ColorReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf(" %s%sРаздел (номер / ключ / b — главное меню / q — выход):%s ",
|
||||||
|
utils.ColorBold, utils.ColorGreen, utils.ColorReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
type linuxBackSignal struct{}
|
||||||
|
|
||||||
|
func waitLinuxBack(scanner *bufio.Scanner) {
|
||||||
|
fmt.Printf("\n %s%s[Enter — назад в меню Linux, b — главное меню]%s ",
|
||||||
|
utils.ColorDim, utils.ColorCyan, utils.ColorReset)
|
||||||
|
if scanner.Scan() {
|
||||||
|
if IsBack(strings.TrimSpace(scanner.Text())) {
|
||||||
|
panic(linuxBackSignal{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
orig := LinuxBook.Run
|
||||||
|
LinuxBook.Run = func(scanner *bufio.Scanner) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
if _, ok := r.(linuxBackSignal); !ok {
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
orig(scanner)
|
||||||
|
}
|
||||||
|
}
|
||||||
16
main.go
16
main.go
|
|
@ -7,11 +7,12 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"rubric/catalog"
|
"rubric/catalog"
|
||||||
"rubric/modules/gomodules"
|
"rubric/modules/gomodules"
|
||||||
|
"rubric/modules/linuxmodules"
|
||||||
"rubric/utils"
|
"rubric/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
book := flag.String("book", "", "открыть справочник напрямую (например: -book go)")
|
book := flag.String("book", "", "открыть справочник напрямую (go, linux)")
|
||||||
topic := flag.String("topic", "", "открыть раздел (используется вместе с -book)")
|
topic := flag.String("topic", "", "открыть раздел (используется вместе с -book)")
|
||||||
list := flag.Bool("list", false, "список всех справочников и разделов")
|
list := flag.Bool("list", false, "список всех справочников и разделов")
|
||||||
help := flag.Bool("help", false, "справка по использованию")
|
help := flag.Bool("help", false, "справка по использованию")
|
||||||
|
|
@ -29,7 +30,7 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -book go -topic basics
|
// -book X -topic Y
|
||||||
if *book != "" && *topic != "" {
|
if *book != "" && *topic != "" {
|
||||||
switch *book {
|
switch *book {
|
||||||
case "go", "g", "golang":
|
case "go", "g", "golang":
|
||||||
|
|
@ -41,6 +42,15 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
m.Run()
|
m.Run()
|
||||||
|
case "linux", "l", "lnx":
|
||||||
|
m, ok := linuxmodules.Find(*topic)
|
||||||
|
if !ok {
|
||||||
|
fmt.Printf("\n %s%sРаздел '%s' не найден в справочнике Linux.%s\n",
|
||||||
|
utils.ColorBold, utils.ColorRed, *topic, utils.ColorReset)
|
||||||
|
linuxmodules.ListModules()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
m.Run()
|
||||||
default:
|
default:
|
||||||
fmt.Printf("\n %s%sСправочник '%s' не найден.%s\n",
|
fmt.Printf("\n %s%sСправочник '%s' не найден.%s\n",
|
||||||
utils.ColorBold, utils.ColorRed, *book, utils.ColorReset)
|
utils.ColorBold, utils.ColorRed, *book, utils.ColorReset)
|
||||||
|
|
@ -50,7 +60,7 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -book go
|
// -book X
|
||||||
if *book != "" {
|
if *book != "" {
|
||||||
b, ok := catalog.Find(*book)
|
b, ok := catalog.Find(*book)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
||||||
189
modules/linuxmodules/linux_backup.go
Normal file
189
modules/linuxmodules/linux_backup.go
Normal file
|
|
@ -0,0 +1,189 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var BackupModule = Module{
|
||||||
|
Key: "backup",
|
||||||
|
Aliases: []string{"bk", "tar", "бэкап"},
|
||||||
|
Title: "Резервное копирование",
|
||||||
|
Description: "Темы 38–40: tar, инкрементальные бэкапы, rsync, VDO",
|
||||||
|
Run: showBackup,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showBackup() {
|
||||||
|
utils.Header("Linux — Резервное копирование")
|
||||||
|
|
||||||
|
// ─── 38. tar ──────────────────────────────────────────────────
|
||||||
|
utils.Section("38. Создание бэкапов с tar")
|
||||||
|
|
||||||
|
utils.Println("tar — основной инструмент архивирования в Linux.")
|
||||||
|
utils.Println(utils.ColorBold + "\nОсновные флаги tar:" + utils.ColorReset)
|
||||||
|
utils.Code(`c — create (создать архив)
|
||||||
|
x — extract (извлечь)
|
||||||
|
t — list (показать содержимое)
|
||||||
|
v — verbose (подробный вывод)
|
||||||
|
f — file (имя файла архива)
|
||||||
|
z — gzip (сжатие gzip, .tar.gz / .tgz)
|
||||||
|
j — bzip2 (сжатие bzip2, .tar.bz2)
|
||||||
|
J — xz (сжатие xz, .tar.xz)
|
||||||
|
p — preserve permissions (сохранить права)
|
||||||
|
C — change directory (распаковать в указанную папку)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Создание архива:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Создать архив:
|
||||||
|
tar -cvf archive.tar /path/to/dir # без сжатия
|
||||||
|
tar -czvf archive.tar.gz /etc/ # с gzip
|
||||||
|
tar -cjvf archive.tar.bz2 /var/www/ # с bzip2
|
||||||
|
tar -cJvf archive.tar.xz /home/alice/ # с xz (медленнее, лучше)
|
||||||
|
|
||||||
|
# Создать с меткой даты:
|
||||||
|
tar -czvf backup_$(date +%Y%m%d_%H%M).tar.gz /etc/
|
||||||
|
|
||||||
|
# Исключить директории:
|
||||||
|
tar -czvf backup.tar.gz /home/ \
|
||||||
|
--exclude=/home/.cache \
|
||||||
|
--exclude='/home/*/.local'
|
||||||
|
|
||||||
|
# Архивировать только изменённые файлы:
|
||||||
|
tar -czvf backup.tar.gz --newer "2024-01-01" /home/`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Извлечение архива:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Извлечь в текущую директорию:
|
||||||
|
tar -xvf archive.tar
|
||||||
|
tar -xzvf archive.tar.gz
|
||||||
|
|
||||||
|
# Извлечь в указанную директорию:
|
||||||
|
tar -xzvf archive.tar.gz -C /tmp/restore/
|
||||||
|
|
||||||
|
# Извлечь только конкретные файлы:
|
||||||
|
tar -xzvf archive.tar.gz etc/nginx/nginx.conf
|
||||||
|
|
||||||
|
# Просмотр содержимого без распаковки:
|
||||||
|
tar -tzvf archive.tar.gz
|
||||||
|
tar -tzvf archive.tar.gz | grep nginx`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "rsync — синхронизация файлов:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Базовый синтаксис: rsync [опции] источник назначение
|
||||||
|
|
||||||
|
# Опции:
|
||||||
|
-a — архивный режим (-rlptgoD: рекурсия, права, время...)
|
||||||
|
-v — verbose
|
||||||
|
-z — сжатие при передаче
|
||||||
|
-P — прогресс + продолжение
|
||||||
|
-n — dry-run (симуляция без изменений)
|
||||||
|
--delete — удалять файлы которых нет в источнике
|
||||||
|
-e ssh — использовать SSH
|
||||||
|
|
||||||
|
# Локальная синхронизация:
|
||||||
|
rsync -av /source/ /dest/ # / после source — содержимое (без самой папки)
|
||||||
|
rsync -av /source /dest/ # без / — копирует саму папку
|
||||||
|
|
||||||
|
# По сети через SSH:
|
||||||
|
rsync -avzP /home/alice/ user@server:/backup/alice/
|
||||||
|
rsync -avzP user@server:/data/ /local/backup/
|
||||||
|
|
||||||
|
# Зеркало (с удалением лишнего):
|
||||||
|
rsync -av --delete /source/ /mirror/
|
||||||
|
|
||||||
|
# Бэкап с сохранением удалённых файлов:
|
||||||
|
rsync -av --backup --backup-dir=/backup/old-$(date +%Y%m%d) \
|
||||||
|
--delete /source/ /mirror/`)
|
||||||
|
|
||||||
|
// ─── 39. Инкрементальные бэкапы ───────────────────────────────
|
||||||
|
utils.Section("39. Инкрементальные бэкапы с tar")
|
||||||
|
|
||||||
|
utils.Println("Инкрементальный бэкап — сохраняет только изменения с момента последнего бэкапа.")
|
||||||
|
utils.Code(`# tar поддерживает инкрементальные бэкапы через snapshot-файл.
|
||||||
|
# Snapshot хранит список файлов и время последнего изменения.
|
||||||
|
|
||||||
|
# Полный бэкап (level 0):
|
||||||
|
tar -czvf backup_full_$(date +%Y%m%d).tar.gz \
|
||||||
|
--listed-incremental=/var/backup/snapshot.snar \
|
||||||
|
/home/
|
||||||
|
|
||||||
|
# Инкрементальный бэкап (только изменения):
|
||||||
|
tar -czvf backup_incr_$(date +%Y%m%d_%H%M).tar.gz \
|
||||||
|
--listed-incremental=/var/backup/snapshot.snar \
|
||||||
|
/home/
|
||||||
|
|
||||||
|
# Восстановление: сначала полный, затем все инкрементальные по порядку:
|
||||||
|
tar -xzvf backup_full_20240101.tar.gz \
|
||||||
|
--listed-incremental=/dev/null -C /restore/
|
||||||
|
tar -xzvf backup_incr_20240102.tar.gz \
|
||||||
|
--listed-incremental=/dev/null -C /restore/
|
||||||
|
|
||||||
|
# Просмотр инкрементального архива:
|
||||||
|
tar -tzvf backup_incr.tar.gz --listed-incremental=/dev/null`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Скрипт автоматического бэкапа:" + utils.ColorReset)
|
||||||
|
utils.Code(`#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BACKUP_DIR="/backup"
|
||||||
|
SOURCE="/home /etc /var/www"
|
||||||
|
SNAPSHOT="/var/backup/snapshot.snar"
|
||||||
|
DATE=$(date +%Y%m%d_%H%M)
|
||||||
|
LOG="/var/log/backup.log"
|
||||||
|
|
||||||
|
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG"; }
|
||||||
|
|
||||||
|
log "Начало бэкапа"
|
||||||
|
|
||||||
|
# Полный бэкап по воскресеньям, инкрементальный остальные дни:
|
||||||
|
if [ "$(date +%u)" -eq 7 ]; then
|
||||||
|
cp "$SNAPSHOT" "${SNAPSHOT}.prev" 2>/dev/null || true
|
||||||
|
ARCHIVE="$BACKUP_DIR/full_$DATE.tar.gz"
|
||||||
|
tar -czvf "$ARCHIVE" --listed-incremental="$SNAPSHOT" $SOURCE
|
||||||
|
log "Полный бэкап: $ARCHIVE"
|
||||||
|
else
|
||||||
|
ARCHIVE="$BACKUP_DIR/incr_$DATE.tar.gz"
|
||||||
|
tar -czvf "$ARCHIVE" --listed-incremental="$SNAPSHOT" $SOURCE
|
||||||
|
log "Инкрементальный бэкап: $ARCHIVE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Удалить старые бэкапы (оставить за 30 дней):
|
||||||
|
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -delete
|
||||||
|
log "Старые бэкапы очищены. Готово."`)
|
||||||
|
|
||||||
|
// ─── 40. VDO ──────────────────────────────────────────────────
|
||||||
|
utils.Section("40. Дедупликация с VDO (Virtual Data Optimizer)")
|
||||||
|
|
||||||
|
utils.Println("VDO — технология RHEL для дедупликации и сжатия данных на блочном уровне.")
|
||||||
|
utils.Println("Уменьшает занимаемое место на диске без изменения работы приложений.")
|
||||||
|
utils.Code(`# VDO доступен в RHEL/CentOS. Установка:
|
||||||
|
dnf install vdo kmod-kvdo
|
||||||
|
|
||||||
|
# Создать VDO-устройство поверх блочного (/dev/sdb):
|
||||||
|
vdo create --name=vdo_data \
|
||||||
|
--device=/dev/sdb \
|
||||||
|
--vdoLogicalSize=100G # виртуальный размер (больше физического)
|
||||||
|
|
||||||
|
# Посмотреть VDO-устройства:
|
||||||
|
vdo list
|
||||||
|
vdo status --name=vdo_data
|
||||||
|
|
||||||
|
# Создать ФС на VDO:
|
||||||
|
mkfs.ext4 -E nodiscard /dev/mapper/vdo_data
|
||||||
|
mount /dev/mapper/vdo_data /mnt/data
|
||||||
|
|
||||||
|
# Статистика экономии:
|
||||||
|
vdostats --human-readable
|
||||||
|
# Показывает: физический размер / использовано / коэффициент сжатия
|
||||||
|
|
||||||
|
# VDO в /etc/fstab:
|
||||||
|
/dev/mapper/vdo_data /mnt/data ext4 defaults,x-systemd.requires=vdo.service 0 2
|
||||||
|
|
||||||
|
# Запустить/остановить:
|
||||||
|
vdo start --name=vdo_data
|
||||||
|
vdo stop --name=vdo_data
|
||||||
|
|
||||||
|
# Удалить VDO:
|
||||||
|
vdo remove --name=vdo_data --force`)
|
||||||
|
|
||||||
|
utils.Note("VDO хорошо работает для виртуализации, контейнеров и бэкапов — там много одинаковых данных.")
|
||||||
|
utils.Note("LVM 2.3+ поддерживает VDO напрямую через lvcreate --type vdo.")
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
238
modules/linuxmodules/linux_bash.go
Normal file
238
modules/linuxmodules/linux_bash.go
Normal file
|
|
@ -0,0 +1,238 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var BashModule = Module{
|
||||||
|
Key: "bash",
|
||||||
|
Aliases: []string{"sh", "shell", "баш"},
|
||||||
|
Title: "Bash: основы и переменные",
|
||||||
|
Description: "Темы 12–13: bash-completion, alias, type, переменные окружения",
|
||||||
|
Run: showBash,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showBash() {
|
||||||
|
utils.Header("Linux — Bash: основы и переменные")
|
||||||
|
|
||||||
|
// ─── 12. Bash #1 ──────────────────────────────────────────────
|
||||||
|
utils.Section("12. Bash #1: bash-completion, alias, type")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "bash-completion — автодополнение Tab:" + utils.ColorReset)
|
||||||
|
utils.Code(`Tab — дополнить команду / путь / аргумент
|
||||||
|
Tab Tab — показать все варианты
|
||||||
|
|
||||||
|
# Примеры:
|
||||||
|
git che<Tab> → git checkout
|
||||||
|
ls /etc/sy<Tab> → ls /etc/systemd/
|
||||||
|
ssh us<Tab> → ssh user@hostname (из ~/.ssh/config)
|
||||||
|
systemctl st<Tab> → systemctl start/status/stop
|
||||||
|
|
||||||
|
# Установить расширенный bash-completion:
|
||||||
|
# Debian/Ubuntu: apt install bash-completion
|
||||||
|
# RHEL/Fedora: dnf install bash-completion
|
||||||
|
# Активировать в ~/.bashrc:
|
||||||
|
[ -f /etc/bash_completion ] && . /etc/bash_completion`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "alias — псевдонимы команд:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Посмотреть все алиасы:
|
||||||
|
alias
|
||||||
|
|
||||||
|
# Создать алиас (действует до конца сессии):
|
||||||
|
alias ll='ls -la'
|
||||||
|
alias la='ls -la'
|
||||||
|
alias ..='cd ..'
|
||||||
|
alias ...='cd ../..'
|
||||||
|
alias grep='grep --color=auto'
|
||||||
|
alias rm='rm -i' # защита от случайного удаления
|
||||||
|
alias df='df -h'
|
||||||
|
alias free='free -h'
|
||||||
|
alias update='sudo apt update && sudo apt upgrade'
|
||||||
|
|
||||||
|
# Использование алиаса:
|
||||||
|
ll /etc
|
||||||
|
|
||||||
|
# Удалить алиас:
|
||||||
|
unalias ll
|
||||||
|
|
||||||
|
# Посмотреть что делает алиас:
|
||||||
|
alias ll`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Постоянные алиасы — добавить в ~/.bashrc:" + utils.ColorReset)
|
||||||
|
utils.Code(`# ~/.bashrc
|
||||||
|
alias ll='ls -la --color=auto'
|
||||||
|
alias la='ls -la'
|
||||||
|
alias l='ls -CF'
|
||||||
|
alias ..='cd ..'
|
||||||
|
alias grep='grep --color=auto'
|
||||||
|
alias h='history'
|
||||||
|
alias c='clear'
|
||||||
|
|
||||||
|
# Применить без перезапуска терминала:
|
||||||
|
source ~/.bashrc
|
||||||
|
# или:
|
||||||
|
. ~/.bashrc`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "type — определить тип команды:" + utils.ColorReset)
|
||||||
|
utils.Code(`type ls
|
||||||
|
# ls is aliased to 'ls --color=auto'
|
||||||
|
|
||||||
|
type cd
|
||||||
|
# cd is a shell builtin
|
||||||
|
|
||||||
|
type python3
|
||||||
|
# python3 is /usr/bin/python3
|
||||||
|
|
||||||
|
type ll
|
||||||
|
# ll is aliased to 'ls -la'
|
||||||
|
|
||||||
|
type if
|
||||||
|
# if is a shell keyword
|
||||||
|
|
||||||
|
# Опции:
|
||||||
|
type -a ls # все варианты (алиас + файл)
|
||||||
|
type -t ls # только тип: alias/builtin/file/keyword`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "which и whereis:" + utils.ColorReset)
|
||||||
|
utils.Command("which python3", "полный путь к исполняемому файлу")
|
||||||
|
utils.Command("which -a python", "все версии python в PATH")
|
||||||
|
utils.Command("whereis nginx", "бинарник, исходники, man-страница")
|
||||||
|
utils.Command("command -v git", "путь или алиас (POSIX-совместимо)")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Работа с историей команд:" + utils.ColorReset)
|
||||||
|
utils.Command("history", "полная история")
|
||||||
|
utils.Command("history 20", "последние 20 команд")
|
||||||
|
utils.Command("!42", "выполнить команду №42")
|
||||||
|
utils.Command("!!", "повторить последнюю команду")
|
||||||
|
utils.Command("!ls", "последняя команда начинающаяся с ls")
|
||||||
|
utils.Command("Ctrl+R", "интерактивный поиск по истории")
|
||||||
|
utils.Command("history -c", "очистить историю")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`# Файл истории: ~/.bash_history
|
||||||
|
# Управление историей через переменные в ~/.bashrc:
|
||||||
|
HISTSIZE=10000 # размер в памяти
|
||||||
|
HISTFILESIZE=20000 # размер файла
|
||||||
|
HISTCONTROL=ignoredups # не сохранять дубли
|
||||||
|
HISTCONTROL=ignorespace # команды с пробелом впереди не сохраняются
|
||||||
|
# Временные метки в истории:
|
||||||
|
HISTTIMEFORMAT="%F %T "`)
|
||||||
|
|
||||||
|
// ─── 13. Bash #2: переменные ──────────────────────────────────
|
||||||
|
utils.Section("13. Bash #2: переменные")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Переменные оболочки:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Создать переменную:
|
||||||
|
name="Alice" # без пробелов вокруг =
|
||||||
|
count=42
|
||||||
|
PATH_BACKUP=$PATH # использовать значение другой переменной
|
||||||
|
|
||||||
|
# Использовать переменную ($ перед именем):
|
||||||
|
echo $name # Alice
|
||||||
|
echo "Привет, $name!" # Привет, Alice!
|
||||||
|
echo "Привет, ${name}!" # фигурные скобки — явное обозначение
|
||||||
|
|
||||||
|
# Удалить переменную:
|
||||||
|
unset name`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Переменные окружения (Environment Variables):" + utils.ColorReset)
|
||||||
|
utils.Code(`# Переменные оболочки vs переменные окружения:
|
||||||
|
# - переменная оболочки видна только в текущем shell
|
||||||
|
# - переменная окружения (export) передаётся дочерним процессам
|
||||||
|
|
||||||
|
# Экспортировать:
|
||||||
|
export name="Alice"
|
||||||
|
export PATH="$PATH:/opt/myapp/bin"
|
||||||
|
|
||||||
|
# Или сразу:
|
||||||
|
export count=42
|
||||||
|
|
||||||
|
# Посмотреть все переменные окружения:
|
||||||
|
env
|
||||||
|
printenv
|
||||||
|
printenv PATH # конкретная переменная
|
||||||
|
echo $PATH # то же`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Важные системные переменные:" + utils.ColorReset)
|
||||||
|
utils.Code(`PATH — список директорий для поиска команд (: разделитель)
|
||||||
|
/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin
|
||||||
|
HOME — домашняя директория (~) /home/alice
|
||||||
|
USER — имя пользователя alice
|
||||||
|
LOGNAME — логин пользователя alice
|
||||||
|
SHELL — оболочка пользователя /bin/bash
|
||||||
|
TERM — тип терминала xterm-256color
|
||||||
|
LANG — язык/локаль en_US.UTF-8
|
||||||
|
LC_ALL — переопределить все локали
|
||||||
|
PWD — текущая директория /home/alice/docs
|
||||||
|
OLDPWD — предыдущая директория
|
||||||
|
PS1 — приглашение командной строки
|
||||||
|
PS2 — вторичное приглашение (>)
|
||||||
|
EDITOR — редактор по умолчанию vim
|
||||||
|
VISUAL — визуальный редактор vim
|
||||||
|
PAGER — пагинатор less
|
||||||
|
HISTSIZE — размер истории в памяти
|
||||||
|
RANDOM — случайное число 0-32767`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Специальные переменные bash:" + utils.ColorReset)
|
||||||
|
utils.Code(`$0 — имя скрипта / оболочки
|
||||||
|
$1..$9 — позиционные параметры (аргументы скрипта)
|
||||||
|
$@ — все аргументы как отдельные строки
|
||||||
|
$* — все аргументы как одна строка
|
||||||
|
$# — количество аргументов
|
||||||
|
$? — код возврата последней команды (0 = успех)
|
||||||
|
$$ — PID текущего процесса
|
||||||
|
$! — PID последнего фонового процесса
|
||||||
|
$_ — последний аргумент предыдущей команды`)
|
||||||
|
|
||||||
|
utils.Code(`# Примеры:
|
||||||
|
echo $? # 0 если последняя команда успешна
|
||||||
|
ls /nonexistent
|
||||||
|
echo $? # 2 (или другой ненулевой) — ошибка
|
||||||
|
|
||||||
|
echo $$ # PID bash
|
||||||
|
echo $RANDOM # случайное число`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Работа со строками переменных:" + utils.ColorReset)
|
||||||
|
utils.Code(`name="alice"
|
||||||
|
|
||||||
|
${name} → alice
|
||||||
|
${name^} → Alice (первая буква заглавная)
|
||||||
|
${name^^} → ALICE (все заглавные)
|
||||||
|
${name,,} → alice (все строчные)
|
||||||
|
|
||||||
|
str="hello world"
|
||||||
|
${#str} → 11 (длина строки)
|
||||||
|
${str:0:5} → hello (подстрока с 0, длиной 5)
|
||||||
|
${str:6} → world (с позиции 6 до конца)
|
||||||
|
|
||||||
|
path="/home/user/file.txt"
|
||||||
|
${path##*/} → file.txt (удалить до последнего /)
|
||||||
|
${path%/*} → /home/user (удалить от последнего /)
|
||||||
|
${path%.*} → /home/user/file (удалить расширение)
|
||||||
|
${path##*.} → txt (только расширение)
|
||||||
|
|
||||||
|
# Значения по умолчанию:
|
||||||
|
${var:-default} → default если var не задана или пустая
|
||||||
|
${var:=default} → присвоить и вернуть default если пустая
|
||||||
|
${var:?ошибка} → вывести ошибку если пустая`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Настройка ~/.bashrc и ~/.bash_profile:" + utils.ColorReset)
|
||||||
|
utils.Code(`~/.bashrc — выполняется при каждом запуске интерактивного bash
|
||||||
|
~/.bash_profile — выполняется при входе в систему (login shell)
|
||||||
|
~/.profile — POSIX-совместимый аналог .bash_profile
|
||||||
|
~/.bash_logout — выполняется при выходе
|
||||||
|
|
||||||
|
# Типичный ~/.bashrc:
|
||||||
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
export EDITOR=vim
|
||||||
|
alias ll='ls -la'
|
||||||
|
alias ..='cd ..'
|
||||||
|
|
||||||
|
# ~/.bash_profile обычно вызывает ~/.bashrc:
|
||||||
|
[[ -f ~/.bashrc ]] && . ~/.bashrc
|
||||||
|
|
||||||
|
# Применить изменения без перезапуска:
|
||||||
|
source ~/.bashrc`)
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
223
modules/linuxmodules/linux_boot.go
Normal file
223
modules/linuxmodules/linux_boot.go
Normal file
|
|
@ -0,0 +1,223 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var BootModule = Module{
|
||||||
|
Key: "boot",
|
||||||
|
Aliases: []string{"bo", "systemd", "grub", "загрузка"},
|
||||||
|
Title: "Загрузка системы и systemd",
|
||||||
|
Description: "Темы 33–35, 41: GRUB, systemd, юниты, управление сервисами",
|
||||||
|
Run: showBoot,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showBoot() {
|
||||||
|
utils.Header("Linux — Загрузка системы и systemd")
|
||||||
|
|
||||||
|
// ─── 33. GRUB ─────────────────────────────────────────────────
|
||||||
|
utils.Section("33. Загрузчик GRUB")
|
||||||
|
|
||||||
|
utils.Println("Процесс загрузки Linux:")
|
||||||
|
utils.Code(`BIOS/UEFI → MBR/GPT → GRUB → Ядро (vmlinuz) → initrd/initramfs → /sbin/init (systemd) → Сервисы → Пользователь
|
||||||
|
|
||||||
|
BIOS/UEFI — инициализация железа, поиск загрузочного устройства
|
||||||
|
MBR/GPT — первый сектор диска, указывает где GRUB
|
||||||
|
GRUB — загрузчик, выбор ядра/ОС
|
||||||
|
vmlinuz — сжатое ядро Linux
|
||||||
|
initramfs — временная корневая ФС в памяти (для монтирования /)
|
||||||
|
systemd — PID 1, запускает все сервисы`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "GRUB — конфигурация:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Основные файлы:
|
||||||
|
/boot/grub/grub.cfg — итоговая конфигурация (не редактировать!)
|
||||||
|
/etc/grub.d/ — скрипты генерации конфига
|
||||||
|
/etc/default/grub — настройки
|
||||||
|
|
||||||
|
# Редактировать настройки:
|
||||||
|
sudo nano /etc/default/grub
|
||||||
|
|
||||||
|
# Ключевые параметры /etc/default/grub:
|
||||||
|
GRUB_DEFAULT=0 # пункт меню по умолчанию (0 = первый)
|
||||||
|
GRUB_TIMEOUT=5 # таймаут выбора (сек)
|
||||||
|
GRUB_CMDLINE_LINUX="" # параметры ядра для всех записей
|
||||||
|
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" # для обычной загрузки
|
||||||
|
|
||||||
|
# Применить изменения:
|
||||||
|
sudo update-grub # Debian/Ubuntu
|
||||||
|
sudo grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL/Fedora`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "GRUB — установка и восстановление:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Установить GRUB на диск:
|
||||||
|
sudo grub-install /dev/sda # Debian/Ubuntu
|
||||||
|
sudo grub2-install /dev/sda # RHEL/Fedora
|
||||||
|
|
||||||
|
# Восстановление GRUB через LiveCD:
|
||||||
|
mount /dev/sda2 /mnt # корневой раздел
|
||||||
|
mount /dev/sda1 /mnt/boot/efi # EFI раздел (UEFI)
|
||||||
|
mount --bind /dev /mnt/dev
|
||||||
|
mount --bind /proc /mnt/proc
|
||||||
|
mount --bind /sys /mnt/sys
|
||||||
|
chroot /mnt
|
||||||
|
grub-install /dev/sda
|
||||||
|
update-grub
|
||||||
|
exit; reboot`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Параметры ядра при загрузке:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Нажать 'e' в меню GRUB для редактирования записи.
|
||||||
|
# Найти строку linux/linuxefi и добавить параметры в конец:
|
||||||
|
|
||||||
|
ro quiet splash — стандартная загрузка
|
||||||
|
rw single — однопользовательский режим (recovery)
|
||||||
|
init=/bin/bash — минимальный shell (без systemd)
|
||||||
|
nomodeset — без KMS (проблемы с видео)
|
||||||
|
rd.break — остановить в initramfs (RHEL)
|
||||||
|
systemd.unit=rescue.target — аварийный режим`)
|
||||||
|
|
||||||
|
// ─── 34. systemd ──────────────────────────────────────────────
|
||||||
|
utils.Section("34. Система инициализации — systemd")
|
||||||
|
|
||||||
|
utils.Println("systemd — PID 1. Управляет всеми сервисами, монтированием, логами.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Юниты (Units):" + utils.ColorReset)
|
||||||
|
utils.Code(`Юнит — объект управления systemd.
|
||||||
|
Типы юнитов:
|
||||||
|
.service — сервис (nginx.service, sshd.service)
|
||||||
|
.socket — сокет (активация по запросу)
|
||||||
|
.target — группа юнитов (graphical.target = GUI)
|
||||||
|
.timer — планировщик (альтернатива cron)
|
||||||
|
.mount — точка монтирования
|
||||||
|
.path — отслеживание файлов/директорий
|
||||||
|
.slice — группа процессов (управление ресурсами)
|
||||||
|
|
||||||
|
# Расположение юнитов:
|
||||||
|
/lib/systemd/system/ — системные (из пакетов)
|
||||||
|
/etc/systemd/system/ — пользовательские (переопределение)
|
||||||
|
/run/systemd/system/ — временные (runtime)`)
|
||||||
|
|
||||||
|
// ─── 35. Управление сервисами ─────────────────────────────────
|
||||||
|
utils.Section("35. Системный менеджер systemd: управление сервисами")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "systemctl — основные команды:" + utils.ColorReset)
|
||||||
|
utils.Command("systemctl status nginx", "статус сервиса")
|
||||||
|
utils.Command("systemctl start nginx", "запустить")
|
||||||
|
utils.Command("systemctl stop nginx", "остановить")
|
||||||
|
utils.Command("systemctl restart nginx", "перезапустить")
|
||||||
|
utils.Command("systemctl reload nginx", "перечитать конфигурацию")
|
||||||
|
utils.Command("systemctl enable nginx", "включить автозапуск")
|
||||||
|
utils.Command("systemctl disable nginx", "выключить автозапуск")
|
||||||
|
utils.Command("systemctl enable --now nginx", "включить и сразу запустить")
|
||||||
|
utils.Command("systemctl disable --now nginx", "выключить и остановить")
|
||||||
|
utils.Command("systemctl is-active nginx", "активен? (active/inactive)")
|
||||||
|
utils.Command("systemctl is-enabled nginx", "в автозапуске? (enabled/disabled)")
|
||||||
|
utils.Command("systemctl is-failed nginx", "завершился с ошибкой?")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Command("systemctl list-units", "список всех активных юнитов")
|
||||||
|
utils.Command("systemctl list-units --type=service", "только сервисы")
|
||||||
|
utils.Command("systemctl list-units --failed", "упавшие юниты")
|
||||||
|
utils.Command("systemctl list-unit-files", "все юниты и их состояние")
|
||||||
|
utils.Command("systemctl daemon-reload", "перечитать файлы юнитов (после изменений)")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Таргеты (targets) — уровни запуска:" + utils.ColorReset)
|
||||||
|
utils.Code(`poweroff.target — выключение (runlevel 0)
|
||||||
|
rescue.target — однопользовательский (runlevel 1)
|
||||||
|
multi-user.target — многопользовательский без GUI (runlevel 3)
|
||||||
|
graphical.target — с GUI (runlevel 5)
|
||||||
|
reboot.target — перезагрузка (runlevel 6)
|
||||||
|
|
||||||
|
# Текущий таргет:
|
||||||
|
systemctl get-default
|
||||||
|
|
||||||
|
# Изменить таргет по умолчанию:
|
||||||
|
systemctl set-default multi-user.target
|
||||||
|
|
||||||
|
# Переключиться немедленно:
|
||||||
|
systemctl isolate multi-user.target
|
||||||
|
|
||||||
|
# Выключение и перезагрузка:
|
||||||
|
systemctl poweroff
|
||||||
|
systemctl reboot
|
||||||
|
systemctl suspend
|
||||||
|
systemctl hibernate`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "journalctl — просмотр логов systemd:" + utils.ColorReset)
|
||||||
|
utils.Command("journalctl", "все логи")
|
||||||
|
utils.Command("journalctl -u nginx", "логи конкретного сервиса")
|
||||||
|
utils.Command("journalctl -f", "следить в реальном времени")
|
||||||
|
utils.Command("journalctl -f -u nginx", "следить за nginx")
|
||||||
|
utils.Command("journalctl -n 50", "последние 50 строк")
|
||||||
|
utils.Command("journalctl --since '2024-01-15 10:00'", "с определённого времени")
|
||||||
|
utils.Command("journalctl --since '1 hour ago'", "за последний час")
|
||||||
|
utils.Command("journalctl -p err", "только ошибки (emerg alert crit err warning notice info debug)")
|
||||||
|
utils.Command("journalctl -b", "с момента последней загрузки")
|
||||||
|
utils.Command("journalctl -b -1", "предыдущая загрузка")
|
||||||
|
utils.Command("journalctl --disk-usage", "объём логов на диске")
|
||||||
|
utils.Command("journalctl --vacuum-size=100M", "оставить только 100МБ логов")
|
||||||
|
|
||||||
|
// ─── 41. Systemd юниты ────────────────────────────────────────
|
||||||
|
utils.Section("41. Создание systemd юнитов")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Структура .service файла:" + utils.ColorReset)
|
||||||
|
utils.Code(`# /etc/systemd/system/myapp.service
|
||||||
|
[Unit]
|
||||||
|
Description=My Application
|
||||||
|
Documentation=https://example.com
|
||||||
|
After=network.target # запустить после сети
|
||||||
|
Requires=postgresql.service # обязательная зависимость
|
||||||
|
Wants=redis.service # желательная зависимость
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple # forking, oneshot, notify, idle
|
||||||
|
User=myapp # от какого пользователя
|
||||||
|
Group=myapp
|
||||||
|
WorkingDirectory=/opt/myapp
|
||||||
|
ExecStart=/opt/myapp/bin/myapp --config /etc/myapp.conf
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
Restart=on-failure # always, on-failure, on-abnormal
|
||||||
|
RestartSec=5
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
Environment=NODE_ENV=production
|
||||||
|
EnvironmentFile=/etc/myapp/env
|
||||||
|
|
||||||
|
# Ограничения:
|
||||||
|
MemoryMax=512M
|
||||||
|
CPUQuota=50%
|
||||||
|
LimitNOFILE=65536
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target`)
|
||||||
|
|
||||||
|
utils.Code(`# Применить новый юнит:
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now myapp
|
||||||
|
|
||||||
|
# Переопределить параметры (без редактирования оригинала):
|
||||||
|
sudo systemctl edit nginx # создаёт /etc/systemd/system/nginx.service.d/override.conf`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Timer юнит (альтернатива cron):" + utils.ColorReset)
|
||||||
|
utils.Code(`# /etc/systemd/system/backup.timer
|
||||||
|
[Unit]
|
||||||
|
Description=Ежедневный бэкап
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=*-*-* 02:00:00 # каждый день в 02:00
|
||||||
|
OnCalendar=Mon *-*-* 03:00 # каждый понедельник в 03:00
|
||||||
|
OnBootSec=15min # через 15 мин после загрузки
|
||||||
|
OnUnitActiveSec=1h # каждый час после последнего запуска
|
||||||
|
Persistent=true # запустить если пропустили время
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
|
||||||
|
# /etc/systemd/system/backup.service
|
||||||
|
[Unit]
|
||||||
|
Description=Скрипт бэкапа
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/local/bin/backup.sh`)
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
211
modules/linuxmodules/linux_disks.go
Normal file
211
modules/linuxmodules/linux_disks.go
Normal file
|
|
@ -0,0 +1,211 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var DisksModule = Module{
|
||||||
|
Key: "disks",
|
||||||
|
Aliases: []string{"d", "lvm", "raid", "диски"},
|
||||||
|
Title: "Диски, файловые системы, LVM и RAID",
|
||||||
|
Description: "Темы 22–26: разделы, mount, LVM, программный RAID",
|
||||||
|
Run: showDisks,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showDisks() {
|
||||||
|
utils.Header("Linux — Диски, файловые системы, LVM и RAID")
|
||||||
|
|
||||||
|
// ─── 22. Работа с дисками ─────────────────────────────────────
|
||||||
|
utils.Section("22. Работа с дисками и разделами")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Именование устройств:" + utils.ColorReset)
|
||||||
|
utils.Code(`/dev/sda — первый SATA/SCSI диск
|
||||||
|
/dev/sdb — второй диск
|
||||||
|
/dev/sda1 — первый раздел первого диска
|
||||||
|
/dev/sda2 — второй раздел первого диска
|
||||||
|
/dev/nvme0n1 — первый NVMe диск
|
||||||
|
/dev/nvme0n1p1 — первый раздел NVMe диска
|
||||||
|
/dev/vda — виртуальный диск (KVM/QEMU)
|
||||||
|
/dev/xvda — диск Xen
|
||||||
|
/dev/loop0 — loop-устройство (ISO-образ)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Просмотр дисков и разделов:" + utils.ColorReset)
|
||||||
|
utils.Command("lsblk", "дерево блочных устройств")
|
||||||
|
utils.Command("lsblk -f", "с типом ФС и UUID")
|
||||||
|
utils.Command("lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE", "выбрать столбцы")
|
||||||
|
utils.Command("fdisk -l", "все диски и разделы (root)")
|
||||||
|
utils.Command("fdisk -l /dev/sda", "разделы диска sda")
|
||||||
|
utils.Command("parted -l", "таблицы разделов (GPT и MBR)")
|
||||||
|
utils.Command("blkid", "UUID и типы ФС всех устройств")
|
||||||
|
utils.Command("blkid /dev/sda1", "UUID конкретного раздела")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Разбивка диска (fdisk):" + utils.ColorReset)
|
||||||
|
utils.Code(`sudo fdisk /dev/sdb # интерактивная работа с разделами
|
||||||
|
|
||||||
|
Команды fdisk:
|
||||||
|
p — показать таблицу разделов
|
||||||
|
n — новый раздел
|
||||||
|
d — удалить раздел
|
||||||
|
t — изменить тип раздела
|
||||||
|
l — список типов разделов
|
||||||
|
w — записать изменения (опасно!)
|
||||||
|
q — выйти без сохранения
|
||||||
|
|
||||||
|
# Для GPT-дисков и дисков > 2ТБ — используйте parted или gdisk`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Создание файловой системы (mkfs):" + utils.ColorReset)
|
||||||
|
utils.Command("mkfs.ext4 /dev/sdb1", "создать ext4")
|
||||||
|
utils.Command("mkfs.xfs /dev/sdb1", "создать xfs")
|
||||||
|
utils.Command("mkfs.ext4 -L data /dev/sdb1", "с меткой 'data'")
|
||||||
|
utils.Command("mkswap /dev/sdb2", "создать swap")
|
||||||
|
utils.Command("swapon /dev/sdb2", "активировать swap")
|
||||||
|
utils.Command("swapon -s", "показать активные swap")
|
||||||
|
utils.Command("swapoff /dev/sdb2", "отключить swap")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Проверка и восстановление ФС:" + utils.ColorReset)
|
||||||
|
utils.Command("fsck /dev/sdb1", "проверить ФС (только при размонтированной!)")
|
||||||
|
utils.Command("fsck -n /dev/sdb1", "только проверить, не исправлять")
|
||||||
|
utils.Command("e2fsck -f /dev/sdb1", "принудительная проверка ext2/3/4")
|
||||||
|
utils.Command("xfs_repair /dev/sdb1", "восстановление XFS")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Использование диска:" + utils.ColorReset)
|
||||||
|
utils.Command("df -h", "занятое и свободное место на ФС")
|
||||||
|
utils.Command("df -hT", "с типом ФС")
|
||||||
|
utils.Command("du -sh /var/log", "размер директории")
|
||||||
|
utils.Command("du -sh /*", "размер каждой директории в корне")
|
||||||
|
utils.Command("du -sh * | sort -h", "отсортировать по размеру")
|
||||||
|
utils.Command("ncdu /var", "интерактивный анализ (нужно установить)")
|
||||||
|
|
||||||
|
// ─── 23–24. Файловые системы и монтирование ───────────────────
|
||||||
|
utils.Section("23–24. Файловые системы и монтирование")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "mount — монтирование:" + utils.ColorReset)
|
||||||
|
utils.Command("mount", "список всех смонтированных ФС")
|
||||||
|
utils.Command("mount /dev/sdb1 /mnt/data", "монтировать раздел")
|
||||||
|
utils.Command("mount -t ext4 /dev/sdb1 /mnt", "указать тип ФС")
|
||||||
|
utils.Command("mount -o ro /dev/sdb1 /mnt", "только чтение")
|
||||||
|
utils.Command("mount -o remount,rw /", "перемонтировать с правами записи")
|
||||||
|
utils.Command("mount UUID=abc123 /mnt/data", "монтировать по UUID")
|
||||||
|
utils.Command("mount -a", "смонтировать всё из /etc/fstab")
|
||||||
|
utils.Command("umount /mnt/data", "размонтировать")
|
||||||
|
utils.Command("umount -l /mnt/data", "ленивое размонтирование (когда занято)")
|
||||||
|
utils.Command("lsof /mnt/data", "кто использует раздел (если umount отказывает)")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "/etc/fstab — автомонтирование при старте:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Формат: устройство точка_монтирования тип опции dump fsck
|
||||||
|
UUID=abc123 /mnt/data ext4 defaults 0 2
|
||||||
|
/dev/sdb1 /mnt/data xfs defaults 0 0
|
||||||
|
//server/share /mnt/smb cifs credentials=/etc/samba.creds 0 0
|
||||||
|
tmpfs /tmp tmpfs defaults,size=2G 0 0
|
||||||
|
|
||||||
|
# Опции монтирования:
|
||||||
|
defaults — rw, suid, exec, auto, nouser, async
|
||||||
|
ro — только чтение
|
||||||
|
rw — чтение и запись
|
||||||
|
noexec — запрет запуска файлов
|
||||||
|
nosuid — игнорировать SUID/SGID биты
|
||||||
|
noatime — не обновлять atime (быстрее)
|
||||||
|
auto — монтировать при mount -a
|
||||||
|
noauto — не монтировать автоматически
|
||||||
|
|
||||||
|
# Столбцы dump и fsck:
|
||||||
|
# dump: 0 = не бэкапить, 1 = бэкапить
|
||||||
|
# fsck: 0 = не проверять, 1 = / (первый), 2 = остальные`)
|
||||||
|
|
||||||
|
utils.Note("Всегда используйте UUID вместо /dev/sdb1 в fstab — имена устройств могут меняться после перезагрузки.")
|
||||||
|
|
||||||
|
// ─── 25. LVM ──────────────────────────────────────────────────
|
||||||
|
utils.Section("25. Управление логическими томами — LVM")
|
||||||
|
|
||||||
|
utils.Println("LVM позволяет гибко управлять дисковым пространством:")
|
||||||
|
utils.Println("объединять несколько дисков, изменять размер томов без перезагрузки.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`Структура LVM:
|
||||||
|
PV (Physical Volume) — физический диск или раздел (/dev/sdb)
|
||||||
|
VG (Volume Group) — группа PV, единый пул пространства
|
||||||
|
LV (Logical Volume) — логический том из VG (аналог раздела)
|
||||||
|
|
||||||
|
PV: /dev/sdb /dev/sdc
|
||||||
|
↓ ↓
|
||||||
|
VG: vg_data (объединённое пространство)
|
||||||
|
↓
|
||||||
|
LV: /dev/vg_data/lv_web /dev/vg_data/lv_db`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Создание LVM:" + utils.ColorReset)
|
||||||
|
utils.Code(`# 1. Создать Physical Volume:
|
||||||
|
pvcreate /dev/sdb /dev/sdc
|
||||||
|
pvs # показать PV
|
||||||
|
pvdisplay # подробно
|
||||||
|
|
||||||
|
# 2. Создать Volume Group:
|
||||||
|
vgcreate vg_data /dev/sdb /dev/sdc
|
||||||
|
vgs # показать VG
|
||||||
|
vgdisplay vg_data
|
||||||
|
|
||||||
|
# 3. Создать Logical Volume:
|
||||||
|
lvcreate -L 20G -n lv_web vg_data # 20 ГБ
|
||||||
|
lvcreate -l 100%FREE -n lv_db vg_data # всё свободное
|
||||||
|
lvs # показать LV
|
||||||
|
lvdisplay /dev/vg_data/lv_web
|
||||||
|
|
||||||
|
# 4. Создать ФС и смонтировать:
|
||||||
|
mkfs.ext4 /dev/vg_data/lv_web
|
||||||
|
mount /dev/vg_data/lv_web /var/www`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Расширение LV:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Расширить LV на 10 ГБ:
|
||||||
|
lvextend -L +10G /dev/vg_data/lv_web
|
||||||
|
|
||||||
|
# Расширить ФС (ext4):
|
||||||
|
resize2fs /dev/vg_data/lv_web
|
||||||
|
|
||||||
|
# Одной командой (ext4):
|
||||||
|
lvextend -L +10G -r /dev/vg_data/lv_web # -r = resize ФС
|
||||||
|
|
||||||
|
# Для XFS (только увеличение):
|
||||||
|
xfs_growfs /var/www`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Добавить диск в VG:" + utils.ColorReset)
|
||||||
|
utils.Code(`pvcreate /dev/sdd
|
||||||
|
vgextend vg_data /dev/sdd`)
|
||||||
|
|
||||||
|
// ─── 26. Программный RAID ─────────────────────────────────────
|
||||||
|
utils.Section("26. Программный RAID — MD (mdadm)")
|
||||||
|
|
||||||
|
utils.Println("RAID — избыточный массив для надёжности и/или производительности.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`Уровни RAID:
|
||||||
|
RAID 0 — страйпинг (производительность), без избыточности
|
||||||
|
RAID 1 — зеркало (надёжность), нужно 2 диска, использует 50%
|
||||||
|
RAID 5 — страйп + чётность, нужно 3+ дисков, теряем 1 диск
|
||||||
|
RAID 6 — двойная чётность, нужно 4+ дисков, теряем 2 диска
|
||||||
|
RAID 10 — зеркало + страйп, нужно 4 диска, теряем до N/2`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "mdadm — управление программным RAID:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Создать RAID 1 из двух дисков:
|
||||||
|
mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb /dev/sdc
|
||||||
|
|
||||||
|
# Создать RAID 5:
|
||||||
|
mdadm --create /dev/md0 --level=5 --raid-devices=3 \
|
||||||
|
/dev/sdb /dev/sdc /dev/sdd
|
||||||
|
|
||||||
|
# Состояние массива:
|
||||||
|
cat /proc/mdstat # текущее состояние
|
||||||
|
mdadm --detail /dev/md0 # подробная информация
|
||||||
|
|
||||||
|
# Сохранить конфигурацию:
|
||||||
|
mdadm --detail --scan >> /etc/mdadm/mdadm.conf
|
||||||
|
|
||||||
|
# Добавить запасной диск:
|
||||||
|
mdadm /dev/md0 --add /dev/sde
|
||||||
|
|
||||||
|
# Удалить диск из массива:
|
||||||
|
mdadm /dev/md0 --fail /dev/sdb
|
||||||
|
mdadm /dev/md0 --remove /dev/sdb
|
||||||
|
|
||||||
|
# Остановить массив:
|
||||||
|
mdadm --stop /dev/md0`)
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
266
modules/linuxmodules/linux_files.go
Normal file
266
modules/linuxmodules/linux_files.go
Normal file
|
|
@ -0,0 +1,266 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var FilesModule = Module{
|
||||||
|
Key: "files",
|
||||||
|
Aliases: []string{"f", "dirs", "файлы"},
|
||||||
|
Title: "Файлы и директории",
|
||||||
|
Description: "Темы 06–10: пути, cp/mv/rm, ссылки, чтение файлов, nano и vi",
|
||||||
|
Run: showFiles,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showFiles() {
|
||||||
|
utils.Header("Linux — Файлы и директории")
|
||||||
|
|
||||||
|
// ─── 06. Пути и директории ────────────────────────────────────
|
||||||
|
utils.Section("06. Пути и директории")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Абсолютный и относительный пути:" + utils.ColorReset)
|
||||||
|
utils.Code(`Абсолютный: начинается с /
|
||||||
|
/home/user/documents/file.txt
|
||||||
|
|
||||||
|
Относительный: относительно текущей директории
|
||||||
|
documents/file.txt (из /home/user)
|
||||||
|
../другой/файл (.. — родительская директория)
|
||||||
|
./скрипт.sh (. — текущая директория)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Специальные обозначения:" + utils.ColorReset)
|
||||||
|
utils.Code(`. — текущая директория
|
||||||
|
.. — родительская директория
|
||||||
|
~ — домашняя директория текущего пользователя
|
||||||
|
~/ — то же самое, используется в путях: ~/docs
|
||||||
|
- — предыдущая директория (cd -)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Навигация:" + utils.ColorReset)
|
||||||
|
utils.Command("pwd", "показать текущую директорию (Print Working Directory)")
|
||||||
|
utils.Command("cd /etc", "перейти в /etc (абсолютный путь)")
|
||||||
|
utils.Command("cd docs", "перейти в docs (относительный)")
|
||||||
|
utils.Command("cd ..", "перейти в родительскую директорию")
|
||||||
|
utils.Command("cd ~", "перейти домой")
|
||||||
|
utils.Command("cd -", "вернуться в предыдущую директорию")
|
||||||
|
utils.Command("cd", "то же что cd ~")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Просмотр содержимого:" + utils.ColorReset)
|
||||||
|
utils.Command("ls", "список файлов текущей директории")
|
||||||
|
utils.Command("ls -l", "длинный формат (права, владелец, размер, дата)")
|
||||||
|
utils.Command("ls -a", "все файлы включая скрытые (начинаются с .)")
|
||||||
|
utils.Command("ls -la", "длинный формат + скрытые")
|
||||||
|
utils.Command("ls -lh", "размер в читаемом виде (K, M, G)")
|
||||||
|
utils.Command("ls -lt", "сортировка по времени (новые сверху)")
|
||||||
|
utils.Command("ls -ltr", "по времени в обратном порядке")
|
||||||
|
utils.Command("ls -R", "рекурсивно (все вложенные)")
|
||||||
|
utils.Command("ls /etc/*.conf", "glob-паттерн: все .conf в /etc")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`# Пример вывода ls -l:
|
||||||
|
drwxr-xr-x 2 alice users 4096 Jan 15 10:30 docs
|
||||||
|
-rw-r--r-- 1 alice users 512 Jan 14 09:00 file.txt
|
||||||
|
lrwxrwxrwx 1 alice users 7 Jan 13 12:00 link -> file.txt
|
||||||
|
│ │ │ │ │ │ │
|
||||||
|
│ │ │ │ │ │ └ имя файла
|
||||||
|
│ │ │ │ │ └ дата изменения
|
||||||
|
│ │ │ │ └ размер (байты)
|
||||||
|
│ │ │ └ группа
|
||||||
|
│ │ └ владелец
|
||||||
|
│ └ количество жёстких ссылок
|
||||||
|
└ тип и права доступа`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Создание директорий:" + utils.ColorReset)
|
||||||
|
utils.Command("mkdir mydir", "создать директорию")
|
||||||
|
utils.Command("mkdir -p a/b/c", "создать вложенные директории")
|
||||||
|
utils.Command("mkdir -p project/{src,docs,tests}", "создать несколько сразу")
|
||||||
|
utils.Command("rmdir mydir", "удалить пустую директорию")
|
||||||
|
|
||||||
|
// ─── 07. Создание и копирование файлов ───────────────────────
|
||||||
|
utils.Section("07. Создание и копирование файлов")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Создание файлов:" + utils.ColorReset)
|
||||||
|
utils.Command("touch file.txt", "создать пустой файл / обновить время доступа")
|
||||||
|
utils.Command("touch file{1..5}.txt", "создать file1.txt … file5.txt")
|
||||||
|
utils.Command("> file.txt", "создать пустой файл / очистить существующий")
|
||||||
|
utils.Command("echo 'текст' > file.txt", "записать текст в файл")
|
||||||
|
utils.Command("echo 'текст' >> file.txt", "добавить текст в конец файла")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Копирование (cp):" + utils.ColorReset)
|
||||||
|
utils.Command("cp src dst", "скопировать файл")
|
||||||
|
utils.Command("cp -r src/ dst/", "скопировать директорию рекурсивно")
|
||||||
|
utils.Command("cp -v src dst", "показать что копируется (-v = verbose)")
|
||||||
|
utils.Command("cp -i src dst", "спросить при перезаписи (-i = interactive)")
|
||||||
|
utils.Command("cp -p src dst", "сохранить права/метаданные (-p = preserve)")
|
||||||
|
utils.Command("cp -a src/ dst/", "архивный режим: -r + -p + символические ссылки")
|
||||||
|
utils.Command("cp *.txt /tmp/", "копировать все .txt в /tmp")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Note("cp -r не сохраняет права и время по умолчанию. Для резервного копирования используйте cp -a.")
|
||||||
|
|
||||||
|
// ─── 08. Перемещение, удаление, ссылки ───────────────────────
|
||||||
|
utils.Section("08. Перемещение, переименование, удаление. Ссылки")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Перемещение и переименование (mv):" + utils.ColorReset)
|
||||||
|
utils.Command("mv old.txt new.txt", "переименовать файл")
|
||||||
|
utils.Command("mv file.txt /tmp/", "переместить в /tmp")
|
||||||
|
utils.Command("mv -v src dst", "подробный вывод")
|
||||||
|
utils.Command("mv -i src dst", "спросить при перезаписи")
|
||||||
|
utils.Command("mv -n src dst", "не перезаписывать существующий")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Удаление (rm):" + utils.ColorReset)
|
||||||
|
utils.Command("rm file.txt", "удалить файл")
|
||||||
|
utils.Command("rm -r dir/", "удалить директорию рекурсивно")
|
||||||
|
utils.Command("rm -rf dir/", "принудительно, без подтверждений")
|
||||||
|
utils.Command("rm -i file.txt", "спросить перед удалением")
|
||||||
|
utils.Command("rm -v file.txt", "показать что удаляется")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Note("rm -rf удаляет безвозвратно. Нет корзины. Будьте внимательны!")
|
||||||
|
utils.Code(`# Защита: никогда не делайте:
|
||||||
|
rm -rf / # удалит всю систему
|
||||||
|
rm -rf ./ # удалит текущую директорию
|
||||||
|
|
||||||
|
# Безопаснее: перенести в /tmp, потом удалить
|
||||||
|
mv dangerous_dir /tmp/ && rm -rf /tmp/dangerous_dir`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Жёсткие ссылки (hard links):" + utils.ColorReset)
|
||||||
|
utils.Code(`Жёсткая ссылка — ещё одно имя для того же inode.
|
||||||
|
|
||||||
|
ln file.txt hardlink.txt # создать жёсткую ссылку
|
||||||
|
|
||||||
|
Особенности:
|
||||||
|
- указывает на те же данные на диске
|
||||||
|
- не отличить от оригинала командой ls
|
||||||
|
- удаление одного имени не удаляет данные
|
||||||
|
(данные удаляются когда счётчик ссылок = 0)
|
||||||
|
- нельзя создать на директорию
|
||||||
|
- нельзя создать на другой раздел/диске`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Символические ссылки (soft links / symlinks):" + utils.ColorReset)
|
||||||
|
utils.Code(`Символическая ссылка — файл, содержащий путь к цели.
|
||||||
|
|
||||||
|
ln -s /etc/nginx/nginx.conf nginx.conf # создать симлинк
|
||||||
|
ln -s /path/to/dir mylink # симлинк на директорию
|
||||||
|
ls -la nginx.conf
|
||||||
|
# lrwxrwxrwx 1 user group 20 Jan nginx.conf -> /etc/nginx/nginx.conf
|
||||||
|
|
||||||
|
Особенности:
|
||||||
|
- показывается как l в ls -la
|
||||||
|
- может указывать на директории
|
||||||
|
- может быть "битым" (цель удалена)
|
||||||
|
- можно создать между разными разделами
|
||||||
|
- readlink nginx.conf — показать куда указывает`)
|
||||||
|
|
||||||
|
utils.Command("stat file.txt", "показать подробную информацию о файле (inode, ссылки)")
|
||||||
|
utils.Command("ls -i file.txt", "показать номер inode")
|
||||||
|
|
||||||
|
// ─── 09. Чтение текстовых файлов ─────────────────────────────
|
||||||
|
utils.Section("09. Чтение текстовых файлов")
|
||||||
|
|
||||||
|
utils.Command("cat file.txt", "вывести весь файл")
|
||||||
|
utils.Command("cat -n file.txt", "с номерами строк")
|
||||||
|
utils.Command("cat -A file.txt", "показать спецсимволы ($ в конце строк)")
|
||||||
|
utils.Command("cat f1 f2 > merged", "объединить файлы")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Command("less file.txt", "постраничный просмотр (рекомендуется для больших файлов)")
|
||||||
|
utils.Command("more file.txt", "постраничный просмотр (только вперёд)")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`Навигация в less:
|
||||||
|
Space / PgDn — следующая страница
|
||||||
|
b / PgUp — предыдущая страница
|
||||||
|
g / G — начало / конец файла
|
||||||
|
/паттерн — поиск вперёд
|
||||||
|
?паттерн — поиск назад
|
||||||
|
n / N — следующее / предыдущее совпадение
|
||||||
|
q — выход`)
|
||||||
|
|
||||||
|
utils.Command("head file.txt", "первые 10 строк")
|
||||||
|
utils.Command("head -n 20 file.txt", "первые 20 строк")
|
||||||
|
utils.Command("head -c 100 file.txt", "первые 100 байт")
|
||||||
|
utils.Command("tail file.txt", "последние 10 строк")
|
||||||
|
utils.Command("tail -n 30 file.txt", "последние 30 строк")
|
||||||
|
utils.Command("tail -f /var/log/syslog", "следить за файлом в реальном времени")
|
||||||
|
utils.Command("tail -F /var/log/nginx/access.log", "следить, даже если файл пересоздаётся")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Command("grep 'текст' file.txt", "поиск строк содержащих 'текст'")
|
||||||
|
utils.Command("grep -i 'TEXT' file.txt", "без учёта регистра")
|
||||||
|
utils.Command("grep -r 'текст' /etc/", "рекурсивный поиск в директории")
|
||||||
|
utils.Command("grep -n 'текст' file.txt", "с номерами строк")
|
||||||
|
utils.Command("grep -v 'текст' file.txt", "строки НЕ содержащие 'текст'")
|
||||||
|
utils.Command("grep -c 'текст' file.txt", "количество совпадений")
|
||||||
|
utils.Command("grep -l 'текст' *.conf", "только имена файлов с совпадениями")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Command("wc file.txt", "количество строк, слов, байт")
|
||||||
|
utils.Command("wc -l file.txt", "только строки")
|
||||||
|
utils.Command("wc -w file.txt", "только слова")
|
||||||
|
utils.Command("sort file.txt", "сортировать строки")
|
||||||
|
utils.Command("sort -r file.txt", "в обратном порядке")
|
||||||
|
utils.Command("sort -n file.txt", "числовая сортировка")
|
||||||
|
utils.Command("sort -u file.txt", "убрать дубли (unique)")
|
||||||
|
utils.Command("uniq file.txt", "убрать соседние одинаковые строки")
|
||||||
|
utils.Command("cut -d: -f1 /etc/passwd", "вырезать первое поле (разделитель :)")
|
||||||
|
utils.Command("cut -d, -f2,4 data.csv", "поля 2 и 4 из CSV")
|
||||||
|
utils.Command("tr 'a-z' 'A-Z' < file.txt", "заменить символы (нижний → верхний регистр)")
|
||||||
|
utils.Command("diff file1 file2", "сравнить два файла")
|
||||||
|
utils.Command("diff -u file1 file2", "unified-формат (как git diff)")
|
||||||
|
|
||||||
|
// ─── 10. Текстовые редакторы ──────────────────────────────────
|
||||||
|
utils.Section("10. Текстовые редакторы: nano и vi/vim")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "nano — простой редактор:" + utils.ColorReset)
|
||||||
|
utils.Command("nano file.txt", "открыть файл в nano")
|
||||||
|
utils.Code(`Основные сочетания клавиш в nano:
|
||||||
|
Ctrl+O — сохранить (Write Out)
|
||||||
|
Ctrl+X — выйти
|
||||||
|
Ctrl+K — вырезать строку
|
||||||
|
Ctrl+U — вставить
|
||||||
|
Ctrl+W — поиск
|
||||||
|
Ctrl+\ — замена
|
||||||
|
Ctrl+G — справка
|
||||||
|
Alt+U — отменить (undo)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "vi / vim — мощный редактор:" + utils.ColorReset)
|
||||||
|
utils.Command("vi file.txt", "открыть в vi")
|
||||||
|
utils.Command("vim file.txt", "открыть в vim (улучшенный vi)")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`Режимы vim:
|
||||||
|
Нормальный (Normal) — навигация, команды. По умолчанию.
|
||||||
|
Вставки (Insert) — ввод текста. Нажать i.
|
||||||
|
Командный (Command) — команды (:). Нажать :
|
||||||
|
Визуальный (Visual) — выделение. Нажать v.
|
||||||
|
|
||||||
|
Переключение:
|
||||||
|
i — режим вставки перед курсором
|
||||||
|
a — режим вставки после курсора
|
||||||
|
o — новая строка ниже, режим вставки
|
||||||
|
O — новая строка выше, режим вставки
|
||||||
|
Esc — вернуться в нормальный режим`)
|
||||||
|
|
||||||
|
utils.Code(`Навигация (нормальный режим):
|
||||||
|
h j k l — ← ↓ ↑ →
|
||||||
|
w / b — следующее / предыдущее слово
|
||||||
|
0 / $ — начало / конец строки
|
||||||
|
gg / G — начало / конец файла
|
||||||
|
:n — перейти на строку n
|
||||||
|
Ctrl+F/B — вперёд / назад на страницу
|
||||||
|
|
||||||
|
Редактирование:
|
||||||
|
dd — удалить строку
|
||||||
|
yy — скопировать строку (yank)
|
||||||
|
p — вставить после курсора
|
||||||
|
P — вставить перед курсором
|
||||||
|
u — отменить (undo)
|
||||||
|
Ctrl+R — повторить (redo)
|
||||||
|
/текст — поиск вперёд
|
||||||
|
n / N — следующее / предыдущее совпадение
|
||||||
|
:%s/old/new/g — заменить все вхождения
|
||||||
|
|
||||||
|
Сохранение и выход:
|
||||||
|
:w — сохранить
|
||||||
|
:q — выйти
|
||||||
|
:wq или ZZ — сохранить и выйти
|
||||||
|
:q! — выйти без сохранения
|
||||||
|
:wq! — принудительно сохранить и выйти`)
|
||||||
|
|
||||||
|
utils.Note("Если застряли в vi — нажмите Esc несколько раз, затем :q! для выхода без сохранения.")
|
||||||
|
utils.Note("vimtutor — встроенный интерактивный учебник по vim (30 мин). Запустите в терминале.")
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
161
modules/linuxmodules/linux_intro.go
Normal file
161
modules/linuxmodules/linux_intro.go
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var IntroModule = Module{
|
||||||
|
Key: "intro",
|
||||||
|
Aliases: []string{"i", "os", "начало"},
|
||||||
|
Title: "Введение. ОС и GNU/Linux",
|
||||||
|
Description: "Темы 01, 04, 05: операционные системы, файловые системы, терминал",
|
||||||
|
Run: showIntro,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showIntro() {
|
||||||
|
utils.Header("Linux — Введение. ОС и GNU/Linux")
|
||||||
|
|
||||||
|
// ─── 01. Операционные системы и GNU/Linux ─────────────────────
|
||||||
|
utils.Section("01. Операционные системы и GNU/Linux")
|
||||||
|
|
||||||
|
utils.Println("Операционная система (ОС) — программа, управляющая аппаратурой и")
|
||||||
|
utils.Println("предоставляющая среду для работы прикладных программ.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Ключевые понятия:" + utils.ColorReset)
|
||||||
|
utils.Code(`Ядро (kernel) — центральная часть ОС, управляет памятью,
|
||||||
|
процессами, устройствами.
|
||||||
|
Userspace — пространство пользователя, где работают
|
||||||
|
обычные программы.
|
||||||
|
Дистрибутив — ядро Linux + набор программ + система управления
|
||||||
|
пакетами (Debian, Ubuntu, RHEL, Fedora, Arch...).`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "История:" + utils.ColorReset)
|
||||||
|
utils.Code(`1969 — AT&T Bell Labs: UNIX (Ричи, Томпсон)
|
||||||
|
1983 — Ричард Столлман: проект GNU (свободное ПО)
|
||||||
|
1991 — Линус Торвальдс: ядро Linux (v0.01)
|
||||||
|
= GNU/Linux: ядро Linux + утилиты GNU
|
||||||
|
POSIX — стандарт совместимости UNIX-подобных систем`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "GNU/Linux vs другие ОС:" + utils.ColorReset)
|
||||||
|
utils.Code(`Linux Windows macOS
|
||||||
|
─────────────────────────────────────────────
|
||||||
|
Открытый код Закрытый Частично открытый
|
||||||
|
Бесплатно Платный Платный (только на Mac)
|
||||||
|
Пакетный менеджер Магазин/exe App Store/Homebrew
|
||||||
|
Множество дистро Одна система Одна система
|
||||||
|
Сильный CLI GUI-ориентирован CLI через zsh/bash`)
|
||||||
|
|
||||||
|
utils.Note("Серверы: >90% работают на Linux. Android — ядро Linux. Суперкомпьютеры: 100% Linux.")
|
||||||
|
utils.Note("RHEL (Red Hat Enterprise Linux) — коммерческий дистрибутив; RHCSA — его сертификация.")
|
||||||
|
|
||||||
|
// ─── 04. О файловых системах ──────────────────────────────────
|
||||||
|
utils.Section("04. О файловых системах")
|
||||||
|
|
||||||
|
utils.Println("Файловая система (ФС) — способ организации хранения данных на диске.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Популярные файловые системы Linux:" + utils.ColorReset)
|
||||||
|
utils.Code(`ext4 — стандарт для большинства дистрибутивов,
|
||||||
|
журналирование, поддержка файлов до 16 ТБ
|
||||||
|
xfs — высокая производительность, RHEL по умолчанию,
|
||||||
|
хорошо для больших файлов
|
||||||
|
btrfs — Copy-on-Write, снапшоты, сжатие
|
||||||
|
vfat — совместимость с Windows (флешки, EFI-раздел)
|
||||||
|
ntfs — чтение/запись Windows-разделов (ntfs-3g)
|
||||||
|
tmpfs — виртуальная ФС в оперативной памяти (/tmp, /run)
|
||||||
|
proc — виртуальная ФС, информация о процессах (/proc)
|
||||||
|
sysfs — виртуальная ФС, информация об устройствах (/sys)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Структура файловой системы Linux (FHS):" + utils.ColorReset)
|
||||||
|
utils.Code(`/ — корень, начало всего дерева
|
||||||
|
├── bin/ — основные бинарные файлы (ls, cp, mv...)
|
||||||
|
├── sbin/ — системные бинарники (root: fdisk, mount...)
|
||||||
|
├── etc/ — конфигурационные файлы
|
||||||
|
├── home/ — домашние директории пользователей
|
||||||
|
├── root/ — домашняя директория root
|
||||||
|
├── var/ — изменяемые данные (логи, кэш, БД)
|
||||||
|
├── tmp/ — временные файлы (очищается при перезагрузке)
|
||||||
|
├── usr/ — пользовательские программы и данные
|
||||||
|
│ ├── bin/ — программы пользователя
|
||||||
|
│ ├── lib/ — библиотеки
|
||||||
|
│ └── share/ — разделяемые данные
|
||||||
|
├── lib/ — системные библиотеки
|
||||||
|
├── dev/ — файлы устройств (sda, tty, null...)
|
||||||
|
├── proc/ — виртуальная ФС: инфо о процессах и ядре
|
||||||
|
├── sys/ — виртуальная ФС: инфо об устройствах
|
||||||
|
├── run/ — данные запущенных процессов (PID-файлы)
|
||||||
|
├── boot/ — загрузчик, ядро (vmlinuz, initrd)
|
||||||
|
├── mnt/ — точки монтирования (временные)
|
||||||
|
└── media/ — автомонтирование съёмных носителей`)
|
||||||
|
|
||||||
|
utils.Note("В Linux всё — файл: устройства, сокеты, каналы, процессы.")
|
||||||
|
utils.Note("Нет буквы диска (C:, D:). Всё монтируется в единое дерево с корнем /")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Типы файлов:" + utils.ColorReset)
|
||||||
|
utils.Code(`- обычный файл (ls показывает -)
|
||||||
|
d директория (ls показывает d)
|
||||||
|
l символическая ссылка (ls показывает l)
|
||||||
|
b блочное устройство (/dev/sda)
|
||||||
|
c символьное устройство (/dev/tty)
|
||||||
|
p именованный канал (FIFO)
|
||||||
|
s сокет`)
|
||||||
|
|
||||||
|
// ─── 05. Текстовый интерфейс пользователя ────────────────────
|
||||||
|
utils.Section("05. Текстовый интерфейс пользователя (CLI)")
|
||||||
|
|
||||||
|
utils.Println("Shell (оболочка) — интерпретатор команд между пользователем и ядром.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Оболочки:" + utils.ColorReset)
|
||||||
|
utils.Code(`bash — Bourne Again Shell, стандарт в большинстве дистро
|
||||||
|
zsh — расширенный bash, Oh My Zsh, популярен у разработчиков
|
||||||
|
sh — POSIX sh (минималистичный, для скриптов)
|
||||||
|
fish — дружелюбный, автодополнение из коробки`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Приглашение командной строки (prompt):" + utils.ColorReset)
|
||||||
|
utils.Code(`user@hostname:~$ — обычный пользователь
|
||||||
|
root@hostname:~# — суперпользователь (root)
|
||||||
|
|
||||||
|
user — имя пользователя
|
||||||
|
hostname — имя машины
|
||||||
|
~ — текущая директория (~ = домашняя)
|
||||||
|
$ — не root; # — root`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Базовые горячие клавиши:" + utils.ColorReset)
|
||||||
|
utils.Code(`Tab — автодополнение команд и путей
|
||||||
|
Tab Tab — показать все варианты
|
||||||
|
↑ / ↓ — история команд
|
||||||
|
Ctrl+C — прервать текущую команду (SIGINT)
|
||||||
|
Ctrl+Z — приостановить процесс (SIGTSTP)
|
||||||
|
Ctrl+D — закрыть сессию / конец ввода (EOF)
|
||||||
|
Ctrl+L — очистить экран (= clear)
|
||||||
|
Ctrl+A — в начало строки
|
||||||
|
Ctrl+E — в конец строки
|
||||||
|
Ctrl+R — поиск по истории команд
|
||||||
|
Ctrl+U — удалить строку до курсора
|
||||||
|
Ctrl+W — удалить слово влево`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Полезные команды общего назначения:" + utils.ColorReset)
|
||||||
|
utils.Command("man команда", "страница руководства (q — выход, /текст — поиск)")
|
||||||
|
utils.Command("info команда", "расширенная документация GNU")
|
||||||
|
utils.Command("команда --help", "краткая справка")
|
||||||
|
utils.Command("type команда", "что такое команда (alias/builtin/файл)")
|
||||||
|
utils.Command("which команда", "полный путь к исполняемому файлу")
|
||||||
|
utils.Command("whereis команда", "бинарник, исходник и man-страница")
|
||||||
|
utils.Command("history", "история команд")
|
||||||
|
utils.Command("history 20", "последние 20 команд")
|
||||||
|
utils.Command("!42", "выполнить команду №42 из истории")
|
||||||
|
utils.Command("!!", "повторить последнюю команду")
|
||||||
|
utils.Command("clear", "очистить экран")
|
||||||
|
utils.Command("exit", "выйти из сессии")
|
||||||
|
utils.Command("echo $SHELL", "какая оболочка используется")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`# Запуск нескольких команд:
|
||||||
|
cmd1 ; cmd2 — выполнить последовательно (всегда)
|
||||||
|
cmd1 && cmd2 — cmd2 только если cmd1 успешна
|
||||||
|
cmd1 || cmd2 — cmd2 только если cmd1 неуспешна
|
||||||
|
cmd1 | cmd2 — передать вывод cmd1 на вход cmd2 (pipe)`)
|
||||||
|
|
||||||
|
utils.Note("Виртуальные консоли: Alt+F1..F6 в Linux. В X11 — Ctrl+Alt+F1..F6. Вернуться: Ctrl+Alt+F7.")
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
109
modules/linuxmodules/linux_kernel.go
Normal file
109
modules/linuxmodules/linux_kernel.go
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var KernelModule = Module{
|
||||||
|
Key: "kernel",
|
||||||
|
Aliases: []string{"k", "ядро"},
|
||||||
|
Title: "Ядро Linux",
|
||||||
|
Description: "Тема 21: ядро, модули, параметры, uname, dmesg",
|
||||||
|
Run: showKernel,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showKernel() {
|
||||||
|
utils.Header("Linux — Ядро (Kernel)")
|
||||||
|
|
||||||
|
utils.Section("21. Ядро Linux")
|
||||||
|
|
||||||
|
utils.Println("Ядро (kernel) — центральная часть ОС. Управляет:")
|
||||||
|
utils.Println("• процессами и планировщиком CPU")
|
||||||
|
utils.Println("• памятью (виртуальная память, swap)")
|
||||||
|
utils.Println("• устройствами (через драйверы)")
|
||||||
|
utils.Println("• файловыми системами")
|
||||||
|
utils.Println("• сетью")
|
||||||
|
utils.Println("• системными вызовами (syscalls)")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "\nИнформация о ядре:" + utils.ColorReset)
|
||||||
|
utils.Command("uname -r", "версия ядра")
|
||||||
|
utils.Command("uname -a", "полная информация (ядро, архитектура, дата)")
|
||||||
|
utils.Command("uname -m", "архитектура (x86_64, aarch64...)")
|
||||||
|
utils.Command("cat /proc/version", "подробная версия (компилятор, дата)")
|
||||||
|
utils.Command("cat /proc/sys/kernel/osrelease", "версия через /proc")
|
||||||
|
utils.Code(`# Пример uname -a:
|
||||||
|
Linux server01 5.15.0-91-generic #101-Ubuntu SMP Tue Nov 14 13:30:08 UTC 2023
|
||||||
|
x86_64 x86_64 x86_64 GNU/Linux
|
||||||
|
│ │ │ └ платформа
|
||||||
|
│ │ └── архитектура процессора
|
||||||
|
│ └── имя хоста
|
||||||
|
└── имя ядра
|
||||||
|
|
||||||
|
# Версия ядра: 5.15.0-91-generic
|
||||||
|
# 5.15 — основная версия
|
||||||
|
# 0 — патч-уровень
|
||||||
|
# 91 — номер пакета дистрибутива`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "dmesg — буфер сообщений ядра:" + utils.ColorReset)
|
||||||
|
utils.Command("dmesg", "все сообщения ядра")
|
||||||
|
utils.Command("dmesg | tail -20", "последние 20 сообщений")
|
||||||
|
utils.Command("dmesg -T", "с человекочитаемыми временными метками")
|
||||||
|
utils.Command("dmesg | grep -i error", "только ошибки")
|
||||||
|
utils.Command("dmesg | grep -i usb", "сообщения о USB-устройствах")
|
||||||
|
utils.Command("dmesg | grep -i sda", "сообщения о диске sda")
|
||||||
|
utils.Command("dmesg -w", "следить за новыми сообщениями (как tail -f)")
|
||||||
|
utils.Command("dmesg -l err,crit", "только критические ошибки")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "\nМодули ядра:" + utils.ColorReset)
|
||||||
|
utils.Println("Модуль — расширение ядра, загружаемое динамически (драйверы, ФС...).")
|
||||||
|
utils.Code(`# Управление модулями:
|
||||||
|
lsmod # список загруженных модулей
|
||||||
|
lsmod | grep ext4 # есть ли модуль ext4?
|
||||||
|
modinfo ext4 # информация о модуле
|
||||||
|
modprobe ext4 # загрузить модуль (с зависимостями)
|
||||||
|
modprobe -r ext4 # выгрузить модуль
|
||||||
|
insmod /path/to/mod.ko # загрузить .ko файл напрямую
|
||||||
|
rmmod ext4 # выгрузить модуль
|
||||||
|
|
||||||
|
# Автоматическая загрузка при старте:
|
||||||
|
# /etc/modules (Debian/Ubuntu)
|
||||||
|
# /etc/modules-load.d/*.conf
|
||||||
|
echo "br_netfilter" > /etc/modules-load.d/k8s.conf
|
||||||
|
|
||||||
|
# Параметры модулей:
|
||||||
|
# /etc/modprobe.d/*.conf
|
||||||
|
echo "options kvm_intel nested=1" > /etc/modprobe.d/kvm.conf`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Параметры ядра (sysctl):" + utils.ColorReset)
|
||||||
|
utils.Code(`# Просмотр параметров:
|
||||||
|
sysctl -a # все параметры
|
||||||
|
sysctl net.ipv4.ip_forward # конкретный параметр
|
||||||
|
cat /proc/sys/net/ipv4/ip_forward # то же через /proc/sys
|
||||||
|
|
||||||
|
# Изменить параметр (временно):
|
||||||
|
sysctl -w net.ipv4.ip_forward=1
|
||||||
|
|
||||||
|
# Постоянно — в /etc/sysctl.conf или /etc/sysctl.d/:
|
||||||
|
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.d/99-custom.conf
|
||||||
|
sysctl -p /etc/sysctl.d/99-custom.conf # применить
|
||||||
|
|
||||||
|
# Полезные параметры:
|
||||||
|
net.ipv4.ip_forward = 1 # маршрутизация (для Docker/Kubernetes)
|
||||||
|
net.ipv4.tcp_syncookies = 1 # защита от SYN flood
|
||||||
|
vm.swappiness = 10 # предпочитать RAM над swap
|
||||||
|
fs.file-max = 2097152 # максимум открытых файлов
|
||||||
|
kernel.dmesg_restrict = 0 # dmesg без root`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Аппаратная информация:" + utils.ColorReset)
|
||||||
|
utils.Command("lscpu", "информация о процессоре")
|
||||||
|
utils.Command("lsmem", "информация о памяти")
|
||||||
|
utils.Command("lspci", "устройства на шине PCI")
|
||||||
|
utils.Command("lspci -v", "подробно")
|
||||||
|
utils.Command("lsusb", "USB-устройства")
|
||||||
|
utils.Command("lsblk", "блочные устройства (диски)")
|
||||||
|
utils.Command("lshw", "полная информация об оборудовании (нужен root)")
|
||||||
|
utils.Command("dmidecode", "данные BIOS/UEFI (тип памяти, серийный номер...)")
|
||||||
|
utils.Command("inxi -Fz", "обзор системы (нужно установить)")
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
175
modules/linuxmodules/linux_logs.go
Normal file
175
modules/linuxmodules/linux_logs.go
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var LogsModule = Module{
|
||||||
|
Key: "logs",
|
||||||
|
Aliases: []string{"l", "cron", "логи"},
|
||||||
|
Title: "Логирование и планировщики",
|
||||||
|
Description: "Темы 36–37: rsyslog, journald, cron, at",
|
||||||
|
Run: showLogs,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showLogs() {
|
||||||
|
utils.Header("Linux — Логирование и планировщики задач")
|
||||||
|
|
||||||
|
// ─── 36. Логирование ──────────────────────────────────────────
|
||||||
|
utils.Section("36. Логирование")
|
||||||
|
|
||||||
|
utils.Println("В современных системах логирование — двухуровневое:")
|
||||||
|
utils.Println("journald (systemd) + rsyslog/syslog (традиционный)")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "\nОсновные лог-файлы в /var/log/:" + utils.ColorReset)
|
||||||
|
utils.Code(`/var/log/syslog — общий системный лог (Debian/Ubuntu)
|
||||||
|
/var/log/messages — общий системный лог (RHEL/Fedora)
|
||||||
|
/var/log/auth.log — аутентификация, sudo, ssh (Debian)
|
||||||
|
/var/log/secure — аутентификация (RHEL)
|
||||||
|
/var/log/kern.log — сообщения ядра
|
||||||
|
/var/log/dmesg — сообщения при загрузке
|
||||||
|
/var/log/boot.log — процесс загрузки
|
||||||
|
/var/log/cron — задания cron
|
||||||
|
/var/log/mail.log — почтовый сервер
|
||||||
|
/var/log/nginx/ — access.log, error.log
|
||||||
|
/var/log/apache2/ — access.log, error.log
|
||||||
|
/var/log/mysql/ — error.log
|
||||||
|
/var/log/dpkg.log — установка пакетов (Debian)
|
||||||
|
/var/log/dnf.log — установка пакетов (RHEL)
|
||||||
|
/var/log/wtmp — история входов (last для чтения)
|
||||||
|
/var/log/btmp — неудачные попытки входа (lastb)
|
||||||
|
/var/log/lastlog — последний вход каждого пользователя`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Работа с логами:" + utils.ColorReset)
|
||||||
|
utils.Command("tail -f /var/log/syslog", "следить за системным логом")
|
||||||
|
utils.Command("tail -n 100 /var/log/auth.log", "последние 100 строк лога входов")
|
||||||
|
utils.Command("grep 'ERROR' /var/log/nginx/error.log", "ошибки nginx")
|
||||||
|
utils.Command("grep -i 'failed' /var/log/auth.log", "неудачные входы")
|
||||||
|
utils.Command("zcat /var/log/syslog.1.gz", "читать сжатый архивный лог")
|
||||||
|
utils.Command("zgrep 'error' /var/log/syslog.*.gz", "поиск в архивных логах")
|
||||||
|
utils.Command("last", "история входов в систему")
|
||||||
|
utils.Command("lastb", "неудачные попытки входа (root)")
|
||||||
|
utils.Command("lastlog", "последний вход каждого пользователя")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "\nrsyslog — конфигурация:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Конфиг: /etc/rsyslog.conf и /etc/rsyslog.d/*.conf
|
||||||
|
# Формат правил: facility.priority назначение
|
||||||
|
|
||||||
|
# Facility (источник):
|
||||||
|
auth, authpriv — аутентификация
|
||||||
|
cron — планировщик
|
||||||
|
daemon — системные демоны
|
||||||
|
kern — ядро
|
||||||
|
mail — почта
|
||||||
|
user — пользовательские программы
|
||||||
|
local0..local7 — зарезервированы для своего использования
|
||||||
|
* — все
|
||||||
|
|
||||||
|
# Priority (уровень, по возрастанию важности):
|
||||||
|
debug, info, notice, warning, err, crit, alert, emerg
|
||||||
|
|
||||||
|
# Примеры правил:
|
||||||
|
*.info;mail.none;authpriv.none /var/log/messages # всё кроме mail и auth
|
||||||
|
authpriv.* /var/log/secure # всё от authpriv
|
||||||
|
mail.* /var/log/maillog # почта
|
||||||
|
cron.* /var/log/cron # cron
|
||||||
|
*.emerg :omusrmsg:* # критичное — всем пользователям
|
||||||
|
local1.* /var/log/myapp.log # своё приложение
|
||||||
|
|
||||||
|
# Перезапустить rsyslog:
|
||||||
|
sudo systemctl restart rsyslog`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "logrotate — ротация логов:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Конфиг: /etc/logrotate.conf и /etc/logrotate.d/*
|
||||||
|
# Пример /etc/logrotate.d/nginx:
|
||||||
|
/var/log/nginx/*.log {
|
||||||
|
daily # каждый день
|
||||||
|
missingok # не ошибаться если файл отсутствует
|
||||||
|
rotate 14 # хранить 14 архивов
|
||||||
|
compress # сжимать gzip
|
||||||
|
delaycompress # не сжимать текущий архив
|
||||||
|
notifempty # не ротировать пустые файлы
|
||||||
|
create 0640 nginx adm # создать новый файл с правами
|
||||||
|
sharedscripts
|
||||||
|
postrotate
|
||||||
|
nginx -s reopen # сообщить nginx открыть новый файл
|
||||||
|
endscript
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ручная ротация (тест):
|
||||||
|
sudo logrotate -d /etc/logrotate.d/nginx # -d = dry run`)
|
||||||
|
|
||||||
|
// ─── 37. Планировщики ─────────────────────────────────────────
|
||||||
|
utils.Section("37. Планировщики задач: cron и at")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "cron — периодические задачи:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Редактировать crontab текущего пользователя:
|
||||||
|
crontab -e
|
||||||
|
|
||||||
|
# Посмотреть:
|
||||||
|
crontab -l
|
||||||
|
|
||||||
|
# Удалить все задачи:
|
||||||
|
crontab -r
|
||||||
|
|
||||||
|
# Для root:
|
||||||
|
sudo crontab -e
|
||||||
|
|
||||||
|
# Формат строки crontab:
|
||||||
|
# мин час день_месяца месяц день_недели команда
|
||||||
|
# 0-59 0-23 1-31 1-12 0-7(0,7=воскресенье)
|
||||||
|
|
||||||
|
# Примеры:
|
||||||
|
* * * * * /script.sh # каждую минуту
|
||||||
|
0 * * * * /script.sh # каждый час в 0 минут
|
||||||
|
0 2 * * * /backup.sh # каждый день в 02:00
|
||||||
|
0 2 * * 0 /weekly.sh # каждое воскресенье в 02:00
|
||||||
|
0 2 1 * * /monthly.sh # 1-го числа каждого месяца
|
||||||
|
*/5 * * * * /check.sh # каждые 5 минут
|
||||||
|
0 9-17 * * 1-5 /work.sh # по будням с 9 до 17
|
||||||
|
0 2 * * * root /root/backup.sh # в /etc/crontab с указанием пользователя
|
||||||
|
|
||||||
|
# Специальные строки:
|
||||||
|
@reboot /script.sh # при каждой загрузке
|
||||||
|
@daily /script.sh # раз в день (= 0 0 * * *)
|
||||||
|
@weekly /script.sh # раз в неделю
|
||||||
|
@monthly /script.sh # раз в месяц
|
||||||
|
@yearly /script.sh # раз в год`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Системные cron-директории:" + utils.ColorReset)
|
||||||
|
utils.Code(`/etc/crontab — системный crontab (с полем user)
|
||||||
|
/etc/cron.d/ — отдельные файлы crontab
|
||||||
|
/etc/cron.hourly/ — скрипты, запускаемые каждый час
|
||||||
|
/etc/cron.daily/ — каждый день
|
||||||
|
/etc/cron.weekly/ — каждую неделю
|
||||||
|
/etc/cron.monthly/ — каждый месяц
|
||||||
|
|
||||||
|
# Поместить скрипт в /etc/cron.daily/:
|
||||||
|
sudo cp backup.sh /etc/cron.daily/
|
||||||
|
sudo chmod +x /etc/cron.daily/backup.sh`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "at — однократные задачи:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Выполнить команду однократно в указанное время:
|
||||||
|
at 14:30 # в 14:30 сегодня
|
||||||
|
at 14:30 tomorrow # завтра в 14:30
|
||||||
|
at 14:30 July 15 # 15 июля
|
||||||
|
at now + 1 hour # через час
|
||||||
|
at now + 30 minutes # через 30 минут
|
||||||
|
|
||||||
|
# Ввод команд (Ctrl+D для завершения):
|
||||||
|
at 02:00
|
||||||
|
> /usr/local/bin/backup.sh
|
||||||
|
> Ctrl+D
|
||||||
|
|
||||||
|
# Список задач:
|
||||||
|
atq
|
||||||
|
at -l
|
||||||
|
|
||||||
|
# Удалить задачу:
|
||||||
|
atrm 5 # удалить задачу №5
|
||||||
|
|
||||||
|
# Посмотреть содержимое задачи:
|
||||||
|
at -c 5`)
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
346
modules/linuxmodules/linux_netfs.go
Normal file
346
modules/linuxmodules/linux_netfs.go
Normal file
|
|
@ -0,0 +1,346 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var NetfsModule = Module{
|
||||||
|
Key: "netfs",
|
||||||
|
Aliases: []string{"nfs", "smb", "samba", "autofs", "сетевые-фс"},
|
||||||
|
Title: "Сетевые файловые системы",
|
||||||
|
Description: "Темы 55–59: IPv6, передача файлов, NFS, SMB/Samba, autofs",
|
||||||
|
Run: showNetfs,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showNetfs() {
|
||||||
|
utils.Header("Linux — Сетевые файловые системы")
|
||||||
|
|
||||||
|
// ─── 55. IPv6 ─────────────────────────────────────────────────
|
||||||
|
utils.Section("55. Работа с IPv6")
|
||||||
|
|
||||||
|
utils.Println("IPv6 — протокол интернета следующего поколения (128-битные адреса).")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Формат IPv6 адресов:" + utils.ColorReset)
|
||||||
|
utils.Code(`Формат: 8 групп по 4 hex-цифры, разделённых :
|
||||||
|
2001:0db8:85a3:0000:0000:8a2e:0370:7334
|
||||||
|
|
||||||
|
Сокращения:
|
||||||
|
- Ведущие нули в группе можно опустить: 0db8 → db8
|
||||||
|
- Одну последовательность групп из нулей → ::
|
||||||
|
2001:db8::1 (полный: 2001:0db8:0000:0000:0000:0000:0000:0001)
|
||||||
|
::1 — loopback (аналог 127.0.0.1)
|
||||||
|
fe80::/10 — link-local (автоконфигурация в подсети)
|
||||||
|
fd00::/8 — уникальные локальные (аналог 192.168.x.x)
|
||||||
|
2000::/3 — глобальные unicast (публичные)
|
||||||
|
|
||||||
|
Длина префикса: 2001:db8::/32 (аналог маски подсети)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Настройка IPv6 через nmcli:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Статический IPv6:
|
||||||
|
nmcli con mod eth0 ipv6.addresses "2001:db8::10/64"
|
||||||
|
nmcli con mod eth0 ipv6.gateway "2001:db8::1"
|
||||||
|
nmcli con mod eth0 ipv6.method manual
|
||||||
|
nmcli con up eth0
|
||||||
|
|
||||||
|
# SLAAC (автоконфигурация):
|
||||||
|
nmcli con mod eth0 ipv6.method auto
|
||||||
|
|
||||||
|
# DHCPv6:
|
||||||
|
nmcli con mod eth0 ipv6.method dhcp
|
||||||
|
|
||||||
|
# Отключить IPv6 для интерфейса:
|
||||||
|
nmcli con mod eth0 ipv6.method disabled`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "IPv6 команды:" + utils.ColorReset)
|
||||||
|
utils.Command("ip -6 addr", "IPv6 адреса интерфейсов")
|
||||||
|
utils.Command("ip -6 route", "IPv6 таблица маршрутов")
|
||||||
|
utils.Command("ping6 ::1", "ping loopback IPv6")
|
||||||
|
utils.Command("ping6 fe80::1%eth0", "ping link-local с указанием интерфейса")
|
||||||
|
utils.Command("traceroute6 2001:4860:4860::8888", "traceroute IPv6")
|
||||||
|
utils.Command("ss -6 -tuln", "IPv6 порты")
|
||||||
|
utils.Command("dig AAAA google.com", "DNS AAAA запись (IPv6)")
|
||||||
|
|
||||||
|
// ─── 56. Передача файлов по сети ─────────────────────────────
|
||||||
|
utils.Section("56. Передача файлов по сети")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "SCP — копирование через SSH:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Скопировать локальный файл на сервер:
|
||||||
|
scp file.txt user@server:/path/to/dest/
|
||||||
|
|
||||||
|
# Скопировать с сервера на локальную машину:
|
||||||
|
scp user@server:/path/file.txt /local/path/
|
||||||
|
|
||||||
|
# Директорию рекурсивно:
|
||||||
|
scp -r mydir/ user@server:/tmp/
|
||||||
|
|
||||||
|
# Нестандартный порт:
|
||||||
|
scp -P 2222 file.txt user@server:/tmp/
|
||||||
|
|
||||||
|
# С указанием ключа:
|
||||||
|
scp -i ~/.ssh/mykey file.txt user@server:/tmp/
|
||||||
|
|
||||||
|
# Между двумя серверами:
|
||||||
|
scp user1@server1:/path/file.txt user2@server2:/path/`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "SFTP — интерактивная передача файлов:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Подключиться:
|
||||||
|
sftp user@server
|
||||||
|
sftp -P 2222 user@server
|
||||||
|
|
||||||
|
# Команды в интерактивном режиме:
|
||||||
|
ls — список файлов на сервере
|
||||||
|
lls — список файлов локально
|
||||||
|
pwd — директория на сервере
|
||||||
|
lpwd — локальная директория
|
||||||
|
cd /remote/path — перейти на сервере
|
||||||
|
lcd /local/path — перейти локально
|
||||||
|
get file.txt — скачать файл
|
||||||
|
get -r dir/ — скачать директорию
|
||||||
|
put file.txt — загрузить файл
|
||||||
|
put -r dir/ — загрузить директорию
|
||||||
|
rm file.txt — удалить на сервере
|
||||||
|
mkdir newdir — создать директорию на сервере
|
||||||
|
exit / quit — выйти`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "rsync — эффективная синхронизация:" + utils.ColorReset)
|
||||||
|
utils.Code(`# rsync передаёт только изменения — быстрее scp для больших объёмов.
|
||||||
|
|
||||||
|
# Синхронизировать локально:
|
||||||
|
rsync -av /source/ /dest/
|
||||||
|
|
||||||
|
# Синхронизировать на удалённый сервер:
|
||||||
|
rsync -avz /local/data/ user@server:/remote/data/
|
||||||
|
|
||||||
|
# С сервера локально:
|
||||||
|
rsync -avz user@server:/remote/data/ /local/data/
|
||||||
|
|
||||||
|
# Ключи:
|
||||||
|
# -a — архивный режим (сохраняет права, время, симлинки)
|
||||||
|
# -v — verbose
|
||||||
|
# -z — сжатие при передаче
|
||||||
|
# -P — прогресс + продолжение прерванной передачи
|
||||||
|
# --delete — удалять файлы которых нет в источнике
|
||||||
|
# --exclude='*.log' — исключить паттерн
|
||||||
|
# -n / --dry-run — симуляция (что будет скопировано)
|
||||||
|
# -e "ssh -p 2222" — нестандартный порт SSH
|
||||||
|
|
||||||
|
# Зеркалирование с исключениями:
|
||||||
|
rsync -avz --delete \
|
||||||
|
--exclude='.git/' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
/project/ user@server:/var/www/project/`)
|
||||||
|
|
||||||
|
// ─── 57. NFS ──────────────────────────────────────────────────
|
||||||
|
utils.Section("57. Сетевые файловые системы — NFS")
|
||||||
|
|
||||||
|
utils.Println("NFS (Network File System) — монтирование директорий с удалённых серверов.")
|
||||||
|
utils.Println("Прозрачно для приложений: работает как обычная локальная ФС.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Сервер NFS — настройка экспорта:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Установка:
|
||||||
|
dnf install nfs-utils # RHEL/Fedora
|
||||||
|
apt install nfs-kernel-server # Debian/Ubuntu
|
||||||
|
|
||||||
|
# Включить и запустить:
|
||||||
|
systemctl enable --now nfs-server # RHEL
|
||||||
|
systemctl enable --now nfs-kernel-server # Ubuntu
|
||||||
|
|
||||||
|
# Настройка экспортов /etc/exports:
|
||||||
|
# директория клиент(опции)
|
||||||
|
/shared 192.168.1.0/24(rw,sync,no_root_squash)
|
||||||
|
/data *(ro,sync) # всем только чтение
|
||||||
|
/home/alice server2(rw,sync,no_subtree_check)
|
||||||
|
|
||||||
|
# Опции:
|
||||||
|
# rw — чтение и запись
|
||||||
|
# ro — только чтение
|
||||||
|
# sync — синхронная запись (безопасно)
|
||||||
|
# async — асинхронная (быстрее, риск потери)
|
||||||
|
# no_root_squash — root клиента = root сервера
|
||||||
|
# root_squash — root клиента → nobody (безопаснее, по умолчанию)
|
||||||
|
# no_subtree_check — не проверять поддерево (производительность)
|
||||||
|
|
||||||
|
# Применить изменения:
|
||||||
|
exportfs -r # перечитать /etc/exports
|
||||||
|
exportfs -v # показать активные экспорты
|
||||||
|
exportfs -a # экспортировать всё из /etc/exports`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Firewall для NFS:" + utils.ColorReset)
|
||||||
|
utils.Code(`firewall-cmd --permanent --add-service=nfs
|
||||||
|
firewall-cmd --permanent --add-service=rpc-bind
|
||||||
|
firewall-cmd --permanent --add-service=mountd
|
||||||
|
firewall-cmd --reload`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Клиент NFS — монтирование:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Установка клиента:
|
||||||
|
dnf install nfs-utils
|
||||||
|
apt install nfs-common
|
||||||
|
|
||||||
|
# Посмотреть экспорты сервера:
|
||||||
|
showmount -e 192.168.1.10
|
||||||
|
|
||||||
|
# Смонтировать:
|
||||||
|
mount -t nfs 192.168.1.10:/shared /mnt/shared
|
||||||
|
mount -t nfs4 192.168.1.10:/data /mnt/data # NFSv4
|
||||||
|
|
||||||
|
# Параметры монтирования:
|
||||||
|
mount -t nfs -o rw,sync,hard,intr 192.168.1.10:/shared /mnt
|
||||||
|
|
||||||
|
# В /etc/fstab (постоянно):
|
||||||
|
192.168.1.10:/shared /mnt/shared nfs defaults,_netdev 0 0
|
||||||
|
# _netdev — монтировать только после настройки сети
|
||||||
|
|
||||||
|
# Размонтировать:
|
||||||
|
umount /mnt/shared`)
|
||||||
|
|
||||||
|
// ─── 58. SMB/Samba ────────────────────────────────────────────
|
||||||
|
utils.Section("58. Сетевые файловые системы — SMB/Samba")
|
||||||
|
|
||||||
|
utils.Println("SMB (Server Message Block) / CIFS — протокол файлового обмена Windows.")
|
||||||
|
utils.Println("Samba — реализация SMB на Linux. Позволяет обмениваться файлами с Windows.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Сервер Samba — установка и настройка:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Установка:
|
||||||
|
dnf install samba samba-client # RHEL
|
||||||
|
apt install samba # Ubuntu
|
||||||
|
|
||||||
|
# Включить и запустить:
|
||||||
|
systemctl enable --now smb nmb # RHEL
|
||||||
|
systemctl enable --now smbd nmbd # Ubuntu`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Конфигурация /etc/samba/smb.conf:" + utils.ColorReset)
|
||||||
|
utils.Code(`[global]
|
||||||
|
workgroup = WORKGROUP # рабочая группа Windows
|
||||||
|
server string = Samba Server
|
||||||
|
security = user # аутентификация по пользователю
|
||||||
|
passdb backend = tdbsam # база паролей
|
||||||
|
|
||||||
|
# Публичная шара (без пароля):
|
||||||
|
[public]
|
||||||
|
path = /srv/samba/public
|
||||||
|
browseable = yes
|
||||||
|
writable = yes
|
||||||
|
guest ok = yes
|
||||||
|
create mask = 0664
|
||||||
|
directory mask = 0775
|
||||||
|
|
||||||
|
# Приватная шара (с паролем):
|
||||||
|
[private]
|
||||||
|
path = /srv/samba/private
|
||||||
|
valid users = alice bob
|
||||||
|
writable = yes
|
||||||
|
browseable = no
|
||||||
|
create mask = 0660`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Управление пользователями Samba:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Пользователь Samba должен существовать в Linux:
|
||||||
|
useradd -s /sbin/nologin alice
|
||||||
|
|
||||||
|
# Добавить пользователя в Samba (отдельный пароль!):
|
||||||
|
smbpasswd -a alice
|
||||||
|
smbpasswd -e alice # включить
|
||||||
|
smbpasswd -d alice # отключить
|
||||||
|
smbpasswd -x alice # удалить
|
||||||
|
|
||||||
|
# Список пользователей Samba:
|
||||||
|
pdbedit -L`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "SELinux + Samba:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Разрешить Samba доступ к домашним директориям:
|
||||||
|
setsebool -P samba_enable_home_dirs on
|
||||||
|
|
||||||
|
# Разрешить Samba читать/писать общие директории:
|
||||||
|
chcon -t samba_share_t /srv/samba/public
|
||||||
|
semanage fcontext -a -t samba_share_t '/srv/samba(/.*)?'
|
||||||
|
restorecon -Rv /srv/samba/`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Firewall для Samba:" + utils.ColorReset)
|
||||||
|
utils.Code(`firewall-cmd --permanent --add-service=samba
|
||||||
|
firewall-cmd --reload`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Клиент SMB — монтирование Windows-шары:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Установка:
|
||||||
|
dnf install cifs-utils samba-client
|
||||||
|
apt install cifs-utils smbclient
|
||||||
|
|
||||||
|
# Просмотр шар на сервере:
|
||||||
|
smbclient -L //192.168.1.20 -U alice
|
||||||
|
|
||||||
|
# Интерактивный клиент:
|
||||||
|
smbclient //192.168.1.20/shared -U alice
|
||||||
|
|
||||||
|
# Монтирование:
|
||||||
|
mount -t cifs //192.168.1.20/shared /mnt/windows \
|
||||||
|
-o username=alice,password=secret
|
||||||
|
|
||||||
|
# С файлом учётных данных (безопаснее):
|
||||||
|
cat > /etc/samba/creds << 'EOF'
|
||||||
|
username=alice
|
||||||
|
password=secret
|
||||||
|
domain=WORKGROUP
|
||||||
|
EOF
|
||||||
|
chmod 600 /etc/samba/creds
|
||||||
|
|
||||||
|
mount -t cifs //192.168.1.20/shared /mnt/windows \
|
||||||
|
-o credentials=/etc/samba/creds
|
||||||
|
|
||||||
|
# В /etc/fstab:
|
||||||
|
//server/shared /mnt/windows cifs credentials=/etc/samba/creds,_netdev 0 0`)
|
||||||
|
|
||||||
|
// ─── 59. Autofs ───────────────────────────────────────────────
|
||||||
|
utils.Section("59. Автоматическое монтирование — Autofs")
|
||||||
|
|
||||||
|
utils.Println("Autofs — демон автоматического монтирования сетевых ФС по запросу.")
|
||||||
|
utils.Println("Монтирует при обращении к директории, размонтирует при простое.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Установка и запуск:" + utils.ColorReset)
|
||||||
|
utils.Code(`dnf install autofs # RHEL
|
||||||
|
apt install autofs # Ubuntu
|
||||||
|
|
||||||
|
systemctl enable --now autofs`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Конфигурация autofs:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Главный файл /etc/auto.master:
|
||||||
|
# точка_монтирования файл_карты [опции]
|
||||||
|
/mnt/nfs /etc/auto.nfs --timeout=60
|
||||||
|
/home /etc/auto.home --timeout=300
|
||||||
|
/- /etc/auto.direct
|
||||||
|
|
||||||
|
# /etc/auto.nfs — монтирование NFS:
|
||||||
|
# ключ опции сервер:путь
|
||||||
|
shared -rw,sync 192.168.1.10:/shared
|
||||||
|
data -ro 192.168.1.10:/data
|
||||||
|
# Обращение: ls /mnt/nfs/shared → автоматически монтируется
|
||||||
|
|
||||||
|
# /etc/auto.home — домашние директории через NFS:
|
||||||
|
* -rw,sync 192.168.1.10:/home/&
|
||||||
|
# & → подставляется ключ (* = любой пользователь)
|
||||||
|
# /home/alice → монтируется 192.168.1.10:/home/alice
|
||||||
|
|
||||||
|
# /etc/auto.direct — прямые точки монтирования:
|
||||||
|
/srv/data -rw,sync 192.168.1.10:/data
|
||||||
|
|
||||||
|
# Применить изменения:
|
||||||
|
systemctl reload autofs
|
||||||
|
# или:
|
||||||
|
automount -v`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Использование с FreeIPA/LDAP:" + utils.ColorReset)
|
||||||
|
utils.Code(`# FreeIPA хранит карты autofs в LDAP.
|
||||||
|
# После настройки sssd + ipa-client autofs
|
||||||
|
# получает карты автоматически.
|
||||||
|
|
||||||
|
# Подключить autofs к SSSD:
|
||||||
|
# В /etc/sssd/sssd.conf:
|
||||||
|
[domain/ipa.example.com]
|
||||||
|
autofs_provider = ipa
|
||||||
|
|
||||||
|
# Перезапустить:
|
||||||
|
systemctl restart sssd autofs`)
|
||||||
|
|
||||||
|
utils.Note("Autofs удобен для сотен пользователей: их домашние директории монтируются автоматически при входе.")
|
||||||
|
utils.Note("--timeout=60 означает размонтировать после 60 секунд бездействия.")
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
238
modules/linuxmodules/linux_network.go
Normal file
238
modules/linuxmodules/linux_network.go
Normal file
|
|
@ -0,0 +1,238 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var NetworkModule = Module{
|
||||||
|
Key: "network",
|
||||||
|
Aliases: []string{"net", "ssh", "сеть"},
|
||||||
|
Title: "Сети и SSH",
|
||||||
|
Description: "Темы 42–44: основы сетей, настройка, SSH",
|
||||||
|
Run: showNetwork,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showNetwork() {
|
||||||
|
utils.Header("Linux — Сети и SSH")
|
||||||
|
|
||||||
|
// ─── 42. Основы сетей ─────────────────────────────────────────
|
||||||
|
utils.Section("42. Основы сетей")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Ключевые понятия:" + utils.ColorReset)
|
||||||
|
utils.Code(`IP-адрес — уникальный адрес устройства в сети
|
||||||
|
IPv4: 192.168.1.10 (4 байта, 0-255)
|
||||||
|
IPv6: 2001:db8::1 (16 байт, hex)
|
||||||
|
Маска сети — определяет границу сети и хостов
|
||||||
|
/24 = 255.255.255.0 (256 адресов, 254 хоста)
|
||||||
|
/16 = 255.255.0.0 (65536 адресов)
|
||||||
|
Шлюз — маршрутизатор для выхода за пределы сети
|
||||||
|
DNS — перевод имён в IP (8.8.8.8 = Google DNS)
|
||||||
|
MAC-адрес — физический адрес сетевого интерфейса
|
||||||
|
DHCP — автоматическое получение IP от сервера
|
||||||
|
|
||||||
|
Приватные сети (RFC 1918):
|
||||||
|
10.0.0.0/8 (10.x.x.x)
|
||||||
|
172.16.0.0/12 (172.16-31.x.x)
|
||||||
|
192.168.0.0/16 (192.168.x.x)
|
||||||
|
|
||||||
|
Localhost:
|
||||||
|
127.0.0.1 — loopback IPv4 (lo)
|
||||||
|
::1 — loopback IPv6`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Информация о сетевых интерфейсах:" + utils.ColorReset)
|
||||||
|
utils.Command("ip addr", "IP-адреса всех интерфейсов")
|
||||||
|
utils.Command("ip addr show eth0", "конкретный интерфейс")
|
||||||
|
utils.Command("ip link", "состояние интерфейсов (UP/DOWN)")
|
||||||
|
utils.Command("ip route", "таблица маршрутизации")
|
||||||
|
utils.Command("ip route show default", "шлюз по умолчанию")
|
||||||
|
utils.Command("ip neigh", "ARP-таблица (MAC → IP)")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`# Старые команды (net-tools, устаревшие):
|
||||||
|
ifconfig # → ip addr
|
||||||
|
route -n # → ip route
|
||||||
|
netstat -rn # → ip route
|
||||||
|
arp -n # → ip neigh`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Диагностика сети:" + utils.ColorReset)
|
||||||
|
utils.Command("ping 8.8.8.8", "проверить доступность хоста")
|
||||||
|
utils.Command("ping -c 4 google.com", "4 пакета")
|
||||||
|
utils.Command("ping6 ::1", "ping для IPv6")
|
||||||
|
utils.Command("traceroute google.com", "маршрут до хоста")
|
||||||
|
utils.Command("tracepath google.com", "маршрут (без root)")
|
||||||
|
utils.Command("mtr google.com", "ping + traceroute в реальном времени")
|
||||||
|
utils.Command("nslookup google.com", "DNS-запрос")
|
||||||
|
utils.Command("dig google.com", "подробный DNS-запрос")
|
||||||
|
utils.Command("dig @8.8.8.8 google.com", "DNS через конкретный сервер")
|
||||||
|
utils.Command("host google.com", "быстрый DNS-запрос")
|
||||||
|
utils.Command("whois 192.168.1.1", "информация об IP/домене")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Сетевые соединения и порты:" + utils.ColorReset)
|
||||||
|
utils.Command("ss -tuln", "прослушиваемые порты (t=tcp u=udp l=listen n=numeric)")
|
||||||
|
utils.Command("ss -tulnp", "с именами процессов (root)")
|
||||||
|
utils.Command("ss -s", "статистика соединений")
|
||||||
|
utils.Command("ss -tn state established", "активные TCP-соединения")
|
||||||
|
utils.Command("netstat -tuln", "аналог ss (устаревший)")
|
||||||
|
utils.Command("lsof -i :80", "что слушает порт 80")
|
||||||
|
utils.Command("lsof -i :22", "что слушает порт 22")
|
||||||
|
utils.Command("nmap -sS 192.168.1.0/24", "сканирование сети (нужно установить)")
|
||||||
|
utils.Command("nmap -p 22,80,443 server", "проверить конкретные порты")
|
||||||
|
|
||||||
|
// ─── 43. Работа с сетью ───────────────────────────────────────
|
||||||
|
utils.Section("43. Настройка сети")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Временная настройка (без сохранения):" + utils.ColorReset)
|
||||||
|
utils.Code(`# Добавить IP:
|
||||||
|
ip addr add 192.168.1.10/24 dev eth0
|
||||||
|
|
||||||
|
# Удалить IP:
|
||||||
|
ip addr del 192.168.1.10/24 dev eth0
|
||||||
|
|
||||||
|
# Включить/выключить интерфейс:
|
||||||
|
ip link set eth0 up
|
||||||
|
ip link set eth0 down
|
||||||
|
|
||||||
|
# Добавить маршрут:
|
||||||
|
ip route add 10.0.0.0/8 via 192.168.1.1
|
||||||
|
ip route add default via 192.168.1.1
|
||||||
|
|
||||||
|
# Удалить маршрут:
|
||||||
|
ip route del default`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "NetworkManager — постоянная настройка:" + utils.ColorReset)
|
||||||
|
utils.Code(`# nmcli — командная строка NetworkManager
|
||||||
|
nmcli device status # список устройств
|
||||||
|
nmcli connection show # все соединения
|
||||||
|
nmcli connection show eth0 # параметры соединения
|
||||||
|
|
||||||
|
# Статический IP:
|
||||||
|
nmcli con mod eth0 ipv4.addresses 192.168.1.10/24
|
||||||
|
nmcli con mod eth0 ipv4.gateway 192.168.1.1
|
||||||
|
nmcli con mod eth0 ipv4.dns "8.8.8.8 8.8.4.4"
|
||||||
|
nmcli con mod eth0 ipv4.method manual # static (не DHCP)
|
||||||
|
nmcli con up eth0 # применить
|
||||||
|
|
||||||
|
# DHCP:
|
||||||
|
nmcli con mod eth0 ipv4.method auto
|
||||||
|
nmcli con up eth0
|
||||||
|
|
||||||
|
# Создать соединение:
|
||||||
|
nmcli con add type ethernet con-name myconn ifname eth1 \
|
||||||
|
ipv4.addresses 10.0.0.5/24 ipv4.gateway 10.0.0.1 \
|
||||||
|
ipv4.method manual
|
||||||
|
|
||||||
|
# nmtui — псевдографический интерфейс:
|
||||||
|
nmtui`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "DNS-настройка:" + utils.ColorReset)
|
||||||
|
utils.Code(`# /etc/resolv.conf — DNS-серверы:
|
||||||
|
nameserver 8.8.8.8
|
||||||
|
nameserver 8.8.4.4
|
||||||
|
search mydomain.local # домен для коротких имён
|
||||||
|
|
||||||
|
# /etc/hosts — локальное разрешение имён:
|
||||||
|
127.0.0.1 localhost
|
||||||
|
192.168.1.10 server01.local server01
|
||||||
|
|
||||||
|
# Порядок разрешения (/etc/nsswitch.conf):
|
||||||
|
hosts: files dns myhostname # сначала /etc/hosts, потом DNS`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "curl и wget — HTTP-запросы:" + utils.ColorReset)
|
||||||
|
utils.Command("curl https://example.com", "GET запрос")
|
||||||
|
utils.Command("curl -I https://example.com", "только заголовки")
|
||||||
|
utils.Command("curl -o file.txt https://example.com/file", "сохранить в файл")
|
||||||
|
utils.Command("curl -L https://example.com", "следовать перенаправлениям")
|
||||||
|
utils.Command("curl -X POST -d 'data' https://api.example.com", "POST запрос")
|
||||||
|
utils.Command("curl -H 'Authorization: Bearer token' https://api.example.com", "с заголовком")
|
||||||
|
utils.Command("wget https://example.com/file.tar.gz", "скачать файл")
|
||||||
|
utils.Command("wget -r -np https://example.com/docs/", "рекурсивно скачать")
|
||||||
|
|
||||||
|
// ─── 44. SSH ──────────────────────────────────────────────────
|
||||||
|
utils.Section("44. Удалённый доступ — SSH")
|
||||||
|
|
||||||
|
utils.Println("SSH (Secure Shell) — зашифрованный протокол удалённого доступа.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Подключение:" + utils.ColorReset)
|
||||||
|
utils.Command("ssh user@server", "подключиться к серверу")
|
||||||
|
utils.Command("ssh user@192.168.1.10", "по IP")
|
||||||
|
utils.Command("ssh -p 2222 user@server", "нестандартный порт")
|
||||||
|
utils.Command("ssh -i ~/.ssh/mykey user@server", "с конкретным ключом")
|
||||||
|
utils.Command("ssh -v user@server", "подробный вывод (отладка)")
|
||||||
|
utils.Command("ssh -A user@server", "пробросить SSH-агент")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "SSH-ключи — аутентификация без пароля:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Генерация пары ключей:
|
||||||
|
ssh-keygen -t ed25519 -C "alice@example.com" # (рекомендуется)
|
||||||
|
ssh-keygen -t rsa -b 4096 -C "alice@example.com" # RSA 4096
|
||||||
|
|
||||||
|
# Файлы:
|
||||||
|
~/.ssh/id_ed25519 — приватный ключ (НИКОМУ не передавать!)
|
||||||
|
~/.ssh/id_ed25519.pub — публичный ключ
|
||||||
|
|
||||||
|
# Скопировать публичный ключ на сервер:
|
||||||
|
ssh-copy-id user@server # автоматически
|
||||||
|
ssh-copy-id -i ~/.ssh/mykey.pub user@server
|
||||||
|
|
||||||
|
# Вручную (добавить в ~/.ssh/authorized_keys на сервере):
|
||||||
|
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
|
||||||
|
chmod 600 ~/.ssh/authorized_keys
|
||||||
|
chmod 700 ~/.ssh/`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "~/.ssh/config — настройка подключений:" + utils.ColorReset)
|
||||||
|
utils.Code(`# ~/.ssh/config
|
||||||
|
Host myserver
|
||||||
|
HostName 192.168.1.10
|
||||||
|
User alice
|
||||||
|
Port 22
|
||||||
|
IdentityFile ~/.ssh/id_ed25519
|
||||||
|
ServerAliveInterval 60
|
||||||
|
|
||||||
|
Host bastion
|
||||||
|
HostName bastion.example.com
|
||||||
|
User admin
|
||||||
|
ForwardAgent yes
|
||||||
|
|
||||||
|
Host internal
|
||||||
|
HostName 10.0.0.5
|
||||||
|
User root
|
||||||
|
ProxyJump bastion # подключиться через bastion
|
||||||
|
|
||||||
|
# Использование:
|
||||||
|
ssh myserver # вместо ssh alice@192.168.1.10 -i ~/.ssh/id_ed25519`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Передача файлов:" + utils.ColorReset)
|
||||||
|
utils.Command("scp file.txt user@server:/path/", "скопировать на сервер")
|
||||||
|
utils.Command("scp user@server:/path/file.txt .", "скопировать с сервера")
|
||||||
|
utils.Command("scp -r dir/ user@server:/path/", "директорию рекурсивно")
|
||||||
|
utils.Command("rsync -avzP dir/ user@server:/path/", "синхронизация (лучше scp)")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Конфигурация сервера (/etc/ssh/sshd_config):" + utils.ColorReset)
|
||||||
|
utils.Code(`Port 22 # порт (лучше изменить)
|
||||||
|
PermitRootLogin no # запретить вход root (рекомендуется)
|
||||||
|
PasswordAuthentication no # только ключи
|
||||||
|
PubkeyAuthentication yes # ключи разрешены
|
||||||
|
AuthorizedKeysFile .ssh/authorized_keys
|
||||||
|
AllowUsers alice bob # только эти пользователи
|
||||||
|
MaxAuthTries 3 # попытки аутентификации
|
||||||
|
|
||||||
|
# Применить изменения:
|
||||||
|
sudo systemctl reload sshd
|
||||||
|
|
||||||
|
# Проверить конфигурацию:
|
||||||
|
sudo sshd -t`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Туннели SSH (Port Forwarding):" + utils.ColorReset)
|
||||||
|
utils.Code(`# Локальный туннель (доступ к удалённому сервису через localhost):
|
||||||
|
ssh -L 8080:localhost:80 user@server
|
||||||
|
# Теперь http://localhost:8080 = http://server:80
|
||||||
|
|
||||||
|
# Удалённый туннель (открыть порт на удалённом сервере):
|
||||||
|
ssh -R 9090:localhost:3000 user@server
|
||||||
|
# Теперь server:9090 → localhost:3000
|
||||||
|
|
||||||
|
# SOCKS-прокси (динамический туннель):
|
||||||
|
ssh -D 1080 user@server
|
||||||
|
# Настроить браузер на SOCKS5 proxy localhost:1080`)
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
191
modules/linuxmodules/linux_packages.go
Normal file
191
modules/linuxmodules/linux_packages.go
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var PackagesModule = Module{
|
||||||
|
Key: "packages",
|
||||||
|
Aliases: []string{"pkg", "dnf", "apt", "пакеты"},
|
||||||
|
Title: "Пакетный менеджер",
|
||||||
|
Description: "Тема 47: dnf (RHEL/Fedora) и apt (Debian/Ubuntu)",
|
||||||
|
Run: showPackages,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showPackages() {
|
||||||
|
utils.Header("Linux — Пакетный менеджер")
|
||||||
|
|
||||||
|
utils.Section("47. Пакетные менеджеры: dnf и apt")
|
||||||
|
|
||||||
|
utils.Println("Пакетный менеджер — инструмент установки, обновления и удаления ПО.")
|
||||||
|
utils.Println("Решает зависимости автоматически, загружает из репозиториев.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Семейства дистрибутивов и их менеджеры:" + utils.ColorReset)
|
||||||
|
utils.Code(`RHEL / CentOS / Fedora / Rocky / AlmaLinux:
|
||||||
|
dnf (современный) / yum (устаревший)
|
||||||
|
Формат пакетов: .rpm
|
||||||
|
Репозитории: /etc/yum.repos.d/*.repo
|
||||||
|
|
||||||
|
Debian / Ubuntu / Linux Mint:
|
||||||
|
apt (фронтенд) / dpkg (низкий уровень)
|
||||||
|
Формат пакетов: .deb
|
||||||
|
Репозитории: /etc/apt/sources.list, /etc/apt/sources.list.d/
|
||||||
|
|
||||||
|
Arch Linux:
|
||||||
|
pacman
|
||||||
|
|
||||||
|
Alpine Linux:
|
||||||
|
apk`)
|
||||||
|
|
||||||
|
// ─── dnf ──────────────────────────────────────────────────────
|
||||||
|
utils.Section("dnf — RHEL / Fedora / CentOS")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Основные операции:" + utils.ColorReset)
|
||||||
|
utils.Command("dnf search nginx", "поиск пакета")
|
||||||
|
utils.Command("dnf info nginx", "информация о пакете")
|
||||||
|
utils.Command("dnf install nginx", "установить")
|
||||||
|
utils.Command("dnf install nginx -y", "без подтверждения")
|
||||||
|
utils.Command("dnf remove nginx", "удалить")
|
||||||
|
utils.Command("dnf update", "обновить все пакеты")
|
||||||
|
utils.Command("dnf update nginx", "обновить конкретный")
|
||||||
|
utils.Command("dnf upgrade --refresh", "обновить с принудительным обновлением метаданных")
|
||||||
|
utils.Command("dnf check-update", "показать доступные обновления")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Запросы и история:" + utils.ColorReset)
|
||||||
|
utils.Command("dnf list installed", "установленные пакеты")
|
||||||
|
utils.Command("dnf list available", "доступные пакеты")
|
||||||
|
utils.Command("dnf list | grep nginx", "найти в списке")
|
||||||
|
utils.Command("dnf provides /usr/bin/python3", "какой пакет предоставляет файл")
|
||||||
|
utils.Command("dnf provides '*/Makefile'", "поиск по glob")
|
||||||
|
utils.Command("rpm -ql nginx", "файлы установленного пакета")
|
||||||
|
utils.Command("rpm -qf /etc/nginx/nginx.conf", "какому пакету принадлежит файл")
|
||||||
|
utils.Command("rpm -qi nginx", "информация об установленном пакете")
|
||||||
|
utils.Command("dnf history", "история операций")
|
||||||
|
utils.Command("dnf history undo 5", "отменить операцию №5")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Группы пакетов:" + utils.ColorReset)
|
||||||
|
utils.Command("dnf group list", "список групп")
|
||||||
|
utils.Command("dnf group info 'Development Tools'", "информация о группе")
|
||||||
|
utils.Command("dnf group install 'Development Tools'", "установить группу")
|
||||||
|
utils.Command("dnf group remove 'Development Tools'", "удалить группу")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Репозитории:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Список репозиториев:
|
||||||
|
dnf repolist
|
||||||
|
dnf repolist all # включая отключённые
|
||||||
|
|
||||||
|
# Включить/выключить репозиторий:
|
||||||
|
dnf config-manager --enable epel
|
||||||
|
dnf config-manager --disable crb
|
||||||
|
|
||||||
|
# Добавить репозиторий:
|
||||||
|
dnf install epel-release # EPEL (Extra Packages for Enterprise Linux)
|
||||||
|
dnf config-manager --add-repo https://rpm.example.com/example.repo
|
||||||
|
|
||||||
|
# Установить из конкретного репозитория:
|
||||||
|
dnf install nginx --repo=epel
|
||||||
|
|
||||||
|
# Файл репозитория (/etc/yum.repos.d/myrepo.repo):
|
||||||
|
[myrepo]
|
||||||
|
name=My Repository
|
||||||
|
baseurl=https://repo.example.com/rhel/$releasever/$basearch/
|
||||||
|
enabled=1
|
||||||
|
gpgcheck=1
|
||||||
|
gpgkey=https://repo.example.com/RPM-GPG-KEY-myrepo`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Кэш и модули:" + utils.ColorReset)
|
||||||
|
utils.Command("dnf clean all", "очистить кэш")
|
||||||
|
utils.Command("dnf makecache", "обновить кэш метаданных")
|
||||||
|
utils.Command("dnf autoremove", "удалить ненужные зависимости")
|
||||||
|
utils.Command("dnf module list", "список модулей (AppStream)")
|
||||||
|
utils.Command("dnf module install nodejs:18", "установить модуль nodejs версии 18")
|
||||||
|
utils.Command("dnf module enable postgresql:15", "включить модуль")
|
||||||
|
|
||||||
|
// ─── apt ──────────────────────────────────────────────────────
|
||||||
|
utils.Section("apt — Debian / Ubuntu")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Основные операции:" + utils.ColorReset)
|
||||||
|
utils.Command("apt search nginx", "поиск пакета")
|
||||||
|
utils.Command("apt show nginx", "информация о пакете")
|
||||||
|
utils.Command("apt install nginx", "установить")
|
||||||
|
utils.Command("apt install nginx -y", "без подтверждения")
|
||||||
|
utils.Command("apt remove nginx", "удалить (конфиги остаются)")
|
||||||
|
utils.Command("apt purge nginx", "удалить с конфигами")
|
||||||
|
utils.Command("apt update", "обновить индекс репозиториев (метаданные)")
|
||||||
|
utils.Command("apt upgrade", "обновить установленные пакеты")
|
||||||
|
utils.Command("apt full-upgrade", "обновить, может удалять и устанавливать новые")
|
||||||
|
utils.Command("apt dist-upgrade", "аналог full-upgrade")
|
||||||
|
utils.Command("apt autoremove", "удалить ненужные зависимости")
|
||||||
|
utils.Command("apt clean", "очистить кэш скачанных пакетов")
|
||||||
|
utils.Command("apt autoclean", "очистить устаревший кэш")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Запросы:" + utils.ColorReset)
|
||||||
|
utils.Command("apt list --installed", "установленные пакеты")
|
||||||
|
utils.Command("apt list --upgradable", "пакеты с доступными обновлениями")
|
||||||
|
utils.Command("dpkg -l nginx", "статус установленного пакета")
|
||||||
|
utils.Command("dpkg -L nginx", "файлы установленного пакета")
|
||||||
|
utils.Command("dpkg -S /etc/nginx/nginx.conf", "какому пакету принадлежит файл")
|
||||||
|
utils.Command("dpkg -s nginx", "информация об установленном пакете")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Репозитории (Debian/Ubuntu):" + utils.ColorReset)
|
||||||
|
utils.Code(`# Конфиг: /etc/apt/sources.list
|
||||||
|
# Ubuntu 22.04:
|
||||||
|
deb http://ru.archive.ubuntu.com/ubuntu jammy main restricted
|
||||||
|
deb http://ru.archive.ubuntu.com/ubuntu jammy-updates main restricted
|
||||||
|
deb http://security.ubuntu.com/ubuntu jammy-security main restricted
|
||||||
|
|
||||||
|
# Добавить PPA (Ubuntu):
|
||||||
|
add-apt-repository ppa:ondrej/php
|
||||||
|
apt update
|
||||||
|
apt install php8.3
|
||||||
|
|
||||||
|
# Добавить сторонний репозиторий (пример nginx):
|
||||||
|
# 1. Импортировать GPG-ключ:
|
||||||
|
curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
|
||||||
|
-o /etc/apt/keyrings/nginx.gpg
|
||||||
|
# 2. Добавить репозиторий:
|
||||||
|
echo "deb [signed-by=/etc/apt/keyrings/nginx.gpg] \
|
||||||
|
http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" \
|
||||||
|
> /etc/apt/sources.list.d/nginx.list
|
||||||
|
# 3. Обновить и установить:
|
||||||
|
apt update && apt install nginx
|
||||||
|
|
||||||
|
# Файл в /etc/apt/sources.list.d/: формат .list или .sources (deb822)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Низкоуровневые операции (dpkg):" + utils.ColorReset)
|
||||||
|
utils.Code(`# Установить .deb файл:
|
||||||
|
dpkg -i package.deb
|
||||||
|
apt install -f # исправить зависимости после dpkg
|
||||||
|
|
||||||
|
# Удалить:
|
||||||
|
dpkg -r package # без конфигов
|
||||||
|
dpkg -P package # с конфигами (purge)
|
||||||
|
|
||||||
|
# Reconfigure (перенастроить):
|
||||||
|
dpkg-reconfigure tzdata
|
||||||
|
dpkg-reconfigure locales`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Общие инструменты управления ПО:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Snap (Ubuntu, кросс-дистрибутивный):
|
||||||
|
snap install code --classic
|
||||||
|
snap list
|
||||||
|
snap remove code
|
||||||
|
snap refresh
|
||||||
|
|
||||||
|
# Flatpak (кросс-дистрибутивный):
|
||||||
|
flatpak install flathub org.gimp.GIMP
|
||||||
|
flatpak run org.gimp.GIMP
|
||||||
|
flatpak list
|
||||||
|
|
||||||
|
# pip (Python):
|
||||||
|
pip install requests
|
||||||
|
pip install -r requirements.txt
|
||||||
|
pip list
|
||||||
|
|
||||||
|
# npm (Node.js):
|
||||||
|
npm install -g pm2
|
||||||
|
npm list -g`)
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
264
modules/linuxmodules/linux_perfomance.go
Normal file
264
modules/linuxmodules/linux_perfomance.go
Normal file
|
|
@ -0,0 +1,264 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var PerformanceModule = Module{
|
||||||
|
Key: "performance",
|
||||||
|
Aliases: []string{"perf", "swap", "tuned", "производительность"},
|
||||||
|
Title: "Производительность системы",
|
||||||
|
Description: "Темы 49–52: виртуальная память, планировщик CPU, tuned, Stratis",
|
||||||
|
Run: showPerformance,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showPerformance() {
|
||||||
|
utils.Header("Linux — Производительность системы")
|
||||||
|
|
||||||
|
// ─── 49. Виртуальная память, swap ────────────────────────────
|
||||||
|
utils.Section("49. Виртуальная память и swap")
|
||||||
|
|
||||||
|
utils.Println("Виртуальная память — механизм ядра, позволяющий процессам иметь")
|
||||||
|
utils.Println("больше памяти, чем физически установлено, за счёт использования диска.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Swap — раздел/файл подкачки:" + utils.ColorReset)
|
||||||
|
utils.Code(`Когда физической RAM не хватает, ядро перемещает
|
||||||
|
редко используемые страницы памяти на swap.
|
||||||
|
Это медленнее RAM в сотни раз, но лучше OOM-killer.
|
||||||
|
|
||||||
|
Типы swap:
|
||||||
|
- раздел swap (swap partition) — отдельный раздел диска
|
||||||
|
- файл swap (swapfile) — обычный файл на любой ФС`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Просмотр swap:" + utils.ColorReset)
|
||||||
|
utils.Command("free -h", "RAM и swap (human-readable)")
|
||||||
|
utils.Command("swapon --show", "активные swap-устройства")
|
||||||
|
utils.Command("cat /proc/swaps", "то же через /proc")
|
||||||
|
utils.Command("vmstat -s", "статистика памяти и swap")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Создание swapfile:" + utils.ColorReset)
|
||||||
|
utils.Code(`# 1. Создать файл нужного размера:
|
||||||
|
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 # 2 ГБ
|
||||||
|
# или быстрее:
|
||||||
|
sudo fallocate -l 2G /swapfile
|
||||||
|
|
||||||
|
# 2. Установить права (только root):
|
||||||
|
sudo chmod 600 /swapfile
|
||||||
|
|
||||||
|
# 3. Форматировать как swap:
|
||||||
|
sudo mkswap /swapfile
|
||||||
|
|
||||||
|
# 4. Активировать:
|
||||||
|
sudo swapon /swapfile
|
||||||
|
|
||||||
|
# 5. Добавить в /etc/fstab для автоматической активации:
|
||||||
|
echo '/swapfile none swap defaults 0 0' | sudo tee -a /etc/fstab`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Управление swap:" + utils.ColorReset)
|
||||||
|
utils.Command("swapon /dev/sdb2", "активировать swap-раздел")
|
||||||
|
utils.Command("swapoff /swapfile", "деактивировать")
|
||||||
|
utils.Command("swapoff -a", "деактивировать все swap")
|
||||||
|
utils.Command("swapon -a", "активировать все из /etc/fstab")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "vm.swappiness — настройка агрессивности swap:" + utils.ColorReset)
|
||||||
|
utils.Code(`# swappiness: 0–100
|
||||||
|
# 0 — использовать swap только при нехватке RAM
|
||||||
|
# 60 — по умолчанию
|
||||||
|
# 100 — активно перемещать страницы в swap
|
||||||
|
|
||||||
|
# Посмотреть:
|
||||||
|
cat /proc/sys/vm/swappiness
|
||||||
|
sysctl vm.swappiness
|
||||||
|
|
||||||
|
# Изменить временно:
|
||||||
|
sudo sysctl -w vm.swappiness=10
|
||||||
|
|
||||||
|
# Постоянно в /etc/sysctl.d/99-swap.conf:
|
||||||
|
vm.swappiness = 10
|
||||||
|
vm.vfs_cache_pressure = 50 # агрессивность освобождения кэша inode`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "OOM-killer (Out Of Memory):" + utils.ColorReset)
|
||||||
|
utils.Code(`Когда память (RAM + swap) исчерпана, ядро убивает процессы.
|
||||||
|
|
||||||
|
# Посмотреть OOM-события в логах:
|
||||||
|
dmesg | grep -i "oom\|killed process"
|
||||||
|
journalctl -k | grep -i oom
|
||||||
|
|
||||||
|
# oom_score — чем выше, тем вероятнее убийство:
|
||||||
|
cat /proc/PID/oom_score
|
||||||
|
|
||||||
|
# Защитить процесс от OOM (от -17 до 15):
|
||||||
|
echo -1000 > /proc/PID/oom_score_adj # максимальная защита
|
||||||
|
# или через systemd в юните:
|
||||||
|
OOMScoreAdjust=-1000`)
|
||||||
|
|
||||||
|
// ─── 50. Планировщик процессов ───────────────────────────────
|
||||||
|
utils.Section("50. Планировщик процессов")
|
||||||
|
|
||||||
|
utils.Println("Планировщик CPU распределяет процессорное время между процессами.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Политики планирования:" + utils.ColorReset)
|
||||||
|
utils.Code(`SCHED_OTHER — обычные процессы (CFS — Completely Fair Scheduler)
|
||||||
|
SCHED_FIFO — реального времени, без вытеснения
|
||||||
|
SCHED_RR — реального времени, с квантованием
|
||||||
|
SCHED_BATCH — фоновые задачи (CPU-bound)
|
||||||
|
SCHED_IDLE — минимальный приоритет (ниже nice 19)
|
||||||
|
SCHED_DEADLINE — задачи с дедлайном`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "nice и renice — управление приоритетом:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Nice: -20 (высший приоритет) → 19 (низший)
|
||||||
|
# По умолчанию: 0
|
||||||
|
# Только root может установить отрицательные значения
|
||||||
|
|
||||||
|
# Запустить с пониженным приоритетом:
|
||||||
|
nice -n 15 make -j8 # фоновая сборка
|
||||||
|
|
||||||
|
# Запустить с повышенным (root):
|
||||||
|
sudo nice -n -10 realtime_app
|
||||||
|
|
||||||
|
# Изменить приоритет запущенного процесса:
|
||||||
|
renice -n 5 -p 1234 # по PID
|
||||||
|
renice -n 10 -u alice # всем процессам пользователя
|
||||||
|
sudo renice -n -5 -p 1234 # повысить (нужен root)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "chrt — управление политикой планирования:" + utils.ColorReset)
|
||||||
|
utils.Command("chrt -p 1234", "показать политику процесса")
|
||||||
|
utils.Command("chrt -f -p 50 1234", "установить FIFO с приоритетом 50")
|
||||||
|
utils.Command("chrt -r 1234", "установить Round-Robin")
|
||||||
|
utils.Command("chrt -o -p 0 1234", "обычная политика (SCHED_OTHER)")
|
||||||
|
utils.Command("chrt -f 50 ./myapp", "запустить с FIFO приоритетом 50")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Просмотр загрузки CPU:" + utils.ColorReset)
|
||||||
|
utils.Command("mpstat 1 5", "загрузка каждого CPU (пакет sysstat)")
|
||||||
|
utils.Command("mpstat -P ALL 1", "все ядра каждую секунду")
|
||||||
|
utils.Command("iostat -x 1", "статистика I/O дисков")
|
||||||
|
utils.Command("sar -u 1 10", "средняя загрузка CPU 10 раз по 1 сек")
|
||||||
|
utils.Command("perf top", "top по использованию CPU (нужен perf)")
|
||||||
|
utils.Code(`# cpupower — управление частотой CPU:
|
||||||
|
cpupower frequency-info # текущий режим
|
||||||
|
cpupower frequency-set -g performance # режим производительности
|
||||||
|
# governors: performance, powersave, ondemand, conservative`)
|
||||||
|
|
||||||
|
// ─── 51. tuned ────────────────────────────────────────────────
|
||||||
|
utils.Section("51. Оптимизация производительности — tuned")
|
||||||
|
|
||||||
|
utils.Println("tuned — демон автоматической оптимизации системы по профилям.")
|
||||||
|
utils.Println("Настраивает CPU, диски, сеть под конкретные сценарии использования.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Управление tuned:" + utils.ColorReset)
|
||||||
|
utils.Command("systemctl status tuned", "статус демона")
|
||||||
|
utils.Command("tuned-adm active", "текущий профиль")
|
||||||
|
utils.Command("tuned-adm list", "список доступных профилей")
|
||||||
|
utils.Command("tuned-adm profile throughput-performance", "применить профиль")
|
||||||
|
utils.Command("tuned-adm recommend", "рекомендованный профиль для этой системы")
|
||||||
|
utils.Command("tuned-adm off", "отключить tuned")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Встроенные профили:" + utils.ColorReset)
|
||||||
|
utils.Code(`balanced — баланс производительности и энергопотребления
|
||||||
|
powersave — минимальное энергопотребление
|
||||||
|
throughput-performance — максимальная пропускная способность (серверы)
|
||||||
|
latency-performance — минимальная задержка (без энергосбережения)
|
||||||
|
network-latency — минимальная сетевая задержка
|
||||||
|
network-throughput — максимальная сетевая пропускная способность
|
||||||
|
virtual-guest — оптимизация для виртуальных машин
|
||||||
|
virtual-host — оптимизация для хоста виртуализации
|
||||||
|
oracle — для Oracle DB
|
||||||
|
mssql — для MS SQL Server
|
||||||
|
desktop — для рабочих станций`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Создание собственного профиля:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Профили хранятся в /usr/lib/tuned/ (системные)
|
||||||
|
# и /etc/tuned/ (пользовательские)
|
||||||
|
|
||||||
|
# Создать профиль на основе существующего:
|
||||||
|
mkdir /etc/tuned/myprofile
|
||||||
|
cat > /etc/tuned/myprofile/tuned.conf << 'EOF'
|
||||||
|
[main]
|
||||||
|
summary=Мой профиль
|
||||||
|
include=throughput-performance
|
||||||
|
|
||||||
|
[cpu]
|
||||||
|
governor=performance
|
||||||
|
energy_perf_bias=performance
|
||||||
|
|
||||||
|
[disk]
|
||||||
|
readahead=>4096
|
||||||
|
|
||||||
|
[sysctl]
|
||||||
|
vm.swappiness=10
|
||||||
|
net.core.somaxconn=65535
|
||||||
|
EOF
|
||||||
|
|
||||||
|
tuned-adm profile myprofile`)
|
||||||
|
|
||||||
|
// ─── 52. Stratis ──────────────────────────────────────────────
|
||||||
|
utils.Section("52. Управление многоуровневым хранилищем — Stratis")
|
||||||
|
|
||||||
|
utils.Println("Stratis — менеджер хранилища от Red Hat (RHEL 8+).")
|
||||||
|
utils.Println("Упрощает создание пулов, снапшотов и тонкого выделения места.")
|
||||||
|
utils.Println("Работает поверх LVM и XFS.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`Архитектура Stratis:
|
||||||
|
Physical Device (/dev/sdb, /dev/sdc)
|
||||||
|
↓
|
||||||
|
Pool (пул хранилища)
|
||||||
|
↓
|
||||||
|
Filesystem (XFS файловая система)
|
||||||
|
|
||||||
|
Особенности:
|
||||||
|
- Тонкое выделение (thin provisioning)
|
||||||
|
- Снапшоты (моментальные снимки)
|
||||||
|
- Кэширование (SSD как кэш для HDD)
|
||||||
|
- Автоматическое управление XFS`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Установка и запуск:" + utils.ColorReset)
|
||||||
|
utils.Code(`# RHEL/Fedora:
|
||||||
|
dnf install stratisd stratis-cli
|
||||||
|
systemctl enable --now stratisd`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Работа с пулами:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Создать пул:
|
||||||
|
stratis pool create mypool /dev/sdb
|
||||||
|
stratis pool create mypool /dev/sdb /dev/sdc # из нескольких дисков
|
||||||
|
|
||||||
|
# Добавить диск в существующий пул:
|
||||||
|
stratis pool add-data mypool /dev/sdd
|
||||||
|
|
||||||
|
# Добавить кэш (SSD):
|
||||||
|
stratis pool add-cache mypool /dev/nvme0n1
|
||||||
|
|
||||||
|
# Список пулов:
|
||||||
|
stratis pool list
|
||||||
|
|
||||||
|
# Детали пула:
|
||||||
|
stratis pool info mypool`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Работа с файловыми системами:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Создать ФС в пуле:
|
||||||
|
stratis filesystem create mypool myfs
|
||||||
|
|
||||||
|
# Список ФС:
|
||||||
|
stratis filesystem list
|
||||||
|
stratis fs
|
||||||
|
|
||||||
|
# Монтирование:
|
||||||
|
mount /stratis/mypool/myfs /mnt/data
|
||||||
|
|
||||||
|
# В /etc/fstab (с x-systemd.requires):
|
||||||
|
/stratis/mypool/myfs /mnt/data xfs defaults,x-systemd.requires=stratisd.service 0 0
|
||||||
|
|
||||||
|
# Создать снапшот:
|
||||||
|
stratis filesystem snapshot mypool myfs myfs-snapshot
|
||||||
|
|
||||||
|
# Удалить ФС:
|
||||||
|
stratis filesystem destroy mypool myfs
|
||||||
|
|
||||||
|
# Удалить пул (сначала удалить все ФС):
|
||||||
|
stratis pool destroy mypool`)
|
||||||
|
|
||||||
|
utils.Note("Stratis автоматически форматирует дискипод XFS. Не используйте mkfs вручную.")
|
||||||
|
utils.Note("Снапшоты — это отдельные ФС. Можно смонтировать для восстановления файлов.")
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
207
modules/linuxmodules/linux_processes.go
Normal file
207
modules/linuxmodules/linux_processes.go
Normal file
|
|
@ -0,0 +1,207 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ProcessesModule = Module{
|
||||||
|
Key: "processes",
|
||||||
|
Aliases: []string{"proc", "ps", "процессы"},
|
||||||
|
Title: "Процессы",
|
||||||
|
Description: "Темы 14–16: информация о процессах, сигналы, управление процессами",
|
||||||
|
Run: showProcesses,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showProcesses() {
|
||||||
|
utils.Header("Linux — Процессы")
|
||||||
|
|
||||||
|
// ─── 14. Процессы №1: информация ─────────────────────────────
|
||||||
|
utils.Section("14. Процессы №1: информация о процессах")
|
||||||
|
|
||||||
|
utils.Println("Процесс — выполняющаяся программа. Каждый процесс имеет уникальный PID.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "ps — информация о процессах:" + utils.ColorReset)
|
||||||
|
utils.Command("ps", "процессы текущего терминала")
|
||||||
|
utils.Command("ps aux", "все процессы всех пользователей (BSD стиль)")
|
||||||
|
utils.Command("ps -ef", "все процессы (UNIX стиль)")
|
||||||
|
utils.Command("ps aux | grep nginx", "найти процессы nginx")
|
||||||
|
utils.Command("ps -u alice", "процессы пользователя alice")
|
||||||
|
utils.Command("ps --forest", "дерево процессов (родитель → потомок)")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`# Вывод ps aux:
|
||||||
|
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
||||||
|
root 1 0.0 0.1 168384 13312 ? Ss Jan01 0:05 /sbin/init
|
||||||
|
alice 1234 2.1 1.5 567890 61234 pts/0 Sl 10:30 0:12 firefox
|
||||||
|
|
||||||
|
Поля:
|
||||||
|
USER — владелец процесса
|
||||||
|
PID — Process ID (уникальный номер)
|
||||||
|
PPID — Parent PID (родительский процесс)
|
||||||
|
%CPU — использование процессора
|
||||||
|
%MEM — использование памяти
|
||||||
|
VSZ — виртуальная память (КБ)
|
||||||
|
RSS — реальная память (КБ)
|
||||||
|
TTY — терминал (? = нет терминала, демон)
|
||||||
|
STAT — состояние процесса
|
||||||
|
START — время запуска
|
||||||
|
TIME — суммарное CPU-время
|
||||||
|
COMMAND — команда
|
||||||
|
|
||||||
|
Коды состояния (STAT):
|
||||||
|
R — Running (работает)
|
||||||
|
S — Sleeping (ожидает, прерываемый)
|
||||||
|
D — Sleeping (ожидает, непрерываемый, I/O)
|
||||||
|
Z — Zombie (завершён, ждёт родителя)
|
||||||
|
T — Stopped (остановлен сигналом)
|
||||||
|
s — лидер сессии
|
||||||
|
+ — процесс переднего плана
|
||||||
|
l — многопоточный`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "pstree — дерево процессов:" + utils.ColorReset)
|
||||||
|
utils.Command("pstree", "дерево всех процессов")
|
||||||
|
utils.Command("pstree -p", "с PID")
|
||||||
|
utils.Command("pstree alice", "только процессы пользователя alice")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "/proc — виртуальная файловая система:" + utils.ColorReset)
|
||||||
|
utils.Code(`/proc — информация о процессах и ядре
|
||||||
|
/proc/PID/ — директория конкретного процесса
|
||||||
|
/proc/PID/cmdline — командная строка запуска
|
||||||
|
/proc/PID/status — статус процесса (память, UID...)
|
||||||
|
/proc/PID/fd/ — открытые файловые дескрипторы
|
||||||
|
/proc/PID/maps — карта памяти процесса
|
||||||
|
/proc/cpuinfo — информация о CPU
|
||||||
|
/proc/meminfo — информация о памяти
|
||||||
|
/proc/loadavg — средняя загрузка
|
||||||
|
|
||||||
|
# Примеры:
|
||||||
|
cat /proc/1/cmdline # команда процесса PID=1
|
||||||
|
cat /proc/cpuinfo | grep "model name"
|
||||||
|
cat /proc/meminfo | grep MemAvail`)
|
||||||
|
|
||||||
|
// ─── 15. Процессы №2: информация ─────────────────────────────
|
||||||
|
utils.Section("15. Процессы №2: мониторинг в реальном времени")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "top — динамический мониторинг:" + utils.ColorReset)
|
||||||
|
utils.Command("top", "интерактивный мониторинг (обновляется каждые 3 сек)")
|
||||||
|
utils.Command("top -u alice", "только процессы пользователя alice")
|
||||||
|
utils.Command("top -p 1234,5678", "только указанные PID")
|
||||||
|
utils.Command("top -b -n 1", "пакетный режим (для скриптов/логирования)")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`Клавиши в top:
|
||||||
|
q — выйти
|
||||||
|
h — справка
|
||||||
|
k — убить процесс (ввести PID)
|
||||||
|
r — изменить nice (приоритет)
|
||||||
|
M — сортировать по памяти
|
||||||
|
P — сортировать по CPU
|
||||||
|
T — сортировать по времени
|
||||||
|
1 — показать каждый CPU отдельно
|
||||||
|
f — настройка столбцов
|
||||||
|
u — фильтр по пользователю`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "htop — улучшенный top (нужно установить):" + utils.ColorReset)
|
||||||
|
utils.Command("htop", "цветной интерактивный мониторинг")
|
||||||
|
utils.Code(`# Установка:
|
||||||
|
apt install htop # Debian/Ubuntu
|
||||||
|
dnf install htop # RHEL/Fedora`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Мониторинг ресурсов:" + utils.ColorReset)
|
||||||
|
utils.Command("free -h", "использование памяти (human-readable)")
|
||||||
|
utils.Command("free -m", "в мегабайтах")
|
||||||
|
utils.Command("vmstat 2 5", "статистика памяти, CPU каждые 2 сек, 5 раз")
|
||||||
|
utils.Command("uptime", "время работы системы и средняя загрузка")
|
||||||
|
utils.Command("w", "кто залогинен и что делает")
|
||||||
|
utils.Command("who", "список залогиненных пользователей")
|
||||||
|
utils.Command("last", "история входов в систему")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`# Средняя загрузка (load average):
|
||||||
|
uptime
|
||||||
|
# 10:30:00 up 5 days, 2:15, 2 users, load average: 0.52, 0.41, 0.35
|
||||||
|
# 1min 5min 15min
|
||||||
|
|
||||||
|
# Значение = количество процессов ждущих CPU
|
||||||
|
# На однопроцессорной системе:
|
||||||
|
# < 1.0 — нормально
|
||||||
|
# = 1.0 — 100% загрузка
|
||||||
|
# > 1.0 — перегрузка (очередь)
|
||||||
|
# На N ядрах перегрузка начинается при load > N`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "lsof — открытые файлы и соединения:" + utils.ColorReset)
|
||||||
|
utils.Command("lsof", "все открытые файлы (очень много)")
|
||||||
|
utils.Command("lsof -p 1234", "открытые файлы процесса 1234")
|
||||||
|
utils.Command("lsof -u alice", "файлы пользователя alice")
|
||||||
|
utils.Command("lsof -i :80", "что использует порт 80")
|
||||||
|
utils.Command("lsof -i TCP", "все TCP соединения")
|
||||||
|
utils.Command("lsof /var/log/syslog", "какие процессы используют этот файл")
|
||||||
|
|
||||||
|
// ─── 16. Процессы №3: управление ─────────────────────────────
|
||||||
|
utils.Section("16. Процессы №3: управление процессами")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Сигналы:" + utils.ColorReset)
|
||||||
|
utils.Code(`Сигнал — асинхронное уведомление процессу.
|
||||||
|
|
||||||
|
Номер Имя Действие по умолчанию
|
||||||
|
──────────────────────────────────────────────────────
|
||||||
|
1 SIGHUP Завершить (или перечитать конфиг для демонов)
|
||||||
|
2 SIGINT Прервать (Ctrl+C)
|
||||||
|
3 SIGQUIT Завершить с core dump (Ctrl+\)
|
||||||
|
9 SIGKILL Убить немедленно (нельзя перехватить/игнорировать)
|
||||||
|
15 SIGTERM Завершить корректно (по умолчанию для kill)
|
||||||
|
17 SIGCHLD Дочерний процесс изменил состояние
|
||||||
|
18 SIGCONT Продолжить остановленный процесс
|
||||||
|
19 SIGSTOP Остановить (нельзя перехватить/игнорировать)
|
||||||
|
20 SIGTSTP Остановить (Ctrl+Z, можно перехватить)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "kill — отправить сигнал процессу:" + utils.ColorReset)
|
||||||
|
utils.Command("kill 1234", "SIGTERM (15) процессу 1234 — корректное завершение")
|
||||||
|
utils.Command("kill -9 1234", "SIGKILL — принудительное убийство")
|
||||||
|
utils.Command("kill -15 1234", "SIGTERM явно")
|
||||||
|
utils.Command("kill -HUP 1234", "SIGHUP (перечитать конфиг)")
|
||||||
|
utils.Command("kill -l", "список всех сигналов")
|
||||||
|
utils.Command("killall nginx", "SIGTERM всем процессам с именем nginx")
|
||||||
|
utils.Command("killall -9 nginx", "SIGKILL всем nginx")
|
||||||
|
utils.Command("pkill nginx", "SIGTERM по имени (поддерживает regex)")
|
||||||
|
utils.Command("pkill -u alice", "завершить все процессы пользователя alice")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Note("Сначала используйте kill (SIGTERM) — даёт процессу завершиться корректно. SIGKILL только если SIGTERM не помог.")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Приоритет процессов (nice):" + utils.ColorReset)
|
||||||
|
utils.Code(`Nice значение: от -20 (максимальный приоритет) до 19 (минимальный)
|
||||||
|
По умолчанию: 0
|
||||||
|
|
||||||
|
# Запустить с пониженным приоритетом:
|
||||||
|
nice -n 10 make -j4
|
||||||
|
|
||||||
|
# Изменить приоритет запущенного процесса:
|
||||||
|
renice -n 5 -p 1234 # PID
|
||||||
|
renice -n 5 -u alice # для пользователя
|
||||||
|
# renice на отрицательное значение требует root`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Фоновые процессы и задания (job control):" + utils.ColorReset)
|
||||||
|
utils.Code(`# Запустить в фоне:
|
||||||
|
command & # & в конце
|
||||||
|
long_task.sh &
|
||||||
|
|
||||||
|
# Управление заданиями:
|
||||||
|
jobs # список фоновых заданий текущего терминала
|
||||||
|
jobs -l # с PID
|
||||||
|
fg # вернуть последнее задание на передний план
|
||||||
|
fg %2 # вернуть задание №2
|
||||||
|
bg # продолжить остановленное в фоне
|
||||||
|
bg %1 # продолжить задание №1 в фоне
|
||||||
|
|
||||||
|
# Ctrl+Z — приостановить текущий процесс (SIGTSTP)
|
||||||
|
# Затем bg — продолжить в фоне
|
||||||
|
|
||||||
|
# Процесс продолжит работу после выхода из терминала:
|
||||||
|
nohup command & # игнорировать SIGHUP при выходе
|
||||||
|
disown %1 # отвязать задание от терминала`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "watch — периодически выполнять команду:" + utils.ColorReset)
|
||||||
|
utils.Command("watch -n 2 'ps aux | grep nginx'", "каждые 2 сек смотреть процессы nginx")
|
||||||
|
utils.Command("watch -d free -h", "следить за памятью, выделять изменения")
|
||||||
|
utils.Command("watch -n 1 uptime", "загрузка каждую секунду")
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
69
modules/linuxmodules/linux_registry.go
Normal file
69
modules/linuxmodules/linux_registry.go
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Module описывает один раздел справочника Linux
|
||||||
|
type Module struct {
|
||||||
|
Key string
|
||||||
|
Aliases []string
|
||||||
|
Title string
|
||||||
|
Description string
|
||||||
|
Run func()
|
||||||
|
}
|
||||||
|
|
||||||
|
// All — список всех модулей в порядке меню
|
||||||
|
var All = []Module{
|
||||||
|
IntroModule,
|
||||||
|
FilesModule,
|
||||||
|
StreamsModule,
|
||||||
|
BashModule,
|
||||||
|
ProcessesModule,
|
||||||
|
UsersModule,
|
||||||
|
KernelModule,
|
||||||
|
DisksModule,
|
||||||
|
ScriptsModule,
|
||||||
|
BootModule,
|
||||||
|
LogsModule,
|
||||||
|
BackupModule,
|
||||||
|
NetworkModule,
|
||||||
|
SecurityModule,
|
||||||
|
PackagesModule,
|
||||||
|
PerformanceModule,
|
||||||
|
SysconfigModule,
|
||||||
|
NetfsModule,
|
||||||
|
ToolsModule,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find ищет модуль по ключу или алиасу
|
||||||
|
func Find(key string) (Module, bool) {
|
||||||
|
key = strings.ToLower(strings.TrimSpace(key))
|
||||||
|
for _, m := range All {
|
||||||
|
if m.Key == key {
|
||||||
|
return m, true
|
||||||
|
}
|
||||||
|
for _, a := range m.Aliases {
|
||||||
|
if a == key {
|
||||||
|
return m, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Module{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListModules выводит краткий список модулей
|
||||||
|
func ListModules() {
|
||||||
|
fmt.Printf("\n%s%sРазделы справочника Linux:%s\n\n",
|
||||||
|
utils.ColorBold, utils.ColorCyan, utils.ColorReset)
|
||||||
|
for i, m := range All {
|
||||||
|
fmt.Printf(" %s%d.%s %-12s — %s\n",
|
||||||
|
utils.ColorDim, i+1, utils.ColorReset,
|
||||||
|
utils.ColorYellow+utils.ColorBold+m.Key+utils.ColorReset,
|
||||||
|
m.Title,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
318
modules/linuxmodules/linux_scripts.go
Normal file
318
modules/linuxmodules/linux_scripts.go
Normal file
|
|
@ -0,0 +1,318 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ScriptsModule = Module{
|
||||||
|
Key: "scripts",
|
||||||
|
Aliases: []string{"sc", "scripting", "скрипты"},
|
||||||
|
Title: "Bash-скрипты",
|
||||||
|
Description: "Темы 27–32: скрипты, условия, циклы, функции, массивы",
|
||||||
|
Run: showScripts,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showScripts() {
|
||||||
|
utils.Header("Linux — Bash-скрипты")
|
||||||
|
|
||||||
|
// ─── 27. Bash скрипты №1 ──────────────────────────────────────
|
||||||
|
utils.Section("27. Основы скриптов. Условия")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Структура скрипта:" + utils.ColorReset)
|
||||||
|
utils.Code(`#!/bin/bash
|
||||||
|
# Shebang — первая строка указывает интерпретатор
|
||||||
|
# Комментарий
|
||||||
|
|
||||||
|
echo "Привет, мир!"
|
||||||
|
|
||||||
|
# Запуск скрипта:
|
||||||
|
chmod +x script.sh # сделать исполняемым
|
||||||
|
./script.sh # запустить
|
||||||
|
bash script.sh # запустить через bash (без chmod)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Переменные в скриптах:" + utils.ColorReset)
|
||||||
|
utils.Code(`#!/bin/bash
|
||||||
|
name="Alice"
|
||||||
|
count=5
|
||||||
|
|
||||||
|
echo "Имя: $name"
|
||||||
|
echo "Счёт: $count"
|
||||||
|
|
||||||
|
# Ввод от пользователя:
|
||||||
|
read -p "Введите имя: " username
|
||||||
|
echo "Привет, $username!"
|
||||||
|
|
||||||
|
# Ввод без отображения (пароль):
|
||||||
|
read -s -p "Пароль: " password`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Условный оператор if:" + utils.ColorReset)
|
||||||
|
utils.Code(`#!/bin/bash
|
||||||
|
# Базовая форма:
|
||||||
|
if [ условие ]; then
|
||||||
|
команды
|
||||||
|
elif [ другое_условие ]; then
|
||||||
|
команды
|
||||||
|
else
|
||||||
|
команды
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Примеры условий:
|
||||||
|
# Сравнение строк:
|
||||||
|
if [ "$name" = "Alice" ]; then echo "Привет, Alice"; fi
|
||||||
|
if [ "$name" != "Bob" ]; then echo "Не Боб"; fi
|
||||||
|
if [ -z "$name" ]; then echo "Пустая строка"; fi # -z = пусто
|
||||||
|
if [ -n "$name" ]; then echo "Не пустая"; fi # -n = не пусто
|
||||||
|
|
||||||
|
# Сравнение чисел:
|
||||||
|
if [ "$count" -eq 5 ]; then ... # equal
|
||||||
|
if [ "$count" -ne 5 ]; then ... # not equal
|
||||||
|
if [ "$count" -gt 3 ]; then ... # greater than
|
||||||
|
if [ "$count" -lt 10 ]; then ... # less than
|
||||||
|
if [ "$count" -ge 5 ]; then ... # greater or equal
|
||||||
|
if [ "$count" -le 5 ]; then ... # less or equal
|
||||||
|
|
||||||
|
# Файлы и директории:
|
||||||
|
if [ -f /etc/passwd ]; then echo "файл существует"; fi
|
||||||
|
if [ -d /tmp ]; then echo "директория существует"; fi
|
||||||
|
if [ -e /dev/sda ]; then echo "путь существует"; fi
|
||||||
|
if [ -r file ]; then echo "доступен для чтения"; fi
|
||||||
|
if [ -w file ]; then echo "доступен для записи"; fi
|
||||||
|
if [ -x script.sh ]; then echo "исполняемый"; fi
|
||||||
|
if [ -s file ]; then echo "файл не пустой"; fi
|
||||||
|
if [ file1 -nt file2 ]; then echo "file1 новее"; fi
|
||||||
|
|
||||||
|
# Логика:
|
||||||
|
if [ cond1 ] && [ cond2 ]; then ... # И
|
||||||
|
if [ cond1 ] || [ cond2 ]; then ... # ИЛИ
|
||||||
|
if ! [ cond ]; then ... # НЕ
|
||||||
|
|
||||||
|
# [[ ]] — расширенные условия bash:
|
||||||
|
if [[ "$str" == *"подстрока"* ]]; then ... # glob
|
||||||
|
if [[ "$str" =~ ^[0-9]+$ ]]; then ... # regex`)
|
||||||
|
|
||||||
|
// ─── 28–29. Bash скрипты №2–3 ─────────────────────────────────
|
||||||
|
utils.Section("28–29. Циклы")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Цикл for:" + utils.ColorReset)
|
||||||
|
utils.Code(`# По списку:
|
||||||
|
for item in один два три; do
|
||||||
|
echo "$item"
|
||||||
|
done
|
||||||
|
|
||||||
|
# По числовому диапазону:
|
||||||
|
for i in {1..5}; do
|
||||||
|
echo "Шаг $i"
|
||||||
|
done
|
||||||
|
|
||||||
|
# С шагом:
|
||||||
|
for i in {0..20..5}; do echo "$i"; done # 0 5 10 15 20
|
||||||
|
|
||||||
|
# C-стиль:
|
||||||
|
for ((i=0; i<5; i++)); do
|
||||||
|
echo "$i"
|
||||||
|
done
|
||||||
|
|
||||||
|
# По файлам:
|
||||||
|
for file in /etc/*.conf; do
|
||||||
|
echo "Обрабатываю: $file"
|
||||||
|
done
|
||||||
|
|
||||||
|
# По строкам вывода команды:
|
||||||
|
for user in $(cat /etc/passwd | cut -d: -f1); do
|
||||||
|
echo "Пользователь: $user"
|
||||||
|
done`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Цикл while:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Пока условие истинно:
|
||||||
|
count=0
|
||||||
|
while [ $count -lt 5 ]; do
|
||||||
|
echo "count = $count"
|
||||||
|
((count++))
|
||||||
|
done
|
||||||
|
|
||||||
|
# Чтение файла построчно:
|
||||||
|
while IFS= read -r line; do
|
||||||
|
echo "Строка: $line"
|
||||||
|
done < /etc/hosts
|
||||||
|
|
||||||
|
# Бесконечный цикл:
|
||||||
|
while true; do
|
||||||
|
echo "Работаю..."
|
||||||
|
sleep 1
|
||||||
|
done`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Цикл until и управление циклами:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Пока условие ложно:
|
||||||
|
until [ -f /tmp/ready ]; do
|
||||||
|
echo "Жду файл..."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
# break — выйти из цикла:
|
||||||
|
for i in {1..10}; do
|
||||||
|
if [ $i -eq 5 ]; then break; fi
|
||||||
|
echo $i
|
||||||
|
done
|
||||||
|
|
||||||
|
# continue — перейти к следующей итерации:
|
||||||
|
for i in {1..10}; do
|
||||||
|
if [ $((i % 2)) -eq 0 ]; then continue; fi
|
||||||
|
echo "Нечётное: $i"
|
||||||
|
done`)
|
||||||
|
|
||||||
|
// ─── 30–31. Bash скрипты №4–5 ─────────────────────────────────
|
||||||
|
utils.Section("30–31. Функции и обработка ошибок")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Функции:" + utils.ColorReset)
|
||||||
|
utils.Code(`#!/bin/bash
|
||||||
|
# Объявление функции:
|
||||||
|
greet() {
|
||||||
|
local name=$1 # local — локальная переменная
|
||||||
|
echo "Привет, $name!"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Или:
|
||||||
|
function greet {
|
||||||
|
echo "Привет, $1!"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Вызов:
|
||||||
|
greet "Alice"
|
||||||
|
greet "Bob"
|
||||||
|
|
||||||
|
# Возвращаемое значение:
|
||||||
|
# Функции возвращают только числа (код возврата 0-255)
|
||||||
|
is_root() {
|
||||||
|
[ "$(id -u)" -eq 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_root; then
|
||||||
|
echo "Запущен как root"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Для передачи строк — echo + подстановка команд:
|
||||||
|
get_hostname() {
|
||||||
|
echo "$(hostname)"
|
||||||
|
}
|
||||||
|
host=$(get_hostname)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Обработка ошибок:" + utils.ColorReset)
|
||||||
|
utils.Code(`#!/bin/bash
|
||||||
|
# Остановить при ошибке:
|
||||||
|
set -e # выйти при любой ошибке (exit on error)
|
||||||
|
set -u # ошибка при неопределённой переменной
|
||||||
|
set -o pipefail # учитывать ошибки в pipe
|
||||||
|
set -euo pipefail # всё вместе (рекомендуется)
|
||||||
|
|
||||||
|
# Проверка кода возврата:
|
||||||
|
if ! mkdir /tmp/mydir 2>/dev/null; then
|
||||||
|
echo "Ошибка создания директории" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Функция для вывода ошибок:
|
||||||
|
error() {
|
||||||
|
echo "ОШИБКА: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[ -f "$1" ] || error "Файл $1 не найден"
|
||||||
|
|
||||||
|
# Trap — обработка сигналов и выхода:
|
||||||
|
cleanup() {
|
||||||
|
rm -f /tmp/tempfile
|
||||||
|
echo "Очищено"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT # при любом выходе
|
||||||
|
trap cleanup INT TERM # при Ctrl+C или kill`)
|
||||||
|
|
||||||
|
// ─── 32. Bash скрипты №6 ──────────────────────────────────────
|
||||||
|
utils.Section("32. Массивы, строки и аргументы скрипта")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Массивы:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Объявление:
|
||||||
|
fruits=("яблоко" "банан" "апельсин")
|
||||||
|
declare -a numbers=(1 2 3 4 5)
|
||||||
|
|
||||||
|
# Доступ:
|
||||||
|
echo "${fruits[0]}" # яблоко (индекс с 0)
|
||||||
|
echo "${fruits[@]}" # все элементы
|
||||||
|
echo "${#fruits[@]}" # количество элементов
|
||||||
|
echo "${fruits[@]:1:2}" # срез: с индекса 1, 2 элемента
|
||||||
|
|
||||||
|
# Добавить элемент:
|
||||||
|
fruits+=("манго")
|
||||||
|
|
||||||
|
# Перебор:
|
||||||
|
for fruit in "${fruits[@]}"; do
|
||||||
|
echo "$fruit"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Перебор с индексом:
|
||||||
|
for i in "${!fruits[@]}"; do
|
||||||
|
echo "$i: ${fruits[$i]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Ассоциативный массив (словарь):
|
||||||
|
declare -A user
|
||||||
|
user[name]="Alice"
|
||||||
|
user[age]=30
|
||||||
|
echo "${user[name]}"
|
||||||
|
echo "${!user[@]}" # ключи
|
||||||
|
echo "${user[@]}" # значения`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Аргументы скрипта:" + utils.ColorReset)
|
||||||
|
utils.Code(`#!/bin/bash
|
||||||
|
# Позиционные параметры:
|
||||||
|
echo "Скрипт: $0"
|
||||||
|
echo "Первый аргумент: $1"
|
||||||
|
echo "Второй аргумент: $2"
|
||||||
|
echo "Все аргументы: $@"
|
||||||
|
echo "Количество аргументов: $#"
|
||||||
|
|
||||||
|
# Проверка аргументов:
|
||||||
|
if [ $# -lt 2 ]; then
|
||||||
|
echo "Использование: $0 <имя> <возраст>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Обработка опций (getopts):
|
||||||
|
while getopts "hv:n:" opt; do
|
||||||
|
case $opt in
|
||||||
|
h) echo "Справка"; exit 0 ;;
|
||||||
|
v) verbose=true ;;
|
||||||
|
n) name="$OPTARG" ;;
|
||||||
|
?) echo "Неизвестный ключ"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# shift — сдвинуть аргументы:
|
||||||
|
shift $((OPTIND - 1)) # убрать опции, остались обычные аргументы`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Полезные приёмы:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Цвета в терминале:
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
echo -e "${RED}Ошибка${NC}"
|
||||||
|
echo -e "${GREEN}Успех${NC}"
|
||||||
|
|
||||||
|
# Прогресс-бар простой:
|
||||||
|
for i in {1..10}; do
|
||||||
|
echo -ne "\rПрогресс: $((i*10))%"
|
||||||
|
sleep 0.1
|
||||||
|
done; echo
|
||||||
|
|
||||||
|
# Логирование:
|
||||||
|
LOG=/var/log/myscript.log
|
||||||
|
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG"; }
|
||||||
|
log "Скрипт запущен"
|
||||||
|
|
||||||
|
# Ожидание с таймаутом:
|
||||||
|
timeout 30 ./long_command.sh || echo "Таймаут!"`)
|
||||||
|
fmt.Println()
|
||||||
|
utils.Note("Проверяйте скрипты на ошибки: bash -n script.sh (синтаксис) и bash -x script.sh (трассировка).")
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
276
modules/linuxmodules/linux_security.go
Normal file
276
modules/linuxmodules/linux_security.go
Normal file
|
|
@ -0,0 +1,276 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var SecurityModule = Module{
|
||||||
|
Key: "security",
|
||||||
|
Aliases: []string{"sec", "selinux", "firewall", "безопасность"},
|
||||||
|
Title: "Безопасность: SELinux и Firewall",
|
||||||
|
Description: "Темы 45–46, 48: SELinux, firewalld, восстановление доступа",
|
||||||
|
Run: showSecurity,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showSecurity() {
|
||||||
|
utils.Header("Linux — Безопасность: SELinux и Firewall")
|
||||||
|
|
||||||
|
// ─── 45. SELinux ──────────────────────────────────────────────
|
||||||
|
utils.Section("45. Принудительный контроль доступа — SELinux")
|
||||||
|
|
||||||
|
utils.Println("SELinux (Security-Enhanced Linux) — система принудительного контроля доступа.")
|
||||||
|
utils.Println("Работает поверх обычных прав Unix: даже root ограничен политикой SELinux.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Режимы SELinux:" + utils.ColorReset)
|
||||||
|
utils.Code(`Enforcing — SELinux активен, запрещённые действия блокируются
|
||||||
|
и логируются (производственный режим)
|
||||||
|
Permissive — SELinux активен, нарушения только логируются
|
||||||
|
(не блокируются). Для отладки.
|
||||||
|
Disabled — SELinux полностью отключён (требует перезагрузки)
|
||||||
|
|
||||||
|
# Текущий режим:
|
||||||
|
getenforce
|
||||||
|
sestatus # подробная информация
|
||||||
|
|
||||||
|
# Временно изменить режим (до перезагрузки):
|
||||||
|
setenforce 0 # Enforcing → Permissive
|
||||||
|
setenforce 1 # Permissive → Enforcing
|
||||||
|
setenforce Permissive # то же самое
|
||||||
|
|
||||||
|
# Постоянно — /etc/selinux/config:
|
||||||
|
SELINUX=enforcing # enforcing / permissive / disabled
|
||||||
|
SELINUXTYPE=targeted # политика
|
||||||
|
|
||||||
|
# После изменения с/на disabled — нужна перезагрузка.
|
||||||
|
# При включении SELinux после disabled — нужна переметка файлов:
|
||||||
|
touch /.autorelabel && reboot`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Контексты SELinux:" + utils.ColorReset)
|
||||||
|
utils.Code(`Каждый файл, процесс и порт имеет SELinux-контекст:
|
||||||
|
user:role:type:level
|
||||||
|
↓ ↓ ↓ ↓
|
||||||
|
system_u:object_r:httpd_sys_content_t:s0
|
||||||
|
|
||||||
|
Самое важное — type (тип): httpd_sys_content_t, etc_t...
|
||||||
|
|
||||||
|
# Просмотр контекстов файлов:
|
||||||
|
ls -Z /var/www/html/
|
||||||
|
ls -lZ /etc/nginx/
|
||||||
|
|
||||||
|
# Просмотр контекста процессов:
|
||||||
|
ps auxZ | grep nginx
|
||||||
|
|
||||||
|
# Просмотр контекста портов:
|
||||||
|
semanage port -l | grep http`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Управление контекстами:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Изменить контекст файла:
|
||||||
|
chcon -t httpd_sys_content_t /var/www/mysite/
|
||||||
|
chcon -R -t httpd_sys_content_t /var/www/mysite/ # рекурсивно
|
||||||
|
|
||||||
|
# Проблема: chcon не постоянен, restorecon сбросит его.
|
||||||
|
# Правильно: использовать semanage fcontext:
|
||||||
|
|
||||||
|
# Добавить постоянное правило для контекста:
|
||||||
|
semanage fcontext -a -t httpd_sys_content_t '/srv/web(/.*)?'
|
||||||
|
# Применить правила к файлам:
|
||||||
|
restorecon -Rv /srv/web/
|
||||||
|
|
||||||
|
# Восстановить контекст по умолчанию:
|
||||||
|
restorecon -Rv /var/www/html/
|
||||||
|
|
||||||
|
# Проверить ожидаемый контекст:
|
||||||
|
matchpathcon /var/www/html/index.html`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Булевые переменные SELinux (Booleans):" + utils.ColorReset)
|
||||||
|
utils.Code(`# Booleans — включают/выключают определённые возможности:
|
||||||
|
|
||||||
|
# Просмотр всех:
|
||||||
|
getsebool -a
|
||||||
|
getsebool -a | grep httpd
|
||||||
|
|
||||||
|
# Включить/выключить (временно):
|
||||||
|
setsebool httpd_can_network_connect on
|
||||||
|
setsebool httpd_can_network_connect off
|
||||||
|
|
||||||
|
# Постоянно (после перезагрузки):
|
||||||
|
setsebool -P httpd_can_network_connect on
|
||||||
|
setsebool -P httpd_enable_homedirs on
|
||||||
|
|
||||||
|
# Полезные booleans:
|
||||||
|
httpd_can_network_connect # nginx/apache → внешняя сеть
|
||||||
|
httpd_can_network_connect_db # nginx/apache → БД
|
||||||
|
httpd_enable_homedirs # доступ к /home
|
||||||
|
samba_enable_home_dirs # Samba к /home
|
||||||
|
ssh_sysadm_login # SSH-вход для sysadmin`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Порты и SELinux:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Посмотреть разрешённые порты:
|
||||||
|
semanage port -l
|
||||||
|
semanage port -l | grep http
|
||||||
|
|
||||||
|
# Разрешить nginx слушать нестандартный порт 8888:
|
||||||
|
semanage port -a -t http_port_t -p tcp 8888
|
||||||
|
|
||||||
|
# Удалить правило порта:
|
||||||
|
semanage port -d -t http_port_t -p tcp 8888
|
||||||
|
|
||||||
|
# Изменить существующее правило:
|
||||||
|
semanage port -m -t http_port_t -p tcp 8888`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Диагностика проблем SELinux:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Логи SELinux:
|
||||||
|
/var/log/audit/audit.log # основной лог
|
||||||
|
|
||||||
|
# Поиск запретов:
|
||||||
|
ausearch -m avc -ts recent # последние запреты AVC
|
||||||
|
grep 'denied' /var/log/audit/audit.log | tail -20
|
||||||
|
|
||||||
|
# audit2why — объяснить запрет:
|
||||||
|
ausearch -m avc -ts recent | audit2why
|
||||||
|
|
||||||
|
# audit2allow — создать модуль для разрешения:
|
||||||
|
ausearch -m avc -ts recent | audit2allow -m mymodule > mymodule.te
|
||||||
|
checkmodule -M -m -o mymodule.mod mymodule.te
|
||||||
|
semodule_package -o mymodule.pp -m mymodule.mod
|
||||||
|
semodule -i mymodule.pp
|
||||||
|
|
||||||
|
# sealert — графическая диагностика (если установлен setroubleshoot):
|
||||||
|
sealert -a /var/log/audit/audit.log`)
|
||||||
|
|
||||||
|
// ─── 46. firewalld ────────────────────────────────────────────
|
||||||
|
utils.Section("46. Межсетевой экран — firewalld")
|
||||||
|
|
||||||
|
utils.Println("firewalld — динамический менеджер firewall в RHEL/Fedora/CentOS.")
|
||||||
|
utils.Println("Работает поверх nftables (или iptables).")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Зоны (Zones) — основное понятие firewalld:" + utils.ColorReset)
|
||||||
|
utils.Code(`Зона определяет уровень доверия к трафику интерфейса.
|
||||||
|
|
||||||
|
drop — всё входящее молча отбрасывается
|
||||||
|
block — входящее отклоняется с сообщением об ошибке
|
||||||
|
public — публичные сети, только явно разрешённое (по умолчанию)
|
||||||
|
external — внешние сети с маскарадингом
|
||||||
|
internal — внутренние сети, больше доверие
|
||||||
|
home — домашние сети
|
||||||
|
work — рабочие сети
|
||||||
|
dmz — демилитаризованная зона
|
||||||
|
trusted — весь трафик разрешён`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Основные команды firewall-cmd:" + utils.ColorReset)
|
||||||
|
utils.Command("firewall-cmd --state", "работает ли firewalld")
|
||||||
|
utils.Command("systemctl status firewalld", "статус сервиса")
|
||||||
|
utils.Command("firewall-cmd --get-active-zones", "активные зоны и интерфейсы")
|
||||||
|
utils.Command("firewall-cmd --get-default-zone", "зона по умолчанию")
|
||||||
|
utils.Command("firewall-cmd --list-all", "все правила активной зоны")
|
||||||
|
utils.Command("firewall-cmd --list-all --zone=public", "правила зоны public")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Управление сервисами и портами:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Разрешить сервис (временно, до перезагрузки):
|
||||||
|
firewall-cmd --add-service=http
|
||||||
|
firewall-cmd --add-service=https
|
||||||
|
firewall-cmd --add-service=ssh
|
||||||
|
|
||||||
|
# Постоянно (--permanent):
|
||||||
|
firewall-cmd --permanent --add-service=http
|
||||||
|
firewall-cmd --permanent --add-service=https
|
||||||
|
firewall-cmd --reload # применить permanent-правила
|
||||||
|
|
||||||
|
# Удалить сервис:
|
||||||
|
firewall-cmd --permanent --remove-service=http
|
||||||
|
|
||||||
|
# Список доступных сервисов:
|
||||||
|
firewall-cmd --get-services
|
||||||
|
|
||||||
|
# Разрешить порт напрямую:
|
||||||
|
firewall-cmd --permanent --add-port=8080/tcp
|
||||||
|
firewall-cmd --permanent --add-port=5000-5100/tcp
|
||||||
|
firewall-cmd --permanent --remove-port=8080/tcp`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Rich rules — сложные правила:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Разрешить SSH только с конкретного IP:
|
||||||
|
firewall-cmd --permanent --add-rich-rule='
|
||||||
|
rule family="ipv4"
|
||||||
|
source address="192.168.1.0/24"
|
||||||
|
service name="ssh" accept'
|
||||||
|
|
||||||
|
# Заблокировать IP:
|
||||||
|
firewall-cmd --permanent --add-rich-rule='
|
||||||
|
rule family="ipv4"
|
||||||
|
source address="10.10.10.5"
|
||||||
|
drop'
|
||||||
|
|
||||||
|
# Ограничить количество соединений (rate limiting):
|
||||||
|
firewall-cmd --permanent --add-rich-rule='
|
||||||
|
rule service name="ssh"
|
||||||
|
limit value="5/m" accept'`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Маскарадинг (NAT):" + utils.ColorReset)
|
||||||
|
utils.Code(`# Включить маскарадинг (нужно для роутера):
|
||||||
|
firewall-cmd --permanent --zone=external --add-masquerade
|
||||||
|
|
||||||
|
# Пробросить порт:
|
||||||
|
firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080
|
||||||
|
# Внешний 80 → внутренний 8080`)
|
||||||
|
|
||||||
|
// ─── 48. Восстановление доступа ───────────────────────────────
|
||||||
|
utils.Section("48. Восстановление доступа")
|
||||||
|
|
||||||
|
utils.Println("Что делать если потеряли пароль root или доступ к системе.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Сброс пароля root (RHEL/CentOS):" + utils.ColorReset)
|
||||||
|
utils.Code(`1. Перезагрузить систему.
|
||||||
|
2. В меню GRUB нажать 'e' на нужной записи.
|
||||||
|
3. Найти строку начинающуюся с linux или linuxefi.
|
||||||
|
4. В конце строки добавить: rd.break
|
||||||
|
5. Нажать Ctrl+X для загрузки.
|
||||||
|
|
||||||
|
# В initramfs shell:
|
||||||
|
mount -o remount,rw /sysroot # перемонтировать с правами записи
|
||||||
|
chroot /sysroot # перейти в систему
|
||||||
|
passwd root # задать новый пароль root
|
||||||
|
# Если SELinux включён:
|
||||||
|
touch /.autorelabel # переметить файлы SELinux
|
||||||
|
exit
|
||||||
|
reboot`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Сброс пароля root (Ubuntu/Debian):" + utils.ColorReset)
|
||||||
|
utils.Code(`1. В GRUB выбрать "Advanced options".
|
||||||
|
2. Выбрать строку "(recovery mode)".
|
||||||
|
3. В меню recovery выбрать "root".
|
||||||
|
|
||||||
|
# Или: в GRUB нажать 'e', найти строку linux,
|
||||||
|
# заменить ro на rw, добавить в конец: init=/bin/bash
|
||||||
|
|
||||||
|
# В shell:
|
||||||
|
passwd root
|
||||||
|
# Если файловая система только для чтения:
|
||||||
|
mount -o remount,rw /
|
||||||
|
passwd root
|
||||||
|
sync
|
||||||
|
reboot -f`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Восстановление из LiveCD:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Загрузиться с LiveCD/LiveUSB
|
||||||
|
|
||||||
|
# Найти системный раздел:
|
||||||
|
lsblk
|
||||||
|
|
||||||
|
# Смонтировать:
|
||||||
|
mount /dev/sda2 /mnt
|
||||||
|
mount /dev/sda1 /mnt/boot # boot раздел
|
||||||
|
|
||||||
|
# Для UEFI:
|
||||||
|
mount /dev/sda1 /mnt/boot/efi
|
||||||
|
|
||||||
|
# Chroot:
|
||||||
|
mount --bind /dev /mnt/dev
|
||||||
|
mount --bind /proc /mnt/proc
|
||||||
|
mount --bind /sys /mnt/sys
|
||||||
|
chroot /mnt
|
||||||
|
|
||||||
|
# Теперь можно: passwd root, grub-install, etc.`)
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
135
modules/linuxmodules/linux_streams.go
Normal file
135
modules/linuxmodules/linux_streams.go
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var StreamsModule = Module{
|
||||||
|
Key: "streams",
|
||||||
|
Aliases: []string{"st", "io", "потоки"},
|
||||||
|
Title: "Стандартные потоки и перенаправление",
|
||||||
|
Description: "Тема 11: stdin, stdout, stderr, перенаправление, pipe",
|
||||||
|
Run: showStreams,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showStreams() {
|
||||||
|
utils.Header("Linux — Стандартные потоки и перенаправление")
|
||||||
|
|
||||||
|
// ─── 11. Стандартные потоки ───────────────────────────────────
|
||||||
|
utils.Section("11. Стандартные потоки (Standard Streams)")
|
||||||
|
|
||||||
|
utils.Println("Каждый процесс в Linux имеет три стандартных потока ввода-вывода:")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`Дескриптор Имя Поток По умолчанию
|
||||||
|
──────────────────────────────────────────────────────
|
||||||
|
0 stdin ввод клавиатура
|
||||||
|
1 stdout вывод терминал
|
||||||
|
2 stderr вывод ошибок терминал
|
||||||
|
|
||||||
|
Программа читает из stdin, пишет результат в stdout,
|
||||||
|
ошибки — в stderr.`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Перенаправление вывода (stdout):" + utils.ColorReset)
|
||||||
|
utils.Code(`> — перенаправить stdout в файл (перезаписать)
|
||||||
|
>> — перенаправить stdout в файл (дописать в конец)
|
||||||
|
|
||||||
|
ls /etc > list.txt # список файлов → файл
|
||||||
|
echo "строка" >> log.txt # дописать в конец
|
||||||
|
date > /dev/null # выбросить вывод в никуда`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Перенаправление ошибок (stderr):" + utils.ColorReset)
|
||||||
|
utils.Code(`2> — перенаправить stderr в файл
|
||||||
|
2>> — дописать stderr в файл
|
||||||
|
2>&1 — направить stderr туда же куда stdout
|
||||||
|
|
||||||
|
ls /nonexistent 2> errors.txt # ошибки → файл
|
||||||
|
ls /etc 1> out.txt 2> err.txt # каждый поток отдельно
|
||||||
|
ls /etc /nonexistent > all.txt 2>&1 # всё в один файл
|
||||||
|
ls /etc /nonexistent &> all.txt # краткая форма bash
|
||||||
|
ls /etc /nonexistent 2>/dev/null # подавить ошибки`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Перенаправление ввода (stdin):" + utils.ColorReset)
|
||||||
|
utils.Code(`< — читать stdin из файла
|
||||||
|
|
||||||
|
sort < unsorted.txt # отсортировать содержимое файла
|
||||||
|
wc -l < file.txt # считать строки из файла
|
||||||
|
|
||||||
|
# Here-document — передать несколько строк:
|
||||||
|
cat << EOF
|
||||||
|
строка 1
|
||||||
|
строка 2
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Here-string — передать строку:
|
||||||
|
grep 'pattern' <<< "одна строка для поиска"`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Конвейер (pipe) |:" + utils.ColorReset)
|
||||||
|
utils.Println("Pipe передаёт stdout одной команды в stdin следующей.")
|
||||||
|
utils.Code(`ls -la | grep '.conf' # только .conf файлы
|
||||||
|
cat /etc/passwd | sort # отсортировать passwd
|
||||||
|
ps aux | grep nginx # найти процессы nginx
|
||||||
|
cat file.txt | wc -l # посчитать строки
|
||||||
|
ls /etc | head -10 # первые 10 строк
|
||||||
|
history | tail -20 | grep git # цепочка из трёх команд`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "tee — записать и передать дальше:" + utils.ColorReset)
|
||||||
|
utils.Code(`# tee читает stdin, пишет в файл И в stdout:
|
||||||
|
ls -la | tee listing.txt | grep '.conf'
|
||||||
|
|
||||||
|
# -a — дописать в файл (append):
|
||||||
|
echo "строка" | tee -a log.txt`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "xargs — передать строки как аргументы:" + utils.ColorReset)
|
||||||
|
utils.Code(`# find возвращает список файлов, xargs передаёт их rm:
|
||||||
|
find /tmp -name '*.tmp' | xargs rm -f
|
||||||
|
|
||||||
|
# -I{} — подстановка каждой строки в {}:
|
||||||
|
cat hosts.txt | xargs -I{} ping -c1 {}
|
||||||
|
|
||||||
|
# -P4 — параллельно (4 процесса):
|
||||||
|
cat urls.txt | xargs -P4 -I{} curl -O {}`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "/dev/null и /dev/zero:" + utils.ColorReset)
|
||||||
|
utils.Code(`/dev/null — "чёрная дыра": запись выбрасывается, чтение → EOF
|
||||||
|
/dev/zero — бесконечный источник нулевых байт
|
||||||
|
/dev/random — случайные байты (медленно, использует энтропию)
|
||||||
|
/dev/urandom — псевдослучайные байты (быстро)
|
||||||
|
|
||||||
|
# Типичные применения:
|
||||||
|
command > /dev/null 2>&1 # подавить весь вывод
|
||||||
|
dd if=/dev/zero of=file bs=1M count=100 # создать 100МБ файл
|
||||||
|
cat /dev/urandom | head -c 16 | base64 # случайный токен`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Подстановка команд (command substitution):" + utils.ColorReset)
|
||||||
|
utils.Code(`# Результат команды используется как аргумент:
|
||||||
|
echo "Сегодня: $(date)"
|
||||||
|
ls -la $(which python3)
|
||||||
|
mkdir backup_$(date +%Y%m%d)
|
||||||
|
|
||||||
|
# Старый стиль (обратные кавычки):
|
||||||
|
echo "Версия: $(uname -r)" # backtick-форма устарела, используйте $()`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Полезные фильтры для pipe:" + utils.ColorReset)
|
||||||
|
utils.Command("grep", "фильтр строк по паттерну")
|
||||||
|
utils.Command("sed 's/old/new/g'", "замена текста в потоке")
|
||||||
|
utils.Command("awk '{print $1}'", "обработка/вывод полей")
|
||||||
|
utils.Command("sort", "сортировка строк")
|
||||||
|
utils.Command("uniq", "удаление дубликатов (после sort)")
|
||||||
|
utils.Command("head -n N", "первые N строк")
|
||||||
|
utils.Command("tail -n N", "последние N строк")
|
||||||
|
utils.Command("wc -l", "подсчёт строк")
|
||||||
|
utils.Command("tr 'a-z' 'A-Z'", "замена символов")
|
||||||
|
utils.Command("cut -d: -f1", "вырезать поле")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`# Практический пример — топ-5 процессов по памяти:
|
||||||
|
ps aux --sort=-%mem | head -6
|
||||||
|
|
||||||
|
# Все уникальные IP из лога nginx:
|
||||||
|
cat /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20
|
||||||
|
|
||||||
|
# Подсчёт файлов по расширению:
|
||||||
|
find . -type f | sed 's/.*\.//' | sort | uniq -c | sort -rn`)
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
191
modules/linuxmodules/linux_sysconfig.go
Normal file
191
modules/linuxmodules/linux_sysconfig.go
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var SysconfigModule = Module{
|
||||||
|
Key: "sysconfig",
|
||||||
|
Aliases: []string{"cfg", "time", "ntp", "chrony", "настройка"},
|
||||||
|
Title: "Конфигурация системы",
|
||||||
|
Description: "Темы 53–54: установка RHEL, настройка времени, NTP, chronyd",
|
||||||
|
Run: showSysconfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showSysconfig() {
|
||||||
|
utils.Header("Linux — Конфигурация системы")
|
||||||
|
|
||||||
|
// ─── 53. Установка RHEL ───────────────────────────────────────
|
||||||
|
utils.Section("53. Установка RHEL и первоначальная настройка")
|
||||||
|
|
||||||
|
utils.Println("RHEL (Red Hat Enterprise Linux) — коммерческий дистрибутив.")
|
||||||
|
utils.Println("Бесплатные альтернативы: AlmaLinux, Rocky Linux (1:1 совместимы с RHEL).")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Получение RHEL:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Бесплатная подписка для разработчиков (до 16 машин):
|
||||||
|
# https://developers.redhat.com/articles/faqs-no-cost-red-hat-enterprise-linux
|
||||||
|
|
||||||
|
# Скачать ISO:
|
||||||
|
# https://access.redhat.com/downloads
|
||||||
|
|
||||||
|
# Альтернативы без подписки:
|
||||||
|
# AlmaLinux: https://almalinux.org
|
||||||
|
# Rocky Linux: https://rockylinux.org
|
||||||
|
# CentOS Stream: https://www.centos.org/centos-stream/`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Первоначальная настройка после установки:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Обновить систему:
|
||||||
|
dnf update -y
|
||||||
|
|
||||||
|
# Настроить hostname:
|
||||||
|
hostnamectl set-hostname server01.example.com
|
||||||
|
hostnamectl status
|
||||||
|
|
||||||
|
# Настроить часовой пояс:
|
||||||
|
timedatectl set-timezone Europe/Moscow
|
||||||
|
|
||||||
|
# Включить автоматическую синхронизацию времени:
|
||||||
|
timedatectl set-ntp true
|
||||||
|
|
||||||
|
# Добавить репозиторий EPEL (Extra Packages):
|
||||||
|
dnf install epel-release -y
|
||||||
|
# или для RHEL:
|
||||||
|
subscription-manager repos --enable codeready-builder-for-rhel-9-x86_64-rpms
|
||||||
|
|
||||||
|
# Включить CRB (CodeReady Builder) — нужен для некоторых пакетов EPEL:
|
||||||
|
dnf config-manager --set-enabled crb # RHEL 9
|
||||||
|
dnf config-manager --set-enabled powertools # RHEL 8`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "subscription-manager — управление подпиской RHEL:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Зарегистрировать систему:
|
||||||
|
subscription-manager register --username=myuser --password=mypass
|
||||||
|
|
||||||
|
# Присоединить подписку:
|
||||||
|
subscription-manager attach --auto
|
||||||
|
|
||||||
|
# Список доступных репозиториев:
|
||||||
|
subscription-manager repos --list
|
||||||
|
|
||||||
|
# Включить репозиторий:
|
||||||
|
subscription-manager repos --enable rhel-9-for-x86_64-baseos-rpms
|
||||||
|
subscription-manager repos --enable rhel-9-for-x86_64-appstream-rpms
|
||||||
|
|
||||||
|
# Отключить регистрацию:
|
||||||
|
subscription-manager unregister`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "hostnamectl — управление именем хоста:" + utils.ColorReset)
|
||||||
|
utils.Command("hostnamectl", "показать всю информацию о хосте")
|
||||||
|
utils.Command("hostnamectl set-hostname myserver", "установить hostname")
|
||||||
|
utils.Command("hostnamectl set-hostname 'My Server' --pretty", "красивое имя")
|
||||||
|
utils.Command("hostname", "показать текущий hostname")
|
||||||
|
utils.Command("cat /etc/hostname", "hostname из файла")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "localectl — настройка локали и раскладки:" + utils.ColorReset)
|
||||||
|
utils.Command("localectl", "показать текущую локаль")
|
||||||
|
utils.Command("localectl list-locales | grep ru", "русские локали")
|
||||||
|
utils.Command("localectl set-locale LANG=ru_RU.UTF-8", "установить русскую локаль")
|
||||||
|
utils.Command("localectl set-keymap ru", "русская раскладка для консоли")
|
||||||
|
utils.Command("localectl list-keymaps | grep ru", "доступные раскладки")
|
||||||
|
|
||||||
|
// ─── 54. Настройка времени ────────────────────────────────────
|
||||||
|
utils.Section("54. Настройка времени. NTP и chronyd")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Типы часов в Linux:" + utils.ColorReset)
|
||||||
|
utils.Code(`RTC (Hardware Clock) — аппаратные часы (BIOS/UEFI), работают без питания
|
||||||
|
System Clock — системные часы ядра, синхронизируются от RTC при загрузке
|
||||||
|
|
||||||
|
UTC vs LOCAL:
|
||||||
|
RTC рекомендуется хранить в UTC, чтобы избежать проблем с летним временем.
|
||||||
|
Отображение в локальном времени — задача ОС.`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "timedatectl — управление временем:" + utils.ColorReset)
|
||||||
|
utils.Command("timedatectl", "показать время, часовой пояс, NTP")
|
||||||
|
utils.Command("timedatectl status", "то же самое")
|
||||||
|
utils.Command("timedatectl list-timezones", "список часовых поясов")
|
||||||
|
utils.Command("timedatectl list-timezones | grep Moscow", "найти московский пояс")
|
||||||
|
utils.Command("timedatectl set-timezone Europe/Moscow", "установить часовой пояс")
|
||||||
|
utils.Command("timedatectl set-time '2024-01-15 14:30:00'", "установить время вручную")
|
||||||
|
utils.Command("timedatectl set-ntp true", "включить синхронизацию по NTP")
|
||||||
|
utils.Command("timedatectl set-ntp false", "отключить NTP")
|
||||||
|
utils.Command("timedatectl set-local-rtc 0", "хранить RTC в UTC")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "hwclock — работа с аппаратными часами:" + utils.ColorReset)
|
||||||
|
utils.Command("hwclock", "показать время RTC")
|
||||||
|
utils.Command("hwclock --systohc", "записать системное время в RTC")
|
||||||
|
utils.Command("hwclock --hctosys", "установить системное время из RTC")
|
||||||
|
utils.Command("hwclock --utc", "RTC в UTC")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "NTP — Network Time Protocol:" + utils.ColorReset)
|
||||||
|
utils.Code(`NTP — протокол синхронизации времени по сети.
|
||||||
|
Иерархия серверов (stratum):
|
||||||
|
Stratum 0 — атомные часы, GPS
|
||||||
|
Stratum 1 — серверы напрямую подключённые к stratum 0
|
||||||
|
Stratum 2 — синхронизируются от stratum 1
|
||||||
|
...
|
||||||
|
Stratum 16 — несинхронизированы
|
||||||
|
|
||||||
|
Популярные публичные NTP-серверы:
|
||||||
|
pool.ntp.org — пул серверов (рекомендуется)
|
||||||
|
time.google.com — Google
|
||||||
|
time.cloudflare.com — Cloudflare
|
||||||
|
ntp1.vniiftri.ru — Россия (ВНИИФТРИ)
|
||||||
|
ntp2.vniiftri.ru — Россия`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "chronyd — рекомендуемый NTP-клиент в RHEL:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Установка (обычно предустановлен):
|
||||||
|
dnf install chrony # RHEL/Fedora
|
||||||
|
apt install chrony # Debian/Ubuntu
|
||||||
|
|
||||||
|
# Управление:
|
||||||
|
systemctl enable --now chronyd
|
||||||
|
systemctl status chronyd`)
|
||||||
|
|
||||||
|
utils.Command("chronyc tracking", "статус синхронизации")
|
||||||
|
utils.Command("chronyc sources", "список NTP-источников")
|
||||||
|
utils.Command("chronyc sources -v", "подробно")
|
||||||
|
utils.Command("chronyc sourcestats", "статистика источников")
|
||||||
|
utils.Command("chronyc makestep", "принудительно синхронизировать (мгновенный шаг)")
|
||||||
|
utils.Command("chronyc ntpdata", "NTP-данные каждого источника")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Конфигурация chronyd (/etc/chrony.conf):" + utils.ColorReset)
|
||||||
|
utils.Code(`# Серверы синхронизации:
|
||||||
|
server pool.ntp.org iburst
|
||||||
|
server ntp1.vniiftri.ru iburst
|
||||||
|
server ntp2.vniiftri.ru iburst
|
||||||
|
pool 2.rhel.pool.ntp.org iburst
|
||||||
|
|
||||||
|
# iburst — отправлять несколько пакетов при первом контакте (быстрее)
|
||||||
|
|
||||||
|
# Разрешить синхронизацию для подсети (NTP-сервер):
|
||||||
|
allow 192.168.1.0/24
|
||||||
|
|
||||||
|
# Синхронизировать RTC с системными часами:
|
||||||
|
rtcsync
|
||||||
|
|
||||||
|
# Сохранять данные о дрейфе:
|
||||||
|
driftfile /var/lib/chrony/drift
|
||||||
|
|
||||||
|
# Принять шаг > 1 сек только при старте:
|
||||||
|
makestep 1.0 3
|
||||||
|
|
||||||
|
# Применить изменения:
|
||||||
|
systemctl restart chronyd`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Настройка chronyd как NTP-сервера для локальной сети:" + utils.ColorReset)
|
||||||
|
utils.Code(`# /etc/chrony.conf на сервере:
|
||||||
|
server pool.ntp.org iburst
|
||||||
|
allow 192.168.1.0/24 # разрешить клиентам из этой подсети
|
||||||
|
|
||||||
|
# На клиентах /etc/chrony.conf:
|
||||||
|
server 192.168.1.10 iburst # указать IP локального NTP-сервера
|
||||||
|
|
||||||
|
# Открыть порт на файрволе сервера:
|
||||||
|
firewall-cmd --permanent --add-service=ntp
|
||||||
|
firewall-cmd --reload
|
||||||
|
|
||||||
|
# Проверить что клиент синхронизирован:
|
||||||
|
chronyc sources`)
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
252
modules/linuxmodules/linux_tools.go
Normal file
252
modules/linuxmodules/linux_tools.go
Normal file
|
|
@ -0,0 +1,252 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ToolsModule = Module{
|
||||||
|
Key: "tools",
|
||||||
|
Aliases: []string{"t", "cockpit", "regex", "awk", "sed", "инструменты"},
|
||||||
|
Title: "Веб-интерфейс и текстовые инструменты",
|
||||||
|
Description: "Темы 60–61: Cockpit, глоббинг, регулярные выражения, grep, sed, awk",
|
||||||
|
Run: showTools,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showTools() {
|
||||||
|
utils.Header("Linux — Веб-интерфейс и текстовые инструменты")
|
||||||
|
|
||||||
|
// ─── 60. Cockpit ──────────────────────────────────────────────
|
||||||
|
utils.Section("60. Веб-интерфейс — Cockpit")
|
||||||
|
|
||||||
|
utils.Println("Cockpit — веб-консоль для администрирования Linux через браузер.")
|
||||||
|
utils.Println("Позволяет управлять сервисами, сетью, дисками, контейнерами и логами.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Установка и запуск:" + utils.ColorReset)
|
||||||
|
utils.Code(`# RHEL/Fedora (обычно предустановлен):
|
||||||
|
dnf install cockpit
|
||||||
|
systemctl enable --now cockpit.socket
|
||||||
|
|
||||||
|
# Ubuntu/Debian:
|
||||||
|
apt install cockpit
|
||||||
|
systemctl enable --now cockpit.socket
|
||||||
|
|
||||||
|
# Открыть порт в firewalld:
|
||||||
|
firewall-cmd --permanent --add-service=cockpit
|
||||||
|
firewall-cmd --reload
|
||||||
|
|
||||||
|
# Доступ: https://hostname:9090
|
||||||
|
# Войти с логином/паролем системного пользователя`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Расширения Cockpit:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Управление виртуальными машинами:
|
||||||
|
dnf install cockpit-machines
|
||||||
|
|
||||||
|
# Управление Podman-контейнерами:
|
||||||
|
dnf install cockpit-podman
|
||||||
|
|
||||||
|
# Управление хранилищем (LVM, RAID, Stratis):
|
||||||
|
dnf install cockpit-storaged
|
||||||
|
|
||||||
|
# 389 DS (LDAP):
|
||||||
|
dnf install cockpit-389-ds
|
||||||
|
|
||||||
|
# Обновления пакетов:
|
||||||
|
dnf install cockpit-packagekit
|
||||||
|
|
||||||
|
# Применить все расширения:
|
||||||
|
systemctl restart cockpit.socket`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Возможности Cockpit:" + utils.ColorReset)
|
||||||
|
utils.Code(`Dashboard — обзор системы: CPU, RAM, диски, сеть
|
||||||
|
Services — управление systemd-сервисами
|
||||||
|
Storage — диски, LVM, RAID, Stratis, NFS
|
||||||
|
Networking — интерфейсы, маршруты, firewall
|
||||||
|
Accounts — пользователи и группы
|
||||||
|
Software Updates — обновление пакетов
|
||||||
|
Terminal — встроенный терминал в браузере
|
||||||
|
Logs — journald логи с фильтрами
|
||||||
|
Podman — управление контейнерами
|
||||||
|
Machines — виртуальные машины (KVM/libvirt)`)
|
||||||
|
|
||||||
|
utils.Note("Cockpit работает в браузере, не требует постоянного подключения: сессия = одна вкладка.")
|
||||||
|
utils.Note("Порт 9090. Сертификат самоподписанный — нужно добавить исключение в браузере или подключить Let's Encrypt.")
|
||||||
|
|
||||||
|
// ─── 61. Глоббинг и регулярные выражения ─────────────────────
|
||||||
|
utils.Section("61. Глоббинг и регулярные выражения")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Глоббинг (Globbing) — шаблоны оболочки:" + utils.ColorReset)
|
||||||
|
utils.Code(`* — любое количество любых символов (кроме /)
|
||||||
|
? — ровно один любой символ
|
||||||
|
[abc] — один символ из набора
|
||||||
|
[a-z] — один символ из диапазона
|
||||||
|
[!abc] — один символ НЕ из набора
|
||||||
|
{a,b,c} — одно из перечисленных
|
||||||
|
|
||||||
|
# Примеры:
|
||||||
|
ls *.log # все файлы .log
|
||||||
|
ls file?.txt # file1.txt, fileA.txt...
|
||||||
|
ls [0-9]*.conf # начинающиеся с цифры
|
||||||
|
ls /etc/{nginx,apache}* # /etc/nginx* или /etc/apache*
|
||||||
|
rm backup_{2023,2024}*.tar # удалить бэкапы 2023 и 2024
|
||||||
|
cp /etc/*.{conf,cfg} /tmp/ # все .conf и .cfg
|
||||||
|
|
||||||
|
# Расширенный глоббинг (shopt -s extglob):
|
||||||
|
?(pattern) — 0 или 1 вхождение
|
||||||
|
*(pattern) — 0 или более
|
||||||
|
+(pattern) — 1 или более
|
||||||
|
@(pattern) — ровно 1
|
||||||
|
!(pattern) — всё кроме`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Регулярные выражения — базовые (BRE):" + utils.ColorReset)
|
||||||
|
utils.Code(`. — любой символ
|
||||||
|
* — 0 или более предыдущего
|
||||||
|
^ — начало строки
|
||||||
|
$ — конец строки
|
||||||
|
[abc] — один символ из набора
|
||||||
|
[^abc] — один символ НЕ из набора
|
||||||
|
\(abc\) — группа
|
||||||
|
\{n,m\} — от n до m повторений
|
||||||
|
|
||||||
|
# Примеры:
|
||||||
|
grep '^root' /etc/passwd # строки начинающиеся с root
|
||||||
|
grep 'bash$' /etc/passwd # строки оканчивающиеся на bash
|
||||||
|
grep '^$' file.txt # пустые строки
|
||||||
|
grep '[0-9]\{3\}' file.txt # три цифры подряд`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Регулярные выражения — расширенные (ERE):" + utils.ColorReset)
|
||||||
|
utils.Code(`+ — 1 или более предыдущего
|
||||||
|
? — 0 или 1 предыдущего
|
||||||
|
| — ИЛИ
|
||||||
|
(abc) — группа (без \)
|
||||||
|
{n,m} — от n до m повторений (без \)
|
||||||
|
|
||||||
|
# Использование ERE: grep -E, egrep, sed -E, awk
|
||||||
|
|
||||||
|
grep -E 'cat|dog' file.txt # cat или dog
|
||||||
|
grep -E '^[0-9]+\.' file.txt # строки начинающиеся с числа.
|
||||||
|
grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}' file.txt # IPv4-адрес
|
||||||
|
grep -E 'error|warning|critical' /var/log/syslog
|
||||||
|
|
||||||
|
# Полезные классы символов:
|
||||||
|
[[:alpha:]] — буквы (a-z, A-Z)
|
||||||
|
[[:digit:]] — цифры (0-9)
|
||||||
|
[[:alnum:]] — буквы и цифры
|
||||||
|
[[:space:]] — пробельные символы
|
||||||
|
[[:upper:]] — заглавные буквы
|
||||||
|
[[:lower:]] — строчные буквы
|
||||||
|
[[:punct:]] — знаки препинания`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "grep — поиск по шаблону:" + utils.ColorReset)
|
||||||
|
utils.Command("grep 'pattern' file", "базовый поиск")
|
||||||
|
utils.Command("grep -i 'pattern' file", "без учёта регистра")
|
||||||
|
utils.Command("grep -v 'pattern' file", "строки НЕ совпадающие")
|
||||||
|
utils.Command("grep -n 'pattern' file", "с номерами строк")
|
||||||
|
utils.Command("grep -c 'pattern' file", "количество совпадений")
|
||||||
|
utils.Command("grep -l 'pattern' *.conf", "только имена файлов")
|
||||||
|
utils.Command("grep -r 'pattern' /etc/", "рекурсивно в директории")
|
||||||
|
utils.Command("grep -A 3 'pattern' file", "3 строки ПОСЛЕ совпадения")
|
||||||
|
utils.Command("grep -B 2 'pattern' file", "2 строки ДО совпадения")
|
||||||
|
utils.Command("grep -C 2 'pattern' file", "2 строки до и после")
|
||||||
|
utils.Command("grep -E 'pat1|pat2' file", "расширенные регулярки")
|
||||||
|
utils.Command("grep -P '\\d+' file", "Perl-совместимые regex")
|
||||||
|
utils.Command("grep -o 'pattern' file", "только совпадающая часть")
|
||||||
|
utils.Command("grep -w 'word' file", "только целые слова")
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "sed — потоковый редактор:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Синтаксис: sed 'команда' файл
|
||||||
|
# -i — изменить файл на месте
|
||||||
|
# -E — расширенные регулярки
|
||||||
|
|
||||||
|
# Замена (s — substitute):
|
||||||
|
sed 's/old/new/' file # первое вхождение в каждой строке
|
||||||
|
sed 's/old/new/g' file # все вхождения (global)
|
||||||
|
sed 's/old/new/gi' file # без учёта регистра
|
||||||
|
sed 's/old/new/2' file # второе вхождение
|
||||||
|
|
||||||
|
# Разделитель можно менять (удобно для путей):
|
||||||
|
sed 's|/old/path|/new/path|g' file
|
||||||
|
sed 's#/etc#/conf#g' file
|
||||||
|
|
||||||
|
# Изменить файл на месте:
|
||||||
|
sed -i 's/old/new/g' file.conf
|
||||||
|
sed -i.bak 's/old/new/g' file.conf # сохранить бэкап .bak
|
||||||
|
|
||||||
|
# Удаление строк:
|
||||||
|
sed '/pattern/d' file # удалить строки с паттерном
|
||||||
|
sed '5d' file # удалить 5-ю строку
|
||||||
|
sed '2,10d' file # удалить строки 2-10
|
||||||
|
sed '/^$/d' file # удалить пустые строки
|
||||||
|
sed '/^#/d' file # удалить комментарии
|
||||||
|
|
||||||
|
# Вставка и добавление:
|
||||||
|
sed '3a новая строка' file # добавить после строки 3
|
||||||
|
sed '3i новая строка' file # вставить перед строкой 3
|
||||||
|
sed '$a последняя' file # добавить в конец
|
||||||
|
|
||||||
|
# Вывод конкретных строк:
|
||||||
|
sed -n '5,10p' file # напечатать строки 5-10
|
||||||
|
sed -n '/start/,/end/p' file # между паттернами
|
||||||
|
|
||||||
|
# Несколько команд:
|
||||||
|
sed -e 's/foo/bar/' -e 's/baz/qux/' file
|
||||||
|
sed 's/foo/bar/; s/baz/qux/' file
|
||||||
|
|
||||||
|
# Практические примеры:
|
||||||
|
# Удалить комментарии и пустые строки:
|
||||||
|
sed '/^#/d; /^$/d' nginx.conf
|
||||||
|
|
||||||
|
# Заменить IP во всех конфигах:
|
||||||
|
sed -i 's/192\.168\.1\.100/10\.0\.0\.1/g' /etc/nginx/*.conf
|
||||||
|
|
||||||
|
# Добавить строку после первого совпадения:
|
||||||
|
sed '/\[global\]/a log level = 2' /etc/samba/smb.conf`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "awk — обработка текста по полям:" + utils.ColorReset)
|
||||||
|
utils.Code(`# awk обрабатывает текст построчно, разбивая на поля.
|
||||||
|
# По умолчанию разделитель — пробел/таб.
|
||||||
|
|
||||||
|
# Поля: $1 $2 $3 ... $NF (последнее), $0 (вся строка)
|
||||||
|
# NF — количество полей, NR — номер строки
|
||||||
|
|
||||||
|
# Вывод конкретного поля:
|
||||||
|
awk '{print $1}' file # первое поле
|
||||||
|
awk '{print $1, $3}' file # первое и третье
|
||||||
|
awk '{print NR, $0}' file # с номерами строк
|
||||||
|
|
||||||
|
# Другой разделитель (-F):
|
||||||
|
awk -F: '{print $1}' /etc/passwd # имена пользователей
|
||||||
|
awk -F: '{print $1, $6}' /etc/passwd # имя и домашняя директория
|
||||||
|
awk -F, '{print $2}' data.csv # второй столбец CSV
|
||||||
|
|
||||||
|
# Условия:
|
||||||
|
awk '$3 > 1000' file # строки где 3-е поле > 1000
|
||||||
|
awk '/pattern/ {print $0}' file # строки с паттерном
|
||||||
|
awk '$1 == "root"' /etc/passwd # строки где $1 = "root"
|
||||||
|
|
||||||
|
# Вычисления:
|
||||||
|
awk '{sum += $1} END {print sum}' file # сумма первого столбца
|
||||||
|
awk 'END {print NR}' file # количество строк (= wc -l)
|
||||||
|
|
||||||
|
# BEGIN и END блоки:
|
||||||
|
awk 'BEGIN {print "Начало"} {print $1} END {print "Конец"}' file
|
||||||
|
|
||||||
|
# Переменные и форматирование:
|
||||||
|
awk -F: '{printf "%-20s %s\n", $1, $6}' /etc/passwd
|
||||||
|
|
||||||
|
# Практические примеры:
|
||||||
|
# Топ процессов по CPU:
|
||||||
|
ps aux | awk 'NR>1 {print $3, $11}' | sort -rn | head -10
|
||||||
|
|
||||||
|
# Сумма размеров файлов (ls -l):
|
||||||
|
ls -l | awk '{sum += $5} END {print sum " bytes"}'
|
||||||
|
|
||||||
|
# Уникальные IP из лога nginx:
|
||||||
|
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
|
||||||
|
|
||||||
|
# Обработка CSV:
|
||||||
|
awk -F, 'NR>1 && $3 > 100 {print $1, $2}' report.csv`)
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
223
modules/linuxmodules/linux_users.go
Normal file
223
modules/linuxmodules/linux_users.go
Normal file
|
|
@ -0,0 +1,223 @@
|
||||||
|
package linuxmodules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"rubric/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var UsersModule = Module{
|
||||||
|
Key: "users",
|
||||||
|
Aliases: []string{"u", "perms", "sudo", "права"},
|
||||||
|
Title: "Пользователи, права и sudo",
|
||||||
|
Description: "Темы 17–20: su, sudo, пользователи, группы, права на файлы",
|
||||||
|
Run: showUsers,
|
||||||
|
}
|
||||||
|
|
||||||
|
func showUsers() {
|
||||||
|
utils.Header("Linux — Пользователи, права и sudo")
|
||||||
|
|
||||||
|
// ─── 19. Пользователи и группы ───────────────────────────────
|
||||||
|
utils.Section("19. Пользователи и группы")
|
||||||
|
|
||||||
|
utils.Println("В Linux каждый файл принадлежит пользователю и группе.")
|
||||||
|
utils.Println("Каждый процесс запускается от имени определённого пользователя.")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Основные файлы пользователей:" + utils.ColorReset)
|
||||||
|
utils.Code(`/etc/passwd — список пользователей
|
||||||
|
/etc/shadow — хэши паролей (только root)
|
||||||
|
/etc/group — группы
|
||||||
|
|
||||||
|
# Формат /etc/passwd:
|
||||||
|
# имя:пароль:UID:GID:комментарий:home:shell
|
||||||
|
alice:x:1000:1000:Alice Smith:/home/alice:/bin/bash
|
||||||
|
root:x:0:0:root:/root:/bin/bash
|
||||||
|
# x — пароль в /etc/shadow
|
||||||
|
# UID 0 — root (суперпользователь)
|
||||||
|
# UID 1-999 — системные пользователи
|
||||||
|
# UID 1000+ — обычные пользователи
|
||||||
|
|
||||||
|
# Формат /etc/group:
|
||||||
|
# имя:пароль:GID:члены
|
||||||
|
sudo:x:27:alice,bob
|
||||||
|
docker:x:999:alice`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Информация о пользователях:" + utils.ColorReset)
|
||||||
|
utils.Command("id", "UID, GID и группы текущего пользователя")
|
||||||
|
utils.Command("id alice", "информация о пользователе alice")
|
||||||
|
utils.Command("whoami", "имя текущего пользователя")
|
||||||
|
utils.Command("groups", "группы текущего пользователя")
|
||||||
|
utils.Command("getent passwd alice", "запись alice из /etc/passwd")
|
||||||
|
utils.Command("getent group docker", "участники группы docker")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Управление пользователями (root):" + utils.ColorReset)
|
||||||
|
utils.Command("useradd alice", "создать пользователя")
|
||||||
|
utils.Command("useradd -m -s /bin/bash -G sudo alice", "с домашней директорией, оболочкой и группой")
|
||||||
|
utils.Command("passwd alice", "установить пароль")
|
||||||
|
utils.Command("usermod -aG docker alice", "добавить alice в группу docker")
|
||||||
|
utils.Command("usermod -s /bin/zsh alice", "изменить оболочку")
|
||||||
|
utils.Command("usermod -L alice", "заблокировать учётную запись")
|
||||||
|
utils.Command("usermod -U alice", "разблокировать")
|
||||||
|
utils.Command("userdel alice", "удалить пользователя")
|
||||||
|
utils.Command("userdel -r alice", "удалить с домашней директорией")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Управление группами:" + utils.ColorReset)
|
||||||
|
utils.Command("groupadd developers", "создать группу")
|
||||||
|
utils.Command("groupdel developers", "удалить группу")
|
||||||
|
utils.Command("gpasswd -a alice developers", "добавить alice в группу")
|
||||||
|
utils.Command("gpasswd -d alice developers", "удалить alice из группы")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Note("После добавления в группу пользователь должен перелогиниться. Или: newgrp groupname")
|
||||||
|
|
||||||
|
// ─── 20. Права на файлы ───────────────────────────────────────
|
||||||
|
utils.Section("20. Права на файлы")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Структура прав доступа:" + utils.ColorReset)
|
||||||
|
utils.Code(`ls -l file.txt
|
||||||
|
-rw-r--r-- 1 alice users 1024 Jan 15 10:00 file.txt
|
||||||
|
│└──────────┘
|
||||||
|
│ 9 бит прав
|
||||||
|
└ тип файла (- файл, d директория, l ссылка...)
|
||||||
|
|
||||||
|
Права разделены на 3 группы по 3 бита:
|
||||||
|
rwx rwx rwx
|
||||||
|
│ │ └── other (остальные пользователи)
|
||||||
|
│ └─────── group (группа владельца)
|
||||||
|
└─────────── owner (владелец)
|
||||||
|
|
||||||
|
r — read (чтение): 4
|
||||||
|
w — write (запись): 2
|
||||||
|
x — execute (выполнение): 1
|
||||||
|
- — нет права: 0
|
||||||
|
|
||||||
|
Пример: rw-r--r--
|
||||||
|
owner: rw- = 6 (4+2) — чтение и запись
|
||||||
|
group: r-- = 4 — только чтение
|
||||||
|
other: r-- = 4 — только чтение
|
||||||
|
Численно: 644`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "chmod — изменить права:" + utils.ColorReset)
|
||||||
|
utils.Code(`# Числовой (восьмеричный) способ:
|
||||||
|
chmod 644 file.txt # rw-r--r--
|
||||||
|
chmod 755 script.sh # rwxr-xr-x
|
||||||
|
chmod 600 private.key # rw-------
|
||||||
|
chmod 777 dir/ # rwxrwxrwx (небезопасно!)
|
||||||
|
chmod 750 script.sh # rwxr-x---
|
||||||
|
|
||||||
|
# Символьный способ:
|
||||||
|
chmod u+x script.sh # добавить execute владельцу
|
||||||
|
chmod g-w file.txt # убрать write у группы
|
||||||
|
chmod o-r secret.txt # убрать чтение у остальных
|
||||||
|
chmod a+r public.txt # добавить чтение всем (a = all)
|
||||||
|
chmod u+x,g-w file # несколько изменений
|
||||||
|
chmod go=r file.txt # установить группе и остальным только r
|
||||||
|
|
||||||
|
# Рекурсивно:
|
||||||
|
chmod -R 755 /var/www/html/`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "Типичные значения прав:" + utils.ColorReset)
|
||||||
|
utils.Code(`644 rw-r--r-- обычный файл (конфиги, тексты)
|
||||||
|
755 rwxr-xr-x исполняемый файл, директория
|
||||||
|
700 rwx------ личный скрипт/директория
|
||||||
|
600 rw------- приватный ключ, .env файл
|
||||||
|
640 rw-r----- конфиг с секретами (owner + group)
|
||||||
|
664 rw-rw-r-- файл для работы в группе
|
||||||
|
1777 rwxrwxrwt /tmp (sticky bit)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "chown — изменить владельца:" + utils.ColorReset)
|
||||||
|
utils.Command("chown alice file.txt", "изменить владельца")
|
||||||
|
utils.Command("chown alice:users file.txt", "изменить владельца и группу")
|
||||||
|
utils.Command("chown :users file.txt", "изменить только группу")
|
||||||
|
utils.Command("chown -R alice:alice /home/alice/", "рекурсивно")
|
||||||
|
utils.Command("chgrp users file.txt", "изменить только группу")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Println(utils.ColorBold + "Специальные биты:" + utils.ColorReset)
|
||||||
|
utils.Code(`SUID (Set User ID) — 4000:
|
||||||
|
Файл запускается с правами владельца файла, а не запускающего.
|
||||||
|
chmod u+s /usr/bin/passwd # или chmod 4755
|
||||||
|
ls -la: -rwsr-xr-x (s вместо x у владельца)
|
||||||
|
Пример: passwd изменяет /etc/shadow (root-файл)
|
||||||
|
|
||||||
|
SGID (Set Group ID) — 2000:
|
||||||
|
Файл: запускается от имени группы файла.
|
||||||
|
Директория: новые файлы наследуют группу директории.
|
||||||
|
chmod g+s /shared/ # или chmod 2755
|
||||||
|
ls -la: drwxrwsr-x
|
||||||
|
|
||||||
|
Sticky Bit — 1000:
|
||||||
|
Директория: файл может удалить только его владелец.
|
||||||
|
chmod +t /tmp/ # или chmod 1777
|
||||||
|
ls -la: drwxrwxrwt
|
||||||
|
Применение: /tmp, /var/tmp`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "umask — маска прав по умолчанию:" + utils.ColorReset)
|
||||||
|
utils.Code(`umask определяет права, которые НЕ назначаются новым файлам.
|
||||||
|
|
||||||
|
umask # показать текущую маску (обычно 0022)
|
||||||
|
umask 0022 # установить маску
|
||||||
|
|
||||||
|
# Как работает:
|
||||||
|
# Файлы создаются с 666, директории с 777.
|
||||||
|
# Umask 022 вычитается:
|
||||||
|
# 666 - 022 = 644 (файлы: rw-r--r--)
|
||||||
|
# 777 - 022 = 755 (директории: rwxr-xr-x)
|
||||||
|
# Umask 077:
|
||||||
|
# 666 - 077 = 600 (файлы: rw-------)
|
||||||
|
# 777 - 077 = 700 (директории: rwx------)
|
||||||
|
|
||||||
|
# Установить постоянно в ~/.bashrc:
|
||||||
|
umask 0027`)
|
||||||
|
|
||||||
|
// ─── 17–18. su и sudo ─────────────────────────────────────────
|
||||||
|
utils.Section("17–18. su, sudo и visudo")
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "su — Switch User:" + utils.ColorReset)
|
||||||
|
utils.Command("su -", "переключиться в root (login shell, нужен пароль root)")
|
||||||
|
utils.Command("su", "переключиться в root (без login shell)")
|
||||||
|
utils.Command("su - alice", "переключиться в alice")
|
||||||
|
utils.Command("su -c 'команда' alice", "выполнить команду от имени alice")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`Разница su vs su -:
|
||||||
|
su — только смена UID, переменные окружения остаются
|
||||||
|
su - — полноценный вход, загружается окружение пользователя
|
||||||
|
(PATH, HOME и т.д.)
|
||||||
|
|
||||||
|
Выйти из su: exit или Ctrl+D`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "sudo — выполнить как другой пользователь:" + utils.ColorReset)
|
||||||
|
utils.Command("sudo command", "выполнить команду как root")
|
||||||
|
utils.Command("sudo -u alice command", "выполнить от имени alice")
|
||||||
|
utils.Command("sudo -i", "интерактивная сессия root (= su -)")
|
||||||
|
utils.Command("sudo -s", "оболочка root с текущим окружением")
|
||||||
|
utils.Command("sudo -l", "показать разрешённые команды для текущего пользователя")
|
||||||
|
utils.Command("sudo -l -U alice", "разрешённые команды для alice")
|
||||||
|
utils.Command("sudo !!", "повторить последнюю команду с sudo")
|
||||||
|
fmt.Println()
|
||||||
|
utils.Code(`sudo кэширует аутентификацию на 15 минут (по умолчанию).
|
||||||
|
sudo -k — сбросить кэш (следующая команда потребует пароль)`)
|
||||||
|
|
||||||
|
utils.Println(utils.ColorBold + "visudo — редактирование /etc/sudoers:" + utils.ColorReset)
|
||||||
|
utils.Code(`# НИКОГДА не редактируйте /etc/sudoers напрямую!
|
||||||
|
# visudo проверяет синтаксис перед сохранением.
|
||||||
|
|
||||||
|
sudo visudo
|
||||||
|
|
||||||
|
# Формат правил:
|
||||||
|
# WHO WHERE=(AS_WHOM) WHAT
|
||||||
|
|
||||||
|
# Примеры /etc/sudoers:
|
||||||
|
root ALL=(ALL:ALL) ALL # root имеет все права
|
||||||
|
%sudo ALL=(ALL:ALL) ALL # группа sudo — все права
|
||||||
|
%wheel ALL=(ALL:ALL) ALL # RHEL: группа wheel
|
||||||
|
|
||||||
|
alice ALL=(ALL) ALL # alice — все команды
|
||||||
|
alice ALL=(ALL) NOPASSWD:ALL # без пароля (небезопасно!)
|
||||||
|
bob ALL=(root) /usr/bin/apt # только apt от root
|
||||||
|
netadmin ALL=(root) /usr/bin/nmtui # только nmtui
|
||||||
|
helpdesk ALL=(root) /usr/bin/passwd, !/usr/bin/passwd root # пароли кроме root
|
||||||
|
|
||||||
|
# Файлы из /etc/sudoers.d/ включаются автоматически.
|
||||||
|
# Лучше создавать файл там, а не редактировать sudoers:
|
||||||
|
sudo visudo -f /etc/sudoers.d/alice`)
|
||||||
|
|
||||||
|
utils.Footer()
|
||||||
|
}
|
||||||
BIN
rubric
BIN
rubric
Binary file not shown.
Loading…
Add table
Reference in a new issue