Половина задач дежурного инженера сводится к одному и тому же взгляду: сколько памяти, что с диском, жив ли сервис. Набирать free, df и systemctl вручную каждые десять секунд быстро надоедает, а выжимки из логов отстают от реальности. Команда watch из состава procps-ng закольцовывает любую команду, обновляет её вывод на чистом экране и подсвечивает то, что изменилось, превращая обычный терминал в живую панель наблюдения. Утилита живёт в базовом наборе системных программ с начала девяностых и почти не изменилась с тех пор: настолько удачной оказалась сама идея. Цикл while со sleep даёт то же повторение, но без очистки экрана, шапки и подсветки, и рассыпается на паузе между командами: watch берёт на себя всю обвязку.
Базовый синтаксис, интервал и точность
Синтаксис предельно прост: watch и команда в кавычках. По умолчанию обновление идёт каждые 2 секунды, интервал меняет -n: watch -n 1 обновляется раз в секунду, дробные значения вроде 0.5 тоже допустимы, минимум 0.1. В шапке экрана видны интервал, сама команда и текущее время, и через неделю работы глаза перестают их замечать, а командная строка под рукой всегда. Двухсекундный интервал по умолчанию не случаен: он достаточно быстр, чтобы заметить изменение, и достаточно ленив, чтобы не мешать системе.
watch -n 1 "date +%T; uptime"
По умолчанию watch запускает команду через shell, поэтому пайпы и перечисления через точку с запятой работают прямо в кавычках. Флаг -x включает прямой запуск без shell, что спасает, когда имя команды совпадает с алиасом или нужен строгий разбор аргументов. Опция -p включает точный тайминг с компенсацией дрейфа: обычный режим запускает команду, потом ждёт интервал, и на быстрых циклах секунды незаметно растягиваются. Для наблюдений с секундным интервалом разница видна по шапке: время обновления стоит как приклеенное.
Кавычки решают всё: watch df -h /var без кавычек передаст в shell только df, а остальное станет аргументами самого watch. Переменные окружения раскрываются при каждом обновлении, и $PID в команде читается заново каждый цикл, что удобно для слежения за конкретным процессом. Подсчёт накопившихся файлов в каталоге приёма, размер растущего файла, число писем в очереди, каждый счётчик становится панелью одной строкой: watch -n 30 "ls /srv/inbox | wc -l".
Подсветка изменений с -d
Флаг -d подсвечивает участки вывода, которые изменились с прошлого обновления, и глаз мгновенно цепляется за выросшие счётчики. В режиме -d=cumulative подсветка остаётся на всех значениях, которые менялись хоть раз, и на живом экране сразу видно, какие числа стабильны, а какие пляшут.
watch -d -n 2 free -h
watch -d=cumulative -n 5 "df -h / /var"
Для растущих логов watch не подходит: журнал нужен потоком, и его место занимает tail -f или journalctl -f. На терминалах без цвета подсветка меняется на инверсию, и эффект сохраняется даже в самом скромном эмуляторе. Свой скрипт в панели смотрится как родной: watch -d -n 2 bash /opt/scripts/queue-status.sh, и правки живут в файле скрипта, а не в истории терминала. Зато счётные метрики, память, диски, очереди, состояния процессов, именно то, что watch показывает в лучшем виде. Подсветка работает и на выводе собственных скриптов: одна строка с числом задач в очереди, обновляемая каждые пять секунд, честнее многих дашбордов. Классический сценарий: наблюдение за файлом счётчика вроде /proc/net/dev. Пока число стоит, экран спокоен, как только строка меняется, она вспыхивает, и реакция наступает раньше, чем кто-то успел обновить экран вручную. Режим cumulative удобен для поиска пиков: максимальное значение за смену остаётся подсвеченным, и вернувшись к терминалу, видно, что подскакивало в отсутствие.
Для широких таблиц стоит сразу выжимать нужные колонки awk-ом: панель из десяти цифр читается быстрее таблицы из пятидесяти.
Автовыход по условию через -g
Флаг -g завершает watch, как только вывод команды изменился, и это готовый инструмент ожидания. Скрипт ждёт файл-маркер от деплоя, инженер дожидается смены состояния сервиса, и всё без бесконечных ручных прогонов.
watch -g -n 5 "test -f /tmp/deploy.done" && echo "маркер появился"
watch -g -n 5 "systemctl is-active nginx" && echo "состояние изменилось"
Родственные флаги дополняют картину: -b подаёт звуковой сигнал, когда команда завершается с ошибкой, -e замораживает экран при сбое, чтобы текст ошибки можно было спокойно прочитать, а -q с числом циклов завершает watch, если вывод не менялся заданное количество обновлений подряд. Ожидание процесса выглядит так же: watch -g -n 5 "pgrep -c mydaemon", и счётчик с нуля на единицу завершит ожидание в момент старта службы. Сочетание -g с shell-логикой превращает watch в дешёвый планировщик ожидания: проверка условия каждые пять секунд стоит копейки по сравнению с отдельным скриптом, и стоп-условие меняется правкой одной строки. Условие может быть сложнее наличия файла: watch -g -n 10 "journalctl -u myapp -n 5 | grep -q Segmentation" завершится, когда в журнале появится нужное слово, а дальше уже работают привычные && и уведомления. Обратная задача, поймать момент завершения, решается -q: когда вывод перестаёт меняться заданное число циклов, watch уходит, и тяжёлая сборка с индикатором больше не занимает терминал.
Память, диск и сеть в живом виде
Связка из трёх команд закрывает повседневный контроль: free -h показывает память с колонкой available, df -h сообщает о заполнении файловых систем, а ip -s link вываливает счётчики пакетов по интерфейсам, где сразу видны ошибки и переполнения.
watch -n 2 "uptime; echo; free -h; echo; df -h / /var; echo; ip -s link"
Load average в выводе uptime читается относительно числа ядер: значение, равное количеству ядер, означает полную загрузку, двукратное превышение это очередь. Подсветка -d здесь особенно полезна на дисках: стабильные цифры не отвлекают, а растущее заполнение /var замечается заранее, а не по сообщению о переполнении. Для температурного контроля сервера в живом виде служит watch sensors, для видеокарт в рабочих задачах nvidia-smi, и оба выглядят как готовые панели без единой строчки конфигурации. Для дисков в живом виде смотрят SMART-атрибуты: температура и число переназначенных секторов в паре строк, и рост последнего подсказывает о планировании замены. Заполнение inode показывает df -i, и файловые системы с миллионами мелких файлов исчерпывают их раньше байтов.
Колонка available точнее привычной free: часть памяти занята кэшем, который ядро отдаст под запрос в любой момент, и тревога из-за нулевой free обычно ложная. df при этом показывает разницу между / и /var на машинах с раздельными разделами, и перенос журналов на другой раздел виден в панели мгновенно. В выводе ip -s link считаются ошибки, отброшенные пакеты и переполнения, и рост этих счётчиков первый сигнал о битом кабеле или перегруженном интерфейсе. Ключи вывода выбирают под задачу: -h для глаз, -m для сравнения с лимитами контейнеров, и одинаковая единица измерения на всех вкладках экономит секунды, которые в инциденте дорогие.
Сервисы, очереди и контейнеры
Состояние сервисов контролируется однострочником: systemctl is-active печатает по строке на юнит, и список критичных служб обновляется сам.
watch -n 5 "systemctl is-active nginx redis postgresql | tr '\n' ' '"
watch -n 10 "kubectl get pods -n production"
watch -n 10 mailq
Для кластеров Kubernetes вывод kubectl get pods обновляется прямо в панели, для почтовых серверов mailq показывает очередь postfix, а список systemctl list-timers напоминает, какие задачи должны были запуститься. Контейнеры смотрятся через docker ps с форматированием, и в сочетании с -d флапающий сервис, который то активен, то перезапускается, виден по постоянно перекрашенным строкам. Такой экран экономит минуты на каждом инциденте: вместо серии прогонов одна живая панель. Поиск проблемных юнитов тоже однострочник: systemctl list-units --state=failed в живом режиме показывает, вернулся ли сервис после вмешательства, а systemctl list-jobs видно, что застряло в очереди старта. Завал в почтовой очереди чистится postqueue -f, и совместное наблюдение очереди и журнала показывает, уходит ли накопленное. Поиск проблемных юнитов тоже однострочник: systemctl list-units --state=failed в живом режиме показывает, вернулся ли сервис после вмешательства, а systemctl list-jobs видно, что застряло в очереди старта. Очередь в базе смотрится тем же способом: короткий запрос count через psql с интервалом в десять секунд не потревожит даже нагруженный сервер. Список контейнеров удобнее ужимать форматированием docker ps до двух колонок, имени и статуса, чтобы панель помещалась в узкое окно.
Цвета, заголовок и поведение при сбое
Свежие версии procps-ng поддерживают -c: ANSI-цвета из команды доходят до экрана, и цветные утилиты вроде dmesg --color=always или diff --color=always остаются цветными под watch. Флаг -t убирает шапку, если экран нужен чистым, например для записи скринкаста или трансляции на стенде.
watch -c -n 2 "dmesg --color=always | tail -n 5"
Интервал выбирают по цене команды: лёгкий просмотр файла можно крутить хоть каждые полсекунды, тяжёлый запрос к кластеру лучше не чаще раза в пять секунд, иначе монитор сам станет источником нагрузки. Команды, пишущие в stderr, тоже отображаются, но при отладке полезно завернуть 2>&1 прямо в кавычках, чтобы ничего не терялось. Ошибки сети внутри команды оставят в панели последний удачный вывод, и об этом стоит помнить: пустой экран честнее устаревшей картинки. Для работы цветов терминал должен их понимать, в tmux это работает из коробки. Шапка с -t убирает и имя команды, что удобно, когда панель смотрят посторонние глаза и внутренние пути показывать не нужно. Обычная шапка служит документацией самой себе: всегда видно, что считается и с каким интервалом, и через месяц не возникает путаницы с чужими панелями.
Экран дежурного инженера и границы метода
Собрать рабочий экран можно за пять шагов:
- выбрать три-четыре метрики, по которым принимаются решения;
- собрать их в одну строку с разделителями echo;
- проверить команду вручную, включая сбойные варианты;
- запустить watch с -d и разумным интервалом на отдельной вкладке;
- добавить -g на условия, требующие реакции.
watch -d -n 3 "uptime; echo; free -h; echo; \
df -h / /var; echo; systemctl is-active nginx redis"
Панель меняют чаще, чем кажется: после релиза стоят одни метрики, во время инцидента другие, и правка строки команды занимает секунды без перезапуска чего-либо. Длинный вывод watch переносит строки, и на узком терминале панель плывёт: либо шрифт мельче, либо команда короче. Автозапуск панели в tmux-сессии превращает её в постоянный стенд, и после рабочей смены ничего не надо собирать заново. Привычка заводит пару alias в .bashrc: короткое имя для двухсекундного интервала с подсветкой и отдельное для медленных метрик, и вызов панели сокращается до трёх букв.
Счётчики складывают в файл и для истории: watch -n 60 "date +%T; free -m | grep Mem" >> /var/log/mem-sample.log, и через неделю график по образцам отвечает на вопрос о пиках. Переход от опроса к событиям делают inotifywait и systemctl, но для дежурных задач опрос с разумным интервалом проще и предсказуемее.
Граница метода проходит по потокам: watch опрашивает, но не слушает, и для непрерывных журналов остаются tail -f и journalctl -f, для графиков и оповещений специализированные системы наблюдения. Вторая граница это история: экран показывает настоящее, и для сравнения за сутки нужны уже метрики из хранилища. Важно отличать интерактивное наблюдение от задач по расписанию: watch живёт, пока открыт терминал, и заменяет планировщик только в ожиданиях с -g, а не в регулярных работах. Смешение этих ролей заканчивается тем, что панель забывают закрыть, а задача не выполняется без открытого окна. Как панель быстрого взгляда без установки чего-либо watch закрывает большинство дежурных вопросов одним терминалом, и именно за это его держат в базовом наборе администратора рядом с ssh, tail и df.