Linux系统的大部分系统配置文件都存放在/etc目录中。按照惯例,每个程序在这里都有一个或多个配置文件。因为Unix系统的程序数目很多,所以/etc目录也会越来越庞大。
不仅很难找到要找的配置文件,而且维护起来也不方便。比如,要更改系统的日志配置,你需要辑/etc/syslog.conf文件。但是你的更改可能会被随后的系统升级覆盖掉。
目前比较常见的方式是将系统配置文件放到/etc下的子目录,如果你运行ls -F /etc查看的话,你会发现大部分配置文件都放到了子目录中。
为了解决配置文件被覆盖的问题,你可以将定制的配置放到子目录里的其他文件中,如/etc/grub.d
基本规律是针对系统的可定制的配置文件在/etc下,如用户信息(/etc/passwd)和网络配置(/etc/network)。然而,与应用程序细节相关的文件不在/etc中,如系统用户界面的默认配置。你会发现那些不可定制的系统配置文件存放在了其他地方,比如预先打包的系统单元文件在/usr/lib/systemd中。
大多数系统程序将它们的日志信息输出到syslog服务。传统的syslogd守护进程等待消息的到来,并根据它们的类型将它们输出到文件、屏幕、用户或其他地方,有的干脆忽略。
系统日志是系统中最重要的部分之一。如果系统出现你不清楚的错误,查看系统日志文件是
第一选择。以下是日志文件示例:
系统日志是系统中最重要的部分之一。如果系统出现你不清楚的错误,查看系统日志文件是第一选择。以下是日志文件示例:
Aug 19 17:59:48 duplex sshd[484]: Server listening on 0.0.0.0 port 22.
大多数Linux系统使用的是syslogd的一个新版本,叫作rsyslogd。它的功能不仅仅限于记录日志信息。比如,你还可以让它加载一个将日志信息写到数据库的模块。不过最简单的方式还是从/var/log目录开始。你看看其中的那些日志文件后,就能够了解它们来自哪里。
rsyslog的基础配置文件是/etc/rsyslog.conf,但你还会在其他地方(如/etc/rsyslog.d)发现另外一些配置文件。其内容包含传统的规则和rsyslog扩展。其中一条规则是任何以字符$
开头的都是扩展。
传统的规则包括一个选择符(selector)和一个操作(action),分别代表从哪里获得日志和将它们写到哪里,如下例所示:
kern.* /dev/console
*.info;authpriv.none➊ /var/log/messages
authpriv.* /var/log/secure,root
mail.* /var/log/maillog
cron.* /var/log/cron
*.emerg *➋
local7.* /var/log/boot.log
左边是选择符,表示要为哪种信息类型记录日志。右边是操作列表,表示要将日志写到哪里。
大部分的操作都是将日志写入文件,也有一些例外:/dev/console表示系统控制台的一个特殊设备,root表示如果root用户登录的话,将消息发送给他,*代表发送消息给系统中的所有用户
设施和优先级
选择符用来匹配日志信息的设施和优先级。设施是指消息的大致分类。
设施的功能很容易通过它们的名称得知,从kern、authpriv、mail、cron和local7这些设施中抓取日志信息,➋处的*号是一个通配符,表示从所有设施中获得输出
设施后的点号(.)后面是优先级,由低到高分别是:debug、info、notice、warning、err、crit、alert或emerge。
为选择符设置了优先级之后,rsyslogd将该优先级及其以上优先级的消息发送到指定目的地。➊处的*.info将抓取大部分日志消息并将它们写到/var/log/messages,因为info是一个相对较低的优先级。
扩展语法
一个比较常用的扩展是让你加载其他的配置文件。rsyslog.conf中就包含这样的指令,让rsyslogd加载/etc/rsyslog.d目录中的所有.conf文件。
$IncludeConfig /etc/rsyslog.d/*.conf
大部分的指令都很好理解,比如以下涉及用户和权限的指令:
$FileOwner syslog
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
故障排除
测试系统日志最简单的方法之一是使用logger命令手动发送日志消息。
logger -p daemon.info something bad just happened
rsyslogd不容易出错。出现问题大都是因为配置文件没有正确配置设施或优先级,因而没有获得想要抓取的日志信息,或者是由于磁盘空间不足。大多数系统会使用logrotate或者类似工具来自动清除/var/log中的文件,不过如果在短时间写入大量日志,还是会出现系统负载增加、磁盘空间用尽的情况。
日志的过去和未来
syslog服务在不断演进。曾经出现过一个叫klogd的守护进程,负责为syslogd截获内核的日志消息,这些日志可以使用dmesg命令查看。后来该功能被并入到了rsyslogd中。
Unix系统支持多用户。用户对于内核而言只是一些数字(用户ID),因为用户名比数字容易记忆,所以用户一般都是用用户名(或登录名)而非用户ID来管理系统。用户名只存在于用户空间,使用到用户名的应用程序在和内核通信时,通常需要将用户名映射为用户ID。
文本文件/etc/passwd中包含一一对应的用户名和用户ID。如下所示:
root:x:0:0:Superuser:/root:/bin/sh
daemon:*:1:1:daemon:/usr/sbin:/bin/sh
bin:*:2:2:bin:/bin:/bin/sh
sys:*:3:3:sys:/dev:/bin/sh
nobody:*:65534:65534:nobody:/home:/bin/false
每一行代表一个用户,一共有7列,用冒号:分隔。这7列所代表的内容如下所示。
x
带包加密过的密码存放在shadow中*
用户不能登录在/etc/passwd中有一些特殊用户。其中,超级用户的UID和GID固定为0
有一些用户如守护进程用户没有登录权限。nobody用户的权限最小。一些进程在nobody用户名下运行,因为它没有任何写入权限。
Linux中的影子密码文件(/etc/shadow)包含用户验证信息以及经过加密的密码和密码过期日期,这些都和/etc/passwd文件中的用户相对应。
普通用户使用passwd命令来更改密码。默认状态下,passwd可以更改用户密码,但你还可以使用-f选项来更改用户名,用-s选项来更改shell。
passwd命令是一个suid-root程序,只有超级用户能够编辑/etc/passwd文件。
使用超级用户来更改/etc/passwd
由于/etc/passwd是纯文本文件,因此超级用户可以使用任何文本编辑器来编辑它。要添加用户,只需加上恰当的命令行并为用户创建一个root目录即可。要删除用户则反之。
很多人不愿意直接编辑passwd文件,因为很容易把文件搞乱。使用另外的终端命令或者GUI会更为方便和安全
可以使用超级用户运行passwd user来设置用户密码。adduser和userdel可以添加和删除用户。
用户组可以将文件访问权设定给某些用户,而使其他用户无权访问。你可以为某组用户设置读写位,从而排除其他的用户。
/etc/group 文件中包含了用户组ID,类似的etc/passewd
*
或者其他默认值使用group命令来查看你所属的用户组。
getty连接到终端并且在其上显示登录提示符。大多数Linux系统中的getty程序很简单,仅仅是在虚拟终端上显示登录提示符。它可以用在管道命令中
$ ps ao args | grep getty
/sbin/getty 38400 tty1
38400是波特率。有些getty不需要该设置。
输入用户名后,getty调用login程序提示你输入密码。如果输入的密码正确,login会调用你的shell(使用exec())。否则你会得到“登录错误”提示信息。
Unix系统的运行依赖精确的计时,而内核则负责维护系统时钟。可以使用date命令来查看,还可以用它设置时间
因为设置的时间有可能不精准,而你的系统时间应该尽可能精准。
计算机硬件有一个使用电池的实时时钟(Real-time Clock,以下简称RTC)。RTC并不是最精准的,但是聊胜于无。内核通常在启动时使用RTC来设置时间。
最好将你的硬件时钟设置为通用协调时间(UniversalCoordinated Time,以下简称UTC),这样可以避免不同时区和夏令时带来的问题。
hwclock --hctosys --utc
不要试图使用hwclock来修复时间误差,因为这会影响那些基于时间的系统事件。你可以运行adjtimex来更新系统时钟,不过最好的办法是使用守护进程来使你的系统时间和网络上的时间保持同步。
内核将当前的系统时间显示为以秒为单位的一串数字,自UTC时间1970年1月1日12:00时起开始。你可以使用以下命令来查看:
$ date +%s
为了保证易读性,用户空间程序会将这组数字转换为本地时间,并且将夏令时和其他因素(比如印第安纳州时间)都考虑在内。文件/etc/localtime(二进制文件)用来控制本地时区。
时区信息在/usr/share/zoneinfo目录中,其中包含了时区及其别名等信息。
如果要手动设置时区,可以将/usr/share/zoneinfo中的某个文件复制到/etc/localtime(或者创建一个符号链接)中,或者使用系统自带的时区工具。(你可以使用tzselect命令寻找时区文件。)
如果你的主机连接到互联网,你可以运行网络时间协议(Network Time Protocol,以下简称NTP)守护进程,借助远程服务器来更新时间。很多Linux系统自带NTP守护进程,但是不一定默认开启。你可以安装ntpd包来运行它。
Unix的cron(意思是定时)服务能够按照日程安排来重复运行程序。cron对多数富有经验的系统管理员来说非常重要,因为它可以完成很多自动化的系统维护工作。
你可以使用cron在任何时间运行任何程序。通过cron运行的程序我们称为定时任务。要添加一个定时任务,可以在crontab(意为定时任务)文件中加入一行,通常是通过执行crontab命令来完成。
例如,你若想将/home/juser/bin/spmake命令安排在每天9:15AM运行,可以加入以下一行:
15 09 * * * /home/juser/bin/spmake
最开始的5列用空格分隔
每个用户都可以有自己的crontab文件,所以系统中经常会有很多个crontab,通常保存在/var/spool/cron/crontabs目录中。普通用户对该目录没有写权限,crontab命令负责安装、查看、编辑和删除用户的crontab。
安装crontab最简便的方法是将crontab条目放入一个文件(如file),然后运行crontab file命令将file文件安装为你的crontab。crontab命令会检查文件的格式,确保没有错误。你可以使用crontab -l列出你的cron任务。使用crontab -r删除crontab文件。
Linux系统通常使用/etc/crontab文件来安排系统任务的运行,而不是使用超级用户的crontab。不要使用crontab命令来编辑该文件,因为它有一个额外的列来设置运行任务的用户。
要想在将来的某一时刻一次性运行任务,如果不使用cron的话,可以使用at服务。例如要在10:30PM运行myjob,可以使用以下命令:
$ at 22:30
at> myjob
使用CTRL-D结束输入。(at从标准输入读取命令。)
sudo和su这样的setuid程序允许你切换用户,login这样的系统组件负责控制用户访问。
更改用户ID有两种方式,均由内核负责完成。第一种是运行setuid程序。第二种是通过setuid()系统调用,该系统调用有很多不同版本,用来处理和进程关联的所有用户ID。
下面是三个基本规则:
进程归属、有效UID、实际UID和已保存UID
到目前为止,本书所讲的有关用户ID的内容都是简化过的。实际上每个进程都有超过一个用户ID。
我们提到过的有效UID(effective user ID,euid)是用来设定某一进程的访问权限。另外还有一个UID是实际UID(real user ID,ruid),即实际启动进程的UID。当你运行setuid程序时,Linux将有效UID设置为程序文件的拥有者,同时将实际UID设置为你的UID。
我们可以将有效UID看作执行者,将实际UID看作所有者。实际UID是可以与进程进行交互的用户,可以终止进程,向进程发送信号。
在Linux系统中,大多数进程的有效UID和实际UID是相同的。ps和其他系统诊断命令默认显示有效UID。要想查看你系统上的有效UID和实际UID,可以使用以下命令,但你会发现,你的系统中的所有进程几乎拥有相同的有效UID和实际UID。
$ ps -eo pid,euser,ruser,comm
除了有效UID和实际UID外,还有一个已保存UID(saved user ID,通常没有简写形式)。进程在运行过程中可以从有效UID切换到实际UID和已保存UID。(实际上Linux还有另外一个UID,即文件系统UID,但很少用到,代表访问文件系统的用户。)
相关安全性
因为Linux内核通过setuid程序和相关系统调用来处理用户切换(以及相关的文件存取权限),系统管理员和开发人员必须特别注意以下两点。
攻击Linux系统的常见方式之一就是利用那些以root名义运行的程序的漏洞,这样的例子数不胜数。
由于攻击系统的手段众多,因此防止系统受到攻击也是一项十分繁重的任务。其中最有效的方式之一是强制使用用户名和密码进行验证。
多用户系统必须支持用户标识(identification)和用户认证(authentication),以保证基本的用户安全。
对于用户标识,Linux内核通过用户ID来管理进程和文件的权限。对于用户认证,Linux内核控制如何执行setuid,以及如何让用户ID执行setuid()系统调用来切换用户。
在传统的Unix系统中,进程会通过以下步骤获得用户名。
实际的过程要比这个复杂。
为了提高用户验证的灵活性,Sun Microsystems公司在1995年提出了一个新的标准,叫作可插入验证模块(Pluggable Authentiation Module,以下简称PAM)。它是一个共享的验证库(由Open Source Software Foundation RFC 86.0组织于1995年10月提出)。
进行用户验证的时候,用户被提交给PAM来决定该用户是否能够成功完成验证。这样比较容易加入新的验证方式和技术,比如两段式验证和物理钥匙。