2019-01-11 17:02:45 huangbaokang 阅读数 190

trap命令可以对信号进行捕获,命令格式如下:

trap command singal

第二个参数是信号名称,第一个参数是遇到信号singal执行的命令。

删除信号捕获,命令格式

trap -- singal
[root@localhost shell]# cat test.sh 
#!/bin/bash
trap "echo 'Sorry,Ctrl-C is trapped.'" SIGINT
count=1
while [ $count -le 5 ]
do
	echo "Loop #$count"
	sleep 1
	count=$[ $count + 1 ]
done

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

运行情况如下:

[root@localhost shell]# ./test.sh 
Loop #1
Loop #2
Loop #3
Loop #4
^CSorry,Ctrl-C is trapped.
Loop #5
I just removed the trap
Second Loop #1
Second Loop #2
^C

在第一个循环中按ctrl+C会执行捕获的命令,由于信号是在捕获被移除前接收到的,那么脚本会按照原先trap命令中的设置进行处理。

2016-09-18 20:36:19 hs794502825 阅读数 2314

linux c捕获信号

在程序中为了实现优雅退出,需要对信号进行处理,本文主要记录一下两个方面:
* 如何捕获SIGINT、SIGTERM、SIGQUIT等信号,并进行处理
* 如何知道是哪个进程给自己发送的信号

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

static int int_count = 0;
static int max_int = 5;
static int max_term = 10;

static struct sigaction siga;

static void multi_handler(int sig, siginfo_t *siginfo, void *context) {
    // get pid of sender,
    pid_t sender_pid = siginfo->si_pid;

    if(sig == SIGINT) {
        printf("INT(%d), from [%d]\n", int_count++, (int)sender_pid);
    } else if(sig == SIGQUIT) {
        printf("Quit, bye, from [%d]\n", (int)sender_pid);
        exit(0);
    } else if(sig == SIGTERM) {
        printf("TERM(%d), from [%d]\n", int_count++, (int)sender_pid);
    }

    return;
}

int raise_test() {
    // print pid
    printf("process [%d] started.\n", (int)getpid());

    // prepare sigaction
    siga.sa_sigaction = *multi_handler;
    siga.sa_flags |= SA_SIGINFO; // get detail info

    // change signal action,
    if (sigaction(SIGINT, &siga, NULL) != 0) {
        printf("error sigaction()");
        return errno;
    }
    if (sigaction(SIGQUIT, &siga, NULL) != 0) {
        printf("error sigaction()");
        return errno;
    }
    if (sigaction(SIGTERM, &siga, NULL) != 0) {
        printf("error sigaction()");
        return errno;
    }

    // use "ctrl + c" to send SIGINT, and "ctrl + \" to send SIGQUIT,
    int sig;
    while (1) {
        if (int_count < max_int) {
        sig = SIGINT;
    } else if (int_count >= max_int && int_count < max_term) {
        sig = SIGTERM;
    } else {
        sig = SIGQUIT;
    }
    raise(sig); // send signal to itself
    sleep(1); // sleep a while, note that: SIGINT will interrupt this, and make program wake up,
    }

    return 0;
}

int main(int argc, char *argv[]) {
    raise_test();
    return 0;
}

运行结果如下

[root@hz01-noah-yanzhijie1.hz01.baidu.com check]# ./noah-agent 
process [64619] started.
INT(0), from [64619]
INT(1), from [64619]
INT(2), from [64619]
INT(3), from [64619]
INT(4), from [64619]
TERM(5), from [64619]
TERM(6), from [64619]
TERM(7), from [64619]
TERM(8), from [64619]
TERM(9), from [64619]
Quit, bye, from [64619]
2017-03-07 19:39:39 derkampf 阅读数 339

一.linux信号对应的值

    #define SIGHUP 1
    #define SIGINT 2
    #define SIGQUIT 3
    #define SIGILL 4
    #define SIGTRAP 5
    #define SIGABRT 6
    #define SIGIOT 6
    #define SIGBUS 7
    #define SIGFPE 8
    #define SIGKILL 9
    #define SIGUSR1 10
    #define SIGSEGV 11
    #define SIGUSR2 12
    #define SIGPIPE 13
    #define SIGALRM 14
    #define SIGTERM 15
    #define SIGSTKFLT 16
    #define SIGCHLD 17
    #define SIGCONT 18
    #define SIGSTOP 19
    #define SIGTSTP 20
    #define SIGTTIN 21
    #define SIGTTOU 22
    #define SIGURG 23
    #define SIGXCPU 24
    #define SIGXFSZ 25
    #define SIGVTALRM 26
    #define SIGPROF 27
    #define SIGWINCH 28
    #define SIGIO 29
    #define SIGPOLL SIGIO

    #define SIGPWR 30
    #define SIGSYS 31
    #define SIGUNUSED 31
    #define SIGRTMIN 32
    #define SIGRTMAX _NSIG

linux下通过kill -l查看

SIGHUP    终止进程    终端线路挂断
SIGINT    终止进程    中断进程
SIGQUIT   建立CORE文件终止进程,并且生成core文件
SIGILL   建立CORE文件      非法指令  
SIGTRAP  建立CORE文件      跟踪自陷
SIGBUS   建立CORE文件      总线错误
SIGSEGV  建立CORE文件      段非法错误
SIGFPE   建立CORE文件      浮点异常
SIGIOT   建立CORE文件      执行I/O自陷
SIGKILL  终止进程    杀死进程
SIGPIPE  终止进程    向一个没有读进程的管道写数据
SIGALARM  终止进程    计时器到时
SIGTERM  终止进程    软件终止信号
SIGSTOP  停止进程    非终端来的停止信号
SIGTSTP  停止进程    终端来的停止信号
SIGCONT  忽略信号    继续执行一个停止的进程
SIGURG   忽略信号    I/O紧急信号
SIGIO    忽略信号    描述符上可以进行I/O
SIGCHLD  忽略信号    当子进程停止或退出时通知父进程
SIGTTOU  停止进程    后台进程写终端
SIGTTIN  停止进程    后台进程读终端
SIGXGPU  终止进程    CPU时限超时
SIGXFSZ  终止进程    文件长度过长
SIGWINCH  忽略信号    窗口大小发生变化
SIGPROF  终止进程    统计分布图用计时器到时
SIGUSR1  终止进程    用户定义信号1
SIGUSR2  终止进程    用户定义信号2
SIGVTALRM 终止进程    虚拟计时器到时
linux下:
ctrl-c 发送 SIGINT 信号给前台进程组中的所有进程。常用于终止正在运行的程序。
ctrl-z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程。
ctrl-d 不是发送信号,而是表示一个特殊的二进制值,表示 EOF。
ctrl-\ 发送 SIGQUIT 信号给前台进程组中的所有进程,终止前台进程并生成 core 文件。
Key Function
Ctrl-c Kill foreground process
Ctrl-z Suspend foreground process
Ctrl-d Terminate input, or exit shell
Ctrl-s Suspend output
Ctrl-q Resume output
Ctrl-o Discard output
Ctrl-l Clear screen

二.以ctrl+c为例,捕捉它的信号量并处理

#include<signal.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

void handler(int signu)
{
    printf("signumber is %d\n", signu);
    exit(1);
}
int main()
{
    signal(SIGINT, handler);
    while(1)
        sleep(1);
}

测试结果
这里写图片描述

2011-04-06 22:25:00 moruite 阅读数 2649

Linux程序经常需要捕获一些中断信号,如按下CTRL+C就会触发SIGTERM信号等,

2019-11-28 21:56:03 chen1415886044 阅读数 216

前言

Linux利用信号与运行在系统中的进程进行通信。当你在终端中按下(Ctrl +C)Linux内核会停止为shell分配CPU处理时间。会生成SIGINT信号中断进程。而下面要将的是trap命令在信号出现时捕获他们并执行命令。

捕获信号

trap命令允许你来指定shell脚本要监看并从shell中拦截的Linux信号。如果在脚本收到了trap命令中列出的信号,该信号不再由shell处理,而是交给本地处理。

trap命令格式:

trap commands signals

现在通过一个例子,展示了如何用trap命令来忽略SIGINT信号,并控制脚本的行为:

#!/bin/bash

#测试信号捕获

trap "echo ' Sorry! I have trapped Ctrl-C'" SIGINT

echo "This is a test script"

count=1
while [ $count -le 10 ]
do 
   echo "Loop #$count"
   sleep 1
   count=$[ $count + 1 ]
done

echo "This is the end of the test script"

输出结果:
在这里插入图片描述上面的例子中用到了trap命令会在每次检测到SIGINT信号时显示一行简单的文本信息。捕获这些信号会阻止用户用bash shell组合键Ctrl + C来停止程序。每次按下Ctrl + c组合键,脚本都会执行trap命令中指定的echo语句,而不是处理该信号并允许shell停止该脚本。

捕获脚本退出

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

#!/bin/bash

#捕获脚本退出信号

trap "echo \"Goodbye"\" EXIT

count=1
while [ $count -le 5 ]
do
    echo "Loop #$count"
    sleep 1
    count=$[ $count +1 ]

done

输出结果:
在这里插入图片描述

当脚本运行时,正常退出位置时,会捕获就被触发了,shell会执行在trap命令行指定的命令。如果提前退出脚本,同样能够捕获到EXIT

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

trap -- SIGINT   #终止脚本运行

可以在删除已设置好的捕获。只需要在trap命令与希望默认行为的信号列表之间加上两个破折号就行了。例如:

#!/bin/bash

#Modifying 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

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

输出结果:
在这里插入图片描述
在移除信号捕获后,脚本按照默认的行为来处理SIGINT信号,也就是终止脚本的运行。但如果信号是在捕获移除前接收到的,那么脚本会按照原先的trap命令中设置进行处理。

在这里插入图片描述因为信号在捕获被移除前已经接收到了,脚本会按照旧的执行trap中指定的命令。捕获随后被移除,再按下Ctrl +c 就能够提前终止脚本。

总结

Linux 系统运行利用信号来控制shell脚本。当bash shell接受信号,并将它们传递给运行在改=该shell进程中的所有进程。可以在脚本中用trap语句来捕获信号并执行特定命令。

参考:Linux命令行与shell脚本编程大全

Linux信号的捕获

阅读数 101

《Linux信号》

阅读数 152

没有更多推荐了,返回首页