Linux为普通用户设置sudo权限及通过sudo切换到root

Linux为普通用户设置sudo权限及通过sudo切换到root

sudo是干嘛用的?

相信稍微了解Linux的童鞋肯定见过sudo,它一般用于被加在正常命令的前面,这样普通用户也能以root权限执行命令,比如sudo nginx -s reload

sudo最初是superuser do的缩写,意思就是“用超级用户来做这件事情”,因为sudo命令最初就是被设置来让普通用户执行超级用户的权限的,但是后来增加“以其他用户的权限来执行”这个功能,也就是说,最开始的时候,这个“其它用户”只有root一个,但是后来变成了不只是root,任何一个其他用户都可以(但需要指定),所以sudo后来被解释成“substitute user do”(代替用户执行,意思是用另一个用户的权限来代替当前用户执行指定的命令)。

设置sudo权限

注意有些最小化安装的Linux(例如Debian)默认是没有sudo命令的,没有就自己安装一下就好:

apt install sudo

为普通用户设置sudo权限,其实就是在/etc/sudoers配置文件中添加一个配置,平时我们编辑配置文件一般都用vi/vim,但是这个配置文件,我们要使用另一个命令visudo来编辑,该命令同样是使用vi来编辑,只不过保存的时候会检查你写的语法是否正确,这样有助于查错,其实你用vi/vim来编辑也是可以的,它只不过是一个配置文件罢了。另外,visudo后面不需要跟文件名,直接输入visudo回车即可自动打开/etc/sudoers配置文件。

注意: visudo命令未必会使用vi来打开/etc/sudoers文件,而是取决于系统默认编辑器,像我就遇到过最小化安装的Debian默认是用nano编辑器的,如果要用vi,我们可以修改一下默认编辑器(centos用这个命令没用):

sudo update-alternatives --config editor

打开配置文件后,找到以下配置

## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL

把该配置复制一行,然后把root改成你要添加sudo权限的用户名,保存退出即可:

## Allow root to run any commands anywhere
root    ALL=(ALL)   ALL
xiebruce    ALL=(ALL)   ALL

注意:该配置保存后立即生效,不需要重启什么东西,也不用关掉终端窗口再开。

添加sudo权限后,普通用户在执行的命令前加上sudo,然后会提示输入密码,回车即可以超级用户的权限执行:

sudo yum -y install vim

详解root ALL=(ALL) ALL

这个到底是什么意思?我想很多人都知道按这格式加一个用户则该用户就可以使用sudo了,但却不知道这具体代表什么意思。
我找了一个StackExchange的回答:
Trying to understand the difference between “modernNeo ALL=(ALL:ALL) ALL” and “modernNeo ALL=(ALL) ALL” in the sudoers file

其实root ALL=(ALL) ALL是简写,root ALL=(ALL:ALL) ALL才是完整的格式,都写ALL真的很难理解,我写个其他方式,你就懂了:

xiebruce    10.37.129.5,10.37.129.6=(laoli:laoli) /bin/cat

详解
xiebruce是用户名,表示对这个用户进行sudo权限设置。
10.37.129.5,10.37.129.6是ip,表示只允许ip为这两个ip的服务器上的xiebruce用户才能使用。特别注意,这个ip并不是限制客户端ip,而是限制服务器本身,因为为了管理方便,有可能多台服务器的/etc/sudoers配置文件是同步的,假设有三台机:
A:10.37.129.5
B:10.37.129.6
C:10.37.129.7
这三台机的/etc/sudoers配置文件都相同,而且三台机都有xiebruce这个账号,但C机由于特殊原因,不允许xiebruce具有sudo权限,就可以像我上面用逗号分隔ip,写A、B两个ip即可。
(laoli:laoli) 这个就是指定xiebruce具有谁的权限(这里是让xiebruce用户以sudo运行时,具有用户名为laoli的权限和组为laoli的权限),如果写ALL那就是具有所有权限,实际上就是root权限。其实centos系统默认都不写组,即一般会写成(ALL)而不是(ALL:ALL),而经过我测试,不写组,那么组就是该用户本身所在的组,因为我试过用root组去执行,结果反而不行:

Xnip2019-01-17_22-09-06.jpg

- /bin/cat 是指允许执行的命令,如果写成ALL,那就允许执行所有命令(当然它还需要结合前面的权限,虽然后面允许,但不一定有权限执行),如果要允许多个命令,跟ip一样,用逗号隔开就行。

以下为实例:

Xnip2019-01-17_14-34-07.jpg

注意该实例使用的配置文件就是上面举例的配置:

xiebruce    10.37.129.5,10.37.129.6=(laoli:laoli) /bin/cat

实例详解:
由上图可以看到,有两个测试文件,分别为:

-rw------- 1 laoli   laoli   89 Jan 17 14:20 file_of_laoli
-rw------- 1 laowang laowang 95 Jan 17 14:10 file_of_laowang

它们的权限,都只有所有人有读写权限,所有组和其他人都没有任何操作权限。

由图可知当前登录用户为xiebruce,所以直接执行以下命令肯定是没有权限的:

cat file_of_laoli
cat file_of_laowang

但是加了sudo也提示没有权限,这是为什么呢?因为sudo有两个选项,-u指定以哪个用户的权限进行运行,-g表示以哪个组的权限运行,如果没有指定-u-g,那么默认相当于指定了-u root -g root,即默认以root用户和root组为目标用户,这就很清楚了,我sudo配置指定的是xiebruce具有laoli的权限,而你现在却以root权限去运行,肯定是不允许的,正确的做法是sudo -u laoli -g laoli cat file_of_laoli,其中-g可以不指定,因为反正-u已经有权限了(从实例截图中也可以看到,sudo -u laoli cat file_of_laoli是执行成功的)。

sudo cat file_of_laoli
sudo cat file_of_laowang

最后三条命令也都是不成功的,其中第一条是以root用户执行,前面说了,不指定的话其实默认也是以root用户执行的,现在指定了也一样,所以这肯定是无权限的,第二条是用laowang的权限去看,更不可能,因为laowang这个用户本身就没有权限看file_of_laoli这个文件。第三条是用laoli这个用户执行,为什么也不行呢?仔细看,这次执行的命令是vim,由前面可知,我只设置了允许cat命令,所以vim命令也是不允许执行的。

sudo -u root cat file_of_laoli
sudo -u laowang cat file_of_laoli
sudo -u laoli vim file_of_laoli

设置无密码使用sudo权限

方法一NOPASSWD方式,即在最后一个ALL前面加个NOPASSWD:

xiebruce    ALL=(ALL)   NOPASSWD:ALL

多个用户名的设置方式(注意NOPASSWD:跟命令之间是有一个空格的,否则虽然不报错,但相当于没有设置NOPASSWD,但(root)NOPASSWD之间是可以不用空格的):

xiebruce   ALL= (root) NOPASSWD: /sbin/mount, (root) NOPASSWD: /bin/umount, (root) NOPASSWD: /mnt/mount, (root) NOPASSWD: /bin/rm, (root) NOPASSWD: /usr/bin/make, (root) NOPASSWD: /bin/ln, (root) NOPASSWD: /bin/sh, (root) NOPASSWD: /bin/mv, (root) NOPASSWD: /bin/chown, (root) NOPASSWD: /bin/chgrp, (root) NOPASSWD: /bin/cp, (root) NOPASSWD: /bin/chmod

方法二:设置密码过期时间方式
设置密码过期时间为-1即可免密码使用sudo,visudo→找到Defaults env_reset,在它后面加上timestamp_timeout=-1

Defaults    env_reset,timestamp_timeout=-1

当然,你还可以设置为0,表示0分钟后要验证,也就是说这样设置会导致每次使用sudo权限都要密码验证:

Defaults    env_reset,timestamp_timeout=0

设置10分钟后过期(即你输入过一次sudo密码后,10分钟内用sudo就不需要密码):

Defaults    env_reset,timestamp_timeout=10

另外,你也可以设置su命令不需要密码,当然不建议:

1)切换到root权限;
2)创建group为wheel,命令为groupadd wheel;
3)将用户加入wheel group中,命令为usermod -G wheel joe;
4)修改su的配置文件/etc/pam.d/su,增加下列项:

 auth       required   pam_wheel.so group=wheel 
# Uncomment this if you want wheel members to be able to
# su without a password.
 auth       sufficient pam_wheel.so trust use_uid

至此你可以使用例如如下的命令且不需要输入密码:su joe -c command。

通过sudo切换到超级用户

除了直接在命令前加sudo外,你也可以直接通过sudo切换到超级用户,以下两个命令都可以切换到超级用户:

sudo -i
sudo -s

根据man sudo
-i:就是initial的缩写
The -i (simulate initial login) option runs the shell specified by the password database entry of the target user as a login shell.
翻译:-i(模拟初始登录)选项将目标用户的密码数据库条目指定的shell作为登录shell运行。

什么是“目标用户的密码数据库条目”?
“目标用户”就是“以哪个用户的权限去执行命令”,sudo -u指定的用户即为目标用户,如果不用-u指定,默认为root。
密码数据库(password database)其实就是指/etc/passwd文件,因为linux系统用户的密码都存放在这里,所以把它说成“密码数据库”也是没错的,“条目”是因为/etc/passwd中的数据都是一个用户一行(即一条数据),所以“目标用户的密码数据库条目”就是指/etc/passwd文件中你的用户对应的那一条(即那一行),所以对于“目标用户的密码数据库条目指定的shell”,假设我用户是xiebruce,那么我对应的shell就是/bin/bash(如下图最后一行):

Xnip2019-01-16_15-48-30.jpg

This means that login-specific resource files such as .profile or .login will be read by the shell.
翻译:这意味着“登录特定的”资源文件比如.profile或.login文件(其实就是用户家目录中的.bashrc/.bash_profile/.zshrc等),将会被那个shell读取(那个shell就是上面说的/bin/bash)。

If a command is specified, it is passed to the shell for execution via the shell’s -c option.
翻译:如果指定了命令,那么这个命令会通过那个shell的-c选项被传到那个shell中去执行。(注意-c选项是shell的选项而不是sudo的选项,比如你的shell是/bin/bash,那么-c就是这个bash的选项,你可以man bash查看到这个选项)。

If no command is specified, an interactive shell is executed. sudo attempts to change to that user’s home directory before running the shell.
翻译:如果没有指定命令,则交互shell将会被执行,并且sudo会在登录到那个用户之前,试图切换到那个用户的家目录。其实这就相当于切换到了root用户,界面看上去也是root,你可以执行whoami命令,你会发现当前用户已经是root了,但跟su -切换到root不同的是,你这个root的权限是受限的,具有受什么限制,得看sudo配置,当然绝大部分情况其实就是完全具有root的所有权限,因为大部分人都是直接全部写ALL(参考前面的root ALL=(ALL) ALL)。

-s:就是shell的缩写
首先看这句:
The -s (shell) option runs the shell specified by the SHELL environment variable if it is set.
解释:-s 选项运行“SHELL环境变量”指定的shell,如果这个shell被设置了的话(当然绝大多数情况下这个$SHELL都是设置了的)。那么“SHELL环境变量”是什么?其实就是$SHELL,你直接执行echo $SHELL即可打印出它的值。

后面接着:or the shell as specified in the password database.
解释:或者password database所指定的shell,“password database”就是密码数据库,前面已经说过了,密码数据库就是/etc/passwd

再往下: If a command is specified, it is passed to the shell for execution via the shell’s -c option.
解释:如果指定了命令,则这个命令会通过那个shell的-c选项传到那个shell中(那个shell就是指前面echo $SHELL输出的那个shell,如果这个shell不存在就会去/etc/passwd中找这个用户的shell)。

最后:If no command is specified, an inter‐active shell is executed.
如果没有指定命令则交互shell将会被执行,其实就是登录到sudo的“目标用户”(不明白什么是目标用户的请往前看),一般情况下目标用户就是root,所以假设你直接执行sudo -s后面不加具体命令的话,则会直接切换为root用户。

总结
sudo -isudo -s有什么区别呢?
sudo -i模拟了登录目标用户的过程,读取了目标用户(-u指定,不写默认为root)的登录配置文件(如.bashrc),并且登录后会切换到目标用户的家目录中,退出时会清空当前屏幕,回到原来登录前的界面,就好像一切都没发生过,跟你登录另一个远程机操作完,退出回到原来的界面类似。

Xnip2019-01-17_23-01-30.jpg

sudo -s是就地切换,不模拟登录,不会切换到目标用户的家目录中,如果目标用户是root,那么环境变量$PATH只有/root/bin及secure_path指定的路径。

Xnip2019-01-17_23-02-54.jpg

sudo -s后面可以跟shell名称,比如sudo -s zsh,那就说明你切换后要使用zsh shell(前提是你电脑安装了zsh shell),如果不指定,那就会直接使用当前用户的默认shell(而不会使用root用户的默认shell)。

sudo报找不到命令

需要注意的是,有可能用普通用户能执行的命令,加了sudo会说找不到该命令,而用普通用户虽然找的到该命令但又不够权限,原因是在 /etc/sudoers 这个文件中有一个配置项是 secure_path , 当使用sudo执行命令的时候 , PATH 变量会被重置为secure_path的值(为了安全,可以控制不是所有命令都可以让普通用户通过sudo就能执行):
Xnip2018-11-10_18-57-26.png
如图所示,secure_path = /sbin:/bin:/usr/sbin:/usr/bin,而我编译的nginx在/usr/local/nginx/sbin/nginx,如果在.bashrc的PATH中添加了nginx的路径,就会导致加sudo无法执行,原因很简单,secure_path里并没有添加nginx环境变量,修改的方法,你可以把nginx软链到/usr/local/bin

sudo ln -s /usr/local/openresty/nginx/sbin/nginx /usr/local/bin/nginx

然后在secure_path里添加/usr/local/bin的环境变量:

Xnip2019-01-04_01-06-16.jpg

也可以直接往secure_path里添加nginx的环境变量:

Xnip2019-01-04_00-55-44.jpg

有可能你买的国外的云服务器是最小安装的,什么都没有,连sudo也没有,你用visudo命令,然报以下错误(看你用的是什么shell)

zsh: command not found: visudo
bash: command not found: visudo

这时你就要自己安装,如下图,使用yum search sudo,找出三个,根据解释,我们要安装的是最后一个『sudo.x86_64』,即安装的时候使用

yum -y install sudo.x86_64

84675029.png

内建命令无法使用sudo问题

内建命令无法直接使用sudo来提升权限,比如sudo cd /etc不会像你预料的那样会切换到/etc目录,而是无任何提示,但还是保持在当前目录,相当于你按了一下回车,没有执行任何命令(我的测试是这样,也有其他人测试提报:sudo: cd: command not found错误)。

内建命令有:typecdaliasunalias.echobreak等,你没看错,英文句点.也是一个命令(用type .来验证),而且是内建命令,判断命令是否为内建命令,用type命令来判断,如:

type cd

如下图,type自己也可以用type命令来判断是否为内建命令,buildin就表示内建命令。

Xnip2019-01-05_23-49-17.jpg

那没有root密码的情况下怎样执行类似cd /etc这种需要root命令来执行的操作呢?你可以用sudo -isudo -s来切换到root用户,这样就可以直接用cd /etc来进入/etc目录了。

为什么不直接用root而用sudo?

根据前面的内容,相信你已经了解sudo是干嘛用的了,而且像这种设置xiebruce ALL=(ALL) ALL就是让“xiebruce”用户具有了root用户的权限,你都有root权限了,还要这个普通用户干嘛呢?为什么不直接用root?

  • 原因一:Linux上的操作有时候会有危险(比如rm -rf之类的命令),如果用普通用户+sudo权限的方式去执行,那么它会提示你输入密码,这样你有一个认真查看命令的机会,也有个反悔的机会,而如果你直接用root,那就直接删掉就删掉了,没机会反悔。

  • 原因二:原因一提到的问题,其实如果你用zsh+ohmyzsh的时候,就算你是root执行rm -rf也不会不问你而直接删除,而是会提示你真的要删除吗?那既然这样,为什么还要用到sudo呢?为什么不直接用root用户呢?因为假如一个公司,都给大家root用户,第一,如果出现操作事故了无法追踪是谁什么时候登录了服务器,第二,如果有一个员工离职了,那么root密码他肯定还保留有,你要换root密码吗?大家都用着,你突然把root密码换了,这也麻烦,你不换吧,又不安全,毕竟前员工知道你们服务器的root密码,但是如果用普通用户,他离职了你删掉他的用户就好了,不需要导致改root密码。

打赏

订阅评论
提醒
guest

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x

扫码在手机查看
iPhone请用自带相机扫
安卓用UC/QQ浏览器扫

Linux为普通用户设置sudo权限及通过sudo切换到root