LINUX.ORG.RU

bash прервать конвейер по таймеру

 


0

2

Здравствуйте, есть следующий конвейер:

stdbuf -o L script.py | while read line
do
echo $line
...
(какие-то действия с $line)
done
но бывает такое, что script.py очень долго ничего не выводит. Можно ли как-то по таймеру (если долго ничего не выводит) прервать цикл или вообще убить весь процесс?



Последнее исправление: user0228 (всего исправлений: 2)

man timeout

anonymous
()

если результат этого "..." должет просто выводить что-то на экран, то можно через tee писать копию вывода во временный файл и пропускать через while с 20 секундной (например) внутри проверкой этого временного файла в фоне

teod0r ★★★★★
()
Последнее исправление: teod0r (всего исправлений: 2)

решил так: создал новый скрипт, который принимает PID, и в нем сначала sleep на заданное время, а потом kill -9 $PID. А в основном цикле запускаю этот скрипт и убиваю предыдущий запущенный. Т.е на каждом выводи запускается новый экземпляр и удаляется старый.

user0228
() автор топика

Решал похожую задачу, используя read −t:

Из man bash:

read [−ers] [−u fd] [−t timeout] [−a aname] [−p prompt] [−n nchars] [−d delim] [name ...]

...

−t timeout

Cause read to time out and return failure if a complete line of input is not read within timeout seconds. 
This option has no effect if read is not reading input from the terminal or a pipe.

Smola
()
Ответ на: комментарий от user0228

Звучит как попытка реализовать timeout из coreutils.

timeout 2s sleep 5s

grazor ★★
()
Ответ на: комментарий от Smola

Хотел предложить ТСу этот вариант, но у меня он почему-то после наступления таймаута ждёт ещё одну строку и только после этого завершается, даже не обработав её. Это как-то можно обойти?

$ cat | while read -t 1 line; do echo LN $line; done; echo done
1
LN 1
2
LN 2
3
LN 3
10 (timeout)
done
grazor ★★
()
Ответ на: комментарий от grazor

Да, есть такая проблема. Как ее решить пока не понял.

Smola
()

Можно ли как-то по таймеру (если долго ничего не выводит) прервать цикл

Да, элементарно:

#!/bin/bash

timeout=10 # s

while read -t $timeout line; do
    printf '%s\n' "$line"
done < \
     <(cat)

Выглядит сие так:

$ /tmp/0228
foo      
foo
ждем десять секунд
ждем десять секунд
$ # и программа завершилась
Zmicier ★★★★★
()
Последнее исправление: Zmicier (всего исправлений: 1)
Ответ на: комментарий от Zmicier

Тут правда есть одна тонкость — такая программа по таймауту завершится *успешно*, а это, наверное, не вполне то, что вам нужно. Но это надо по логике решать: в простейшем случае — exit 1 в конец программы безусловно, а exit 0 куда-то внутрь цикла условно или на сигнал.

Zmicier ★★★★★
()

но бывает такое, что script.py очень долго ничего не выводит. Можно ли как-то по таймеру (если долго ничего не выводит) прервать цикл или вообще убить весь процесс?

А может лучше разобраться, почему именно он долго ничего не выводит (да и должен ли вообще?) и исправить это, а не городить костыли и подпорки, исходя из каких-то заблуждений?

blexey ★★★★★
()
Ответ на: комментарий от user0228

Если ты в теле цикла не запускаешь ничего в фон по '&' и не используешь подстановку процесса '<( ... )' или '>( ... )' (насчёт 'coproc' не знаю), можешь добавить после цикла kill ${!}.

ABW ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.