在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有以下几种:
|
组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中需要监控的资源主要有 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 | 实时监控系统中各个进程资源的资源使用情况。 |
常用命令组合:
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 | 与打印机活动有关。 |
邮件日志。 | |
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 是 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 进程根据选择器决定如何操作日志。
对配置文件的几点说明:
对日志的操作包括:
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 各选项的含义:
日志转储也叫日志回卷或日志轮转。Linux中的日志通常增长很快,会占用大量硬盘空间,需要在日志文件达到指定大小时分开存储。
syslog 只负责接收日志并保存到相应的文件,但不会对日志文件进行管理,因此经常会造成日志文件过大,尤其是WEB服务器,轻易就能超过1G,给检索带来困难。
大多数Linux发行版使用 logrotate 或 newsyslog 对日志进行管理。logrotate 程序不但可以压缩日志文件,减少存储空间,还可以将日志发送到指定 E-mail,方便管理员及时查看日志。
例如,规定邮件日志 /var/log/maillog 超过1G时转储,每周一次,那么每隔一周 logrotate 进程就会检查 /var/log/maillog 文件的大小:
可以看到,每次转存都会创建一个新文件(如果不存在),命名格式为日志文件名加一个数字(从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 也可以作为命令直接运行来修改配置文件。
信号(signal)是Linux进程间通信的一种机制,全称为软中断信号,也被称为软中断。信号本质上是在软件层次上对硬件中断机制的一种模拟。
与其他进程间通信方式(例如管道、共享内存等)相比,信号所能传递的信息比较粗糙,只是一个整数。但正是由于传递的信息量少,信号也便于管理和使用,可以用于系统管理相关的任务,例如通知进程终结、中止或者恢复等。
每种信号用一个整型常量宏表示,以SIG开头,比如SIGCHLD、SIGINT等,它们在系统头文件
信号由内核(kernel)管理,产生方式多种多样:
信号传递的过程:
下表列出了一些常见信号:
信号名称 | 数字表示 | 说明 |
---|---|---|
SIGHUP | 1 | 终端挂起或控制进程终止。当用户退出Shell时,由该进程启动的所有进程都会收到这个信号,默认动作为终止进程。 |
SIGINT | 2 | 键盘中断。当用户按下 |
SIGQUIT | 3 | 键盘退出键被按下。当用户按下 |
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发行版支持的信号可能不同。
每种信号都会有一个默认动作。默认动作就是脚本或程序接收到该信号所做出的默认操作。常见的默认动作有终止进程、退出程序、忽略信号、重启暂停的进程等,上表中也对部分默认动作进行了说明。
有多种方式可以向程序或脚本发送信号,例如按下
还可以通过 kill 命令发送信号,语法为:
$ kill -signal pid
signal为要发送的信号,可以是信号名称或数字;pid为接收信号的进程ID。例如:
$ kill -1 1001
将SIGHUP信号发送给进程ID为1001的程序,程序会终止执行。
又如,强制杀死ID为1001的进程:
$ kill -9 1001
通常情况下,直接终止进程并不是我们所希望的。例如,按下
可以通过编程来捕获这些信号,当终止信号出现时,可以先进行清场和保存处理,再退出程序。
用户程序可以通过C/C++等代码捕获信号,这将在Linux C编程中进行讲解,这里仅介绍如果通过Linux命令捕获信号。
通过 trap 命令就可以捕获信号,语法为:
$ trap commands signals
commands为Linux系统命令或用户自定义命令;signals为要捕获的信号,可以为信号名称或数字。
捕获到信号后,可以有三种处理:
1) 清理临时文件
脚本捕获到终止信号后一个常见的动作就是清理临时文件。例如:
$ trap "rm -f $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 2
当用户按下
注意:exit 命令是必须的,否则脚本捕获到信号后会继续执行而不是退出。
修改上面的脚本,使接收到 SIGHUP 时进行同样的操作:
$ trap "rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2
几点注意:
上面的脚本,执行到 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 信号的默认动作。