【Linux入门教程】4 用户管理、系统性能分析、系统日志及日志分析、信号机制与信号处理

2023-11-13

Linux用户管理

在Linux中,有三种用户:

  • Root 用户:也称为超级用户,对系统拥有完全的控制权限。超级用户可以不受限制的运行任何命令。Root 用户可以看做是系统管理员。
  • 系统用户:系统用户是Linux运行某些程序所必须的用户,例如 mail 用户、sshd 用户等。系统用户通常为系统功能所必须的,不建议修改这些用户。
  • 普通用户:一般用户都是普通用户,这些用户对系统文件的访问受限,不能执行全部Linux命令。


Linux支持用户组,用户组就是具有相同特征的用户的集合。一个组可以包含多个用户,每个用户也可以属于不同的组。用户组在Linux中扮演着重要的角色,方便管理员对用户进行集中管理。

与用户和组有关的系统文件

与用户和组有关的系统文件:

系统文件 说明
/etc/passwd 保存用户名和密码等信息,Linux系统中的每个用户都在/etc/passwd文件中有一个对应的记录行。这个文件对所有用户都是可读的。
/etc/shadow /etc/shadow中的记录行和/etc/passwd中的相对应,他由pwconv命令根据/etc/passwd中的数据自动产生,它的格式和/etc/passwd类似,只是对密码进行了加密。并不是所有的系统都支持这个文件。
/etc/group 以记录行的形式保存了用户组的所有信息。


来看一下/etc/passwd文件的结构:

$cat /etc/passwd
root:x:0:0:Superuser:/:
daemon:x:1:1:System daemons:/etc:
bin:x:2:2:Owner of system commands:/bin:
sys:x:3:3:Owner of system files:/usr/sys:
adm:x:4:4:System accounting:/usr/adm:
uucp:x:5:5:UUCP administrator:/usr/lib/uucp:
auth:x:7:21:Authentication administrator:/tcb/files/auth:
cron:x:9:16:Cron daemon:/usr/spool/cron:
listen:x:37:4:Network daemon:/usr/net/nls:
lp:x:71:18:printer administrator:/usr/spool/lp:
sam:x:200:50:Sam san:/usr/sam:/bin/sh

可以看到,/etc/passwd文件中一行记录对应着一个用户,每行记录又被冒号分隔为7个字段,其格式和具体含义如下图所示:


对每个字段的说明:

字段 说明
用户名 用户名是惟一的,长度根据不同的linux系统而定,一般是8位。
密码 由于系统中还有一个/etc/shadow文件用于存放加密后的口令,所以在这里这一项是“x”来表示,如果用户没有设置口令,则该项为空。如果passwd字段中的第一个字符是“*”的话,那么,就表示该账号被查封了,系统不允许持有该账号的用户登录。
用户ID 系统内部根据用户ID而不是用户名来识别不同的用户,用户ID有以下几种:
  • 0代表系统管理员,如果你想建立一个系统管理员的话,可以建立一个普通帐户,然后将该账户的用户ID改为0即可。
  • 1~500系统预留的ID。
  • 500以上是普通用户使用。
组ID 其实这个和用户ID差不多,用来管理群组,与/etc/group文件相关。
描述信息 这个字段几乎没有什么用,只是用来解释这个账号的意义。在不同的Linux系统中,这个字段的 格式并没有统一。在许多Linux系统中,这个字段存放的是一段任意的注释性描述文字,用做finger命令的输出。
用户主目录 用户登录系统的起始目录。用户登录系统后将首先进入该目录。root用户默认是/,普通用户是/home/username。
用户Shell 用户登录系统时使用的Shell。

管理用户和组

下面是一些常用的管理用户和组的命令:

命令 说明
useradd 添加用户。
usermod 修改用户信息。
userdel 删除用户。
groupadd 添加用户组。
groupmod 修改用户组信息。
groupdel 删除用户组。

创建用户组

添加用户时,可以将用户添加到现有的用户组,或者创建一个新的用户组。可以在 /etc/groups 文件中看到所有的用户组信息。

默认的用户组通常用来管理系统用户,不建议将普通用户添加到这些用户组。使用groupadd命令创建用户组的语法为:

groupadd [-g gid [-o]] [-r] [-f] groupname

每个选项的含义如下:

选项 说明
-g GID 以数字表示的用户组ID。
-o 可以使用重复的组ID。
-r 建立系统组,用来管理系统用户。
-f 强制创建。
groupname 用户组的名称。


如果不指定选项,系统将使用默认值。例如创建一个 developers 用户组:

$ groupadd developers

修改用户组

groupmod命令可以用来修改用户组,语法为:

$ groupmod -n new_modified_group_name old_group_name

例如,将用户组 developers_2 重命名为 developer:

$ groupmod -n developer developer_2

将developer用户组的ID改为545:

$ groupmod -g 545 developer

删除用户组

通过groupdel命令可以删除用户组。例如,删除developer组:

$ groupdel developer

groupdel 仅仅删除用户组,并不删除与之相关的文件,这些文件仍然可以被所有者访问。

添加用户

添加用户可以使用useradd命令,语法为:

useradd -d homedir -g groupname -m -s shell -u userid accountname

每个选项的含义如下:

选项 描述
-d homedir 指定用户主目录。
-g groupname 指定用户组。
-m 如果主目录不存在,就创建。
-s shell 为用户指定默认Shell。
-u userid 指定用户ID。
accountname 用户名。


如果不指定任何选项,系统将使用默认值。useradd 命令将会修改 /etc/passwd、/etc/shadow、and /etc/group 三个文件,并创建用户主目录。

下面的例子将会添加用户 mcmohd,并设置主目录为 /home/mcmohd,用户组为 developers,默认 Shell 为  Korn Shell:

$ useradd -d /home/mcmohd -g developers -s /bin/ksh mcmohd

注意:添加用户前请确认 developers 用户组存在。

用户被创建后,可以使用 passwd 命令来设置密码,例如:

$ passwd mcmohd20
Changing password for user mcmohd20.
New Linux password:******
Retype new UNIX password:******
passwd: all authentication tokens updated successfully.

注意:如果你是管理员,输入 $ passwd username 可以修改你所管理的用户的密码;否则只能修改你自己的密码(不需要提供username)。

修改用户

usermod 命令可以修改现有用户的信息。usermod 命令的选项和 useradd 相同,不过可以增加 -l 选项来更改用户名。

下面的例子将用户 mcmohd 的用户名修改为 mcmohd20,主目录修改为 /home/mcmohd20:

$ usermod -d /home/mcmohd20 -m -l mcmohd mcmohd20

删除用户

userdel 命令可以用来删除现有用户。userdel 是一个危险的命令,请谨慎使用。

userdel 命令仅有一个选项 -r,用来删除用户主目录和本地邮件。例如,删除用户  mcmohd20:

$ userdel -r mcmohd20

为了便于恢复被误删的用户,可以忽略 -r 选项,保留用户主目录,之后确认无误可以随时删除主目录。



Linux系统性能分析

这篇教程的目的是向大家介绍一些免费的系统性能分析工具(命令),使用这些工具可以监控系统资源使用情况,便于发现性能瓶颈。

系统的整体性能取决于各种资源的平衡,类似木桶理论,某种资源的耗尽会严重阻碍系统的性能。


Linux中需要监控的资源主要有 CPU、主存(内存)、硬盘空间、I/O时间、网络时间、应用程序等。

影响系统性能的主要因素有:

因素 说明
用户态CPU CPU在用户态运行用户程序所花费的时间,包括库调用,但是不包括内核花费的时间。
内核态CPU CPU在内核态运行系统服务所花费的时间。所有的 I/O 操作都需要调用系统服务,程序员可以通过阻塞 I/O 传输来影响这部分的时间。
I/O 时间和网络时间 响应 I/O 请求、处理网络连接所花费的时间。
内存 切换上下文和交换数据(虚拟内存页导入和导出)花费的时间。
应用程序 程序等待运行的时间——CPU正在运行其他程序,等待切换到当前程序。


说明:一般认为用户态CPU和内核态CPU花费的时间小于70%时是良好状态。

下面的命令可以用来监控系统性能并作出相应调整:

命令 说明
nice 启动程序时指定进程优先级。
renice 调整现有进程的优先级。
netstat 显示各种网络相关信息,包括网络连接情况、路由表、接口状态(Interface Statistics)、masquerade 连接、多播成员 (Multicast Memberships)等。实际上,netstat 用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。
time 检测一个命令运行时间以及资源(CPU、内存、I/O等)使用情况。
uptime 查看系统负载情况。
ps 查看系统中进程的资源使用情况(瞬时状态,不是动态监控)。
vmstat 报告虚拟内存使用情况。
gprof 精确分析程序的性能,能给出函数调用时间、调用次数、调用关系等。
top 实时监控系统中各个进程资源的资源使用情况。


常用命令组合:

  • vmstat、sar、mpstat检测是否存在CPU瓶颈;
  • vmstat、free检测是否存在内存瓶颈;
  • iostat检测是否存在磁盘I/O瓶颈;
  • netstat检测是否存在网络I/O瓶颈。


Linux系统日志及日志分析

Linux系统拥有非常灵活和强大的日志功能,可以保存几乎所有的操作记录,并可以从中检索出我们需要的信息。

大部分Linux发行版默认的日志守护进程为 syslog,位于 /etc/syslog 或 /etc/syslogd,默认配置文件为 /etc/syslog.conf,任何希望生成日志的程序都可以向 syslog 发送信息。 

Linux系统内核和许多程序会产生各种错误信息、警告信息和其他的提示信息,这些信息对管理员了解系统的运行状态是非常有用的,所以应该把它们写到日志文件中去。完成这个过程的程序就是syslog。syslog可以根据日志的类别和优先级将日志保存到不同的文件中。例如,为了方便查阅,可以把内核信息与其他信息分开,单独保存到一个独立的日志文件中。默认配置下,日志文件通常都保存在“/var/log”目录下。

日志类型

下面是常见的日志类型,但并不是所有的Linux发行版都包含这些类型:

类型 说明
auth 用户认证时产生的日志,如login命令、su命令。
authpriv 与 auth 类似,但是只能被特定用户查看。
console 针对系统控制台的消息。
cron 系统定期执行计划任务时产生的日志。
daemon 某些守护进程产生的日志。
ftp FTP服务。
kern 系统内核消息。
local0.local7 由自定义程序使用。
lpr 与打印机活动有关。
mail 邮件日志。
mark 产生时间戳。系统每隔一段时间向日志文件中输出当前时间,每行的格式类似于 May 26 11:17:09 rs2 -- MARK --,可以由此推断系统发生故障的大概时间。
news 网络新闻传输协议(nntp)产生的消息。
ntp 网络时间协议(ntp)产生的消息。
user 用户进程。
uucp UUCP子系统。

日志优先级

常见的日志优先级请见下标:

优先级 说明
emerg 紧急情况,系统不可用(例如系统崩溃),一般会通知所有用户。
alert 需要立即修复,例如系统数据库损坏。
crit 危险情况,例如硬盘错误,可能会阻碍程序的部分功能。
err 一般错误消息。
warning 警告。
notice 不是错误,但是可能需要处理。
info 通用性消息,一般用来提供有用信息。
debug 调试程序产生的信息。
none 没有优先级,不记录任何日志消息。

常见日志文件

所有的系统应用都会在 /var/log 目录下创建日志文件,或创建子目录再创建日志文件。例如:

文件/目录 说明
/var/log/boot.log 开启或重启日志。
/var/log/cron 计划任务日志
/var/log/maillog 邮件日志。
/var/log/messages 该日志文件是许多进程日志文件的汇总,从该文件可以看出任何入侵企图或成功的入侵。
/var/log/httpd 目录 Apache HTTP 服务日志。
/var/log/samba 目录 samba 软件日志

 

/etc/syslog.conf 文件

/etc/syslog.conf 是 syslog 的配置文件,会根据日志类型和优先级来决定将日志保存到何处。典型的 syslog.conf 文件格式如下所示:

*.err;kern.debug;auth.notice /dev/console
daemon,auth.notice           /var/log/messages
lpr.info                     /var/log/lpr.log
mail.*                       /var/log/mail.log
ftp.*                        /var/log/ftp.log
auth.*                       @see.xidian.edu.cn
auth.*                       root,amrood
netinfo.err                  /var/log/netinfo.log
install.*                    /var/log/install.log
*.emerg                      *
*.alert                      |program_name
mark.*                       /dev/console

第一列为日志类型和日志优先级的组合,每个类型和优先级的组合称为一个选择器;后面一列为保存日志的文件、服务器,或输出日志的终端。syslog 进程根据选择器决定如何操作日志。

对配置文件的几点说明:

  • 日志类型和优先级由点号(.)分开,例如 kern.debug 表示由内核产生的调试信息。
  • kern.debug 的优先级大于 debug。
  • 星号(*)表示所有,例如 *.debug 表示所有类型的调试信息,kern.* 表示由内核产生的所有消息。
  • 可以使用逗号(,)分隔多个日志类型,使用分号(;)分隔多个选择器。


对日志的操作包括:

  • 将日志输出到文件,例如 /var/log/maillog 或 /dev/console。
  • 将消息发送给用户,多个用户用逗号(,)分隔,例如 root, amrood。
  • 通过管道将消息发送给用户程序,注意程序要放在管道符(|)后面。
  • 将消息发送给其他主机上的 syslog 进程,这时 /etc/syslog.conf 文件后面一列为以@开头的主机名,例如@see.xidian.edu.cn。

logger 命令

logger 是Shell命令,可以通过该命令使用 syslog 的系统日志模块,还可以从命令行直接向系统日志文件写入一行信息。

logger命令的语法为:

logger [-i] [-f filename] [-p priority] [-t tag] [message...]

每个选项的含义如下:

选项 说明
-f filename 将 filename 文件的内容作为日志。
-i 每行都记录 logger 进程的ID。
-p priority 指定优先级;优先级必须是形如 facility.priority 的完整的选择器,默认优先级为 user.notice。
-t tag 使用指定的标签标记每一个记录行。
message 要写入的日志内容,多条日志以空格为分隔;如果没有指定日志内容,并且 -f filename 选项为空,那么会把标准输入作为日志内容。


例如,将ping命令的结果写入日志:

$ ping 192.168.0.1 | logger -it logger_test -p local3.notice&
$ tail -f /var/log/userlog
Oct 6 12:48:43 kevein logger_test[22484]: PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
Oct 6 12:48:43 kevein logger_test[22484]: 64 bytes from 192.168.0.1: icmp_seq=1 ttl=253 time=49.7 ms
Oct 6 12:48:44 kevein logger_test[22484]: 64 bytes from 192.168.0.1: icmp_seq=2 ttl=253 time=68.4 ms
Oct 6 12:48:45 kevein logger_test[22484]: 64 bytes from 192.168.0.1: icmp_seq=3 ttl=253 time=315 ms
Oct 6 12:48:46 kevein logger_test[22484]: 64 bytes from 192.168.0.1: icmp_seq=4 ttl=253 time=279 ms
Oct 6 12:48:47 kevein logger_test[22484]: 64 bytes from 192.168.0.1: icmp_seq=5 ttl=253 time=347 ms
Oct 6 12:48:49 kevein logger_test[22484]: 64 bytes from 192.168.0.1: icmp_seq=6 ttl=253 time=701 ms
Oct 6 12:48:50 kevein logger_test[22484]: 64 bytes from 192.168.0.1: icmp_seq=7 ttl=253 time=591 ms
Oct 6 12:48:51 kevein logger_test[22484]: 64 bytes from 192.168.0.1: icmp_seq=8 ttl=253 time=592 ms
Oct 6 12:48:52 kevein logger_test[22484]: 64 bytes from 192.168.0.1: icmp_seq=9 ttl=253 time=611 ms
Oct 6 12:48:53 kevein logger_test[22484]: 64 bytes from 192.168.0.1: icmp_seq=10 ttl=253 time=931 ms

ping命令的结果成功输出到 /var/log/userlog 文件。

命令 logger -it logger_test -p local3.notice 各选项的含义:

  • -i:在每行都记录进程ID;
  • -t logger_test:每行记录都加上“logger_test”这个标签;
  • -p local3.notice:设置日志类型和优先级。

日志转储

日志转储也叫日志回卷或日志轮转。Linux中的日志通常增长很快,会占用大量硬盘空间,需要在日志文件达到指定大小时分开存储。

syslog 只负责接收日志并保存到相应的文件,但不会对日志文件进行管理,因此经常会造成日志文件过大,尤其是WEB服务器,轻易就能超过1G,给检索带来困难。

大多数Linux发行版使用 logrotate 或 newsyslog 对日志进行管理。logrotate 程序不但可以压缩日志文件,减少存储空间,还可以将日志发送到指定 E-mail,方便管理员及时查看日志。

例如,规定邮件日志 /var/log/maillog 超过1G时转储,每周一次,那么每隔一周 logrotate 进程就会检查 /var/log/maillog 文件的大小:

  • 如果没有超过1G,不进行任何操作。
  • 如果在1G~2G之间,就会创建新文件 /var/log/maillog.1,并将多出的1G日志转移到该文件,以给 /var/log/maillog 文件瘦身。
  • 如果在2G~3G之间,会继续创建新文件 /var/log/maillog.2,并将 /var/log/maillog.1 的内容转移到该文件,将 /var/log/maillog 的内容转移到 /var/log/maillog.1,以保持 /var/log/maillog 文件不超过1G。


可以看到,每次转存都会创建一个新文件(如果不存在),命名格式为日志文件名加一个数字(从1开始自动增长),以保持当前日志文件和转存后的日志文件不超过指定大小。

logrotate 的主要配置文件是 /etc/logrotate.conf,/etc/logrotate.d 目录是对 /etc/logrotate.conf 的补充,或者说为了不使 /etc/logrotate.conf 过大而设置。

可以通过 cat 命令查看它的内容:

$cat /etc/logrotate.conf
# see "man logrotate" for details  //可以查看帮助文档
# rotate log files weekly
weekly                             //设置每周转储一次
# keep 4 weeks worth of backlogs
rotate 4                           //最多转储4次
# create new (empty) log files after rotating old ones
create                             //当转储后文件不存储时创建它
# uncomment this if you want your log files compressed
#compress                          //以压缩方式转储
# RPM packages drop log rotation information into this directory
include /etc/logrotate.d           //其他日志文件的转储方式,包含在该目录下
# no packages own wtmp -- we'll rotate them here
/var/log/wtmp {                    //设置/var/log/wtmp日志文件的转储参数
    monthly                        //每月转储
    create 0664 root utmp          //转储后文件不存在时创建它,文件所有者为root,所属组为utmp,对应的权限为0664
    rotate 1                       //最多转储一次
}


注意:include 允许管理员把多个分散的文件集中到一个,类似于C语言的 #include,将其他文件的内容包含进当前文件。

include 非常有用,一些程序会把转储日志的配置文件放在 /etc/logrotate.d 目录,这些配置文件会覆盖或增加 /etc/logrotate.conf 的配置项,如果没有指定相关配置,那么采用 /etc/logrotate.conf 的默认配置。

所以,建议将 /etc/logrotate.conf 作为默认配置文件,第三方程序在 /etc/logrotate.d 目录下自定义配置文件。

logrotate 也可以作为命令直接运行来修改配置文件。

 



Linux信号机制与信号处理

信号(signal)是Linux进程间通信的一种机制,全称为软中断信号,也被称为软中断。信号本质上是在软件层次上对硬件中断机制的一种模拟。

与其他进程间通信方式(例如管道、共享内存等)相比,信号所能传递的信息比较粗糙,只是一个整数。但正是由于传递的信息量少,信号也便于管理和使用,可以用于系统管理相关的任务,例如通知进程终结、中止或者恢复等。

每种信号用一个整型常量宏表示,以SIG开头,比如SIGCHLD、SIGINT等,它们在系统头文件<signal.h>中定义。

信号由内核(kernel)管理,产生方式多种多样:

  • 可以由内核自身产生,比如出现硬件错误、内存读取错误,分母为0的除法等,内核需要通知相应进程。
  • 也可以由其他进程产生并发送给内核,再由内核传递给目标进程。


信号传递的过程:

  • 内核中针对每一个进程都有一个表来保存信号。
  • 当内核需要将信号传递给某个进程时,就在该进程对应的表中写入信号,这样就生成了信号。
  • 当该进程由用户态陷入内核态,再次切换到用户态之前,会查看表中的信号。如果有信号,进程就会首先执行信号对应的操作,此时叫做执行信号。
  • 从生成信号到将信号传递给对应进程这段时间,信号处于等待状态。
  • 我们可以编写代码,让进程阻塞(block)某些信号,也就是让这些信号始终处于等待的状态,直到进程取消阻塞(unblock)或者忽略信号。

信号种类

下表列出了一些常见信号:

信号名称 数字表示 说明
SIGHUP 1 终端挂起或控制进程终止。当用户退出Shell时,由该进程启动的所有进程都会收到这个信号,默认动作为终止进程。
SIGINT 2 键盘中断。当用户按下<Ctrl+C>组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号。默认动作为终止进程。 
SIGQUIT 3 键盘退出键被按下。当用户按下<Ctrl+D>或<Ctrl+\>组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号。默认动作为退出程序。
SIGFPE 8 发生致命的运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为0等所有的算法错误。默认动作为终止进程并产生core文件。
SIGKILL 9 无条件终止进程。进程接收到该信号会立即终止,不进行清理和暂存工作。该信号不能被忽略、处理和阻塞,它向系统管理员提供了可以杀死任何进程的方法。
SIGALRM 14 定时器超时,默认动作为终止进程。
SIGTERM 15 程序结束信号,可以由 kill 命令产生。与SIGKILL不同的是,SIGTERM 信号可以被阻塞和终止,以便程序在退出前可以保存工作或清理临时文件等。


通过 kill -l 命令可以查看系统支持的所有信号:

$ kill -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

上面仅是一个演示,不同的Linux发行版支持的信号可能不同。

每种信号都会有一个默认动作。默认动作就是脚本或程序接收到该信号所做出的默认操作。常见的默认动作有终止进程、退出程序、忽略信号、重启暂停的进程等,上表中也对部分默认动作进行了说明。

发送信号

有多种方式可以向程序或脚本发送信号,例如按下<Ctrl+C>组合键会发送SIGINT信号,终止当前进程。

还可以通过 kill 命令发送信号,语法为:

$ kill -signal pid

signal为要发送的信号,可以是信号名称或数字;pid为接收信号的进程ID。例如:

$ kill -1 1001

将SIGHUP信号发送给进程ID为1001的程序,程序会终止执行。

又如,强制杀死ID为1001的进程:

$ kill -9 1001

捕获信号

通常情况下,直接终止进程并不是我们所希望的。例如,按下<Ctrl+C>,进程被立即终止,不会清理创建的临时文件,带来系统垃圾,也不会保存正在进行的工作,导致需要重做。

可以通过编程来捕获这些信号,当终止信号出现时,可以先进行清场和保存处理,再退出程序。

用户程序可以通过C/C++等代码捕获信号,这将在Linux C编程中进行讲解,这里仅介绍如果通过Linux命令捕获信号。

通过 trap 命令就可以捕获信号,语法为:

$ trap commands signals

commands为Linux系统命令或用户自定义命令;signals为要捕获的信号,可以为信号名称或数字。

捕获到信号后,可以有三种处理:

  • 执行一段脚本来做一些处理工作,例如清理临时文件;
  • 接受(恢复)信号的默认操作;
  • 忽略当前信号。

1) 清理临时文件

脚本捕获到终止信号后一个常见的动作就是清理临时文件。例如:

$ trap "rm -f $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 2

当用户按下<Ctrl+C>后,脚本先清理临时文件 work1$$ 和 dataout$$ 再退出。

注意:exit 命令是必须的,否则脚本捕获到信号后会继续执行而不是退出。

修改上面的脚本,使接收到 SIGHUP 时进行同样的操作:

$ trap "rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2

几点注意:

  • 如果执行多个命令,需要将命令用引号包围;
  • 只有脚本执行到 trap 命令时才会捕获信号;
  • 再次接收到信号时还会执行同样的操作。


上面的脚本,执行到 trap 命令时就会替换 WORKDIR 和 $$ 的值。如果希望接收到 SIGHUP 或 SIGINT 信号时再替换其值,那么可以将命令放在单引号内,例如:

$ trap 'rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit' 1 2

2) 忽略信号

如果 trap 命令的 commands 为空,将会忽略接收到的信号,即不做任何处理,也不执行默认动作。例如:

$ trap '' 2

也可以同时忽略多个信号:

$ trap '' 1 2 3 15

注意:必须被引号包围,不能写成下面的形式:

$ trap  2

3) 恢复默认动作

如果希望改变信号的默认动作后再次恢复默认动作,那么省略 trap 命令的 commands 即可,例如:

$ trap 1 2

将恢复SIGHUP 和 SIGINT 信号的默认动作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Linux入门教程】4 用户管理、系统性能分析、系统日志及日志分析、信号机制与信号处理 的相关文章

  • 我们可以在 Bash 脚本中使用 PHP 吗?

    我有一个 bash 脚本abcd sh bin sh for i in seq 8 do ssh w i uptime ps elf grep httpd wc l free m mpstat done pid sleep 1 kill 9
  • Linux Shellcode“你好,世界!”

    我有以下可用的 NASM 代码 global start section text start mov eax 0x4 mov ebx 0x1 mov ecx message mov edx 0xF int 0x80 mov eax 0x1
  • %config(noreplace) 文件上出现意外的 RPM 冲突

    我正在创建我自己的RPM using rpmbuild My RPM 包含配置文件哪个应该永远不会被覆盖 即使 RPM 包含这些配置文件的新版本 为了存档这个 我用以下标签标记了它们 config noreplace opt mypacka
  • 有没有办法只安装mysql客户端(Linux)? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有没有不需要安装整个mysql db安装包的Linux mysql命令行工具 我想做的是从服务器 1 应用程序服务器 执行将在服务器 2
  • 如何清理 Runtime.exec() 中使用的用户输入?

    我需要通过命令行调用自定义脚本 这些脚本需要很少的参数并在 Linux 机器上调用 当前版本容易出现各种shell注入 如何清理用户给出的参数 参数包括登录名和路径 Unix 或 Windows 路径 用户应该能够输入任何可能的路径 该路径
  • 如何防止 CMake 在构建时(而不是安装时)为共享库创建符号链接?

    我正在使用 CMake 在 Linux 上使用 Bullet3 构建一个项目 在构建整个解决方案时 它会构建附加了 SOVERSION 的 Bullet 输出库 并创建一个不带版本的符号链接 对于我的特定场景 我不喜欢这种行为 并且我不想编
  • 动态加载库和共享全局符号

    由于我在动态加载的库中观察到全局变量的一些奇怪行为 因此我编写了以下测试 首先我们需要一个静态链接库 头文件test hpp ifndef BASE HPP define BASE HPP include
  • 如何从python导入路径中删除当前目录

    我想使用 Mercurial 存储库hg本身 也就是说 我克隆了 Mercurialhttps www mercurial scm org repo hg https www mercurial scm org repo hg并想运行一些h
  • 如何从 Linux 命令行打开 Sublime Text 2 文件到选项卡,而不是新窗口

    我有 ST2 设置 这样我就可以执行 sublime file txt 它将在 ST2 窗口中打开 但是我怎样才能让它在当前打开的窗口的新选项卡中打开呢 尝试 Sublime 命令行帮助 subl 帮助 Sublime Text 2 内部版
  • 有没有办法改变vim的默认模式

    有谁知道如何更改vim的默认模式 它的默认模式是命令模式 但是我可以将其更改为插入模式吗 只需将以下行添加到您的 vimrc 中 start Vim s default mode will be changed to Insert mode
  • 检查 Linux 中给定进程的打开 FD 限制

    我最近有一个 Linux 进程 泄露 了文件描述符 它打开了文件描述符 但没有正确关闭其中一些文件描述符 如果我对此进行监控 我就可以提前得知该过程已达到其极限 有没有一种很好的 Bash 或 Python 方法来检查 Ubuntu Lin
  • Python 线程与 Linux 中的多处理

    基于此question https stackoverflow com questions 807506 threads vs processes in linux我假设创建新流程应该几乎和创造新线程在Linux中 然而 很少的测试显示出截
  • 如何使用 shell 脚本解压所有 .tar.gz?

    我试过这个 DIR path tar gz if ls A DIR 2 gt dev null then echo not gz else tar zxvf path tar gz C path tar fi 如果该文件夹有一个 tar 则
  • 如何更改Linux服务器中的MySQL表名不区分大小写?

    我正在开发一个旧网站 该网站曾经托管在 Apple 服务器上 当它迁移到新的 Linux 服务器时 它停止工作 我很确定这是因为 php 脚本中使用的所有 MySQL 查询对于表名都有不同的大小写组合 我不知道为什么原始开发人员在创建表名或
  • 使用 xargs 时如何获取退出代码(并行)

    我制作了一个用于启动并行 rsync 进程的脚本 bin bash LIST 1 DEST DIR 2 RSYNC OPTS 3 echo rsyncing From SRC DIR To DEST DIR RSYNC OPTS RSYNC
  • 检查上次更改密码的时间[关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的
  • 多线程进程的线程ID可以与另一个正在运行的进程的进程ID相同吗?

    我正在尝试找到一种方法来唯一标识多进程环境中的线程 我有一个服务器 它跟踪连接到它的不同进程 其中一些是多线程的 一些不是 为了识别多线程连接中的线程 我使用线程 ID 作为唯一标识符 在任何给定时间最多有 1 个多线程进程连接 我的问题是
  • pip 找不到满足要求的版本 django==2.2.1

    我刚刚将操作系统更改为 linux 并且想安装 django 但我无法安装最新版本的 django 我努力了 pip install django 但是它安装了 django 1 11 11 这不是我需要的 我还将我的 pip 升级到了 1
  • 对符号“pthread_key_delete@@GLIBC_2.2.5”的未定义引用

    我正在尝试在 Ubuntu 中创建一个文件 当我创建时 我不断收到此错误 usr bin ld gtest 1 7 0 libgtest a gtest all cc o undefined reference to symbol pthr
  • 串口读取未完成

    下面的函数用于在Linux下从串口读取数据 我在调试时可以读取完整的数据 但是当我启动程序时 读缓冲区似乎并不完整 我正确接收了一小部分数据 但缓冲区的其余部分完全正确zero 可能是什么问题呢 int8 t serial port ope

随机推荐

  • 阿里达摩院金榕:从技术到科学,中国AI向何处去?

    点击下方卡片 关注 CVer 公众号 AI CV重磅干货 第一时间送达 本文转载自 机器之心 作者 金榕 阿里巴巴达摩院副院长 原密歇根州立大学终身教授 如果从达特茅斯会议起算 AI 已经走过 65 年历程 尤其是近些年深度学习兴起后 AI
  • Python爬虫的解析(学习于b站尚硅谷)

    目录 一 xpath 1 xpath插件的安装 2 xpath的基本使用 1 xpath的使用方法与基本语法 路径查询 谓词查询 内容查询 使用text查看标签内容 属性查询 模糊查询 逻辑运算 2 安装lxml库 3 代码的演示 3 获取
  • cmake升级及多版本管理

    查看原有的cmake cmake version which cmake gt gt gt usr bin cmake 下载要装的cmake源文件 解压并进入 使用已有的cmake安装 mkdir build cd build cmake
  • 计算机操作系统面试题

    一 认识汇编语言 汇编的本质是机器语言的助记符号 汇编语言本质就是机器语言 二 CPU的基本组成 PC 程序计数器 记录将要执行的指令的地址 Registers 暂时存储CPU计算需要用到的数据 ALU 寄存器中取到数据 进行运算然后将结果
  • 分布式存储基础知识

    2018 4 26 分布式存储的数据类型有以下三类 非结构化的数据 主要是数据之间的关联系不大 像文本图片之类的数据 结构化的数据 数据之间关联系很大 关系型数据库这种 可以用表进行表示的 半结构化的数据 介于上述两种数据类型之间 数据之间
  • DCMTK解析DICOM汇总

    DICOM头信息示例如下 0002 0000 Group Length VR UL Length 4 Value 184 0002 0001 File Meta Information Version VR OB Length 2 Valu
  • 抖音综合榜单数据爬虫案例

    偶然在抖音创作平台中看到了一系列的排行榜 如热搜榜 热门视频榜 娱乐明星榜 音乐榜等等 网页链接 https creator douyin com billboard home 登陆后可见数据 榜单接口 接口名 类型 链接 热搜榜单 Get
  • SNPP/VIIRS 数据介绍和下载

    SNPP VIIRS 数据介绍和下载 最近刚接触VIIRS卫星数据 用于洪水监测 主要记录VIIRS数据相关资料和数据下载方法 一 VIIRS数据简介 1 NPP卫星系统 NPP National Polar orbiting Partne
  • 一个自动生成卡通头像的工具网站

    1 打开网站 https deepai org machine learning model toonify 2 选择照片 3 上传照片 4 结果
  • flutter 获取屏幕宽度工具类

    import dart ui 工具类 class GlobalUtils static num screenW 0 设备的宽高 static num screenH 0 设备的宽高 static num devicePixelRatio 0
  • 在IE9使用CORS的思路——XDomainRequest

    前端最常用的就是CORS来调用Restful接口 但是IE9却真够侘寂的 连常规的XHR都不能完整支持 于是 动手写一遍IE10以下专属的 XDomainRequest 但是我测试了一下XDomainRequest 它能接收html tex
  • 开始学习Webpack-应用TypeScript,配置热加载和Source Map

    项目初始化 采用TypeScript 我们的版本是 node version v8 5 0 npm version 5 5 1 1 2 3 4 npm版本升级了 因为npm最近带来了新特性 本地会生成package lock json 能
  • python程序实例源代码-python实例-兔子和獾(塔防游戏)附源码

    原文 兔子和獾大战python小游戏 英文 https www raywenderlich com 24252 beginning game programming for teens with python 中文 http blog jo
  • Anaconda使用conda连接网络出现错误

    在进行更新或者其他操作时报网络连接错误如下 CondaHTTPError HTTP None None for url https repo continuum io pkg Elapsed None An HTTP error occur
  • java在线播放_Java实现视频在线播放flv视频

    1 首先使用Idea创建一个Spring Boot项目 2 在application properties文件下加入以下代码 进行DEBUG日志输出 配置pom xml文件 logging日志配置 logging level root WA
  • QT connect函数

    connect是信号与槽的连接函数 调用方法大致分为以下几类 以QPushButton为例 一 信号 槽函数均不带参数 connect button SIGNAL clicked this SLOT onbuttonClicked conn
  • C、C++中对json格式数据的解析和封装

    C 首先需要调库 include
  • Linux配置kdump大小,linux6下kdump的配置

    linux6下kdump的配置 背景知识 kexec是一个快速启动机制 允许通过已经运行的内核的上下文启动一个Linux内核 不需要经过BIOS BIOS可能会消耗很多时间 特别是带有众多数量的外设的大型服务器 这种办法可以为经常启动机器的
  • 竞赛 基于机器视觉的火车票识别系统

    文章目录 0 前言 1 课题意义 课题难点 2 实现方法 2 1 图像预处理 2 2 字符分割 2 3 字符识别 部分实现代码 3 实现效果 最后 0 前言 优质竞赛项目系列 今天要分享的是 基于机器视觉的火车票识别系统 该项目较为新颖 适
  • 【Linux入门教程】4 用户管理、系统性能分析、系统日志及日志分析、信号机制与信号处理

    Linux用户管理 在Linux中 有三种用户 Root 用户 也称为超级用户 对系统拥有完全的控制权限 超级用户可以不受限制的运行任何命令 Root 用户可以看做是系统管理员 系统用户 系统用户是Linux运行某些程序所必须的用户 例如