Linux的用户与管理
很久以来,我对Linux用户的概念都很模糊,只知道如果碰到“Permission Denied”就用sudo来执行,甚至在服务器上跑的很多东西都是用root来跑的。今天花时间学习了一下Linux用户有关的知识,记一下笔记。
本文所有代码都是在virtualbox虚拟机中进行,环境:Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-87-generic x86_64),用户名vagrant,密码vagrant。
一、用户与用户组
1.Linux是如何分辨每一个用户的
Linux并不是通过用户名来分辨每一个用户的,而是通过UID(计算机认识数字比较容易,而人类认识单词比较容易),我们平时所说的用户名只是便于人类操作和记忆。
1
2
3
4
5
|
vagrant@saltmaster:~$ ls -l
total 256
-rw-r--r-- 1 root root 256191 Nov 13 06:26 bootstrap-salt.sh
-rw-rw-r-- 1 vagrant vagrant 0 Nov 26 08:44 filea
-rw-r--r-- 1 root root 100 Nov 20 06:30 nettools.sls
|
对于每个文件,记录的其实是一个UID,之所以显示成用户名“vagrant”、“root”,是因为在/etc/passwd
中存储了有关的用户信息,ls程序在显示的时候,会根据此文件将对应的UID显示成用户名。如果我们在/etc/passwd
这个文件中将UID修改,那么ls将显示的是一个UID,而不是用户名。
用户登录Linux的流程如下:
-
寻找
/etc/passwd
是否有这个用户名,如果有,读出对象的UID和GID(group ID),以及主目录和配置 -
读取
/etc/shadow
,核对密码 -
进入shell
2. passwd文件和shadow文件
Linux所有的用户都保存在/etc/passwd
文件中,格式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
vagrant@saltmaster:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
|
每一行代表一个账户,通过:
来分割信息。数一数会发现一共有7个字段,这7个字段分别代表:
-
账户名称
-
密码,可以看到所有的密码都是
x
,这是因为很多程序会读/etc/passwd
,将用户名和密码放在一起很不安全,后来密码移动到/etc/shadow
文件中了,/etc/passwd
文件只留一个x占位。 -
UID
-
GID
-
用户信息说明
-
主目录(即登录之后立即所在的位置)
-
shell 登录之后启动的shell,这里有一个特殊的shell就是
nologin
,上面的例子中,像是backup
这种账户是无法登录shell的。所以当我们新建一些系统服务的账号,类似apache,Jenkins等都可以让它们不要登录系统
/etc/shadow
文件的格式如下:
1
2
3
4
5
6
|
vagrant@saltmaster:~$ clear
vagrant@saltmaster:~$ sudo head -n 4 /etc/shadow
root:!:17466:0:99999:7:::
daemon:*:17379:0:99999:7:::
bin:*:17379:0:99999:7:::
sys:*:17379:0:99999:7:::
|
可以看到,这也是用:
来分割的,一共有9列,每一列代表的意思如下:
-
账户名称
-
密码
-
最近改动密码的日期(相对于第0天,也就是1970年1月1日的偏移天数)
-
密码不可改动的日期,如果是0则可以随时修改
-
密码需要重新更改的日期,如果不改账户将会变为过期。可以看到默认设置是99999=273年
-
字段5前几天进行提醒
-
密码过期后的宽限时间,字段5+本字段天数之后依然没有更改才算过期。宽限时间内用户登录会被强制要求修改密码
-
账户失效日期,到期无法使用
-
保留字段
3.有效用户组与初始用户组
每一个用户都有一个用户组,和UID一样,Linux分辨用户组也是通过GID的,而不是通过名字。和/etc/passwd
/etc/shadow
一样,对于用户组有 /etc/group
/etc/gshadow
。
先来看/etc/group
:
1
2
3
4
5
|
vagrant@saltmaster:~$ sudo head -n 4 /etc/group
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
|
一共四个字段:
-
用户组名字
-
用户组密码,其实很少用,和passwd一样,用x占位了
-
GID
-
此用户组的用户列表,逗号分搁,没有空格(一个用户组可以有多个用户,一个用户可以在多个用户组)
/etc/gshadow
的内容几乎和/etc/group
一样:
1
2
3
4
5
6
|
vagrant@saltmaster:~$ sudo head -n 4 /etc/gshadow
root:*::
daemon:*::
bin:*::
sys:*::
systemd-timesync:!::
|
要注意的事第二个字段,是密码,如果第二个字段是!
,表明该用户组没有用户组管理员。不过由于sudo
的存在,其实用户组管理员的功能很少使用了。
-
用户组名字
-
密码列
-
用户组管理员的账号
-
该用户组的所属账号
仔细观察你可能发现这样一个问题:在/etc/passwd
里面说某一个用户的用户组ID是a,但是在/etc/group
的a用户组ID下并没有看到这个账户的名字啊?
这是因为,passwd里面的用户组叫做“初始化用户组”,就是你登录到shell的用户组。这个用户组不需要写到groups里面。
如果一个用户属于很多用户组,这么这些用户组的权限,该用户都会有。那么创建一个文件,默认的用户组应该是哪个呢?
答案是“有效用户组”,通过groups
命令,可以查看当前用户的所在用户组,其中,排在第一个的是有效用户组,如果创建文件就会模式使用这个用户组。
下面的命令演示了有效用户组以及用户组的切换:
1
2
3
4
5
6
7
8
|
vagrant@saltmaster:~$ groups
adm cdrom sudo dip plugdev lxd lpadmin sambashare vagrant
vagrant@saltmaster:~$ touch test_a
vagrant@saltmaster:~$ newgrp sudo
vagrant@saltmaster:~$ touch test_b
vagrant@saltmaster:~$ ll test_*
-rw-rw-r-- 1 vagrant adm 0 Nov 26 15:46 test_a
-rw-rw-r-- 1 vagrant sudo 0 Nov 26 15:47 test_b
|
需要注意的是,newgrp
是通过新开一个shell来赋予用户新的用户组的权限,通过exit
可以回到之前的用户组。
1
2
3
4
5
6
7
|
vagrant@saltmaster:~$ exit
exit
vagrant@saltmaster:~$ touch test_c
vagrant@saltmaster:~$ ll test_*
-rw-rw-r-- 1 vagrant adm 0 Nov 26 15:46 test_a
-rw-rw-r-- 1 vagrant sudo 0 Nov 26 15:47 test_b
-rw-rw-r-- 1 vagrant adm 0 Nov 26 15:48 test_c
|
二、创建与管理用户
1.useradd
了解了用户和用户组的概念,接下来开始讲用户的管理。
创建一个新的账户的命令是useradd
,执行这个命令需要读写/etc/passwd
等文件,所以一般需要root账户来执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
vagrant@saltmaster:/home$ useradd tom
useradd: Permission denied.
useradd: cannot lock /etc/passwd; try again later.
vagrant@saltmaster:/home$ sudo -s
root@saltmaster:/home# useradd tom
root@saltmaster:/home# ls
vagrant
root@saltmaster:/home# grep tom /etc/passwd /etc/shadow /etc/group
/etc/passwd:tom:x:1001:1001::/home/tom:
/etc/shadow:tom:!:17496:0:99999:7:::
/etc/group:tom:x:1001:
root@saltmaster:/home# ls
vagrant
root@saltmaster:/home# su - tom
No directory, logging in with HOME=/
$ pwd
/
$ touch tom_file
touch: cannot touch 'tom_file': Permission denied
|
上面的代码新建了一个tom账户,可以看到,系统并没有默认为tom创建一个home目录。在CentOS中,使用useradd
,系统一般会默认帮你做这几件事:
-
在
/etc/passwd
中创建一行与账号相关的数据 -
在
/etc/shadow
创建相关数据,但是密码为空 -
在
/etc/group
创建一个与用户名一模一样的名称 -
在
/home
下创建一个和用户名一样的目录,权限700
我们简单的使用useradd
命令,Linux会帮我们自动配置一些参数,这些参数是参考的哪里呢?见下面两条命令的输出就明白了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
vagrant@saltmaster:~$ useradd -D
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/sh
SKEL=/etc/skel
CREATE_MAIL_SPOOL=no
vagrant@saltmaster:~$ cat /etc/default/useradd
# Default values for useradd(8)
#
# The SHELL variable specifies the default login shell on your
# system.
# Similar to DHSELL in adduser. However, we use "sh" here because
# useradd is a low level utility and should be as general
# as possible
SHELL=/bin/sh
#
# The default group for users
# 100=users on Debian systems
# Same as USERS_GID in adduser
# This argument is used when the -n flag is specified.
# The default behavior (when -n and -g are not specified) is to create a
# primary user group with the same name as the user being added to the
# system.
# GROUP=100
#
# The default home directory. Same as DHOME for adduser
# HOME=/home
#
# The number of days after a password expires until the account
# is permanently disabled
# INACTIVE=-1
#
# The default expire date
# EXPIRE=
#
# The SKEL variable specifies the directory containing "skeletal" user
# files; in other words, files such as a sample .profile that will be
# copied to the new user's home directory when it is created.
# SKEL=/etc/skel
#
# Defines whether the mail spool should be created while
# creating the account
# CREATE_MAIL_SPOOL=yes
vagrant@saltmaster:~$
|
2.passwd
创建用户用useradd
,然后需要为用户创建密码,使用passwd
命令。需要注意的有以下几点:
-
passwd
修改自己账户的密码,普通用户需要输入旧密码,root用户不需要 -
root用户可以修改其他用户的密码而不需要输入旧密码
-
普通用户在创建密码时会经过PAM模块检查密码的强度,而root无需遵守强度检查
3.其他一些修改账户的命令(sudo)
chage
命令可以修改密码参数有关的信息。
1
2
3
4
5
6
7
8
|
vagrant@saltmaster:~$ chage -l vagrant
Last password change: Oct 27, 2017
Password expires: never
Password inactive: never
Account expires: never
Minimum number of days between password change: 0
Maximum number of days between password change: 99999
Number of days of warning before password expires: 7
|
usermod
可以修改有效用户组、初始用户组、主目录等与用户有关的信息。
userdel
可以删除用户。这个命令非常危险,将会从/etc/passwd
,/etc/shadow
,中删除用户,也会删除/home/user
用户目录。一般情况下,我们暂停某个账户可以只将账户的状态设置为不可用,例如/etc/shadow
第八个字段(账号失效日期)设置为0即可。如果确实需要删除用户,也可以用userdel -r username
,这样会先删除find / -user username
,然后再删除用户。
4.用户可以使用的一些命令
上面介绍的都是sudo
用户对账户的管理,还有一些命令普通用户就可以使用:
-
finger
查阅用户有关的信息 -
chfn
change finger,修改用户的详细信息 -
chsh
改变默认登录的shell -
id
可以用来查询用户的id
5.用户组的管理
在上面我们已经认识了用户和用户组,以及用户的管理。其实用户组的管理也是类似,只不过是/etc/group
与/etc/gshadow
而已。要注意的是,newgrp
是新开启一个shell,用新的环境来登录用户和用户组的。仔细想想, 这是一个很有趣的问题。正好我在写这篇文章的第三天(本文估计要写一个周),Julia写了一篇博客:How do groups work on Linux? 这篇博客正好说明了newgrp
的行为:Linux运行的进程都保存着有效组GID的属性,当进程想要通过组权限(这里略去了UID检查过程)读一个文件的时候,当看一个文件是否可以读的时候,Linux检查一下此进程的有效组里面是否有等于文件的组的,如果有那么就可以读。Julia之前误认为是:Linux检查一下此进程的用户是否可以读文件,如果不可以,就看一下用户所在的组,是否有等于文件所属的组的。——这样的话,就要每次去读/etc/passwd
了!
另外有关用户组还要知道的一个命令是gpasswd
,这个命令可以分配组管理员。组管理员可以添加或删除用户到某一个用户组。有点像论坛的版主的意思。
三、精确的权限控制ACL
我们知道,Linux的文件系统有三组权限,分别是“owner group other”,这样无法做到对同一group的成员,或对都是others的成员控制权限。所以就有了ACL(Access Control List)。ACL可以针对单一用户、单一文件或目录进行rwx的权限设置。这是一个UNIX-Like操作系统权限外的支持项目,需要文件系统的支持(mount | grep acl
)。
这里没有啥需求所以没有仔细研究,更多的资料读者可以自行搜索,推荐IBM Linux ACL 体验。
四、用户切换su, su – 和sudo
su
用来切换用户,使用方法是 su - username
, -
的意思是环境变量。比如说su - vagrant
那么会以vagrant来登录shell,所有的环境变量都会变成vagrant的。如果不加-
那么就只是id变成vagrant,进去之后如果收MAIL,还会是原来的用户的。
su - root
就可以登录root账户了!其实root可以省略,su -
就是登录root账户的意思。使用某个账户临时运行一下命令:su - root -c command
,这里的root也可以省略。注意如果root
账户没有密码的话,会出现 Authentication failure。
su是简单的切换命令。现在有一个问题,如果每个人都有用root账户权限的需求,那么就要有很多人知道root账户的密码,这很不安全,所以就有了sudo
命令。sudo可以让你用其他用户(通常是root账户)来执行命令。使用sudo的账户必须在/etc/sudoers
里面。系统验证sudo的过程如下:
-
当用户执行sudo命令时,系统先从
/etc/sudoers
文件中检查用户是否有执行权限 -
如果有,让用户输入自己的密码
-
执行sudo后面的命令
sudoers文件支持对用户组授权(以%开头)。格式如下:
1
2
|
用户账号 登陆者的来源主机名=可切换的身份 可执行的命令(绝对路径)
root ALL=(ALL) ALL
|
其中,可以修改最后一列为NOPASSWD:ALL
来免除每次运行sudo都需要的密码操作。(设置之后简直每天可以多好几秒呢!)
好了,基本的管理和操作到这里差不多了,上面的学习过程都是参考的鸟哥的Linux私房菜第三版(这本书讲的挺细的但是有点啰嗦,让人摸不透重点)。其余还提到了一些内容,下面就只列一下,有需要的可以去了解:
-
PAM模块,对密码强度的的检查就是这个模块实现的,基本上就是个API
-
查询在线用户与登录日志: w, who, last, lastlog
-
用户之间发送消息: write, mesg, wall
-
发送mail:MAIL
-
一些用户有关的检查工具:pwck, pwconv, pwunconv, chpasswd
-
如何批量创建账号?
passwd --stdin