• Shell编程—控制脚本


    1处理信号

    1.1信号表

    编号

    信号名称

    缺省操作

    解释

    1

    SIGHUP

    Terminate

    挂起控制终端或进程

    2

    SIGINT

    Terminate

    来自键盘的中断

    3

    SIGQUIT

    Dump

    从键盘退出

    4

    SIGILL

    Dump

    非法指令

    5

    SIGTRAP

    Dump

    跟踪的断点

    6

    SIGABRT

    Dump

    异常结束

    6

    SIGIOT

    Dump

    等价于SIGABRT

    7

    SIGBUS

    Dump

    总线错误

    8

    SIGFPE

    Dump

    浮点异常

    9

    SIGKILL

    Terminate

    强迫进程终止

    10

    SIGUSR1

    Terminate

    对进程可用

    11

    SIGSEGV

    Dump

    无效的内存引用

    12

    SIGUSR2

    Terminate

    对进程可用

    13

    SIGPIPE

    Terminate

    向无读者的管道写

    14

    SIGALRM

    Terminate

    实时定时器时钟

    15

    SIGTERM

    Terminate

    进程终止

    16

    SIGSTKFLT

    Terminate

    协处理器栈错误

    17

    SIGCHLD

    Ignore

    子进程停止、结束或在被跟踪时获得信号

    18

    SIGCONT

    Continue

    如果已停止则恢复执行

    19

    SIGSTOP

    Stop

    停止进程执行

    20

    SIGTSTP

    Stop

    从tty发出停止进程

    21

    SIGTTIN

    Stop

    后台进程请求输入

    22

    SIGTTOU

    Stop

    后台进程请求输出

    23

    SIGURG

    Ignore

    套接字上的紧急条件

    24

    SIGXCPU

    Dump

    超过CPU时限

    25

    SIGXFSZ

    Dump

    超过文件大小的限制

    26

    SIGVTALRM

    Terminate

    虚拟定时器时钟

    27

    SIGPROF

    Terminate

    概况定时器时钟

    28

    SIGWINCH

    Ignore

    窗口调整大小

    29

    SIGIO

    Terminate

    I/O现在可能发生

    29

    SIGPOLL

    Terminate

    等价于SIGIO

    30

    SIGPWR

    Terminate

    电源供给失败

    31

    SIGSYS

    Dump

    坏的系统调用

    31

    SIGUNUSED

    Dump

    等价于SIGSYS

    1.2捕获信号

    rap命令允许你来指定shell 脚本要监看并从shell中拦截的Linux信号。trap命令的格式是:

    trap commands signals

    其中commands你是要执行的操作,sianals是信号(可以是信号名,也可以是信号编号)

    这里有个简单例子,展示了如何使用trap命令来忽略SIGINT信号,并控制脚本的行为。

    $ cat test1.sh
    #!/bin/bash
    # Testing signal trapping
    # trap "echo ' Sorry! I have trapped Ctrl-C'" 2
    # echo This is a test script
    # count=1 
    while [ $count -le 5 ] 
    do
        echo "Loop #$count"    
        sleep 1    
        count=$[ $count + 1 ] 
    done 
    echo "This is the end of the test script"

    本例中用到的trap命令会在每次检测到SIGINT(2)信号时显示一行简单的文本消息。捕获这些信号会阻止用户用bash shell组合键Ctrl+C来停止程序。

    $ ./test1.sh
    This is a test script
    Loop #1
    Loop #2
    ^C Sorry! I have trapped Ctrl-C
    Loop #3
    ^C Sorry! I have trapped Ctrl-C
    Loop #4
    Loop #5
    This is the end of the test script $

    每次使用Ctrl+C组合键,脚本都会执行trap命令中指定的echo语句,而不是处理该信号并允许shell停止该脚本。

    1.3 捕获脚本退出

    除了在shell脚本中捕获信号,你也可以在shell脚本退出时进行捕获。要捕获shell脚本的退出,只要在trap命令后加上EXIT信号就行:

    $ cat test2.sh
    #!/bin/bash
    # Trapping the script exit
    trap "echo Goodbye..." EXIT
    count=1 
    while [ $count -le 5 ] 
    do
       echo "Loop #$count" 
       sleep 1    
       count=$[ $count + 1 ] 
       done
    
    $ ./test2.sh
    Loop #1
    Loop #2
    Loop #3
    Goodbye...

    当脚本运行到正常的退出位置时或者是提退出,捕获就被触发了,shell会执行在trap命令行指定的命令。

    1.4修改或移除捕获

    要想在脚本中的不同位置进行不同的捕获处理,只需重新使用带有新选项的trap命令:

    $ cat test3.sh
    #!/bin/bash
    # Modifying a set trap
    trap "echo ' Sorry... Ctrl-C is trapped.'" 2
    count=1 
    while [ $count -le 5 ] 
    do
        echo "Loop #$count"    
        sleep 1    
        count=$[ $count + 1 ] 
    done  
    trap "echo ' I modified the trap!'" 2
    count=1 
    while [ $count -le 5 ] 
    do
        echo "Second Loop #$count"    
        sleep 1    
        count=$[ $count + 1 ] 
    done 

    修改了信号捕获之后,脚本处理信号的方式就会发生变化。但如果一个信号是在捕获被修改前接收到的,那么脚本仍然会根据最初的trap命令进行处理。

    $ ./test3.sh
    Loop #1
    Loop #2
    Loop #3
    ^C Sorry... Ctrl-C is trapped.
    Loop #4
    Loop #5
    Second Loop #1
    Second Loop #2
    ^C I modified the trap!
    Second Loop #3
    Second Loop #4
    Second Loop #5

    也可以删除已设置好的捕获。只需要在trap命令与希望恢复默认行为的信号列表之间加上破折号(-或者--)就行了:

    $ cat test3b.sh 
    #!/bin/bash 
    # Removing a set trap 
    trap "echo ' Sorry... Ctrl-C is trapped.'" SIGINT 
    count=1 
    while [ $count -le 5 ] 
    do
        echo "Loop #$count"    
        sleep 1    
        count=$[ $count + 1 ] 
    done 
    
    # Remove the trap 
    trap -- SIGINT 
    echo "I just removed the trap" 
    count=1 
    while [ $count -le 5 ] 
    do
        echo "Second Loop #$count"    
        sleep 1    
        count=$[ $count + 1 ] 
    done 
    
    $ ./test3b.sh 
    Loop #1 
    Loop #2 
    Loop #3 
    Loop #4 
    Loop #5 
    I just removed the trap 
    Second Loop #1 
    Second Loop #2 
    Second Loop #3 
    ^C 

     

    2以后台模式运行脚本

    2.1后台运行脚本

    以后台模式运行shell脚本非常简单。只要在命令后加个&符就行了。$ cat test4.sh

    #!/bin/bash
    # Test running in the background
    count=1
    while [ $count -le 10 ] 
    do
       sleep 1
       count=$[ $count + 1 ] 
    done
    
    $ ./test4.sh &
    [1] 3231

    显示的第一行是:

    [1] 3231

    方括号中的数字是shell分配给后台进程的作业号。下一个数是Linux系统分配给进程的进程ID(PID)。Linux系统上运行的每个进程都必须有一个唯一的PID。

    一旦系统显示了这些内容,新的命令行界面提示符就出现了。你可以回到shell,而你所执行的命令正在以后台模式安全的运行。这时,你可以在提示符输入新的命令

    当后台进程结束时,它会在终端上显示出一条消息:

    [1]   Done                    ./test4.sh

    这表明了作业的作业号以及作业状态(Done),还有用于启动作业的命令。

    注意,当后台进程运行时,它仍然会使用终端显示器来显示STDOUT和STDERR消息。所以最好将消息重定向,不然会导致屏幕信息混乱。

    2.2运行多个后台作业

    可以在命令行提示符下同时启动多个后台作业。

    $ ./test6.sh &
    [1]  3568
    $ This is Test Script #1
     
    $ ./test7.sh &
    [2]  3570
    $ This is Test Script #2
     
    $ ./test8.sh &
    [3]  3573
    $ And...another Test script
     
    $ ./test9.sh &
    [4]  3576
    $ Then...there was one more test script

    每次启动新作业时,Linux系统都会为其分配一个新的作业号和PID。通过ps命令,可以看到所有脚本处于运行状态。

    $ ps
      PID TTY          TIME CMD
     2431 pts/0    00:00:00 bash
     3568 pts/0    00:00:00 test6.sh
     3570 pts/0    00:00:00 test7.sh
    3573  pts/0    00:00:00 test8.sh
    3574  pts/0    00:00:00 sleep
    3575  pts/0    00:00:00 sleep
    3576  pts/0    00:00:00 test9.sh
    3577  pts/0    00:00:00 sleep
    3578  pts/0    00:00:00 sleep
    3579  pts/0    00:00:00 ps

    注意,在ps命令的输出中,每一个后台进程都和终端会话(pts/0)终端联系在一起。如果终端会话退出,那么后台进程也会随之退出。

     

    3       在非控制台下运行脚本

    nohup命令运行了另外一个命令来阻断所有发送给该进程的SIGHUP信号。这会在退出终端会话时阻止进程退出。

    nohup命令的格式如下:

    $ nohup ./test1.sh & 
    [1] 3856
    $ nohup: ignoring input and appending output to 'nohup.out'

    和普通后台进程一样,shell会给命令分配一个作业号,Linux系统会为其分配一个PID号。区别在于,当你使用nohup命令时,如果关闭该会话,脚本会忽略终端会话发过来的SIGHUP信号。 6由于nohup命令会解除终端与进程的关联,进程也就不再同STDOUT和STDERR联系在一起。为了保存该命令产生的输出,nohup命令会自动将STDOUT和STDERR的消息重定向到一个名为nohup.out的文件中。

    在进程完成运行后,你可以查看nohup.out文件中的输出结果:

    $ cat nohup.out
    This is a test script
    Loop 1
    Loop 2 
    Loop 3 
    Loop 4 
    Loop 5 
    Loop 6
    Loop 7
    Loop 8
    Loop 9
    Loop 10
    This is the end of the test script
  • 相关阅读:
    iphone 图标下载
    iphone 下拉刷新(转)
    技术书评(.NET为主)
    我也设计模式——3.Singleton
    我也设计模式——14.Flyweight
    Web2.0技术研究笔记——1.分类与资源
    我也设计模式——4.Builder
    C#之CLR读书笔记 0
    IMemento 永远置顶
    我也设计模式——21.Memento
  • 原文地址:https://www.cnblogs.com/ericz2j/p/12045643.html
Copyright © 2020-2023  润新知