Skip to content

Скрипты-оркестраторы: разбираем netlab-tmux.sh и пишем сами (Linux + Windows) ​

Что такое «скрипт-оркестратор»: не программа, а «пульт запуска» — проверяет окружение, поднимает зависимости, создаёт рабочее место (окна, вкладки, сессии) и подключает тебя туда. Наша цель: одна команда → готовое рабочее место, и запускать её можно хоть сто раз подряд.

Разберём ~/NetLab/netlab-tmux.sh досконально, потом выведем правила и перепишем идею под Windows.


1. Разбор netlab-tmux.sh построчно ​

bash
#!/bin/bash

Shebang — кто исполняет файл. Обязательна первая строка, иначе файл запустится «чем попало» при ./script.sh.

bash
set -e

Fail-fast: любая команда, вернувшая ошибку, немедленно роняет скрипт. Без этого скрипт пошёл бы дальше с полусломанным состоянием (например, создал бы сессию без окон). Компромисс: где ошибка допустима, пишем || true.

bash
cd "$(dirname "$0")"

Переход в папку скрипта. $0 — путь, откуда запустили; dirname — его каталог. Зачем: скрипт ссылается на соседние файлы (./netlab-up.sh) и хочет работать вне зависимости от того, из какой папки его вызвали. Кавычки обязательны: пути с пробелами разорвут незакавыченный вариант.

bash
SESSION="NetLab"

Константа вверху. Все настраиваемые значения — в начале файла, одним блоком. Правило: открыв скрипт, за 5 секунд понять, что он трогает.

bash
if ! ping -c1 -W2 192.168.122.10 >/dev/null 2>&1; then
  ./netlab-up.sh
  sleep 40
fi

Guard-проверка: «зависимость жива?» Вместо слепого «поднимем всё всегда» скрипт сначала спрашивает у реальности: CHR отвечает? Только если нет — тратит время на подъём. Это ключевой принцип — автодетект состояния вместо ритуалов (>/dev/null 2>&1 — прячем вывод: нам нужен только код возврата; ! — инверсия: «если НЕ пингуется»).

bash
if tmux has-session -t "$SESSION" 2>/dev/null; then
  exec tmux attach -t "$SESSION"
fi

Идемпотентность — главное качество оркестратора. Сессия уже существует? Не плодим вторую — просто подключаемся. 2>/dev/null глушит ошибку «нет такой сессии» (она ожидаема). exec — заменить процесс скрипта процессом tmux: скрипт завершится вместе с attach, лишний процесс не висит в памяти.

bash
tmux new-session -d -s "$SESSION" -n kimi -c "$HOME/NetLab" "kimi"
tmux new-window -t "$SESSION" -n chr -c "$HOME/NetLab" "ssh chr"
...

Создание сущностей. -d — detached (не цепляемся сразу, собираем всё молча), -n — имя окна (видно в статусной строке), -c — стартовая папка окна, последний аргумент — команда, которая выполнится внутри. Имена kimi, chr, alpine1 — алиасы из ~/.ssh/config, так что никаких -i ключ в самом скрипте.

bash
tmux select-window -t "$SESSION:kimi"

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

bash
exec tmux attach -t "$SESSION"

И только в конце — подключение. Структура скрипта: check → prepare → create → attach. Запомни эту схему — она универсальна.

2. Правила хорошего оркестратора (чек-лист) ​

  1. Одна команда — готовое место. Пользователь не должен помнить порядок действий.
  2. Идемпотентность. Запуск N раз = запуск 1 раза. Всегда проверяй «уже существует?».
  3. Автодетект, а не ритуал. Не «поднимай всё всегда», а «подними, только если мёртво» (ping/port-check/флаг-файл).
  4. Константы наверху, кавычки вокруг всех переменных, set -e + локальные || true где фейл законен.
  5. Именованные сущности (окна/сессии/контейнеры) — самодокументация.
  6. Человекочитаемый финал: вывести, что создано и как этим пользоваться.
  7. Не хранить секреты в скрипте — ссылки на алиасы SSH/переменные окружения.

3. Тот же пульт для Windows (PowerShell + Windows Terminal) ​

В Windows нет tmux, но есть его практический аналог — Windows Terminal (wt.exe): программируемые вкладки и панели из командной строки. А ssh.exe встроен в Windows 10/11. Тот же пульт, другой синтаксис — ~/NetLab/netlab.ps1:

powershell
#Requires -Version 5.1
# netlab.ps1 — рабочее место NetLab в Windows Terminal (аналог netlab-tmux.sh)
$ErrorActionPreference = 'Stop'                    # как "set -e": любая ошибка стоп

# --- 0. Guard: доступен ли CHR? (аналог ping-проверки) ---
$chrAlive = Test-Connection -TargetName 192.168.122.10 -Count 1 -Quiet -TimeoutSeconds 2
if (-not $chrAlive) {
    Write-Host "CHR не отвечает. Лаба живёт на ноутбуке с Linux — подними её там (netlab-up.sh)." -ForegroundColor Yellow
    # На Windows-машине можно лишь проверить сеть до неё; подъём VM здесь не делаем.
}

# --- 1. Открываем Windows Terminal с вкладками (wt — сам мультиплексирует) ---
# new-tab: каждая вкладка со своей командой; wsl ssh ... — если SSH-алиасы настроены в ~/.ssh/config WSL
wt --title "NetLab" new-tab --title "chr"     ssh chr    `; new-tab --title "alpine1" ssh alpine1 `; new-tab --title "alpine2" ssh alpine2

Разбор PowerShell-конструкций (эквиваленты bash):

BashPowerShellЧто делает
set -e$ErrorActionPreference = 'Stop'падать при любой ошибке
ping -c1 -W2 XTest-Connection X -Count 1 -Quietпроверка доступности (True/False)
[[ -z "$x" ]][string]::IsNullOrEmpty($x)проверка «пусто ли»
if ! cmd; thenif (-not (Test-...))инверсия условия
$1, $2 (аргументы)$args[0] или param([string]$Name)параметры
echo "..."Write-Host "..."вывод
exit 1 / $?exit 1 / $LASTEXITCODEкоды возврата
"$HOME/dir""$HOME\dir" / Join-Path $HOME 'dir'пути (Join-Path — безопаснее)
export VAR=x$env:VAR = 'x'переменные окружения

И совсем короткий «голый» вариант без Windows Terminal — просто три окна PowerShell (если wt не установлен):

powershell
Start-Process powershell -ArgumentList '-NoExit','-Command','ssh chr'
Start-Process powershell -ArgumentList '-NoExit','-Command','ssh alpine1'
Start-Process powershell -ArgumentList '-NoExit','-Command','ssh alpine2'

4. Порядок написания своего оркестратора ​

  1. Сначала вручную выполни сценарий один раз, записав каждую команду.
  2. Разложи команды по схеме check → prepare → create → attach.
  3. На каждом разрушающем/создающем шаге задай вопрос: «а если это уже есть?» — добавь guard.
  4. Все имена/пути/адреса — в константы наверху.
  5. Прогони три раза подряд: первый (создаёт), второй (подключается к существующему), третий после перезагрузки (восстанавливает) — все три должны заканчиваться одинаково: рабочим местом.
  6. В финале — инструкция пользователю (как переключаться, как выйти).

5. Проверь себя ​

  1. Зачем exec перед финальным tmux attach, чем отличается от просто tmux attach? (Заменяет процесс скрипта: после выхода из tmux не остаётся висящего процесса-родителя.)
  2. Что изменится, если убрать set -e и первый ping упадёт? (Скрипт полезет создавать сессию, даже если лаба не поднялась — получим окна с битым SSH.)
  3. В PowerShell-версии мы НЕ стали поднимать лабу при мёртвом CHR. Почему это правильно для скрипта-оркестратора? (Оркестратор отвечает за то, что может контролировать; чужая инфраструктура → диагностика и подсказка человеку, а не слепые действия.)

См. также: Bash для сетевика (операторы, перенаправления, sed), Диагностика Windows-клиента (Win-экосистема: Test-NetConnection, netsh).