Как часто вы запускали какую‑нибудь штуку в терминале — и она зависала навсегда? Или наоборот: вам нужно было увидеть, как что‑то меняется каждую секунду, а вы упорно жали стрелку вверх и Enter? А может вы хотели запланировать задачу через 5 минут, но cron — это уже overkill?
Для всех этих сценариев в Linux есть три проверенных утилиты: timeout
, watch
, at
. И, да, можно было бы обойтись скриптами и велосипедами, но... мы же не зря используем Unix‑подход, где всё уже давно придумано.
Сегодня мы рассмотрим: как управлять временем выполнения команд в Linux с помощью timeout, watch и at.
timeout
timeout
— это часть пакета GNU coreutils. Его задача: запуск команды и слежка за временем. Если команда превышает лимит — она завершается по сигналу.
Сигнал по дефолту — SIGTERM
, и это важно понимать: процессу дают шанс закончить работу корректно.
timeout 5s ./my_script.sh
Это значит: если my_script.sh
не завершится через 5 секунд, он получит SIGTERM
. Не завершится после — будет убит. Но только если вы явно попросите.
Как определить, почему команда завершилась?
Код возврата | Что означает |
---|---|
124 | Команда убита по таймауту |
125 | Ошибка в |
126 | Команда не исполняема |
127 | Команда не найдена |
Остальное | Это код завершения самой команды |
timeout 3s sleep 5
echo $?
# Выведет 124
Допустим, у вас не просто скрипт, а демон или сервер, и его нельзя гасить жёстко. Вы хотите сперва вежливо постучаться (SIGTERM), а если не открыл — вломиться (SIGKILL).
timeout --signal=SIGTERM --kill-after=2s 10s ./long_running_job
Через 10 секунд посылается SIGTERM. Если процесс не отреагировал — через 2 секунды ему прилетает SIGKILL.
Вот такая цепочка просто обязательна. Потому что просто убить процесс — полдела. Нужно дать ему шанс закрыть файлы, отписаться от сокетов и так далее.
Иногда вы хотите, чтобы timeout
не вмешивался в exit‑код команды, если она завершилась сама. Тогда:
timeout --preserve-status 5s ./backup_script.sh
Без этого флага, даже если скрипт завершится с 0, timeout
может вернуть 124 или 137 в зависимости от сигнала.
Безопасный curl с таймаутом:
if ! timeout 3s curl -s https://example.com > /dev/null; then
echo "Request failed or timed out"
fi
Зачем делать так, если есть curl --max-time
? Потому что timeout
:
Универсален (не зависит от утилиты).
Может работать с любыми программами, а не только с сетевыми.
Позволяет детектировать не только долгую загрузку, но и зависание любого рода (например, если
curl
повис на DNS).
Дерево процессов
Если команда timeout
запускает процесс, а тот — порождает других, то:
По дефолту
timeout
убьёт только первый процесс.Все дочерние останутся жить, если они не завершатся сами.
Пример:
timeout 3s bash -c "sleep 5 & wait"
sleep
останется жить даже после завершения bash
, потому что он — отдельный процесс. Чтобы всё завершить как положено:
Вариант 1: setsid
timeout --foreground 3s setsid bash -c "sleep 5"=
setsid
запускает процесс в новой session group. timeout
может тогда убить всю группу сигналом.
Вариант 2: trap внутри скрипта
Если вы управляете кодом скрипта, можно повесить ловушку:
#!/bin/bash
trap "kill 0" EXIT
sleep 5 &
wait
И тогда timeout
убьёт скрипт, а тот — всех своих детей.
Пример скрипта с логикой таймаута и логированием
#!/bin/bash
log_file="/var/log/mytask.log"
cmd="./long_task.sh"
timeout_sec=30
echo "[INFO] Running command with timeout ${timeout_sec}s" | tee -a "$log_file"
if timeout --kill-after=5s "$timeout_sec" "$cmd" >> "$log_file" 2>&1; then
echo "[INFO] Command finished successfully" | tee -a "$log_file"
else
status=$?
if [ "$status" -eq 124 ]; then
echo "[ERROR] Command timed out" | tee -a "$log_file"
elif [ "$status" -eq 137 ]; then
echo "[ERROR] Command killed forcefully" | tee -a "$log_file"
else
echo "[ERROR] Command failed with exit code $status" | tee -a "$log_file"
fi
fi
Безопасно, читаемо, и можно засунуть хоть в Ansible, хоть в init‑скрипт.
watch
watch
— это как cron
. Он не ставит задачи в фон, он — показывает результат команды каждые N секунд.
watch -n 2 'команда'
-n 2
— интервал между запусками. 'команда'
— в одиночных кавычках обязательно, если есть пайпы или сложность.
Пример:
watch -n 1 'ls -lh /var/log/myapp'
Полезные флаги
Минимум, который надо выучить и запомнить:
Флаг | Что делает |
---|---|
| Интервал между вызовами (по умолчанию 2 сек) |
| Подсвечивает строки, которые изменились |
| Убирает шапку ( |
| Не очищает экран между итерациями ( |
| Завершить |
Разбор типовых сценариев
Мониторинг свободного места на диске:
watch -d -n 5 df -h /mnt/data
Идеально, если у вас летит выгрузка, миграция или ETL на пару гигабайт и вы не хотите остаться без диска.
Просмотр последних строк в логе:
watch -n 0.5 'tail -n 10 /var/log/syslog'
Полсекунды — нормальный интервал для чтения вживую. Если логи идут быстро, tail -F
может быть даже полезнее, но watch
проще в использовании.
Следим за systemd сервисом:
watch -n 1 'journalctl -u nginx.service -n 10 --no-pager'
--no-pager
обязателен. Иначе journalctl
залипнет, ожидая нажатия клавиш.
Приме
watch -n 1 'ps -eo pid,etime,%cpu,%mem,cmd --sort=-%cpu | head -10'
Это выводит топ-10 процессов по загрузке CPU.
Подсветка изменений: -d
Когда вы отслеживаете метрики (CPU, IO, tx/rx по сетевым интерфейсам), -d
показывает только изменившиеся строки. Не нужно глазами искать, что именно поменялось.
Пример:
watch -d -n 1 'netstat -antp | grep ESTABLISHED'
Алиасы и привычки
В ~/.bash_aliases
:
alias wtail="watch -n 1 'tail -n 20'"
alias wdf="watch -d -n 2 'df -h'"
alias wps="watch -n 1 'ps aux --sort=-%cpu | head -10'"
Быстрее вбить wps
, чем каждый раз вспоминать ps aux
и флаги сортировки.
Ограничения и особенности
По умолчанию watch
пишет только stdout. Поэтому, если команда падает, вы можете не заметить. Чтобы всё увидеть:
watch -n 1 'команда 2>&1'
Если вы забыли кавычки, и в команде есть пайпы, watch
может отработать странно или вообще не запуститься.
Плохо:
watch -n 1 tail -n 10 /var/log/syslog | grep error
Хорошо:
watch -n 1 'tail -n 10 /var/log/syslog | grep error'
Переходим к at.
at: запуск команды в будущем
Если cron
— это про регулярность, то at
— про раз и навсегда. Прямой, удобный, Unix‑way инструмент, если тебе нужно что‑то запустить через 5 минут и забыть. И не, не нужно писать костыльный sleep 300 && your_command &
.
at
не всегда стоит из коробки. Поэтому на Debian/Ubuntu:
sudo apt install at
sudo systemctl enable --now atd
Если не включить atd
, то можно сколько угодно пихать задачи в очередь, но никто их исполнять не будет.
Синтаксис
Всё просто:
echo "команда" | at <время>
Или интерактивно:
at 10:30
И тебе открывается ввод команд (одна на строку), а завершение по Ctrl+D
.
Примеры использования
Запись в файл через 2 минуты:
echo "echo 'Hello from the future' > ~/future.txt" | at now + 2 minutes
Перезапуск сервиса:
echo "sudo systemctl restart nginx" | at now + 10 minutes
Удаление временных файлов:
echo "rm -rf /tmp/my-temp" | at 03:00
Отправка уведомления себе:
echo "DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus notify-send 'Сделай перерыв!'" | at now + 1 hour
notify-send
требует правильных переменных окружения, особенно в десктоп‑средах. Сам at
запускается как system user и без GUI‑окружения — нужно передать DISPLAY
и DBUS_SESSION_BUS_ADDRESS
вручную.
Как посмотреть очередь
atq
Пример вывода:
1 2025-07-28 12:30 a user
2 2025-07-28 14:00 a user
Где:
Первый столбец — ID задания
Время — когда оно будет выполнено
a
— активное (ещё не исполнено)
Удалить задание
atrm <job_id>
Пример:
atrm 1
Или:
atq | grep rotate | awk '{print $1}' | xargs atrm
Удалит все задания, связанные с конкретным словом в команде (если ты хранишь логику именования).
Как это использовать
Плановый рестарт сервиса ночью:
echo "sudo systemctl restart myservice" | at 02:30
Бэкап текущей директории через 15 минут:
echo "tar czf ~/backup_$(date +\%Y\%m\%d).tar.gz $(pwd)" | at now + 15 minutes
Отправка сообщения себе в Telegram:
echo "curl -s -X POST https://api.telegram.org/bot$TOKEN/sendMessage -d chat_id=$CHAT -d text='Пора встать и пройтись'" | at now + 45 minutes
Альтернативные форматы времени
Вот что понимает at
:
Формат | Пример |
---|---|
| от текущего момента |
| сегодня в 00:00 |
| сегодня в 16:00 |
| завтра в 00:00 |
| сегодня в 12:30 |
| точная дата и время |
Если нужно быстро сделать задачу «отложить команду и забыть» используем at
.
Итоги
timeout
, watch
и at
— три скромные, но очень полезные утилиты, которые закрывают кучу сценариев: от убийства зависших процессов до live‑мониторинга и точечного запуска задач. Делитесь своими кейсами в комментариях.
Если вы работаете с Linux и стремитесь систематизировать знания — обратите внимание на курс Administrator Linux. На нем разбираем работу с процессами, планировщиками задач, службами и журналами — в том числе утилиты вроде
timeout
,watch
иat
.Чтобы узнать больше о курсах по Linux и получить доступ к записям открытых уроков, переходите в телеграм‑бот.