318 lines
9.9 KiB
Go
318 lines
9.9 KiB
Go
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()
|
||
}
|