Команда watch у Linux: інтервал, diff і канали
Як правильно використовувати watch у Linux: інтервал за замовчуванням 2 секунди, підсвічування diff, вихід після зміни та лапки для pipe.
Призначення команди watch
Команда watch повторно виконує іншу команду через заданий інтервал і перемальовує її вивід у тому самому місці на екрані. Інтервал за замовчуванням становить 2 секунди. Використовуйте її, коли потрібно стежити за зміною числового значення: заповненням диска, завершенням запуску контейнера, поновленням сертифіката або спорожненням черги.
watch входить до складу procps-ng і вже встановлена на новому Ubuntu або Debian VPS як частина пакета 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 не є окремою файловою системою, кореневу файлову систему буде показано двічі. Це швидкий спосіб визначити, як розділено диск.
Порівняння виконується за позиціями. Це означає, що рядки нового кадру порівнюються з попереднім посимвольно. У виводі, де ширина стовпців змінюється, буде підсвічено майже весь текст, тому віддавайте перевагу командам зі стабільним форматом. Поточна версія 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?
Це помилка, з якою стикається майже кожен. Причина в shell, а не у watch.
watch docker compose ps | grep webВаш інтерактивний shell читає весь рядок до початку виконання й розділяє його за pipe. Він запускає watch docker compose ps і передає власний вивід watch до grep. watch більше не записує дані безпосередньо в термінал, тому відображення працює неправильно або залишається порожнім, а grep фільтрує вивід перемальовування, а не список контейнерів.
Візьміть увесь pipeline у лапки, щоб передати його як один аргумент.
watch 'docker compose ps | grep web'watch передає цей рядок до sh -c, а цей shell виконує pipeline один раз за цикл. Glob працює за тим самим правилом, але помилка менш помітна.
watch ls -l /var/log/*.log
watch 'ls -l /var/log/*.log'У першому рядку glob розгортається один раз у вашому shell у момент натискання Enter. Потім watch повторно використовує незмінний список імен файлів, тому файл журналу, створений через хвилину, не з’явиться. У другому рядку glob передається до watch, який розгортає його всередині sh під час кожного циклу. Тому нові файли з’являються автоматично.
Лапки також визначають, коли обчислюється змінна або підстановка команди. watch "echo $(date)" виконує date один раз у вашому shell, а потім безперервно виводить зафіксований рядок. watch 'echo $(date)' виконує date під час кожного циклу. Одинарні лапки означають «пізніше». Подвійні лапки означають «зараз».
Це sh -c має ще два наслідки:
- Aliases і shell-функції всередині нього недоступні.
watch llзавершується помилкоюsh: 1: ll: not found, оскількиsh -cне читає ваш.bashrc. Вкажіть повну команду або передайте повний шлях до бінарного файлу, який доступний лише у вашому інтерактивномуPATH. - Варто перехоплювати стандартний потік помилок. Додайте
2>&1усередині лапок, якщо потрібно виводити текст помилок у межах кадру, а не розподіляти його по екрану.
Коли робота з лапками стає незручною, -x (--exec) запускає команду безпосередньо, а не через sh -c. Аргументи з пробілами обробляються простіше, але pipe і glob повністю припиняють працювати, оскільки їх більше немає кому інтерпретувати.
Права доступу працюють за тією самою логікою, оскільки 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 під watch, щоб бачити, чи продовжує показник зростати.
Контейнер, який постійно перезапускається
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 має обмеження. Він порівнює один кадр із попереднім і не вміє перевіряти умову, тому ніколи не повідомить: "кількість досягла нуля". Для цього можна використати звичайний цикл shell із підстановкою команд, щоб отримувати кількість на кожній ітерації:
until [ "$(find /srv/queue/incoming -type f | wc -l)" -eq 0 ]; do sleep 5; done; echo 'queue drained'Коли команду watch використовувати не варто
watch повторно запускає команду, не зберігає інформацію про попередній запуск і не враховує призначення цієї команди. Для df цього достатньо. Але в чотирьох ситуаціях watch використовувати не слід.
- Журнали. watch перемальовує фіксований кадр, тому рядки, які з’явилися та прокрутилися між двома циклами, буде втрачено. Використовуйте
journalctl -fu nginxабоtail -f. Вони виводять нові рядки в міру їх запису. - Ресурсомісткі команди.
du -sh /або запит до завантаженої бази даних за будь-якого інтервалу створює постійне фонове навантаження, оскільки watch знову запускає команду після кожного циклу. - Будь-які команди з побічними ефектами. Команда, яка записує дані, надсилає запити, перезапускає або встановлює компоненти, виконуватиме цю дію в кожному циклі.
curlдо API кожні дві секунди — це 43,200 запитів на добу. Через це безкоштовний API key можуть заблокувати. - Перевірки, що мають працювати тривалий час. watch працює у вашому терміналі та завершується разом із сеансом. Після закриття ноутбука він нікого не сповіщає і не зберігає історію. Для цього потрібен повноцінний монітор стану, наприклад Uptime Kuma або запланована перевірка, яка працює на сервері.
Чітка межа — це час. watch призначений для десяти хвилин очікування конкретної події. Усе, що має продовжувати перевірятися завтра, належить до запланованого timer або повноцінного монітора.
Запускайте 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 ігнорує канал у watch mycmd | grep foo?
Ваша оболонка розділяє рядок на каналі ще до запуску 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, тому ваші псевдоніми та функції оболонки в ній недоступні. Зазвичай повідомлення означає sh: 1: ll: not found. Вкажіть реальну команду повністю або використайте повний шлях до двійкового файла, який доступний лише у вашому інтерактивному PATH.