Який простий спосіб дозволити команді працювати 5 хвилин? [дублікат]


66

Чи існує простий спосіб дозволити певній команді (лише до кінця Ctrl-C) автоматично працювати протягом 5 хвилин?

Наприклад:

minute-command 5-minutes ping www.google.com

або будь-яка інша команда, яка не припиняє себе.

Я хотів би мати змогу вказати обмеження часу, а не лише 5 хвилин.

Відповіді:


67

Існують (принаймні) дві програми, які забезпечують цю функціональність:

ІМ’Я

timelimit - ефективно обмежувати абсолютний час виконання процесу

СИНОПИС

timelimit [-pq] [-S killsig] [-s warnsig] [-T killtime] [-t warntime] command [arguments ...]

і

ІМ’Я

timeout - запустити команду з обмеженням часу

СИНОПИС

timeout [OPTION] DURATION COMMAND [ARG]...
timeout [OPTION]

Вони упаковуються наступним чином:

$ dlocate `which timeout timelimit`
timelimit: /usr/bin/timelimit
coreutils: /usr/bin/timeout

Порівняння:

/-----------------------------+------------+----------------\
|            Feature          |  timelimit |     timeout    |
+=============================+============+================+
|   time to run               | -t time    | first argument |
+-----------------------------+------------+----------------+
|   terminate signal          | -s signal  | -s signal      |
+-----------------------------+------------+----------------+
|   grace period              | -T time    | -k time        |
+-----------------------------+------------+----------------+
|   kill signal               | -S signal  | (note 1)       |
+-----------------------------+------------+----------------+
|   propagate signals         | -p         | (note 2)       |
\-----------------------------+------------+----------------/

Примітки:

  1. timeoutзавжди використовує SIGKILLв якості останнього сигнал.
  2. timeout не має функціональних можливостей для виходу із сигналом, коли це робить дочірня програма.

Статус виходу двох програм відрізняється, але це важко акуратно підсумувати, тому я пропоную вам проінформувати самі сторінки інструкцій.

Оскільки timeoutвстановлено у більшості систем за замовчуванням ( coreutilsце стандартний пакет у багатьох дистрибутивах), я пропоную вам скористатися цим випадком, якщо вам не потрібна додаткова функціональність, що надається компанією timelimit.


10
Чому б ви використовували один, а не інший?
Бріс М. Демпсі

2
@ BriceM.Dempsey На моїй локальній машині час очікування є, але часу немає (хоча це доступно в репо). Отже, якщо один із них встановлений заздалегідь ... Окрім того, лише переглядаючи підписи методу, я бачу, що вони роблять різні речі та мають різні випадки використання.
Benubird

Зауважте, що існує щонайменше дві реалізації timelimit. Дивіться, як я можу вбити процес і переконайтесь, що PID не використовувався повторно для отримання додаткової інформації про них та час очікування GNU.
sch

1
@ BriceM.Dempsey timeoutвходить в GNU coreutils , timelimitні. Ви можете встановити жодного, одного або обох. Для другого повідомляється, що timelimit виконує команду та припиняє породжений процес через заданий час із заданим сигналом. Спочатку надсилається сигнал "попередження" , потім, після закінчення тайм-ауту, сигнал "вбити", подібний до того, як init (8) працює при відключенні. Тож навіть інша в середній поведінці.
Гастур

Оскільки GNU coreutils попередньо встановлюється на кожному GNU / Linux, timeoutце шлях до цього.
rexkogitans

87

Насправді це те, що timeoutдля:

TIMEOUT(1)                          User Commands                         TIMEOUT(1)

NAME
       timeout - run a command with a time limit

SYNOPSIS
       timeout [OPTION] DURATION COMMAND [ARG]...
       timeout [OPTION]

DESCRIPTION
       Start COMMAND, and kill it if still running after DURATION.

lx@lxtp:~$ dpkg -S /usr/bin/timeout
coreutils: /usr/bin/timeout

16

Чисто bashвбудований, без стрижнів

Я виявив, що це рішення працює, bashспираючись на вбудовану команду без виклику зовнішнього виконуваного файлу. Він працює в системі, де з часом навіть не були встановлені основні системи [ 1 ]

YourCommand & read -t 300 ;  kill $!                           # 1st version
YourCommand & read -t 300 || kill $!                           # 2nd version 

Пояснення : як зазвичай при використанні команди у фоновому режимі з &його PID зберігається у внутрішній змінної $!( в даний час в сучасній версії dash, csh, bash, tcsh, zsh...).
Що насправді має різницю серед оболонок - це наявність вбудованої команди read[ 2 ] та опції -t. У першій версії, якщо користувач не завершить рядок введення до вказаної кількості секунд, інструкція буде припинена та буде сформовано код повернення помилки.

-t TIMEOUT Причина зчитування для очікування та виходу з ладу, якщо повна лінія вводу не буде прочитана протягом TIMEOUT секунд.

Друга версія працює як перша, але ви можете перервати час очікування вбивства просто натиснувши enter.
Дійсно, або оператор ||виконує killоператор, лише якщо readкоманда закінчується кодом повернення, відмінним від нуля, як, коли час закінчення закінчився. Якщо натиснути enterдо цього моменту, він поверне 0, і це не вб'є вашу попередню команду.


Рішення Coreutils [ 1 ]

Коли Coreutils присутні у вашій системі , і ви не потребуєте , щоб заощадити час і ресурси , щоб викликати зовнішню програму, timeoutі sleepта є досконалими способами , щоб досягти своєї мети.

timeoutВикористання timeoutпрямолінійно.
Зрештою, ви можете розглянути можливість використання також -kопції для надсилання додаткового сигналу вбивства, якщо перший не вдасться.

timeout 5m YourCommand                                         # 3rd version 

sleep З sleepвами можна використати свою фантазію або взяти натхнення [ 3 ] . Зауважте, що ви можете залишити свою команду у фоновому режимі чи на передньому плані (наприклад, topзазвичай це має бути на передньому плані).

YourCommand & sleep 5m; kill $!                                # 4th Background
YourCommand & pid=$! ; (sleep 5m; kill $pid;) &                # 5th Background

bash -c '(sleep 5m; kill $$) & exec YourCommand'               # 6th Foreground
(cmdpid=$BASHPID; (sleep 5m; kill $cmdpid) & exec YourCommand) # 7th Foreground

Пояснення

  • У 4-й версії ви виконуєте у фоновому режимі, YourCommandа потім оболонку sleep- 5 хвилин. Після завершення останнього фонового процесу ( $!) буде вбито. Ви зупиняєте свою оболонку.
  • У 5-й версії замість цього ви виконуєте у фоновому режимі, YourCommandі ви негайно зберігаєте цей PID у змінній $pid. Тоді ви виконуєте у фоновому режимі дрімоту в 5 хвилин і її послідовну команду, яка знищить збережений PID. Оскільки ви надіслали цю групу команд у фоновому режимі, ви не зупиняєте свою оболонку. Потрібно зберігати PID у змінній, оскільки значення $!може бути оновлено можливим виконанням іншої програми у фоновому режимі. Простими словами, ви уникаєте ризику вбити неправильний процес або взагалі немає процесу.
  • У 6-й версії вона називається новою оболонкою, яка самогубства через 5 хвилин $$, після чого виконується ваша команда, що залишається на передньому плані.
  • У 7-й версії він викликається підзаголовком, ()який зберігає свій PID у змінній ( cmdpid) і вбиває себе за допомогою іншої підзарядки, надісланої у фоновому виконанні, а потім запускає YourCommand на передньому плані.

Звичайно, у кожній версії ви можете надсилати потрібний сигнал вбивства, починаючи від типового до крайнього kill -9 , використовуватися лише тоді, коли це дійсно потрібно.

Список літератури

  • [ 1 ] Кореутіли
  • [ 2 ] Посібник для початківців Bash
  • [ 3 ] BashFAQ

2
"Сном ви можете використовувати свою фантазію або взяти натхнення [посилання на FAQ Bash]" +1 #thatsenoughinternetfortoday
joeytwiddle

11

Для вашого конкретного випадку більшість реалізацій pingпідтримки -cабо --countприпиняються після певної кількості пінг:

ping -c 300 host.example.com

Для більш загального рішення дивіться інші відповіді.


7
Я вражаю, що ОП якраз pingі є конкретним прикладом. Він не хоче вирішувати конкретні випадки для кожної різної програми.
користувач1717828

8

Ви можете зробити це за допомогою простого сценарію, подібного до цього:

#!/bin/bash

#
# $1 is the time to let the program run, and $2, $3, ... are the command itself.
#

"${@:2}" &
PID=$!
sleep "${@:1:1}"
kill -2 $PID

(сигнал SIGINT = 2, використаний відповідно до пропозиції Matija Nalis у коментарі нижче).

Пояснення (нечастого?) Виразу bash $@:...: позиційні параметри, ( $*, $@, "$*", "$@") допускають наступну додаткову специфікацію, наприклад:

"${@:START:COUNT}"

що означає: з усіх параметрів візьміть COUNT з них, перший з них - на початку START; якщо пропущено COUNT, візьміть їх до кінця, починаючи з позиції START. Пам'ятайте, що $0це назва програми. Якщо START негативний, почніть рахувати з кінця, і пам’ятайте, що COUNT не може бути негативним, отже, останній аргумент "${@:-1}". Крім того, майже завжди включайте позиційні параметри всередині подвійних лапок.


1
Я, мабуть, спроектував сценарій, щоб взяти час як перший або останній аргумент, і запустити всі інші аргументи як команду. Дозволити баш-розділити слова $1досить грубо. Також ви могли просто sleep "$1"або щось увійти countdown.
Пітер Кордес

1
@PeterCordes Готово, відповідно до ваших побажань.
MariusMatutiae

Час у першому аргументі дозволяє вам робити time=$1; shift, а потім вам не потрібен синтаксис нарізки масиву для позиційних параметрів. Але так, це набагато простіше.
Пітер Кордес

1
@PeterCordes Погодився, але ти попросив мене подивитися, чи знаю я безпечніший спосіб зробити це, і я щойно лінивий, чи я просто неосвічений. Лол.
MariusMatutiae

як плакат спеціально запитав про програму, яку можна перервати ctrl-c, можливо, краще спробувати kill -INTзамість цього kill -9(або принаймні спробувати -9лише через кілька секунд, якщо перший не вдався - це дає програмі можливість вийти чисто і не залишати тимчасові файли тощо навколо)
Matija Nalis

5

Оскільки ви згадуєте pingу своєму прикладі; у цієї команди є кілька варіантів зупинки через певний проміжок часу:

  • w Кінцевий термін Вкажіть тайм-аут у секундах, перш ніж ping закінчиться, незалежно від кількості пакетів, надісланих чи отриманих. У цьому випадку ping не припиняється після надсилання пакета для підрахунку , він чекає або закінчиться кінцевий термін, або доти, поки відповість зонди підрахунку чи з’явиться повідомлення про помилку в мережі.
  • W Час очікування Час очікування відповіді в секундах. Цей параметр впливає лише на час очікування, якщо немає відповідей, інакше ping чекає двох RTT.

-man ping

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.