Linux 下运行 sudo 命令如何取消输密码提示

小助手读文章 00:00 / 00:00

不考虑企业运维中权限管控十分严格的情况,个人运维基本上都是一个密码,在此背景下,现在的云主机或者系统一般在新建时都要求不能使用默认的 root 账户,而是新建一个普通用户,造成在运行 sudo 命令时再输一遍密码才能继续,这显然是十分浪费时间的。

解决办法

如果想立即解决输密码问题,参照下列命令直接新增文件即可,可以不用继续看后面的原理分析:

# vim /etc/sudoers.d/sudoers 
sudoers ALL=(ALL:ALL) NOPASSWD:ALL
# chmod 440 /etc/sudoers.d/sudoers 

其中,命令中的 sudoers 是登录系统时的账户。

原理分析

Linux 是多用户多任务的操作系统, 共享该系统的用户往往不只一个。出于安全性考虑, 有必要通过 useradd 创建一些非 root 用户, 只让它们拥有不完全的权限,如有必要,再来提升权限执行。

sudo就是来解决这个需求的:这些非 root 用户不需要知道 root 的密码,就可以提权到 root,执行一些 root 才能执行的命令。

执行 sudo -u <用户名> <命令>, 将允许当前用户,提权到<用户名>的身份,再执行后面的<命令>, 即使<命令>原本需要 root 权限。

提权到<用户名>身份时,是以<用户名>的身份来执行命令的,因此创建的文件默认属于<用户名>用户。

因此,当 userB 执行如下命令时:

sudo -u userA touch /tmp/belong-to-who.tmp

创建的 /tmp/belong-to-who.tmp 文件属于用户 userA。

如果不带 -u, 则默认使用 root 用户,而大多数时候 sudo 都是要提权到 root 的,所以 -u <用户名>可以省略为:

sudo <命令>

需要注意的是: 执行 sudo 时输入的密码是当前用户的密码, 并非<用户名>的密码。

sudo -u <用户名>su - <用户名>相比:

前者需要输入当前用户的密码,提权到<用户名>身份执行命令后> 返回当前用户,后者则是输入目标用户的密码,切换到目标用户。

赋予用户 sudo 操作的权限

关于Linux 用户和用户组管理的知识点不是本篇文章要讨论的, 如对 useradd、 usermod、 passwd、 groupadd 等指令生疏,可移步链接 ,那里有详细的讲解。

通过 useradd 添加的用户,并不具备 sudo 权限。在 ubuntu/centos 等系统下,需要将用户加入 admin 组或者 wheel 组或者 sudo 组。

以 root 用户身份执行如下命令,将用户加入 wheel/admin/sudo 组:

usermod -a -G wheel <用户名>

如果提示 wheel 组不存在, 则还需要先创建该组:

groupadd wheel

用公式讲解 /etc/sudoers 的内容

sudo 的权限控制可以在 /etc/sudoers 文件中查看到。

如果想要控制某个用户(或某个组用户)只能执行 root 权限中的一部分命令,或者允许某些用户使用 sudo 时不需要输入密码,就需要对该文件有所了解。

一般来说,通过 cat /etc/sudoers 指令来查看该文件,会看到如下几行代码:

root   ALL=(ALL:ALL) ALL
%wheel ALL=(ALL) ALL
%sudo  ALL=(ALL:ALL) ALL

/etc/sudoers 文件进行编辑的代码公式可以概括为:

授权用户/组 主机=[(切换到哪些用户或组)] [是否需要输入密码验证] 命令1,命令2,...

凡是 [ ] 中的内容都能省略,命令和命令之间用 , 号分隔;

为了方便说明,将公式的各个部分称呼为字段 1 - 字段 5:

授权用户/组    主机    =[(切换到哪些用户或组)]     [是否需要输入密码验证]    命令1,命令2,...
字段 1        字段 2     =  [(字段 3)]            [字段 4]   字段 5

字段 3、字段 4,是可以省略的,在上面的默认例子中:

“字段 1” 不以 % 号开头的表示 “将要授权的用户”,比如例子中的 root;以 % 号开头的表示“将要授权的组”, 比如例子中的 %wheel 组和 %sudo 组。

“字段 2” 表示允许登录的主机,ALL表示所有,如果该字段不为ALL,表示授权用户只能在某些机器上登录本服务器来执行 sudo命令,比如:

jack mycomputer=/usr/sbin/reboot,/usr/sbin/shutdown

表示:普通用户 jack 在主机(或主机组) mycomputer上,可以通过 sudo 执行 reboot 和 shutdown 两个命令。"字段 3"和"字段 4"省略。

“字段 3” 如果省略,相当于(root:root),表示可以通过 sudo 提权到 root ;如果为 (ALL) 或者 (ALL:ALL),表示能够提权到(任意用户:任意用户组)
请注意,“字段 3”如果没省略,必须使用 ( ) 双括号包含起来,这样才能区分是省略了 “字段 3” 还是省略了 “字段 4”。

“字段 4” 的可能取值是 NOPASSWD:。请注意 NOPASSWD后面带有冒号 :,表示执行 sudo 时可以不需要输入密码。比如:

lucy ALL=(ALL) NOPASSWD: /bin/useradd

表示:普通用户 lucy 可以在任何主机上通过 sudo 执行 /bin/useradd 命令,并且不需要输入密码;

又比如:

peter ALL=(ALL) NOPASSWD: ALL

表示:普通用户 peter 可以在任何主机上,通过 sudo 执行任何命令,并且不需要输入密码。

“字段 5” 是使用逗号分开一系列命令,这些命令就是授权给用户的操作,ALL 表示允许所有操作。
你可能已经注意到了,命令都是使用绝对路径,这是为了避免目录下有同名命令被执行,从而造成安全隐患。
如果你将授权写成如下安全性欠妥的格式:

lucy ALL=(ALL) chown,chmod,useradd

那么用户就有可能创建一个他自己的程序,也命名为 userad, 然后放在它的本地路径中,如此一来他就能够使用 root 来执行这个名为 useradd 的程序,这是相当危险的!

命令的绝对路径可通过 which 指令查看到,比如 which useradd 可以查看到命令 useradd 的绝对路径:/usr/sbin/useradd

公式还要扩充

例子 1:

papi ALL=(root) NOPASSWD: /bin/chown,/usr/sbin/useradd

表示:用户 papi 能在所有可能出现的主机上,提权到 root 下执行 /bin/chown,不必输入密码,但运行 /usr/sbin/useradd 命令时需要密码,这是因为 NOPASSWD: 只影响了其后的第一个命令:命令 1。

所以上面给出的公式只是简化版,完整的公式如下:

授权用户/组    主机    =    [(切换到哪些用户或组)]    [是否需要输入密码验证]    命令 1, [(字段 3)]    [字段 4]    命令 2, ...

在具有 sudo 操作的用户下, 执行 sudo -l 可以查看到该用户被允许和被禁止运行的命令.

通配符和取消命令

例子 2:

papi ALL=/usr/sbin/*,/sbin/*,!/usr/sbin/fdisk

表示:用户 papi 在所有可能出现的主机上,能够运行目录 /usr/sbin/sbin 下所有的程序,但 fdisk 除外。

开始编辑

“你讲了这么多,但是在实践中,我去编辑 /etc/sudoers 文件,系统提示我没权限啊,怎么办?”

这是因为 /etc/sudoers 的内容如此敏感,以至于该文件是只读的。所以,编辑该文件前,请确认清楚你知道自己正在做什么。

强烈建议通过 visudo 命令来修改该文件,通过 visudo 修改,如果配置出错,会有提示。

不过,系统文档推荐的做法,不是直接修改 /etc/sudoers 文件,而是将修改写在 /etc/sudoers.d/ 目录下的文件中。

如果使用这种方式修改 sudoers,需要在 /etc/sudoers 文件的最后行,加上 #includedir /etc/sudoers.d 一行(默认已有):

#includedir /etc/sudoers.d

注意了,这里的指令 #includedir 是一个整体,前面的 # 号不能丢,并非注释,也不能在 # 号后有空格。

任何在 /etc/sudoers.d/目录下,不以 ~ 号结尾的文件和不包含 . 号的文件,都会被解析成 /etc/sudoers 的内容。

文档中是这么说的:

# This will cause sudo to read and parse any files in the /etc/sudoers.d
# directory that do not end in '~' or contain a '.' character.

# Note that there must be at least one file in the sudoers.d directory (this
# one will do), and all files in this directory should be mode 0440.

# Note also, that because sudoers contents can vary widely, no attempt is
# made to add this directive to existing sudoers files on upgrade.

# Finally, please note that using the visudo command is the recommended way
# to update sudoers content, since it protects against many failure modes.

其他知识

输入密码时有反馈

当使用 sudo 后输入密码,并不会显示任何东西 —— 甚至连常规的星号都没有。有个办法可以解决该问题。

打开 /etc/sudoers 文件找到下述一行:

Defaults env_reset

修改成:

Defaults        env_reset,pwfeedback

修改 sudo 会话时间

如果你经常使用 sudo 命令,你肯定注意到过当你成功输入一次密码后,可以不用再输入密码就可以运行几次 sudo 命令,但是一段时间后,sudo 命令会再次要求你输入密码。

默认是 15分钟,该时间可以调整。添加 timestamp_timeout=分钟数即可(时间以分钟为单位,-1 表示永不过期,但强烈不推荐)。

比如我希望将时间延长到 1小时,还是打开 /etc/sudoers 文件找到下述一行:

Defaults env_reset

修改成:

Defaults        env_reset,pwfeedback,timestamp_timeout=60

参考文章:

1、《sudoers的深入剖析与用户权限控制
2、《How to Run ‘sudo’ Command Without Entering a Password in Linux


ArmxMod for Typecho
个性化、自适应、功能强大的响应式主题

推广

 继续浏览关于 linux密码方法sudo 的文章

 本文最后更新于 2019/01/17 10:34:53,可能因经年累月而与现状有所差异

 引用转载请注明:VirCloud's Blog > 运维 > Linux 下运行 sudo 命令如何取消输密码提示