第3章 用户管理
本章主要介绍Red Hat Enterprise Linux系统的用户管理,讨论怎样增加、修改或删除用户与用户组,介绍与用户管理有关的系统文件,说明如何设置用户的运行环境,详细讨论插件式认证模块,以及超级用户与sudo命令。
用户与用户组是Linux系统管理的一个重要部分,也是系统安全的基础。在Linux系统中,所有的文件、程序或正在运行的进程都从属于一个特定的用户。每个文件和程序都具有一定的访问权限,用于限制不同用户的访问行为。作为系统管理员,管理用户和用户组是一项重要的任务,有助于防止用户越权访问与其身份不相符的文件,执行系统任务,对系统造成破坏。总之,如果没有有效的用户管理,就无法保证系统的安全。
3.1 增加与删除用户
在Linux系统中,每个用户都具有一个唯一的身份标识,称做用户ID(或简称UID),以区别于其他用户。Linux系统按照一定的原则把用户划分为用户组,以便相关的同组用户之间能够共享文件。
一般来讲,Linux系统中的用户可以分为三类:超级用户(root)、管理用户和普通用户。但也可以把超级用户和管理用户通称为系统用户。
超级用户是一个特殊的用户(其用户标识号为0),拥有至高无上的访问权限,可以访问任何程序和文件。任何系统都会自动提供一个超级用户账号。
管理用户用于运行一定的系统服务程序,支持和维护相应的系统功能。这些用户的ID号位于1~499的范围之内。例如,ftp就是一个管理用户,用做FTP匿名用户,维护匿名用户的文件传输,同时提供匿名用户的默认主目录。
除了系统用户之外,其他均为普通用户。在访问Linux系统之前,每个用户都需要拥有一个用户账号。因此,系统管理员需要为每一个普通用户事先分配一个注册账号,把用户名及其他有关信息加到系统中。在利用用户名和密码成功地注册之后,用户才能访问系统提供的资源和服务,执行系统命令,开发和运行应用程序,以及访问数据库等。
对于自己的文件,用户均拥有绝对的权力,可以赋予自己、同组用户或其他用户访问文件的权限。例如,允许同组用户共享自己的文件,其他用户只能阅读或执行,但不能写文件等。
3.1.1 passwd文件
在安装Red Hat Enterprise Linux系统之后,系统已经事先创建了若干系统用户账号,其中包括超级用户root和管理用户daemon、bin和sys等,用于执行不同类型的系统管理和日常维护任务。
Linux系统中的用户账号信息是由/etc/passwd和/etc/shadow文件共同维护的。在这两个文件中,每个用户都有一个相应的记录。当利用控制台等终端注册,按照系统的提示输入用户名和密码之后,系统将会根据用户提供的用户名检查/etc/passwd文件,然后根据用户提供的密码,利用同一加密算法加密后再与/etc/shadow文件中的密码字段进行比较,同时检查其他诸如密码有效期等字段。如果通过了验证,按照passwd文件指定的主目录和命令解释程序,用户即可进入自己的主目录,通过命令解释程序等界面访问Linux系统。
除了用户名和密码之外,每个用户还具有用户ID、用户组ID、主目录和命令解释程序等相关信息。这些信息分别存放在passwd和shadow文件中。
passwd文件包含了Linux系统中除密码之外的主要用户信息,每个用户信息占用一行,每一行由7个字段组成,字段之间以冒号“:”作为分隔符。passwd文件的格式定义如下:
username:password:uid:gid:comment:home_dir:login_shell
表3-1给出了passwd文件中的每个字段及其简单说明。
表3-1 /etc/passwd文件
下面是Red Hat Enterprise Linux系统提供的初始用户信息(其中最后一个是安装系统时自定义的用户,也即sudo用户):
$ cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin …… gqxing:x:500:500:gqxing:/home/gqxing:/bin/bash $
3.1.2 shadow文件
/etc/shadow是一个限制普通用户访问的系统文件,其中存有加密形式的密码以及其他相关信息。与passwd文件相对应,shadow文件中的每个用户密码信息占用一行,每一行由9个字段组成,中间以冒号“:”作为分隔符。其文件格式定义如下:
username:password:lastchanged:mindays:maxdays:warn:inactive:expire:reserve
表3-2给出了shadow文件中的每个字段及其简单说明。
表3-2 /etc/shadow文件
下面是Red Hat Enterprise Linux系统的初始shadow文件:
# cat /etc/shadow root:$1$iMqBUysA$lf29r0iI8rf5vb3tXFmT..:14951:0:99999:7::: bin:*:14790:0:99999:7::: daemon:*:14790:0:99999:7::: adm:*:14790:0:99999:7::: …… gqxing:$6$PodDPhah$XmVNLbVMuO28VGjg……rl01:14562:0:99999:7::: #
3.1.3 用户管理实例
在Red Hat Enterprise Linux系统中,若想管理用户和用户组,可从GNOME桌面中选择“系统→管理→用户和组群”菜单,在进入如图3-1所示的窗口之后,即可开始增加新的用户或用户组,修改及删除用户或用户组。注意,在使用GNOME桌面系统管理用户和用户组时,用户ID和用户组ID的默认起始编号为501(安装Red Hat Enterprise Linux系统时创建的第一个用户占用了编号为500的用户ID和用户组ID)。
图3-1 “用户管理者”窗口
在“用户管理者”窗口中单击“添加用户”按钮,进入如图3-2所示的“创建新用户”窗口。此时,可在“用户名”和“全称”字段中分别输入用于注册的用户名和实际用户名,在“口令”和“确认口令”字段重复输入密码。后续几项可以保持默认设置不变,必要时可在“登录Shell”下拉列表框中选择自己喜欢的Shell,或勾选“手工指定用户ID”复选框,自己指定用户ID等。
图3-2 “添加新用户”窗口
在完成上述设置之后,单击“确定”按钮,返回如图3-3所示的“用户设置”窗口,可以看到已经把用户加到了系统中。
图3-3 完成设置后的“用户管理者”窗口
除了GNOME桌面桌面环境,还可以使用Linux系统的基本命令,实现用户和用户组的管理与维护。下面以命令行方式为例,说明怎样增加、修改和删除用户。
1.增加新用户
在命令行方式下,为了增加用户,可以使用useradd命令,其语法格式如下:
useradd [-u uid] [-g group] [-G groups] [-d home_dir] [-s shell] [-c comment] [–m [-k skel_dir]] [-N] login
其中,login表示新增用户的注册用户名。其他选项的说明如表3-3所示。
表3-3 useradd命令的常用选项
例如,为了增加一个用户cathy,同时增加一个用户组cathy,可以使用下列命令:
#useradd -u 501-d /home/cathy –m -s /bin/bash cathy #
执行上述命令之后,将会在/etc/passwd、/etc/shadow和/etc/group文件中各增加一行新用户cathy的有关信息:
# grep cathy /etc/passwd cathy:x:501:501::/home/cathy:/bin/bash # grep cathy /etc/shadow cathy:!!:14951:0:99999:7::: # grep cathy /etc/group cathy:x:501: #
采用useradd命令增加用户之后,还需要使用passwd命令为用户设置一个临时密码,否则无法正常注册。用户注册之后,可以再使用passwd命令修改自己的密码:
# passwd cathy Changing password for user cathy. New password: Retype new password: passwd: all authentication tokens updated successfully. #
在选用用户名、用户ID和用户组ID时通常应遵循下列原则:
· 用户名应包含2~8个字母和数字,第一个字符必须是字母,而且至少有一个字符是小写字母。注意,即使用户名中允许包含句点“.”、下画线“_”或连字符“-”,也不建议使用。
· 避免使用/etc/passwd和/etc/group文件中已有的用户名、用户ID、用户组名以及用户组ID。此外,用户ID和用户组ID号0~499是系统保留的,普通用户不应使用。
一旦创建了用户账号,就可以使用passwd命令设置密码。使用usermod等命令修改passwd和shadow文件,更改用户的其他相关属性。
注意,在增加、修改和删除用户时,如果采用编辑器,手工修改passwd和shadow文件,必须考虑以下因素:
· 用户属于哪个用户组,相应的用户组是否存在。
· 除了修改passwd文件之外,还要在/etc/shadow文件中增加、修改和删除相应的用户项。
· 创建和删除用户主目录。
· 另外还要创建或复制用户初始化文件,如.profile和.bashrc等文件(取决于选定的命令解释程序)。
2.修改用户账号信息
除非用户名或用户ID与其他用户冲突,一般情况下不要轻易修改用户账号中的用户名和用户ID,因为这将涉及到用户已经创建的所有文件和目录。否则,需要同时修改用户所有文件和目录的文件属主等属性。但可以放心地修改用户账号的其他字段:
· 注释字段。
· 命令解释程序。
· 密码及密码的其他属性(shadow文件)。
· 主目录及主目录的访问权限。
修改用户信息时,可以利用编辑器,以手工方式直接编辑passwd和shadow文件,也可以使用usermod命令。usermod命令的语法格式如下:
usermod [-u uid] [-g group] [-d home_dir] [-s shell] [-c comment] [-f inactive] [-e expire] [-l new_logname] login
其中,“-l”选项用于指定一个新的注册用户名。其他选项的说明参见表3-3。
例如,若想把用户cathy的命令解释程序bash更换为tcsh,可以使用下列命令:
# usermod -s /bin/tcsh cathy #
注意,除了超级用户root的密码之外,不要试图修改和删除系统用户账号的任何信息。
3.删除用户
一旦用户不再需要访问Linux系统,理应从系统中删除其账号信息。删除用户账号时可以使用userdel命令,也可以采用手工编辑的方式。使用userdel命令的好处是,只需一个命令即可删除passwd、shadow和group文件中的相应用户和用户组信息,同时还会把用户主目录中的所有文件和目录一同删除。如果采用手工方式,既需要编辑passwd、shadow或group文件,还需要删除用户主目录及其中的文件。userdel命令的语法格式如下:
userdel [-r] login
其中,“-r”选项意味着同时从系统中删除用户的主目录,包括其中的文件和子目录。
4.封锁用户账号
有时,也许需要临时或永久禁止或者封锁某个用户账号,禁止其注册。为此,可以使用passwd命令,或者直接修改/etc/shadow文件,在密码字段前面增加一个感叹号“!”前缀,或把密码字段改为星号“*”字符,以封锁相应的用户账号,从而防止用户再利用此账号注册到系统。另外一种方法是,利用usermod命令修改shadow文件中的expire字段,把其中的日期改成一个过时的日期。passwd命令的语法格式简写如下:
passwd [-dlSu] [login]
表3-4给出了passwd命令的部分选项及其说明(除非特别说明,相应的选项仅限于超级用户使用)。
表3-4 passwd命令的部分选项
例如,若想封锁guest的用户账号,可以使用下列命令:
# passwd -l guest Locking password for user guest. passwd: Success # 若想查询用户cathy的密码属性,可以使用下列命令: # passwd -S cathy cathy PS 2010-12-07 0 99999 7 -1 (Password set, MD5 crypt.) #
在上述输出信息中,PS表示用户cathy已经设置了密码。其他密码属性包括LK,表示用户账号已经封锁。
5.检验用户的有效用户ID
为了检查当前用户的有效用户ID,可以使用id命令。例如,当cathy注册到系统之后, id命令的输出结果如下:
$ id
uid=501(cathy) gid=501(cathy) groups=501(cathy) context=unconfined_u:
unconfined_r:unconfined_t:s0-s0:c0.c1023
$
使用su命令能够改变用户的有效用户ID,而不必另行注册。在输入其他用户名和密码之后,一个用户可以“合法地变成”另一个用户。除此之外,如果在su命令之后加上连字符“-”、“-l”或“--login”选项,还可以直接进入其他用户的主目录,如同使用其他用户名和密码直接注册一样。否则,即使改变用户身份,仍会保持之前的工作目录不变。例如:
$ su cathy Password: $ pwd /home/gqxing $ exit exit $ su – cathy Password: $ pwd /home/cathy $
3.2 定制用户的工作环境
除了分配用户名和用户ID,设定用户主目录,供用户创建和存储文件之外,还需要有一个工作环境,使用户能够借助系统提供的各种工具和资源访问系统,开发和运行自己的应用。在注册到系统之后,用户的工作环境是由选定的命令解释程序和相应的用户初始化文件确定的。因此,用户管理的另外一个任务是选择作为用户界面的命令解释程序和用户初始化文件。
3.2.1 选择命令解释程序
Linux系统配备的标准命令解释程序是Bash(bash),但同时也支持Korn Shell(ksh)、TC Shell(tcsh)以及Z Shell(zsh)等,用户可以自由选用。每个Shell各具特色,根据自己的需要,用户可以选用不同的命令解释程序。/etc/shells文件中列出了Red Hat Enterprise Linux系统支持的所有命令解释程序(注意,zsh需要单独安装):
$ cat /etc/shells /bin/sh /bin/bash /sbin/nologin /bin/tcsh /bin/csh $
任何时刻,每个用户只能使用一个命令解释程序,但可以随时从一个Shell切换到另外一个Shell环境。为了确定当前究竟处于哪一个Shell环境,可以使用“ps -f”命令,找出PS的父进程,即可确定当前使用的是哪一个Shell,例如:
$ ps –f UID PID PPID C STIME TTY TIME CMD gqxing 2596 2594 0 19:43 pts/0 00:00:00 bash gqxing 3217 2596 2 21:37 pts/0 00:00:00 ps -f $
增加用户时,每个用户都可以选定一个命令解释程序,如果未做出选择,系统默认的命令解释程序为Bash。如果需要,也可以通过usermod等命令修改用户账号信息,或直接修改passwd文件,随时更换命令解释程序。一经注册,即可调用指定或默认的命令解释程序。
Shell是大多数用户访问Linux系统的主要命令行界面,Shell功能的任何改进,如命令行编辑、命令或文件名补充以及命令提示符定制等,都有助于提高用户访问Linux系统的效率。Shell的熟悉程度、功能和特点是用户选择Shell的依据。
用户可以使用默认的Bash,可以选用TC Shell或Z Shell,也可以选用自己熟悉的K Shell等。
3.2.2 设置用户初始化文件
初始化文件(也称启动文件)是一种Shell脚本,其中包含用户注册后必须执行的各种命令,以便在注册之后,能够设置用户的工作环境。原则上讲,初始化文件与普通Shell脚本一样,可执行任何处理任务。但是,初始化文件的主要任务是设定用户的工作环境。
初始化文件分为系统初始化文件和用户初始化文件。系统初始化文件主要用于设置系统范围的用户工作环境,如设置命令检索路径、用户主目录、命令提示符以及终端类型等环境变量。用户初始化文件主要用于进一步定制自己的工作环境,如设置命令别名、个性化的命令提示符以及命令检索路径等。
每个Shell都提供并支持各自的初始化文件,其中包括位于/etc目录的系统初始化文件,如/etc/profile文件。以及位于用户主目录的用户初始化文件,如$HOME/.profile文件等。表3-5给出了各种Shell支持的用户初始化文件。
表3-5 Shell支持的用户初始化文件
如果选用的是Bash,当用户注册或打开一个新的终端窗口时,系统首先会运行系统初始化文件/etc/profile。用户可以查阅系统初始化文件,但不应修改其中的任何内容,以免影响其他用户。之后,系统还会检测并执行相应的用户初始化文件,以定制用户自己的运行环境。
每个Linux系统通常都提供若干标准的用户初始化文件,其中的默认设置基本上都能够满足用户的常规要求。如有特殊需求,如定制系统提示符、设置命令别名等,只需在此基础上进行适当的修改,增加特定的变量设置或命令即可。
下面是Red Hat Enterprise Linux系统提供的用户初始化模板文件:
· /etc/skel/.bash_logout
· /etc/skel/.bash_profile
· /etc/skel/.bashrc
在利用useradd命令增加新的用户账号时,如果使用“-k”和“-m”选项指定了/etc/skel目录,useradd将会把/etc/skel/目录中的所有文件复制到用户的主目录。此时,应根据选用的命令解释程序,删除不必要的文件(如果存在)。然后,利用.profile文件作为用户初始化文件的起点,定制自己的Shell工作环境。
在Red Hat Enterprise Linux系统的Bash运行环境中,用户需要设置和使用的通常只有~/.profile和~/.bashrc两个初始化文件。如果想要增加自己的设置,应尽量加在~/.profile文件中,因为这个文件仅在注册时执行一次,但~/.bashrc文件有可能多次执行,因而会影响系统的性能。
3.2.3 定制Shell工作环境
1. Shell运行环境
每个Shell都会维护一组由login程序、系统用户初始化文件及用户初始化文件定义的各种变量。其中包括:
·环境变量:可用于Shell调度执行的所有进程的变量称为环境变量。使用env或set命令可以查阅这些变量的设置情况。
· Shell本地变量:仅对当前Shell有效的变量称为本地变量。在TC Shell中,一组Shell本地变量(如user、term、home和path)与相应的环境变量具有特殊的关系,二者之间互相影响。
在Bash中,本地变量和环境变量通常均统一采用大写字母(但并不禁止使用小写字母和其他字符)。如果期望变量的设置能够用于随后调度执行的任何命令或程序,必须使用export命令公布用户自己设置的变量。
在用户初始化文件中,可以修改预定义变量的值,也可以设置附加的变量,定制自己的Shell工作环境。如果想在Bash和Korn Shell的用户初始化文件中设置变量,可以使用下列命令:
VARIABLE=value; export VARIABLE
例如,为了使vim编辑器等能够正常工作,需要根据自己使用的具体终端类型,采用“TERM=termtype;export TERM”的命令形式定义终端,以便系统能够检索TERMINFO数据库,确定终端的特性。
2. 设置环境变量
在数据库等应用程序中,需要用到许多环境变量。一些软件厂商通常也都提供一个环境变量设置脚本,供用户设置运行环境。
为使环境变量的设置能够用于当前的Shell运行环境,可以采用两种方法:一是利用“.”或source命令读取并执行Shell脚本,在当前的Shell中设置运行环境;二是把环境变量的设置语句加到.profile等用户初始化文件中。
“.”或source命令的主要功能是在当前Shell的控制下,读取指定的Shell脚本文件,由当前的Shell解释执行。“.”或source命令的调用方法如下:
. script
或
source script
其中,script是一个Shell脚本文件,文件中包含必要的环境变量设置语句。
使用“.”或source命令的主要目的是执行指定脚本文件中的命令,在当前的Shell中设置环境变量。例如,在使用MySQL数据库之前,用户也许需要运行诸如“mysql_env.sh”的环境变量设置脚本,或者在.profile文件中增加下列内容,从而设置自己的运行环境:
MYSQL_HOST=iscas MYSQL_TCP_PORT=3306 TMPDIR=/tmp export MYSQL_HOST MYSQL_TCP_PORT TMPDIR
假定mysql_env.sh是一个环境变量设置脚本,可使用“.”或source命令读取并运行mysql_env.sh脚本文件中的语句,在当前的Shell中设置环境变量。即使退出脚本,环境变量的设置仍将保持有效:
$ . ./mysql_env.sh $
如果使用下列命令,则在退出子Shell或Shell脚本之后,当前的Shell环境不会留存脚本中设置的任何变量。
$ sh mysql_env.sh
或
$ ./mysql_env.sh
3. 设置命令检索路径
设置环境变量的一个重要内容是设置PATH变量。Shell变量PATH用于设置命令的检索路径,定义命令所在的目录。PATH变量包含一系列目录,目录名之间由冒号“:”分隔。目录的列举顺序确定了命令的检索顺序。为了提高系统的响应速度,常用命令所在的目录应放在靠前的位置。
假定环境变量PATH设置为“/usr/bin:/usr/sbin:”,意味着命令的检索路径依次为/usr/bin、/usr/sbin和当前目录。指定当前目录至少有三种方法:一是使用两个相邻的冒号,二是在原有路径名的前部或后部增加一个冒号“:”,三是增加一个句点“.”。
当用户采用完整的绝对路径提交命令(输入的命令名以斜杠“/”开始)时,Shell将会省略PATH变量检索步骤,按照给定的路径检索命令,直接加载并执行指定的命令。否则,当用户仅输入命令名本身时,Shell将会根据PATH变量指定的目录顺序,依次检索与之匹配的命令文件。
不管在哪一个目录位置,如果发现了匹配的命令文件,文件的访问权限是可执行的,而且也不是目录文件时,则创建一个新的进程,执行该命令。如果指定的命令既非绝对路径,从PATH变量列举的目录中也找不到匹配的命令文件,系统将会输出下列错误信息:
bash: cmd: command not found
上述错误信息表明:或者命令名的输入有误;或者给定的命令确实不在PATH变量指定的检索目录中。对于第二种情况,校正的办法之一是使用绝对路径名,之二是修改PATH变量,把命令所在的目录加到PATH变量中,如附加到PATH变量值的后面。
在安装第三方的软件时,通常需要修改PATH变量,以免出现“命令不存在”或使用绝对路径名运行命令的麻烦。
用户初始化文件通常已经设定了PATH变量,包括命令路径的检索顺序。但是,大多数用户均会修改这个变量,增加自己的命令检索路径,或调整命令路径的检索顺序。例如,为了把当前目录作为PATH变量中的一个命令检索路径,可以使用下列命令:
PATH=$PATH:.; export PATH
注意,如果PATH变量的命令检索路径设置不当,有可能导致系统响应时间过长,也可能导致系统执行不正确的命令。为了提高PATH变量检索的有效性,下面是设置目录检索路径的若干建议:
· 如果想加入当前工作目录,通常应把当前工作目录作为最后一个检索路径。如果安全并非主要问题,可以把当前工作目录作为第一个检索路径。
· 应尽可能地缩短命令检索路径,以减少响应时间,提高系统的性能。
· 命令的检索顺序是从左到右,经常使用的命令,其所在目录应位于检索路径的最前面。
· 确保命令检索路径不包含重复的目录,以免执行重复的检索。
· 应尽量避免检索大的目录,如果可能,应把大的目录置于检索路径的最后面。
· 如果存在,应把本地目录置于远程目录前端,以减少出现系统挂起的机会,也减轻不必要的网络负载。
为了定制用户自己的命令检索路径,使之能够首先检索系统目录,同时把自己的特定目录及当前工作目录也包括在检索路径中,可在用户初始化文件中增加下列内容:
PATH=$PATH:$HOME/bin:: export PATH
4. 设定语言环境
LANG和LC系列环境变量用于设置特定的语言环境(locale),包括系统提示信息、格式转换、应用惯例和表达方式、字符排序原则,以及日期、时间、货币和数值的输出形式等。
通常,只需设置LANG环境变量,即可确定一个语言环境。实际上,在设置LANG环境变量时,系统也能够连带设置所有的LC系列变量(LC_ALL变量除外),因而能够提供正确的语言环境。同样,设置LC_ALL变量也能同时设置其他LC系列变量,但LANG与LC_ALL两个变量互不影响。此外,也可以单独设置下列LC系列变量,以设置部分语言环境:
· LC_COLLATE(指定字符排序原则)
· LC_CTYPE(指定语言类型,包括字符类型、字符转换与多字节字符的宽度等)
· LC_MESSAGES(指定系统提示信息采用的语言)
· LC_NUMERIC(指定小数点与千分位的表达方式)
· LC_MONETARY(指定货币符号等)
· LC_TIME(指定日期与时间的表示方式)
· LC_ALL(意味着设定上述的所有LC*变量)
Red Hat Enterprise Linux系统采用POSIX格式“xx_YY.CHARSET”定义语言环境,其中,xx是ISO-639标准定义的语言代码,YY是ISO-3166标准定义的国家或地区代码,charset是/usr/share/i18n/locales目录中列举的字符集之一。注意,Red Hat Enterprise Linux系统仅支持Unicode(UTF-8)字符集。
为了利用环境变量设置简体中文语言环境,可以把LANG变量设置为zh_CN.UTF-8或zh_CN.utf8。因此,可在用户初始化文件中增加下列内容:
LANG=zh_CN.UTF-8; export LANG
为了查询Linux系统支持的语言环境,可以运行“locale -a”命令。欲了解当前设定的语言环境,可以运行下列locale命令:
$ locale
LANG=zh_CN.utf8
LC_CTYPE="zh_CN.utf8"
LU_NUMERIC="zh_CN.utf8"
LC_TIME="zh_CN.utf8"
LC_COLLATE="zh_CN.utf8"
LC_MONETORY="zh_CN.utf8"
LC_MESSAGES="zh_CN.utf8"
……
LC_ALL=
$
如果想要在中英文语言环境之间切换,可把环境变量LANG交替地设置成zh_CN.utf8或C。
5. 定制命令提示符
当以命令行方式注册到Linux系统,或在GNOME桌面打开一个终端窗口时,窗口的左边将会出现Shell命令提示符,说明调用的Shell已经就绪,用户可以输入命令。通常,Linux系统的提示符为“[\u@\h \W]\$”。其中,“\u”表示注册的用户名,“\h”表示系统的主机名,“\W”表示当前工作目录最后一个子目录的名字,“\$”表示根据用户的身份显示“$”(普通用户)或“#”(超级用户)命令提示符。
例如,当使用gqxing注册时,其命令提示符如下(为了使命令的输出清晰起见,本书的示例中均省略了方括号及其中的内容,特此说明):
[gqxing@iscas ~]$
Linux系统的命令提示符共分为四级,依次由Shell的内置变量PS1、PS2、PS3和PS4定义。当输入的命令不完整,输入的引号未成对出现,或直接在命令行上输入Shell编程语句时才会用到第二级命令提示符。PS3和PS4分别用于select循环结构和Shell脚本调试。
最常见的命令提示符主要是第一级命令提示符。在Bash中,命令提示符能够给出丰富的提示信息,有助于用户输入命令。对于资深用户来讲,系统默认的命令提示符在提供较多信息的同时,有时也会显得冗长,且容易与命令的输出混杂在一起。为了定制自己的命令提示符,实际上只需参照PS1变量的设置(PS1=‘[\u@\h \W]\$ ’),修改PS1变量的定义,即可达到改变命令提示符的目的。
表3-6中给出了设置Bash命令提示符时可用的部分特殊字符,这些特殊字符可用于显示注册的用户名、系统的主机名或当前的工作目录等信息,用户可根据自己的爱好予以选用。
表3-6 Bash命令提示符中可用的部分特殊字符
但在Korn Shell中,命令提示符只是简单的注释符号“#”或美元符号“$”。为了改变这种单调的命令提示符,也可以简单地修改PS1变量的定义。例如,假定希望命令提示符中能够包含命令序号和当前工作目录,可以采用下列设置方法:
$ PS1='[! `pwd`]$ ' [160 ~]$
当输入了部分命令,或误输入的引号未成对出现而按下Enter键时,Shell将会输出第二级命令提示符(通常为大于号“>”)。出现这一情况时,解决的办法一是继续完成命令的输入,二是利用Ctrl-C组合键终止误输入的命令,使Shell能够继续处理新的命令。为了把默认的第二级命令提示符改为more,可以使用下列命令:
$ PS2='more ? ' $
6. 定义命令别名
命令别名的定义仅在当前的Shell中有效,一旦退出Shell,所有的命令别名定义也将随之消失。为了设置永久性的命令别名,可在$HOME/.profile文件中定义,不管何时注册到Linux系统,随时都可以直接使用。
通常,cp、rm或mv等命令存在误删或覆盖原有同名文件的潜在问题。为了防止此类情况出现,可将下列命令别名加到自己的.profile或.bashrc文件中(为了彻底解决这个问题,也可以由系统管理员一次性地修改/etc/skel目录中的.profile或.bashrc文件,把下列命令别名定义加到其中):
alias rm='rm –i' alias cp='cp –i' alias mv='mv –i'
注意,每当启动Shell时,Shell都会读取并执行.profile文件。如果定义的命令别名过多, Shell的启动过程将会减慢。因此,一般不要定义太多的命令别名。
7. 定制用户初始化文件
这里以Bash为例,说明怎样以标准的用户初始化文件为基础,定制自己的用户初始化文件。
若想定制自己的运行环境,修改Shell的检索路径,使之包含用户主目录及当前目录,设置中文语言环境,以vi/vim作为命令行编辑器等,可以利用任何编辑器,修改.profile,增加下列内容:
PATH=$PATH:$HOME/bin:. LANG=zh_CN.utf8 EDITOR=vi export PATH LANG EDITOR alias r='fc -e -' alias rm='rm –i' alias cp='cp –i' alias mv='mv –i' ……
3.3 增加与删除用户组
为了使相关的用户能够访问共同的资源与服务,Linux系统支持用户组的概念。Linux系统中的每个用户都从属于某个用户组,同组的用户具有相同的用户组访问权限。此外,每个用户还可以临时改换其有效用户组,以便与其他用户组相关联。这种灵活性意味着用户除了可以按照工作性质或所在部门(如产品部或技术支持部)从属于一个主要用户组,还可以根据工作的需要(如项目组),与其他用户组共享数据与访问权限。
在Red Hat Enterprise Linux系统中,最典型的一个例子就是,如果一个用户从属于用户组admin,即可运行sudo命令,执行系统管理与维护方面的系统命令。
在Linux系统中,与用户组有关的所有信息通常均存储在/etc/group系统文件中(参见表3-7)。文件中的每一行定义一个用户组,其语法格式如下:
group_name:password:gid:user_list
表3-7 /etc/group文件
下面是安装Red Hat Enterprise Linux系统之后系统提供的默认用户组信息:
$ cat /etc/group root:x:0:root bin:x:1:root,bin,daemon daemon:x:2:root,bin,daemon sys:x:3:root,bin,adm adm:x:4:root,adm,daemo …… wheel:x:10:root …… gqxing:x:500: $
为了在系统中增加新的用户组,可以手工编辑/etc/group文件,也可以使用groupadd命令。groupadd命令的语法格式如下:
groupadd [-g gid [-o]] group
其中,“-g”选项用于指定新增的用户组ID。如果忽略此选项,默认的用户组ID为已分配的最大ID号加1。例如,如果用户组ID号1000、1005和2000已经分配,则默认的用户组ID为2001。
如果想要增加一个名为banking,用户组ID为2000的用户组,可以使用下列命令:
# groupadd –g 1000 banking #
然后,可以使用grep、cat命令或其他工具验证用户组是否已经加到系统中:
$ grep banking /etc/group banking:x:1000: $
如果想要修改或删除用户组,可以分别使用groupmod和groupdel命令。因为用户组的修改和删除比较简单,故此处不再赘述。在管理和维护用户组时,最简单的方法其实是利用编辑器,手工编辑/etc/group文件。
3.4 监控用户
用户管理的一个重要目的就是保证用户的活动总是处于一个正常的范围之内。如果某个用户正在过度地占用CPU资源,则可以使用nice命令降低用户进程的优先级别。从系统安全的角度考虑,监控用户的活动可能会发现一些未经授权或非正常的用户行为。一旦发现诸如此类的现象,可以采取各种措施,如封锁用户账号等。
3.4.1 利用who命令查询用户
为了查询当前系统中都有哪些用户,这些用户都来自哪里,可以使用who命令。who命令能够输出当前已注册到系统的所有用户,其语法格式如下:
who [-abdHlmpqrstTu] [file]
其中,“-a”选项表示同时选用其他多个选项,从而给出较多的信息。“-H”选项表示在输出数据之上增加一个标题行。“-r”选项用于查询系统当前所处的运行级。如果未指定文件名,表示读取并显示默认的/var/run/utmp文件中的内容,也即当前系统中的用户注册与活动信息。为了查询早期的历史记录,可以使用/var/log/wtmp文件。
who命令的输出数据通常包括下列字段:
NAME LINE TIME [IDLE] [PID] COMMENT [EXIT]
其中,NAME字段表示注册的用户名。LINE字段表示用户使用的终端设备名,TIME字段表示用户注册的起始时间,IDLE字段表示用户自上一个处理活动以来的空闲时间,PID字段表示用户的进程ID,COMMENT字段通常给出用户所在系统的主机名,EXIT字段表示用户的退出状态。
例如,下列信息表明当前系统中只有三个用户,三个用户均来自控制台终端(其中后两个用户是由于打开终端窗口注册的):
$ who
gqxing tty7 2010-12-12 01:47 (:0)
gqxing pts/0 2010-12-12 03:38 (:0.0)
gqxing pts/1 2010-12-12 03:53 (:0.0)
gqxing pts/2 2010-12-12 04:35 (:0.0)
$
如果使用“-H”选项,将会在输出数据之上增加一个标题行,以便了解每一行输出数据的意义,例如:
$ who -H NAME LINE TIME COMMENT gqxing tty7 2010-12-12 01:47 (:0) gqxing pts/0 2010-12-12 03:38 (:0.0) gqxing pts/1 2010-12-12 03:53 (:0.0) gqxing pts/2 2010-12-12 04:35 (:0.0) $
使用“-a”选项可以显示更多的系统与用户活动数据,例如:
$ who -Ha NAME LINE TIME IDLE PID COMMENT EXIT system boot Dec 12 01:20 run-level 5 Dec 12 01:20 LOGIN tty2 Dec 12 01:20 1766 id=2 LOGIN tty3 Dec 12 01:20 1768 id=3 LOGIN tty4 Dec 12 01:20 1770 id=4 LOGIN tty5 Dec 12 01:20 1774 id=5 LOGIN tty6 Dec 12 01:20 1778 id=6 gqxing - tty7 Dec 12 01:47 old 2446 (:0) gqxing + pts/0 Dec 12 03:38 00:03 3687 (:0.0) gqxing + pts/1 Dec 12 03:53 00:25 3687 (:0.0) gqxing + pts/2 Dec 12 04:35 . 3687 (:0.0) $
3.4.2 利用w命令查询用户活动
为了查询系统中现有的注册用户,以及每个用户当前正在做什么等信息,还可以使用w命令。w命令的语法格式如下:
w [-husfVo] [user]
其中,“-h”选项表示禁止输出包括标题的前两行信息。在输出的信息中,USER字段表示注册的用户名,TTY字段表示用户使用的终端设备名,FROM字段表示用户所在系统的名字,“LOGIN@”字段表示用户注册的起始时间,IDLE字段表示空闲时间(从上一次输入命令后至今的持续时间),JCPU字段表示从同一终端设备上运行的所有进程及其子进程使用的整个CPU时间,PCPU字段表示当前进程使用的CPU时间,WHAT字段表示当前进程的命令名及其参数。
如果未加任何选项,w命令的输出信息如下:
$ w
04:39:41 up 3:19, 4 users, load average: 0.01, 0.03, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
gqxing tty7 :0 01:47 3:19m 2:37 0.10s pam: gdm-passwo
gqxing pts/0 :0.0 03:38 6.00s 0.25s 3.87s gnome-terminal
gqxing pts/1 :0.0 03:53 27:06 0.23s 3.87s gnome-terminal
gqxing pts/2 :0.0 04:35 1.00s 0.11s 0.08s w
$
在上述命令输出信息中,第一行信息分别表示当前的系统时间、系统已经运行了多长时间、当前有多少个注册的用户,以及在过去的1分钟、5分钟和15分钟内系统的平均负载。
3.4.3 向注册用户发送消息
Linux系统提供大量的工具供注册的用户之间相互进行实时通信。通常,向注册用户发送日常消息的方法是利用/etc/motd(message of the day)文件。管理人员可以随时修改这个文件,一旦用户注册,即可见到motd文件的内容。
但上述方法仅在用户注册时有效,对于已经注册的用户,则看不到motd文件修改后的内容,除非再次注册。一旦有紧急情况需要通知用户,如因停电或系统故障需要立即停机时,可利用wall(write to all)命令向注册的用户发送紧急通知。例如:
$ wall
This system will shut down for emergency maintenance now.
You have 5 minutes to save your work and log out.
^D
不管用户当前正在做什么,wall命令将会把按下Ctrl-D键之前输入的文字信息立即写到用户的终端窗口中:
Broadcast message from root@iscas (pts/0) (Fri Dec 24 22:40:32 2010) This system will shut down for emergency maintenance now. You have 5 minutes to save your work and log out.
3.5 插件式认证模块
插件式认证模块(Linux Pluggable Authentication Modules,PAM)使系统管理员或应用程序能够决定如何利用通用的认证技术验证用户的身份。PAM提供一个共享模块库(位于/lib/security目录中),当需要认证用户时,应用程序只需调用共享模块库即可实现。位于/etc/pam.d目录中的每个配置文件均包含一组需要调用的模块或模块栈,这些模块决定了每个系统服务的认证处理方法。必要时,PAM也可以使用其他文件,如/etc/passwd,实现用户认证。插件式认证模块意味着用户能够随意增加或从认证栈中删除任何模块。
在应用程序开发过程中,程序员只需充分调用PAM提供的共享认证模块库,不必自己编写认证代码,即可实现用户认证要求。此外,对于给定的应用,系统管理员也能够利用PAM改变认证机制,而无需修改现有的应用。PAM为各种系统服务提供了认证机制,如login、ftp、su和sudo等。用户也可以利用认证栈技术的方法及其灵活性,采用不同的认证机制,组合一定的认证模块,集成一个诸如RSA、DCE或Kerberos的系统认证服务。
从用户注册到执行sudo命令,从执行su命令到关闭系统,无论何时需要用户提供密码验证,系统管理员都可以使用PAM配置认证处理过程,且对使用PAM实现认证的所有系统服务或应用程序而言,其处理过程基本上都是相同的。对于每一个系统服务(或应用程序),存储在/etc/pam.d目录中的配置文件描述了其认证处理过程。这些配置文件通常都有一个与系统服务(或应用程序)相同或类似的名字。例如,login注册认证的配置文件为/etc/pam.d/login。
在认证过程中,如果遇到问题,PAM发出的警告信息将会记录到/var/log/messages或/var/log/secure文件中,如果在修改PAM配置文件后没有达到预期的结果或出现异常,也可以查询这些日志文件,找出问题所在。为了防止图谋不轨的用户看到PAM信息,PAM仅把错误信息写入日志文件而非送到终端屏幕。
3.5.1 配置文件、模块类型与控制标志
PAM采用/etc/pam.conf或/etc/pam.d目录中以各种服务命名的文件作为配置文件,配置文件中的每一行表示PAM需要在认证过程中执行的处理动作。如果/etc/pam.d目录存在,PAM将会忽略/etc/pam.conf配置文件。在/etc/pam.d目录中,每个配置文件的语法格式如下:
type control module-path [module-arguments]
其中,type是认证模块类型标识符,表示当前模块属于哪一种模块类型;control是如何处理认证的控制标志;module-path是PAM模块文件的完整路径名,也可以是针对默认存储位置(/lib/security)的相对路径名;作为认证模块的参数,module-arguments是选用的,如果存在,可以是一个参数或多个由空格分隔的参数表,用于调整给定模块的处理功能。
认证模块类型用于区分不同性质或适用不同处理需求的各种认证模块。当前PAM主要支持account、auth、password及session四种不同类型的认证模块。表3-8给出了各种认证模块的说明。
表3-8 认证模块类型
account认证模块的功能类似于auth认证模块,其主要差别是仅当用户通过认证之后才能调用前者。account认证模块可以作为一种附加的安全检测措施,以便在用户能够访问系统之前再做进一步的限定检测。例如,可以利用account认证模块强制用户只能在上班时间注册到系统等。
session认证模块用于启动和终止一个用户会话。在Linux系统中,一个通用的会话模块是pam_mail,当用户注册到传统字符界面的系统环境时,可以使用这个模块通知用户是否有新的邮件到来。
认证控制标志用于控制怎样进行认证,以及如何处理认证模块返回的认证结果。在PAM配置文件中,可以采用表3-9所示的关键字,设置认证模块的控制标志。
表3-9 认证控制标志
PAM可以使用应用程序要求的各类认证模块,实现用户账号状态检测、会话管理及密码修改等认证方式。PAM可用的认证模块通常均位于/lib/security目录中。
/etc/pam.d目录中的各种配置文件定义了执行用户认证时需要用到的一组认证模块。同一类型的认证模块称做认证栈,PAM将会按照配置文件中的列举顺序,从栈顶开始依次调用每一个认证模块。每个认证模块依次向PAM返回认证成功或失败的结果,根据认证模块的控制标志,再由PAM向调用程序返回整个处理过程的认证结果。
注意,PAM认证的成功与失败只是一种说明性的概念,与Linux系统中的真假概念是完全不同的。
除了采用required、requisite、sufficient及optional等关键字表示控制标志之外,PAM还支持采用下列复杂的语法格式表示的控制标志:
[value1=action1 value2=action2 ...]
其中,valueN相当于认证模块的返回值,如success、ignore、new_authtok_reqd、try_again、abort、bad_item、incomplete和default等。default意味着没有明显定义的其他返回值。
actionN可以是一个整数n(表示下一步处理动作是跳转到认证栈中的第n个模块),也可以是ignore、bad、die、ok、done和reset等。其中,ignore表示当前模块的返回状态不影响整个认证栈的最终认证结果,可以忽略不计。bad表示当前模块的认证失败。如果当前模块是认证栈中的第一个模块,其认证结果可以看做整个认证栈的认证结果。die等同于bad,不同之处是立即终止整个认证栈,返回认证失败。ok表示当前模块的认证可以看做整个认证栈的最终认证结果。注意,如果认证栈中先前模块的认证结果表示失败,这个认证结果不能取代先前的认证结果。done相当于ok,不同之处是立即终止认证栈,返回认证成功。reset表示清除认证栈先前所有模块的认证结果,从下一个模块开始继续认证。
如果采用第二种语法格式,前述的四个关键字required、requisite、sufficient和optional可分别表示如下:
· required [success=ok new_authtok_reqd=ok ignore=ignore default=bad]
· requisite [success=ok new_authtok_reqd=ok ignore=ignore default=die]
· sufficient [success=done new_authtok_reqd=done default=ignore]
· optional [success=ok new_authtok_reqd=ok default=ignore]
下面的login文件是PAM配置文件的一个实例(采用grep命令的目的是剔除以注释符“#”为起始字符的注释行),主要用于处理用户的系统注册过程:
$ grep '^[^#]' /etc/pam.d/login auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so auth include system-auth account required pam_nologin.so account include system-auth password include system-auth session required pam_selinux.so close session required pam_loginuid.so session optional pam_console.so session required pam_selinux.so open session required pam_namespace.so session optional pam_keyinit.so force revoke session include system-auth -session optional pam_ck_connector.so $
在上述配置文件中,每一行的第一个字段是模块类型标识符,如auth及session等。第二个字段是控制标志,表示一旦认证失败时PAM应采取的处理动作。从第三个字段开始是PAM模块文件(位于/lib/security目录)的相对路径名或选用的参数。PAM模块库利用/etc/pam.d目录中的配置文件确定由哪一些模块负责相应的认证处理。以“@include”为起始字符串的文本行表示在相应的位置插入指定的文件。
现以上述的/etc/pam.d/login配置文件为例,说明用户注册的认证过程。我们知道,注册过程是由login程序引导用户输入用户名和密码实现用户认证的。login命令首先提示用户输入一个用户名,然后调用PAM,依次启动一系列认证模块,开始用户的认证过程:
(1)按照login文件列举的顺序,PAM首先调用pam_securetty模块,确保超级用户只能从指定的终端(如控制台)注册。若想保证整个认证结果的成功,必须确保pam_securetty模块的认证结果是成功的。在这一认证过程中,仅当有人试图从禁用的终端中以超级用户的身份注册,pam_securetty模块才会报告失败。如果接受认证的用户并非超级用户,或者即使是超级用户,但用户是从允许使用的终端注册的,pam_securetty模块仍会报告认证成功。
(2)include引入的common-auth文件含有pam_env、pam_unix和pam_limits等模块。其中pam_env模块用于设置环境变量。除非使用envfile和readenv参数指定了其他文件,默认的变量设置取自/etc/security/pam_env.conf配置文件,同时也利用/etc/environment文件设置环境变量。“readenv=1”是一个控制开关,表示是否允许(0表示禁止,1表示允许)使用envfile参数指定的文件设置环境变量。“envfile=/etc/default/locale”表示使用/etc/default/locale文件替换默认的变量设置。当不同的服务需要不同的变量设置时,envfile参数是非常有用的。
(3)pam_unix模块是一种传统的UNIX认证方式,主要采用/etc/passwd和/etc/shadow文件认证用户名与密码。
(4)pam_limits模块用于设置用户在会话期间的系统资源限制。通常,默认的系统资源限制取自/etc/security/limits.conf配置文件。/etc/security/limits.d目录中的文件可以用做进一步的修正。
(5)采用pam_nologin认证模块时,如果/etc/nologin文件存在,系统只允许超级用户root注册,而禁止任何普通用户注册。一旦普通用户尝试注册,系统将会显示nologin文件的内容,说明禁止注册的原因。也就是说,仅当nologin文件不存在,或当前注册的用户是root, pam_nologin模块才能报告认证成功。
(6)两个pam_selinux模块主要用于建立用户映射关系,设置SELinux安全环境等。
(7)pam_loginuid模块用于记录注册用户的UID。
(8)pam_console模块用于确认用户是否占用系统控制台,从而设置相应的访问权限。
(9)pam_keyinit模块用于维护用户会话期间的账号与密码等信息。
3.5.2 修改PAM配置文件
有些UNIX或Linux系统要求用户必须是wheel用户组中的成员,才能使用su命令。尽管Red Hat Enterprise Linux系统并未采用这种配置方法,但通过编辑/etc/pam.d/su文件,仍可利用PAM达到此目的。下面是系统提供的原始文件:
$ cat /etc/pam.d/su #%PAM-1.0 auth sufficient pam_rootok.so # Uncomment the following line to implicitly trust users in the "wheel" group. #auth sufficient pam_wheel.so trust use_uid # Uncomment the following line to require a user to be in the "wheel" group. #auth required pam_wheel.so use_uid auth include system-auth account sufficient pam_succeed_if.so uid = 0 use_uid quiet account include system-auth password include system-auth session include system-auth session optional pam_xauth.so $
上述的“#auth required pam_wheel.so use_uid”一行前面存在一个注释符“#”。如果删除注释符,意味着只有wheel用户组的成员才能使用su命令(其认证控制标志为required),禁止普通用户利用su命令获取超级用户的访问权限。此外,如果删除“#auth sufficient pam_wheel.so trust use_uid”一行前面的注释符“#”,表示wheel用户组的成员在运行su命令时也不必提供密码(其认证控制标志为sufficient)。
注意,除非确实了解怎样配置PAM,一般不要轻易修改/etc/pam.d目录中的文件。修改PAM配置文件的错误,有可能导致用户无法正常访问系统。为避免此类问题,在修改之前应事先备份PAM配置文件,同时打开一个新的终端窗口,进入超级用户的Shell环境。然后再仔细测试修改后的配置文件,确保能够正常注册,新的设置能够达到预期的目的。如果出现错误,可以在打开的超级用户终端窗口,利用备份的配置文件恢复修改有误的文件。
3.6 超级用户与sudo命令
超级用户root拥有无限的权利,在长时间的系统访问过程中,如果运用不当,或在无意中出现失误,有可能损坏系统,如破坏文件系统等,严重时甚至可能引起系统瘫痪。有些系统特权命令还可能会侵犯用户的隐私,或危及系统的安全。因此,为了确保系统能够安全地正常运行,Red Hat Enterprise Linux系统通常不建议用户使用超级用户root直接注册系统,在整个会话过程中,一直以超级用户的身份和权限访问系统,直至退出系统。当需要以超级用户root的身份和权限运行特权命令,执行系统管理与维护任务时,Red Hat Enterprise Linux系统至少提供下列两种途径或方法,使用户能够获得超级用户的访问权限:
· 利用sudo命令临时获取超级用户的访问权限,执行系统管理与维护等特权命令,运行结束之后,立即恢复用户本来的身份及访问权限。但是,Red Hat Enterprise Linux系统只允许授权的用户运行sudo命令。
· 利用su或“sudo -i”命令进入超级用户的Shell运行环境,可以在较长的时间内,以超级用户的身份和权限访问系统,直至运行exit命令或按Ctrl-D组合键退出。
3.6.1 超级用户的访问控制
利用/etc/securetty和/etc/security/access.conf等配置文件,PAM能够控制或限定哪些用户,何时以及如何以超级用户root的身份注册到系统。例如,/etc/securetty文件用于控制用户能够从哪些网络或终端上,以超级用户root的身份注册,/etc/security/access.conf文件又进一步增加了用户与注册方式的组合控制措施。
禁止用户以超级用户root的身份从网上注册是Linux系统采取的一项默认的安全策略,这一安全措施就是利用PAM安全模块与/etc/security/access.conf文件实现的。access.conf配置文件包含允许以超级用户root身份注册的所有用户以及网络与终端访问方式。在初始安装Red Hat Enterprise Linux系统之后,这个文件中均为注释行,表示禁止任何用户在网络上以超级用户root的身份注册访问。
/etc/security/access.conf配置文件可以看做一个注册访问控制表,用于指定系统接受或拒绝注册的用户及其注册方式(如通过TTY设备、主机或网络等方式访问系统)。当用户注册到系统时,系统将会扫描这个文件,找出第一个匹配的“用户/TTY设备”、“用户/主机”或“用户/网络”组合,根据其中的访问权限定义,可以确定究竟是接受还是拒绝用户的注册。access.conf文件的每一行由三个字段组成,中间以冒号“:”作为分隔符,其语法格式如下:
permission:users:origins
其中,permission字段可以是一个加号“+”(表示允许相应的用户注册)或减号“-”(表示拒绝相应的用户注册)。users字段是一个或多个注册的用户名、用户组名或ALL(表示可以匹配任何用户或用户组)。origins字段可以是一个或多个TTY设备名(表示非网络连接的注册)、主机名、域名(最前面需增加一个句点“.”前缀)、主机IP地址、网络号(最后面需附加一个句点“.”后缀)、网络地址加子网掩码(子网掩码可以是一个十进制的数值或IP地址)、ALL(表示匹配任何设备)或LOCAL(表示匹配不包含句点“.”的任何字符串)。
例如,下面的例子表示允许超级用户root通过X终端“:0”与pts/0~pts/6等终端设备注册访问系统:
+ : root : :0 pts/0 pts/1 pts/2 pts/3 pts/4 pts/5 pts/6
下面的例子表示用户能够从指定IP地址(192.168.90.1、192.168.90.2和192.168.90.6)的主机,以及本地系统(127.0.0.1)中,以超级用户root的身份注册访问系统:
+ : root : 192.168.90.1 192.168.90.2 192.168.90.6 + : root : 127.0.0.1
下面的例子表示,除了采用sudo或su命令获取超级用户访问权限的途径之外,禁止超级用户root以任何方式直接注册访问系统:
- : root : ALL
注意,利用OpenSSH,用户仍然能够以超级用户root的身份从网上注册。这是因为在Linux系统中,ssh并不受securetty安全模块或access.conf文件的限制。例如,在/etc/ssh/sshd_config文件中,如果把PermitRootLogin设置为yes,仍然能够利用ssh,以超级用户root的身份从网上注册。
3.6.2 利用sudo运行特权命令
传统上,用户大多喜欢采用超级用户root直接注册到系统,或使用su命令获取超级用户的访问权限。出于系统安全的考虑,建议赋予部分用户利用sudo命令运行特权命令,处理部分系统管理与维护任务,如安装移动存储介质的文件系统等。Red Hat Enterprise Linux系统提供的sudo命令及其相关机制,可以替代传统的超级用户权限获取方法。利用sudo命令,可以像利用root注册成为超级用户一样,在命令行界面中运行任何系统管理方面的特权命令。sudo命令的语法格式简写如下:
sudo [-b] [-u user] command sudo [-ikLls]
其中,“-b”选项表示以后台方式运行指定的命令;“-u”选项表示使用指定用户的身份和权限执行指定的命令,如果未加此选项,sudo将会以超级用户的身份和权限运行当前的命令;command可以是准备执行的任何命令或Shell脚本。“-i”选项表示调用超级用户root的注册Shell,运行其初始化文件(如.profile),在超级用户的Shell环境中访问系统;“-k”选项表示重新设置sudo命令的时戳,这意味着,当再次运行sudo命令时,必须重新输入sudo密码;“-L”选项用于显示当前用户在/etc/sudoers文件Defaults一行中能够设置的参数;“-l”选项用于显示当前用户在本地系统中能够利用sudo运行的命令;“-s”选项表示调用超级用户的注册Shell(类似于“-i” 选项,但不改变现有的运行环境)。
当需要以超级用户的身份和权限运行特权命令,执行系统管理与维护任务时,可在命令行界面中使用sudo命令,即在实际运行的命令前面增加一个sudo前缀,当提示用户输入密码时,输入sudo密码。密码通常会保存15分钟,在此期间,如果再次运行sudo命令,则无需提供密码。超过此限,需要重新输入密码。sudo命令将会影响同一命令行上的所有命令,直至遇到换行符或另一个sudo命令。
注意,并非任何用户都能运行sudo命令,只有/etc/sudoers配置文件授权的用户才能利用sudo命令运行特权命令。下面是系统提供的sudoers原始文件:
# cat /etc/sudoers …… ## Allow root to run any commands anywhere root ALL=(ALL) ALL ## Allows members of the 'sys' group to run networking, software, ## service management apps and more. # %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS ## Allows people in group wheel to run all commands # %wheel ALL=(ALL) ALL ## Same thing without a password # %wheel ALL=(ALL) NOPASSWD: ALL ## Allows members of the users group to mount and unmount the ## cdrom as root # %users ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom ## Allows members of the users group to shutdown this system # %users localhost=/sbin/shutdown -h now #
按照上述配置,只有超级用户root才能使用sudo命令,而这是多此一举,实际上没有任何意义。如果删除“%wheel ALL=(ALL) ALL”一行前面的注释符“#”,意味着用户组wheel中的任何成员均可利用sudo命令获取超级用户的访问权限,运行系统管理与维护方面的特权命令。
在“%wheel ALL=(ALL) ALL”的用户权限定义中,“%wheel”表示用户组wheel,等号“=”左边的ALL表示这个权限定义适用于所有主机系统,中间和最后一个ALL表示wheel用户组的所有成员都能够以任何用户的身份运行任何命令,尤其能够利用sudo命令,以超级用户的身份和权限运行任何特权命令。如此一来,就不必总是使用超级用户root注册,指定的普通用户也可以利用sudo命令执行系统维护任务。
作为wheel用户组中的任何一个成员,第一次运行sudo命令时,sudo通常会提示用户输入密码(注意,此时不要输入超级用户root的密码),如果输入的密码是正确的,sudo命令将会开始计时,如果在15分钟之内继续运行sudo命令,sudo不会再提示用户输入密码。
下面的例子表示,普通用户gqxing无权直接使用date命令设置系统时钟:
$ date 122218502010 date: cannot set date: Operation not permitted Wed Dec 22 18:50:00 CST 2010 $
但如果修改/etc/group文件,把用户gqxing设为wheel用户组的成员,便可利用sudo运行date命令,设置系统时钟时,sudo命令在收到正确的密码后,便能确保用户成功地执行date命令:
$ sudo date 122218502010 [sudo] password for gqxing: Wed Dec 22 18:50:00 CST 2010 $
使用“-l”选项运行sudo命令时,可以查询当前用户能够利用sudo命令运行哪些命令。由于gqxing也是wheel用户组中的一个成员,故能够以任何用户(包括超级用户)的身份运行任何命令(包括特权命令):
$ sudo -l Matching Defaults entries for gqxing on this host: requiretty, always_set_home, env_reset, …… User gqxing may run the following commands on this host: (ALL) ALL $
当有若干特权命令需要以超级用户的身份和权限运行时,最简单的方法是启动一个超级用户的Shell运行环境,直至运行完所有的特权命令之后,再利用exit命令或按下Ctrl-D组合键,退出超级用户的Shell环境,而无需在每次执行特权命令时都输入一个sudo命令前缀。为此,可以使用带有“-i”选项的sudo命令:
$ sudo -i [sudo] password for gqxing: # id uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),…… # pwd /root # exit logout $
在上述情况下,调用“sudo -i”命令将会进入超级用户的运行环境。如果仅想拥有超级用户的访问权限,而保持用户当前的运行环境不变,可以使用“sudo -s”命令:
$ sudo -s # id uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),…… # pwd /home/gqxing # exit exit $
3.6.3 sudoers配置文件
在Linux系统中,根据/etc/sudoers配置文件的设置,确定是否赋予用户利用sudo命令运行特权命令的权限。sudoers配置文件的初始设置不一定完全能够适应用户的实际需求,有时可能需要调整其配置。若想修改sudoers文件,最好的方法是采用专用的编辑程序visudo:
# visudo
visudo编辑程序能够提供加锁、编辑以及语法检测等功能。通常,visudo主要调用vim编辑器修改sudoers文件。通过设置VISUAL环境变量,用户也可以使用自己熟悉的编辑器,如emacs,编辑sudoers文件:
# export VISUAL=emacs
注意,如果直接使用vi/vim等文本编辑器修改/etc/sudoers文件,当出现语法错误时,可能会导致用户无法利用sudo命令获得超级用户的访问权限。因此,强烈建议用户使用visudo命令修改sudoers文件。visudo程序能够检测语法错误。一旦出现错误,visudo不会允许用户轻易写入sudoers文件,且提供一个修正错误的机会:或者重新编辑,或者放弃修改而退出,最后一个选择是强制保存修改(这是一个比较危险的选择,visudo标记为DANGER!)。
/etc/sudoers文件含有两种类型的信息:用户别名与用户权限规范的定义,每个定义占用一行。通过增加反斜杠“\”后缀,也可以延续到后续行。此外,以注释符“#”为起始字符的行是注释行,注释行可以出现在任何位置。
1.用户权限规范
在/etc/sudoers文件中,定义用户权限规范的语法格式如下(等号“=”前后的空格可有可无):
user_list host_list = [(runas_list)] [tag_list] command_list
在用户权限规范的语法格式中,每个字段的意义及用途说明如下:
· user_list —— 用于指定单个或一组用户,表示当前定义的权限适用的用户对象。指定用户时可以采用用户名、用户组(增加一个百分号“%”前缀)和用户别名。此外,还可以使用内部定义的别名ALL,表示所有的用户,意味着当前的权限定义适用于所有的用户。
· host_list —— 用于指定当前的权限定义施加的主机对象。主机对象可以是一个或多个主机名、IP地址或主机别名。此外,还可以使用内部定义的别名ALL,表示所有的主机系统,意味着当前的权限定义适用于含有此sudoers文件的所有系统。
· runas_list —— 类似于user_list,用于指定单个或一组用户,两者唯一的差别是指定runas_list时可以采用用户ID。当使用“-u”选项调用sudo命令时,command_list中定义的命令能够以这里指定的用户身份运行(同样,指定的用户可以是用户名、加百分号“%”前缀的用户组名和用户别名)。runas_list是选用的,如果省略了runas_list,意味着sudo以超级用户root的身份运行command_list中指定的命令。
· tag_list —— 针对某些特殊命令的设置或限定。例如,使用PASSWD和NOPASSWD可以限定用户执行某些管理和维护命令时是否需要提供密码,使用NOEXEC能够防止任何程序启动新的Shell(因为一旦能够使用sudo命令运行某个程序,程序在整个运行期间都会拥有超级用户的访问权限,因而也能够启动拥有超级用户特权的Shell,最终绕过sudoers文件设定的任何限制)。
· command_list —— 指定权限定义适用的实用程序。指定实用程序时可以采用程序的名字、存有实用程序的目录名和命令别名,而且所有的文件名或目录名必须是绝对路径名。
如果命令后面附加一个空的双引号,表示用户不能在运行时指定任何命令行参数和选项。此外,也可以在命令后面指定固定的参数或通配符,限制用户能够使用的参数。
例如,下列用户权限规范使用户cathy能够在含有此sudoers文件的所有系统(ALL)中使用sudo运行mount和umount命令,安装和卸载文件系统:
cathy ALL=(root) /bin/mount, /bin/umount
在下面的例子中,cathy用户可以利用sudo命令,在命令行中使用umount命令卸载/paper文件系统:
$ umount /paper umount: /mnt is not in the fstab (and you are not root) $ sudo umount /paper [sudo] password for cathy: $
如果把上述用户权限规范改写如下,则意味着禁止用户hwang卸载/paper文件系统,但可以使用mount和umount命令安装或卸载其他任何文件系统:
hwang ALL=(root) /bin/mount, /bin/umount, !/bin/umount /paper
在此情况下,当用户hwang使用sudo运行下列mount命令时,将会遭到拒绝:
$ sudo umount /paper [sudo] password for hwang: hwang is not in the sudoers file. This incident will be reported. $
在用户权限规范定义中,runas_list是选用的,如果省略了runas_list,意味着普通用户能够利用sudo命令,以超级用户root的身份运行用户权限规范中定义的命令。例如,sudoers文件中的下列定义表示用户组users中的任何成员均可作为超级用户root,运行指定的CD/DVD安装与卸载命令:
## Allows members of the users group to mount and unmount the ## cdrom as root %users ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom
2.别名
别名机制用于定义或组合一组用户、主机或命令等,以便在sudoers文件中引用,其语法格式如下:
alias_type alias_name = alias_list
其中,alias_type用于定义不同类型的别名,如User_Alias、Runas_Alias、Host_Alias以及Cmnd_Alias等;alias_name是一个便于引用的别名,按照惯例,别名通常均采用大写字母命名;alias_list是由一个或多个名字(如用户名、主机名和命令等)组成的名字列表,列举的名字之间需加空格或逗号“,”分隔符。别名定义中也可以嵌套其他别名,例如,在指定用户时可以使用先前定义的用户别名。系统提供一个内部定义的别名ALL,可以匹配其所在位置的任何对象,包括用户名或系统等。例如,如果在用户名位置使用ALL,意味着匹配所有的用户。如果某个名字前面加有感叹号“!”前缀,意味着取其反义。
· User_Alias —— 用于定义用户别名,以便引用一组限定的用户。指定的用户可以是单个用户名或用户组(用户组名字前面需加一个百分号“%”前缀,如%admin,表示用户组admin的所有成员)等。下面的例子表示sudoers文件定义了三个用户别名:OFFICE、ADMIN和ADMIN2。用户别名OFFICE包括cathy、hwang和wzhang三个用户;用户别名ADMIN包括wzeng、qchen以及admin用户组的所有成员;用户别名ADMIN2包括除dzhao之外的所有admin用户组成员。
User_Alias OFFICE = cathy, hwang, wzhang User_Alias ADMIN = wzeng, qchen, %admin User_Alias ADMIN2 = %admin, !dzhao
· Runas_Alias —— 也用于定义用户别名,以便指定的用户能够以超级用户之外的其他用户身份运行指定的命令。下面定义的用户别名GUEST表示用户能够以guest或visitor的用户身份运行指定的命令:
Runas_Alias GUEST = guest, visitor
· Host_Alias —— 用于定义主机别名,以便引用一组限定的主机。仅当在多个主机上运行的sudo命令引用的是同一sudoers文件时,主机别名才有意义。如果想要采用规范域名,如iscas.abc.net,而非iscas,必须设置fqdn标志。注意,在定义主机别名时采用规范域名会影响sudo命令的运行效率。下面定义的主机别名TESTING包括iscas与sinosoft两个主机系统:
Host_Alias TESTING = iscas, sinosoft
· Cmnd_Alias —— 用于设置命令别名,以便引用一组限定的命令。下列命令别名定义了三个命令文件和一个目录(其后面附有一个斜杠字符“/”,表示目录中的所有命令文件):
Cmnd_Alias BASIC = /bin/cat, /usr/bin/vim, /bin/df, /usr/local/bin/
下面的例子说明了怎样使用别名。在使用sudo命令运行shutdown、halt或poweroff等命令关闭系统时,通常需要提供sudo密码。为了避免总是输入密码,可以定义下列命令别名:
Cmnd_Alias SHUTDOWN_CMDS = /sbin/shutdown, /sbin/halt, /sbin/poweroff
然后,在sudoers文件中增加下列用户权限规范定义即可:
%wheel ALL=(ALL) NOPASSWD: SHUTDOWN_CMDS
此外,还可以彻底禁止运行sudo命令时提示用户输入密码。如前所述,第一次使用sudo命令时,用户必须提供密码,才能运行随后的系统管理与维护命令。密码的有效持续时间是15分钟,如果超过此限,再次使用sudo命令时仍需要提供密码。为了继续使用sudo命令获取超级用户的访问权限,但禁止sudo命令提示用户输入密码,可以编辑sudoers文件,在文件的后面增加下列配置:
user_or_group_name ALL=NOPASSWD: ALL
例如,下述设置表示,用户gqxing任何时间运行sudo命令时,均不需要提供密码:
gqxing ALL=NOPASSWD: ALL
下述设置表示,wheel用户组中的任何成员在任何时间运行sudo命令,均不需要提供密码(参见sudoers文件):
## Same thing without a password %wheel ALL=(ALL) NOPASSWD: ALL
3.默认值
利用关键字Defaults,可以修改配置选项的默认值。在sudoers文件中,大多数配置选项的值都是布尔值on或off,部分配置选项的值可以是一个字符串。在一个Defaults定义行中,增加一个配置选项表示启用相应的标志,如果在配置选项前增加一个感叹号“!”前缀则意味着关闭相应的标志。例如,sudoers初始文件中的下列Defaults定义行表示启用env_reset标志:
Defaults env_reset
下面是部分常用的配置选项及其默认值(完整的说明可以查阅sudoers手册):
· fqdn=on/off —— 如果想在sudoers文件中使用规范域名,应当启用这个标志,以便能够调用DNS服务器实现主机域名解析。在此情况下,可以混合使用简单的主机名或规范域名。采用规范域名的缺点是影响sudo运行的性能,尤其是当DNS系统工作不正常时。一旦设置这个标志,必须引用主机的实际域名,而不能使用CNAME记录定义的别名。注意,如果hostname命令返回的是规范域名,不需要设置这个标志。这个标志的默认值是on。
· passwd_tries=num —— 设置允许用户尝试输入密码的次数。当用户输入的密码不正确时,sudo允许用户尝试输入其他密码,超过此限,sudo不会再提示用户,并立即退出。默认值是3。
· rootpw=on/off ——设置这个标志之后,当调用的sudo命令提示用户输入密码时,只能输入超级用户root的密码。由于sudo命令输出的提示信息完全相同,启用这个标志后可能会给用户造成混淆。此外,如果超级用户root没有解锁(即未设置密码),不要启用这个标志,否则无法运行sudo命令。一旦出现此类问题,可以把系统引导至恢复模式,然后关闭这个标志。这个标志的默认值为off,意味着sudo提示的是安装系统时创建的第一个用户的密码。如果rootpw设置为on,且已经为超级用户root设置了密码,当调用要求提供密码的图形界面程序时,也需要提供超级用户root的密码。
· shell_noargs=on/off —— 如果设置了这个标志,当未加任何参数调用sudo命令时,系统将会调用超级用户root的Shell,但不改变当前的运行环境,其效果等同于使用“-s”选项调用sudo命令。这个标志的默认值是off。
· timestamp_timeout=mins —— 用于设置sudo命令密码保持有效的最小时间长度(分钟数)。这个时效的默认值是15。如果把这个值设置为-1,表示密码的时效没有限制。
3.6.4 以其他用户身份访问系统
总是使用sudo运行特权命令也并非最佳选择。在一个多用户的共享系统中,尤其是在一个集中管理的服务器中,使用sudo命令可能比使用su命令更安全一些。但在一个单用户的个人系统中,经常使用sudo命令与审慎地使用su命令并没有太大的差别。作为一个UNIX/Linux系统的资深用户,如果不习惯或根本就不喜欢使用sudo命令,最简单易行的方法就是解除超级用户账号的封锁,以便随时能够使用su命令,获取超级用户的访问权限,甚至进入超级用户的Shell运行环境。
su(substitute user)命令的主要功能是改变用户的身份,使普通用户能够成为超级用户,当然也可以变身为其他普通用户。利用su命令,能够以指定的用户或超级用户root(默认值)的身份和权限,调用新的注册Shell,在新的运行环境中访问系统。通过运行exit命令或按下Ctrl-D键,可以返回先前的Shell工作环境。当然,这样做的前提是需要知道超级用户root或其他用户的密码。
单独运行su命令而不加任何选项与参数时,系统将会调用具有超级用户权限的Shell,进入超级用户的Shell工作环境,改变当前用户的有效用户ID与用户组ID,但会保持先前的工作目录不变。下面的例子说明了用户cathy使用su命令前后的环境变化情况:
$ id uid=501(cathy) gid=501(cathy) groups=501(cathy) …… $ echo $PATH /usr/lib/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin :/sbin:/home/cathy/bin $ pwd /home/cathy $ su Password: # id uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm), 6(disk),10(wheel) …… # echo $PATH /usr/lib/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin :/sbin:/home/cathy/bin # pwd /home/cathy #
当以“su -”、“su -l”或“su --login”形式运行su命令时,可以启用超级用户的Shell工作环境,直接进入超级用户的主目录,如同使用root注册一样。不仅是用户ID与用户组ID,整个运行环境也完全等同于超级用户root的运行环境。下面的例子说明了用户gqxing使用“su -”命令前后的环境变化情况:
$ id uid=500(gqxing) gid=500(gqxing) groups=500(gqxing) …… $ echo $PATH /usr/lib/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin :/sbin:/home/gqxing/bin # pwd /home/gqxing $ su - Password: # id uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm), 6(disk),10(wheel) …… # echo $PATH /usr/lib/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/u sr/bin:/root/bin # pwd /root #
使用“-c”选项运行su命令时,普通用户能够以超级用户的身份及其访问权限执行特权命令,在命令运行结束后,立即返回原来的Shell工作环境。下面的例子表示普通用户无法使用kill命令终止一个进程,但当使用“su -c”命令并提供超级用户的密码之后,即可正常执行kill命令(注意,“-c”选项后面的同令、选项及其参数前后需要加双引号):
$ kill -15 1670 bash: kill: (1670) - Operation not permitted $ su -c "kill -15 5575" Password: $