Таймаут в сценарии оболочки

Это напоминает мне, я должен использовать checkinstall чаще! Тем путем я просто делаю обычное

 ./configure
 make

сопровождаемый

 sudo checkinstall

создать .deb файл...

53
06.04.2011, 01:43
7 ответов

Что относительно этого:

foo=`{ { cat 1>&3; kill 0; } | { sleep 2; kill 0; } } 3>&1`

Это: выполните производящую вывод команду и sleep в той же группе процесса, группе процесса только для них. Какой бы ни команда возвращается, сначала уничтожает целую группу процесса.

Был бы любой задаваться вопросом: Да, канал не используется; это обошло использование перенаправлений. Единственная цель его состоит в том, чтобы иметь оболочку, выполняет эти два процесса в той же группе процесса.


Как Gilles указал в своем комментарии, это не будет работать в сценарии оболочки, потому что процесс сценария был бы уничтожен наряду с двумя подпроцессами.

Один путь ¹, чтобы вынудить команду работать в отдельной группе процесса состоит в том, чтобы запустить новую интерактивную оболочку:

#!/bin/sh
foo=`sh -ic '{ cat 1>&3; kill 0; } | { sleep 2; kill 0; }' 3>&1 2>/dev/null`
[ -n "$foo" ] && echo got: "$foo" || echo timeouted

Но могли бы быть протесты с этим (например, когда stdin не является tty?). stderr перенаправление там для избавлений от "Завершенного" сообщения, когда интерактивная оболочка уничтожается.

Протестированный с zsh,bash и dash. Но что относительно старых произведений?

B98 предлагает, чтобы следующее изменение, работающее над Mac OS X, с GNU, колотило 3.2.57, или Linux с тире:

foo=`sh -ic 'exec 3>&1 2>/dev/null; { cat 1>&3; kill 0; } | { sleep 2; kill 0; }'`


1. кроме setsid который, кажется, нестандартен.

33
27.01.2020, 19:33
  • 1
    мне вполне нравится это, я не думал об использовании группы процесса тот путь. Это довольно просто и нет никакого состояния состязания. Я должен протестировать его на мобильность еще немного, но это похоже на победителя. –  Gilles 'SO- stop being evil' 14.08.2011, 21:50
  • 2
    , К сожалению, это перестало работать эффектно, как только я поместил это в сценарий: конвейер в замене команды не работает в ее собственной группе процесса, и kill 0 заканчивает тем, что уничтожил вызывающую сторону сценария также. Существует ли портативный способ вызвать конвейер в его собственную группу процесса? –  Gilles 'SO- stop being evil' 16.08.2011, 17:09
  • 3
    @Gilles: Eek! не мог найти путь к setprgp() без setsid на данный момент :-( –  Stéphane Gimenez 16.08.2011, 18:06
  • 4
    мне действительно нравится прием, таким образом, я награждаю щедрость. Это, кажется, работает над Linux, у меня не было времени для тестирования его в других системах все же. –  Gilles 'SO- stop being evil' 20.08.2011, 22:05
  • 5
    @Zac: не возможно инвертировать упорядочивание в исходном случае, потому что только первый процесс получает доступ к stdin. –  Stéphane Gimenez 14.06.2012, 22:46
me=$$
(sleep 2; kill $me >/dev/null 2>&1) & nuker=$!
# do whatever
kill $nuker >/dev/null 2>&1

Вы уже захватываете 15 (числовая версия SIGTERM, который является что kill отправляет, если не сказали иначе), таким образом, необходимо уже быть хорошими для движения. Тем не менее, если Вы смотрите на предPOSIX, знать, что функции оболочки не могут существовать ни один (они произошли из оболочки System V).

6
27.01.2020, 19:33
  • 1
    Дело не в этом простой. При захвате сигнала много оболочек (тире, удар, pdksh, zsh …, вероятно, все кроме ATT ksh) игнорируют его, в то время как они ожидают cat выходить. Я уже экспериментировал немного, но не нашел что-либо, чем я удовлетворен до сих пор. –  Gilles 'SO- stop being evil' 06.04.2011, 02:11
  • 2
    На мобильности: к счастью у меня есть функции везде. Я не уверен в $!, Я думаю некоторые из тех машин, которые я использую, редко не имеют управления заданиями, $! универсально доступный? –  Gilles 'SO- stop being evil' 06.04.2011, 02:13
  • 3
    @Gilles: Гм, yeh. Я вспоминаю некоторых действительно отвратительных и bash- определенный материал я сделал однажды вовлечение злоупотребления -o monitor. Я думал с точки зрения действительно древних оболочек, когда я записал, что (это работало в v7). Тем не менее я думаю, что можно сделать любую из двух других вещей: (1) фон "вообще" и wait $!, или (2) также отправляют SIGCLD/SIGCHLD... но на достаточно взрослых машинах последний или не существует или является непортативным (первый - Система III/V, последний BSD, и V7 не имел ни одного). –  geekosaur 06.04.2011, 02:17
  • 4
    @Gilles: $! возвращается к V7, по крайней мере, и конечно предшествует a sh- как этот знал что-либо об управлении заданиями (на самом деле, в течение долгого времени /bin/sh на BSD не сделал управления заданиями; необходимо было работать csh получить его — но $! был ли). –  geekosaur 06.04.2011, 02:18
  • 5
    я не могу фон "вообще", мне нужен его вывод. Спасибо за информацию о $!. –  Gilles 'SO- stop being evil' 06.04.2011, 02:21

Хотя coretuils с версии 7.0 включает команду тайм-аута, Вы упомянули некоторые среды, которые не будут иметь его. К счастью, pixelbeat.org записали сценарий тайм-аута sh.

Я использовал его прежде несколько раз, и это работает очень хорошо.

http://www.pixelbeat.org/scripts/timeout (Примечание: сценарий ниже был немного изменен от того на pixelbeat.org, см. комментарии ниже этого ответа.)

#!/bin/sh

# Execute a command with a timeout

# Author:
#    http://www.pixelbeat.org/
# Notes:
#    Note there is a timeout command packaged with coreutils since v7.0
#    If the timeout occurs the exit status is 124.
#    There is an asynchronous (and buggy) equivalent of this
#    script packaged with bash (under /usr/share/doc/ in my distro),
#    which I only noticed after writing this.
#    I noticed later again that there is a C equivalent of this packaged
#    with satan by Wietse Venema, and copied to forensics by Dan Farmer.
# Changes:
#    V1.0, Nov  3 2006, Initial release
#    V1.1, Nov 20 2007, Brad Greenlee <brad@footle.org>
#                       Make more portable by using the 'CHLD'
#                       signal spec rather than 17.
#    V1.3, Oct 29 2009, Ján Sáreník <jasan@x31.com>
#                       Even though this runs under dash,ksh etc.
#                       it doesn't actually timeout. So enforce bash for now.
#                       Also change exit on timeout from 128 to 124
#                       to match coreutils.
#    V2.0, Oct 30 2009, Ján Sáreník <jasan@x31.com>
#                       Rewritten to cover compatibility with other
#                       Bourne shell implementations (pdksh, dash)

if [ "$#" -lt "2" ]; then
    echo "Usage:   `basename $0` timeout_in_seconds command" >&2
    echo "Example: `basename $0` 2 sleep 3 || echo timeout" >&2
    exit 1
fi

cleanup()
{
    trap - ALRM               #reset handler to default
    kill -ALRM $a 2>/dev/null #stop timer subshell if running
    kill $! 2>/dev/null &&    #kill last job
      exit 124                #exit with 124 if it was running
}

watchit()
{
    trap "cleanup" ALRM
    sleep $1& wait
    kill -ALRM $$
}

watchit $1& a=$!         #start the timeout
shift                    #first param was timeout for sleep
trap "cleanup" ALRM INT  #cleanup after timeout
"$@" < /dev/tty & wait $!; RET=$?    #start the job wait for it and save its return value
kill -ALRM $a            #send ALRM signal to watchit
wait $a                  #wait for watchit to finish cleanup
exit $RET                #return the value
4
27.01.2020, 19:33
  • 1
    Кажется, что это не позволяет получать вывод команды. См., что "Я не могу фон “безотносительно “" комментария Gilles в другом ответе. –  Stéphane Gimenez 14.08.2011, 21:27
  • 2
    , интересный. Я изменил сценарий (таким образом, он не будет соответствовать тому на pixelbeat больше) перенаправить/dev/stdin в команду. Это, кажется, работает в моем тестировании. –  bahamat 14.08.2011, 23:33
  • 3
    Это не работает, чтобы считать команду из входа стандарта, кроме (странно) в ударе. </dev/stdin нет. </dev/tty позволил бы этому читать из терминала, который достаточно хорош для моего варианта использования. –  Gilles 'SO- stop being evil' 15.08.2011, 21:10
  • 4
    @Giles: прохладный, я сделаю то обновление. –  bahamat 15.08.2011, 21:42
  • 5
    Это не может работать без значительно большего усилия: Я должен получить вывод команды, и я не могу сделать этого, если команда в фоновом режиме. –  Gilles 'SO- stop being evil' 16.08.2011, 17:12

Что относительно (ab) используют NC для этого

Как;

   $ nc -l 0 2345 | cat &  # output come from here
   $ nc -w 5 0 2345   # input come from here and times out after 5 sec

Или свернутый в единственную командную строку;

   $ foo=`nc -l 0 2222 | nc -w 5 0 2222`

Последняя версия, хотя смотря stange на самом деле работает, когда я тестирую ее в системе Linux - мое лучшее предположение - то, что она должна работать над любой системой, и если не изменение перенаправления вывода может решить для мобильности. преимущество здесь - то, что никакие фоновые процессы не включены.

3
27.01.2020, 19:33
  • 1
    Не достаточно портативный. Я не имею nc на некотором старом Unix boxen, ни на многих встроил Linux. –  Gilles 'SO- stop being evil' 18.02.2014, 19:51
Другой способ запустить конвейер в собственной группе процессов - это запустить [11784]sh -c '....'[11785] в псевдотерминале с помощью команды [11786] script[11787] (которая неявно применяет функцию [11788]setsid[11789]).[12131]
0
27.01.2020, 19:33

Ответ в https://unix.stackexchange.com/a/18711 очень хороший.

Я хотел добиться аналогичного результата, но без необходимости снова явно вызывать оболочку, потому что я хотел вызывать существующие функции оболочки.

Используя bash, можно сделать следующее:

eval 'set -m ; ( ... ) ; '"$(set +o)"

Предположим, у меня уже есть функция оболочки f :

f() { date ; kill 0 ; }

echo Before
eval 'set -m ; ( f ) ; '"$(set +o)"
echo After

Выполняя это, я вижу:

$ sh /tmp/foo.sh
Before
Mon 14 Mar 2016 17:22:41 PDT
/tmp/foo.sh: line 4: 17763 Terminated: 15          ( f )
After
0
27.01.2020, 19:33
timeout_handler () { echo Timeout. goodbye.;  exit 1; }
trap timeout_handler ALRM
( sleep 60; kill -ALRM $$ ) &
-2
27.01.2020, 19:33

Теги

Похожие вопросы