1. 程式人生 > >2018-9-17-bash之信號捕捉

2018-9-17-bash之信號捕捉

gts 行處理 例如 好的 處理 -bash sigalrm 最後一個元素 trap命令

一、概述

我們在上一章當中示例了檢測ip地址是否在線的腳本,但是有一個問題,運行的過程中,無論使用Ctrl+c怎麽制止,並沒有什麽卵用,還是繼續運行,直到將最後一個IP地址ping完,無法制止,只是將當前的ping操作結束,下一個ping操作就要運行,但是如果連續的按下快捷鍵,總有一個信號捕捉到,但只有被當前進程的腳本捕捉到才能夠停止,而不是ping進程,這就是信號。

我們也可以手動定制信號捕捉的功能,那麽如何自定義信號捕捉的處理,那麽在ping操作時,由於信號捕捉不到,那麽能不能在捕捉信號之後做出相應的處理操作,對於bash而言這是可以的,在系統當中有一個trap命令,通過部署一個陷阱捕捉到信號,或者激發其某個事件進行捕捉處理。

我們可使用-l選項來列出可捕捉的所有信號。

# trap -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX    

不過,使用kill -l也是獲得相同的結果,不過要想了解其信號意義,我們可通過man手冊來進行查看。

信號捕捉:
    列出信號:
        trap -l
        kill -l
        man 7 signal

信號是進程間通信間的一種機制,而trap命令可以讓bash腳本自定義如何捕捉信號,但需要註意的是,不能捕捉TERMKILL的信號,因為捕捉信號的意義在於一旦捕捉到之後能夠作出什麽操作,因此一般捕捉到信號為HUP以及INT等,當然其它的信號也可以捕捉,但是沒有以上這兩個用的那麽頻繁。

    常用的信號:
        HUP, INT

示例:

#!/bin/bash

trap  ‘echo "Dou ni wan"‘ INT

for i in {1..254}; do
    if ping -W1 -c1 192.168.$i.1 &> /dev/null; then
        echo "192.168.$i.1 is up."
    else
        echo "192.168.$i.1 is down."
    fi
done
# bash trap.sh 
192.168.1.1 is down.
192.168.2.1 is down.
^CDou ni wan
192.168.3.1 is down.
^CDou ni wan
192.168.4.1 is down.
^CDou ni wan
192.168.5.1 is down.
^CDou ni wan
192.168.6.1 is down.

從以上的運行結果看出,一旦發出Ctrl+c就是INT信號後,會顯示出Dou ni wan,但是其實並沒有停止其ping進程,只是停止了當前的ping,而下一個循環的ping開始運行,如果徹底退出的當前bash進程的話,要用另一種方式。

#!/bin/bash

trap  ‘echo "quit"; exit 1‘ INT

for i in {1..254}; do
    if ping -W1 -c1 192.168.$i.1 &> /dev/null; then
        echo "192.168.$i.1 is up."
    else
        echo "192.168.$i.1 is down."
    fi
done

那麽這就是trap命令的意義,能夠其捕捉信號,且捕捉到信號後,使用所定義好的命令來進行處理如何進行,那麽以上的信號處理就是顯示quit並退出shell進程。

那麽trap命令的方法很簡單,後面跟上其參數,並跟上信號聲明,而一旦捕捉到其信號之後,我們作出什麽樣的處理操作,而它的命令用法為:

trap ‘COMMAND‘ SIGNALS

我們可以使用以函數中所定義好的命令的形式來對trap進行定義而後對其進行捕捉。

#!/bin/bash
#

trap ‘mytrap‘ INT
mytrap() {
    echo "Quit"
    exit 1
}

for i in {1..254}; do
    if ping -W1 -c1 192.168.$i.1 &> /dev/null; then
        echo "192.168.$i.1 is up"
    else
        echo "192.168.$i.1 is down"
    fi
done

而在每次ping操作完成之後,可創建其臨時文件保存其相關的信息。放在循環內部,每一次創建完成可保證將其可以刪除,也需要保證三叉輸出。

但是這樣的話會創建無數個臨時文件,我們需要創建其數組用來其追加到最後一個元素中,遇到終止信號時將其文件進行刪除。

#!/bin/bash
#

declare -a hosttmpfiles
trap ‘mytrap‘ INT
mytrap() {
    echo "Quit"
    rm -f ${hosttmpfiles[@]}
    exit 1
}

for i in {1..254}; do
    tmpfile=$(mktemp /tmp/ping.XXXXXX)
    if ping -W1 -c1 192.168.$i.1 &> /dev/null; then
        echo "192.168.$i.1 is up" | tee $tmpfiles
    else
        echo "192.168.$i.1 is down" | tee $tmpfiles
    fi
    hosttmpfiles[${#hosttmpfiles[*]}]=$tmpfile
done

echo ${hosttmpfiles[@]}

在信號捕捉中的函數內部可以寫出一些復雜的處理邏輯,包括退出及刪除未處理的文件等。

二、在bash中使用ASCII顏色

echo命令中如何進行著色是一件很簡單的事情,關於相關的教程網上也是一抓一大把,那麽其著色定義格式為:

\033[31m hello \033[0m

以上這種格式表示隨後控制的字體顯示為什麽顏色,以及在那裏進行關閉,如果沒有關閉的話隨後都是以這個顏色進行顯示,除非到下一個命令有自己的輸出流時才能結束,為了避免這種影響,所以要在後面需加上\033[0m,表示不要影響其後面的著色,就在這個範圍內進行著色。

而那兩個數字也有個不同的意義。

    ##m:
        左側#:
            3: 前景色;
            4: 背景色;
        右側#: 顏色種類
            1, 2, 3, 4, 5, 6, 7

如果使用的是單個數字的話,會改變文本的格式,例如加粗或閃爍等。

    #m:
        加粗、閃爍等功能;

多種控制符,可組合使用,彼此間用分號隔開;
echo -e "\033[42;35;5,hello world\033[0m"

2018-9-17-bash之信號捕捉