timeout и sleep
Ограничить время работы команды (timeout -s -k, код 124) и сделать паузу (sleep с единицами s, m, h, d)
timeout запускает команду и, если та не закончилась за отведённое время, посылает ей сигнал (по умолчанию SIGTERM). Нужен, чтобы зависший curl, проверка или скрипт не висели вечно — в cron, CI, циклах ожидания. sleep просто ждёт указанное время; вместе они дают классический цикл «проверять раз в секунду, но не дольше минуты».
Синтаксис
timeout [опции] длительность команда [аргументы…]
sleep число[единица]…
Длительность
| Запись | Значение |
|---|---|
5 или 5s | 5 секунд (секунды — по умолчанию) |
0.5 | полсекунды — дробные числа допустимы |
2m / 1h / 1d | минуты / часы / сутки |
sleep 1m 30s | у sleep несколько аргументов складываются: 90 секунд |
sleep infinity | ждать бесконечно (удобно, чтобы контейнер не завершался) |
timeout 0 … | ограничение отключено |
Опции timeout
| Опция | Что делает |
|---|---|
-s сигнал | какой сигнал послать по истечении времени: TERM (по умолчанию), INT, HUP, KILL или номер |
-k время | если через это время после первого сигнала команда ещё жива — послать SIGKILL |
--preserve-status | вернуть код самой команды (например, 143 = убита SIGTERM), а не 124 |
--foreground | не уводить команду в фон: она может читать с терминала и получать Ctrl+C; дочерние процессы при этом по таймауту не убиваются |
-v | сообщить в stderr, какой сигнал был послан |
Коды возврата timeout
| Код | Когда |
|---|---|
| код команды | команда успела завершиться сама |
124 | время вышло и команде послан сигнал (кроме KILL) |
125 | ошибка самого timeout (неверная опция или длительность) |
126 | команда найдена, но не запускается (нет прав x) |
127 | команда не найдена |
137 | команда убита SIGKILL (-s KILL или сработал -k): 128 + 9 |
Примеры
# не ждать ответа сервера больше 5 секунд
timeout 5 curl -s http://localhost:8080/health
# отличить «не успел» от «упал»
timeout 10 ./check.sh
rc=$?
if [ "$rc" -eq 124 ]; then echo "превышено время"; elif [ "$rc" -ne 0 ]; then echo "ошибка $rc"; fi
# вежливо попросить завершиться, через 5 секунд — убить
timeout -k 5 30 ./long-job.sh
# послать Ctrl+C-сигнал вместо TERM (программа успеет сохранить состояние)
timeout -s INT 60 ./collector
# ждать, пока порт откроется, но не дольше 30 секунд
timeout 30 bash -c 'until ss -ltn | grep -q ":8080 "; do sleep 1; done'
# то же для файла
timeout 10 bash -c 'while [ ! -f /tmp/ready ]; do sleep 0.5; done' || echo "не дождались"
# паузы
sleep 2
sleep 0.2
sleep 1m 30s
sleep infinity &
# собрать данные ровно за 3 секунды
timeout 3 tail -f /var/log/syslog > sample.log
Подводные камни
- Код 124 — это не ошибка команды. В
set -e-скриптах и проверках CItimeoutпо истечении времени даёт ненулевой код 124 даже для «нормального»tail -f. Обрабатывай его явно:timeout 3 tail -f log || [ $? -eq 124 ]. - Функции, алиасы и встроенные команды не работают.
timeout 5 cd /tmpилиtimeout 5 моя_функция— «failed to run command», код 127:timeoutзапускает только программы. Оборачивай вbash -c '…'. - Сигнал можно проигнорировать. Если команда перехватывает или игнорирует
SIGTERM, она отработает до конца, аtimeoutвсё равно вернёт 124. Защита —-k 5(добавочныйSIGKILL) или-s KILL. - С
-s KILLи-kкод — 137, а не 124. Проверяй оба значения. timeoutуводит команду в фоновую группу процессов. Интерактивные программы (запрос пароля,readс терминала) не смогут читать ввод и Ctrl+C не дойдёт до них. Для них —--foreground.- Внутри конвейера ограничен только один элемент.
cat big | timeout 1 head …ограничитhead;catполучитSIGPIPE(код 141) после его завершения. Чтобы ограничить весь конвейер —timeout 1 bash -c 'a | b'. sleep 1xиsleep -1— ошибка с кодом 1, а не пауза. Единицы — толькоs,m,h,d.- Цикл
while sleep 1безtimeoutили счётчика может ждать вечно, если условие так и не выполнится.
См. также
background · kill · exit-codes · conditions-loops · curl · date