LoginSignup
3
1

More than 5 years have passed since last update.

自作timeoutスクリプト

Posted at

TL;DR

あるコマンドを一定時間で強制終了させたいときには、timeoutコマンドを使っていました。
ところが、なんとインストールされていない環境で作業することがあったので、
簡易タイムアウトスクリプトを自作しました。

参考:timeoutコマンド

ryotakata@ryotakata-ubuntu03:~/timeout$ timeout --help
使用法: timeout [OPTION] DURATION COMMAND [ARG]...
または: timeout [OPTION]
Start COMMAND, and kill it if still running after DURATION.

Mandatory arguments to long options are mandatory for short options too.
      --preserve-status
                 exit with the same status as COMMAND, even when the
                 command times out
      --foreground
                 When not running timeout directly from a shell prompt,
                 allow COMMAND to read from the TTY and receive TTY signals.
                 In this mode, children of COMMAND will not be timed out.
  -k, --kill-after=DURATION
                 also send a KILL signal if COMMAND is still running
                 this long after the initial signal was sent.
  -s, --signal=SIGNAL
                 specify the signal to be sent on timeout.
                 SIGNAL may be a name like 'HUP' or a number.
                 See 'kill -l' for a list of signals
      --help     この使い方を表示して終了する
      --version  バージョン情報を表示して終了する

自作したtimeoutスクリプト

#!/bin/bash

function main () {
    SCRIPT_PATH=$(cd $(dirname $0) && pwd)
    SCRIPT_NAME=$(basename $0)

    ###  5 sec 経過でタイムアウトする
    ### [1] timeout コマンドを使う##############################################
    # timeout 5 ./hoge.sh
    ### [2] 下記Step1/2を1 sec毎に実行する######################################
    # Step1: kill -0 ${TGT_PID} or ${TIM_PID}でprocessの死活(終了/実行中)を取得
    # Step2: ${TIM_PID}, ${TIM_PID}の終了をOR条件で判定、killする
    # ※  ${TGT_PID}: タイムアウト監視対象のPID
    # ※  ${TIM_PID}: タイマーのPID
    ./hoge.sh &
    TGT_PID=$!
    sleep 5 &
    TIM_PID=$!

    err_msg=$(
    echo "${SCRIPT_PATH}/${SCRIPT_NAME}: "
    echo "Process ${TGT_PID} will be killed by ${SCRIPT_NAME}."
    )

    while true; do
        kill -0 ${TGT_PID}
        if [ ! $? -eq 0 ]; then
            killtree ${TIM_PID} KILL
            exit
        fi
        kill -0 ${TIM_PID}
        if [ ! $? -eq 0 ]; then
            killtree ${TGT_PID} KILL
            echo ${err_msg}
            exit 1
        fi
        sleep 1
    done
    wait
    ###########################################################################
    exit
}


### kill all members of a process group
function killtree() {
    if [ $# -eq 0 -o $# -gt 2 ]; then
        echo "Usage: $(basename $0) <pid> [signal]"
        exit 1
    fi
    local _pid=$1
    local _sig=${2:-TERM}
    kill -stop ${_pid} # needed to stop quickly forking parent from producing child between child killing and parent killing
    for _child in $(ps -o pid --no-headers --ppid ${_pid}); do
        killtree ${_child} ${_sig}
    done
    kill -${_sig} ${_pid}
}

main

参考にした記事

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1