SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor

Как правильно использовать команду watch в Linux

Узнайте, как настроить интервал обновления, подсветить изменения через флаг -d и завершить работу при появлении разницы. Разбираем нюансы экранирования конвейеров в watch.

Что делает команда watch

Команда watch повторно выполняет другую команду через заданный интервал и обновляет её вывод в том же месте экрана. Интервал по умолчанию составляет две секунды. Используйте её, когда ожидаете изменения какого-либо значения: заполнения диска, запуска контейнера, завершения обновления сертификата или очистки очереди.

Утилита watch входит в состав пакета procps-ng и уже установлена на свежем VPS с Ubuntu или Debian как часть пакета procps. Проверьте версию перед использованием флагов, описанных ниже, так как две полезные опции появились недавно.

watch --version

В Ubuntu 24.04 эта команда выводит строку вида watch from procps-ng 4.0.4. Рассмотрим простейший полезный пример.

watch df -h /

Экран очищается и отображает заголовок, пустую строку, а затем вывод команды df -h /:

Every 2.0s: df -h /                          server1: Sun Aug  9 10:21:44 2026

Слева указан интервал и сама команда, которую выполняет watch. Справа — имя хоста и текущее время. Часы — полезная часть, так как они подтверждают, что экран обновляется, даже если цифры ниже не меняются. Нажмите Ctrl+C для выхода.

watch отрисовывает один кадр, который помещается в терминал. Длинные строки переносятся, а флаг -w обрезает их; всё, что выходит за пределы нижней строки, не отображается. Внутри кадра нет прокрутки, так как каждый цикл перезаписывает предыдущий. Этот факт определяет основную область применения watch.

Как часто watch должен перезапускать команду?

Две секунды — это лишь значение по умолчанию. Выбирайте интервал в зависимости от того, как быстро меняется значение и насколько ресурсозатратен один запуск.

  • -n 0.5 для счетчиков, которые постоянно меняются, например ss -s или количество байт в сетевом интерфейсе. Минимальный интервал, который принимает watch, составляет 0.1 секунды.
  • -n 30 или -n 60 для дисков и сертификатов. Файловой системе, которая заполняется в течение суток, не нужно тридцать обновлений в минуту.

watch выполняет команду, дожидается её завершения и только после этого переходит в режим ожидания на заданный интервал. Время выполнения прибавляется к паузе, поэтому команда, которая выполняется восемь секунд при -n 2, будет обновляться каждые десять секунд, при этом процессор будет занят всё это время. Добавьте -p (--precise), и watch будет стараться запускать команду каждые интервал секунд, отсчитывая время от начала одного запуска до начала следующего.

Если вы хотите изменить значение по умолчанию на постоянной основе, экспортируйте WATCH_INTERVAL в профиле вашей оболочки. Явно указанный флаг -n всё равно имеет приоритет. Выполните watch --help, чтобы убедиться, что ваша сборка считывает эту переменную.

Выделение изменений с помощью -d

Чтение массива идентичного текста в поисках одного изменившегося поля — трудоемкая задача. -d (--differences) выполняет её за вас.

watch -n 30 -d 'df -h / /var'

Символы, отличающиеся от предыдущего кадра, отображаются в инвертированном видео, поэтому ячейка Use% подсвечивается в момент изменения, а остальной текст остается статичным. Если /var не является отдельной файловой системой, вы увидите корневую файловую систему в списке дважды; это быстрый способ узнать, как был разбит диск на разделы.

Сравнение происходит по позициям, то есть watch сопоставляет строки нового кадра со старым посимвольно. Вывод, в котором меняется ширина столбцов, будет подсвечен почти полностью, поэтому отдавайте предпочтение командам со стабильной версткой. Текущая версия procps-ng также поддерживает watch --differences=permanent, которая сохраняет подсветку всех позиций, когда-либо изменившихся, вместо отображения только последнего изменения. Проверьте это с помощью watch --help, прежде чем полагаться на данную функцию.

Как сделать так, чтобы watch завершался при изменении вывода?

-g (--chgexit) останавливает watch при первом же отличии вывода от предыдущего запуска. Управление возвращается в командную строку, поэтому вы можете добавить следующую команду в той же строке.

watch -n 10 -g 'systemctl is-active myapp' ; echo 'state changed'

Этот флаг превращает watch в инструмент для отслеживания завершения развертывания. У него есть одна особенность, на которой попадаются все: сравнение затрагивает весь вывод целиком. Любые часы или PID (идентификатор процесса) в выводе меняются при первом же обновлении, и watch немедленно завершается. systemctl status myapp выводит прошедшее время и использование памяти, поэтому -g для него бесполезен. Сократите команду до одного стабильного факта, который вы ожидаете, — именно это позволяет сделать systemctl is-active.

Более новые версии procps-ng добавляют противоположный тест, --equexit <cycles>, который завершается после того, как вывод остается неизменным в течение указанного количества циклов. Это позволяет ответить на вопрос: «сообщи мне, когда здесь всё успокоится». Проверьте watch --help, так как в старых сборках его нет.

Почему watch игнорирует мой pipe и glob?

Это ошибка, с которой сталкиваются все, и её причина кроется в вашей оболочке, а не в watch.

watch docker compose ps | grep web

Ваша интерактивная оболочка считывает всю строку целиком до запуска чего-либо и разделяет эту строку в месте установки pipe. Она запускает watch docker compose ps и подключает вывод экрана самого watch к grep. watch больше не пишет в терминал, поэтому отображение ломается или остается пустым, а grep фильтрует вывод перерисовки вместо списка контейнеров.

Заключите весь конвейер в кавычки, чтобы он передавался как один аргумент.

watch 'docker compose ps | grep web'

watch передает эту строку в sh -c, и эта оболочка выполняет конвейер один раз за цикл. Globs подчиняются тому же правилу, но с менее заметными симптомами.

watch ls -l /var/log/*.log
watch 'ls -l /var/log/*.log'

Первая строка раскрывает glob один раз, в вашей оболочке, в момент нажатия Enter. Затем watch перезапускает замороженный список имен файлов, поэтому файл журнала, созданный минуту спустя, никогда не появится. Вторая строка передает glob в watch, который раскрывает его внутри sh на каждом цикле, поэтому новые файлы появляются сами по себе.

Кавычки также определяют, когда вычисляется переменная или подстановка команды. watch "echo $(date)" запускает date один раз, в вашей оболочке, а затем бесконечно выводит эту фиксированную строку. watch 'echo $(date)' запускает date на каждом цикле. Одинарные кавычки означают «потом». Двойные кавычки означают «сейчас».

Еще два последствия использования sh -c:

  • Псевдонимы (aliases) и функции оболочки внутри него не существуют. watch ll завершается ошибкой sh: 1: ll: not found, потому что sh -c никогда не читает ваш .bashrc. Напишите полную команду или укажите полный путь к бинарному файлу, который находится только в вашей интерактивной PATH.
  • Стандартный поток ошибок стоит перехватывать. Поместите 2>&1 внутрь кавычек, если хотите, чтобы текст ошибки отображался в кадре, а не был разбросан по нему.

Когда использование кавычек становится затруднительным, -x (--exec) запускает команду напрямую, а не через sh -c. Аргументы с пробелами становятся проще, а pipe и globs перестают работать полностью, так как не остается оболочки для их интерпретации.

Привилегии следуют той же логике, так как watch — это обычный процесс. watch 'sudo ss -tulpn' вызывает запрос пароля, который вы не видите и в который не можете ввести данные. Вместо этого запустите sudo watch 'ss -tulpn' и помните, что весь цикл будет выполняться от имени root, пока вы не нажмете Ctrl+C.

Четыре показателя, за которыми стоит следить на VPS

Заполнение диска

watch -n 30 -d 'df -h / /var'

df запрашивает у ядра уже имеющиеся данные, поэтому команда потребляет минимум ресурсов и её можно запускать постоянно. du -sh /var/log работает иначе: она обходит каждый файл в дереве каталогов при каждом запуске. При использовании с watch она непрерывно читает диск и замедляет работу системы, которую вы пытаетесь диагностировать. Запустите du один раз или используйте ncdu, а затем оставьте df в режиме наблюдения, чтобы видеть, продолжает ли расти число.

Контейнер, который постоянно перезапускается

cd /srv/myapp
watch -n 5 -d 'docker compose ps'

Столбец состояния показывает время работы каждого контейнера. Контейнер в цикле аварийных завершений постоянно сбрасывает время до "Up 2 seconds", и -d делает это заметным с первого взгляда. Сначала перейдите в нужный каталог, так как watch наследует рабочую директорию оболочки, из которой была запущена, а docker compose требует доступа к каталогу проекта. watch показывает, что происходит перезапуск. docker compose logs -f web объясняет причину. Как только вы узнаете причину, оформите решение в виде healthcheck в Compose, который перезапустит контейнер за вас, чтобы никому не приходилось следить за этим вручную.

Обновление сертификата

sudo -i
watch -n 60 -g 'openssl x509 -noout -enddate -in /etc/letsencrypt/live/example.com/fullchain.pem'

Команда выводит одну строку, notAfter=Nov 7 09:14:22 2026 GMT, и больше ничего, поэтому -g срабатывает ровно в момент замены файла на обновлённый. Файлы в /etc/letsencrypt/live доступны только пользователю root, поэтому команда выполняется в root-оболочке. Учтите, что она отслеживает сертификат на диске. Запущенный веб-сервер хранит старый сертификат в памяти до перезагрузки, поэтому проверяйте, что именно отдаётся клиентам, с помощью echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate. Не запускайте эту команду с интервалом в две секунды против публичного хоста. Само обновление должно быть настроено через systemd-сервис и таймер, а systemctl list-timers покажет время следующего запуска.

Опустошение очереди

watch -n 15 'postqueue -p | tail -n 1'

Эта команда выводит итоговую строку, например -- 24 Kbytes in 6 Requests., или Mail queue is empty после завершения работы. Тот же подход применим к любой очереди, которую можно посчитать: watch -n 5 'find /srv/queue/incoming -type f | wc -l'.

Здесь возможности watch заканчиваются. Утилита сравнивает текущий кадр с предыдущим и не умеет проверять условия, поэтому она не сообщит вам, что «счётчик достиг нуля». С этим справится обычный цикл оболочки, использующий подстановку команд для получения значения счётчика на каждой итерации:

until [ "$(find /srv/queue/incoming -type f | wc -l)" -eq 0 ]; do sleep 5; done; echo 'queue drained'

Когда команда watch — неподходящий инструмент

Команда watch перезапускает вашу команду, не сохраняя состояние предыдущего выполнения и не учитывая специфику самой команды. Это допустимо для df. Однако в четырех ситуациях это решение будет ошибочным.

  • Логи. watch перерисовывает фиксированный кадр, поэтому строки, которые появляются и исчезают в промежутках между циклами, теряются. Используйте journalctl -fu nginx или tail -f, которые выводят новые строки по мере их записи.
  • Ресурсоемкие команды. du -sh / или запрос к нагруженной базе данных превращаются в постоянную фоновую нагрузку с любым интервалом, так как watch продолжает запускать их снова и снова.
  • Любые действия с побочными эффектами. Команда, которая выполняет запись, отправку данных, перезапуск или установку, будет повторять это на каждом цикле. curl к API каждые две секунды — это 43,200 запросов в день, что приводит к блокировке бесплатного API key.
  • Длительные проверки. watch работает в вашем терминале и завершается вместе с сессией. Она никого не оповещает и не сохраняет историю после того, как вы закрываете ноутбук. Для таких задач вам нужно настоящее средство мониторинга состояния, например Uptime Kuma, или запланированная проверка, работающая на сервере.

Граница применения определяется временем. watch предназначена для десяти минут ожидания конкретного события. Всё, что должно проверяться и завтра, должно быть оформлено в виде запланированного таймера или полноценной системы мониторинга.

Запуск watch внутри tmux при работе по SSH

При работе по SSH время жизни команды watch ограничено стабильностью соединения. При разрыве связи оболочка получает сигнал SIGHUP и завершает работу watch. Использование tmux решает эту проблему, делая watch по-настоящему полезным инструментом на удаленном сервере.

tmux new -As ops
watch -n 30 -d 'df -h /'

Нажмите Ctrl+b, а затем d для отсоединения от сессии. Цикл выполнения команды продолжит работать на сервере. При повторном подключении с помощью tmux attach -t ops вы увидите, что данные продолжают обновляться, что подтверждается часами в заголовке. Разделите окно, чтобы запустить watch в одной части, а journalctl -f — в другой; в этом и заключается основная идея рабочего окружения на базе tmux. Если одна и та же задача требует мониторинга нескольких серверов одновременно, лучше использовать инструмент для управления множеством серверов Linux, а не создавать множество панелей с watch.

Приведенные здесь снимки экрана носят иллюстративный характер. Расположение столбцов и версии могут различаться в зависимости от дистрибутива и выпусков procps-ng, поэтому изучите man watch на вашей машине, чтобы узнать, какие именно флаги поддерживает ваша сборка.

FAQ

Почему watch игнорирует pipe в watch mycmd | grep foo?

Ваша оболочка разделяет строку по символу pipe до того, как запускается watch, поэтому она перенаправляет вывод отрисовки экрана самого watch в grep, а вывод команды не фильтруется. Заключите весь конвейер в кавычки: watch 'mycmd | grep foo'. watch передает этот единственный аргумент в sh -c, которая выполняет конвейер один раз за цикл. Это же правило применимо к подстановкам имен файлов (glob) и подстановке команд.

Какой интервал следует использовать с watch?

Подбирайте его в зависимости от того, как быстро меняется значение и насколько ресурсоемким является выполнение команды. Полсекунды подходят для быстрых счетчиков, а 0.1 секунды — это минимальный интервал, который принимает watch. От тридцати до шестидесяти секунд подходят для дисков и сертификатов. Время выполнения команды прибавляется к паузе, если вы не используете флаг -p, поэтому медленная команда с -n 1 будет просто выполняться непрерывно без пауз.

Может ли watch отслеживать лог-файл?

Нет. watch перерисовывает один кадр и не хранит историю, поэтому любая строка, которая появилась и исчезла между двумя циклами, будет потеряна навсегда. journalctl -fu <unit> и tail -f выводят новые строки по мере их поступления, что и требуется для логов. Используйте watch для значений, имеющих текущее состояние, таких как процент заполнения диска или длина очереди.

Как сделать так, чтобы watch останавливался, когда происходит ожидаемое событие?

Используйте -g (--chgexit) и укажите команду, вывод которой остается неизменным до наступления этого события. Вывод, содержащий часы или PID, меняется при первом же обновлении, из-за чего команда немедленно завершается, поэтому systemctl is-active myapp работает там, где systemctl status myapp не подходит. Для реального условия, например, когда счетчик достигает нуля, используйте цикл until в оболочке, так как watch может только обнаружить, что вывод изменился.

Почему watch сообщает «command not found» для того, что работает в моей оболочке?

watch передает команду в sh -c, а эта оболочка не считывает .bashrc, поэтому ваши псевдонимы (aliases) и функции оболочки там отсутствуют. Сообщение обычно выглядит как sh: 1: ll: not found. Напишите полную команду или используйте полный путь к бинарному файлу, который находится только в вашей интерактивной PATH.