Давно не виделись. Давай сразу к делу. У меня есть скрипт с бесконечным циклом, который выполняет какие-то действия.

Задача: нужно, чтобы скрипт отработал 3 минуты и завершился.

Можно, конечно, запустить скрипт, подождать 3 минуты и руками его стопнуть через Ctrl+C, но это не трувей. А что, если нужно 5 минут или 45? Не буду же я сидеть всё это время в ожидании.

К счастью, у нас с тобой есть утилита timeout, которая уже идёт в коробке с Linux.

Вот с помощью этой утилиты можно ограничивать по времени выполнение скриптов и команд. Давай рассмотрим примеры.

timeout 3s ping www.bashdayz.ru

Команда ping отработает 3 секунды и завершится. Конечно, у ping есть свои ключи для этого, но сегодня у нас про другое.

Синтаксис у команды timeout довольно простой:

timeout DURATION COMMAND

DURATION = длительность. Это число с плавающей запятой и с необязательным суффиксом следующего вида:

  • s = секунды;
  • m = минуты;
  • h = часы;
  • d = дни.

COMMAND = сама команда или скрипт, которому нужно ограничить работу по времени.

Допустим, мне нужно запустить какое-то приложение (например, top) на удалённом сервере и через 3 минуты всё это безобразие прекратить. Ок, делаем такое:

timeout 3m ssh user@bashdayz.ru -- /usr/bin/top

Прошло 3 минуты, приложение гасится, SSH-сессия завершается. Удобно? Удобно!

Если по истечении этого времени у тебя в терминале исчез курсор (частенько такое бывает), то выполни команду reset, терминал сбросится и всё вернётся на круги своя.

Также можно послать определённый сигнал завершения для приложения. К примеру:

timeout -s 9 3m ping www.bashdayz.ru

Чтобы получить список всех сигналов, можешь выполнить команду kill -l и посмотреть. Их там достаточно много. Я не заморачиваюсь и рублю с плеча сигналом 9 (SIGKILL). Убивать так убивать.

Вместо номера сигнала можно указывать явное имя:

timeout -s SIGTERM 5m ping www.bashdayz.ru

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

Ладно. Утилита timeout — это клёво, а как реализовать то же самое, не применяя её, на чистом Bash? Смотри:

ping www.bashdayz.ru & read -t 3 || kill $!

В этом примере выполняется ping и по прошествии 3 секунд завершается. Тут уже тебе самому решать: использовать timeout либо подобную конструкцию.

А, точно, забыл объяснить про символ «$!». Эта конструкция содержит в себе идентификатор процесса (PID) последнего выполненного фонового конвейера. В примере выше последним выполненным заданием был ping. То есть явно не нужно указывать PID, чтобы kill корректно отработал.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
В Linux столько всего интересного, но не каждый про это интересное знает. Я изначально использовал Bash-конструкцию и только спустя какое-то время узнал про утилиту timeout.

Собственно, на этом всё. Век живи, век учись. Котиков тебе и удачи. Давай, увидимся!