为什么 useradd -rs /bin/false service 创建的用户无法用 su 切换?

问题现象

在 Linux 系统中,我们有时会使用以下命令为服务创建一个专用的系统用户:

bash 复制代码
sudo useradd -rs /bin/false service

这条命令创建了一个名为 service 的用户,但当我们尝试切换到该用户时:

bash 复制代码
su service

系统会提示类似以下的错误:

复制代码
This account is currently not available.

或者直接拒绝切换,返回失败。本文将深入解析这个问题的根本原因,并提供多种解决方案。

命令参数解析

首先,让我们拆解 useradd -rs /bin/false service 命令中每个参数的含义:

  • -r:创建系统用户(UID < 1000),这类用户通常用于运行系统服务而非交互式登录。
  • -s:指定用户的登录 Shell。
  • /bin/false:一个特殊的 Shell,它不做任何事情,只是立即以非零状态码退出。
  • service:要创建的用户名。

根本原因

su 命令(substitute user)在执行时,会尝试启动目标用户的登录 Shell。当 Shell 被设置为 /bin/false 时,su 进程会:

  1. 验证用户凭据(如果需要密码)
  2. 切换到目标用户的身份和环境
  3. 尝试执行 /bin/false 作为交互式 Shell
  4. /bin/false 立即退出,导致整个 su 会话终止

由于 /bin/false 的设计目的就是阻止任何形式的交互式登录 ,因此 su 命令自然无法成功切换到该用户。

为什么使用 /bin/false?

在服务部署中,将服务用户的 Shell 设置为 /bin/false/sbin/nologin 是一种安全最佳实践,原因包括:

  1. 防止交互式登录:攻击者即使获取了该用户的凭据,也无法通过 SSH、控制台等方式登录系统。
  2. 最小权限原则:服务账户只需要运行特定进程,不需要完整的 Shell 环境。
  3. 减少攻击面:没有 Shell 意味着无法执行任意命令,降低了被利用的风险。

解决方案

根据您的实际需求,有以下几种解决方案:

方案一:临时切换到服务用户(推荐用于调试)

如果您需要临时 以服务用户身份执行命令,可以使用 su -s 指定一个可用的 Shell:

bash 复制代码
# 使用 bash 作为临时 Shell
sudo su -s /bin/bash service

# 或者使用 sh
sudo su -s /bin/sh service

执行单条命令:

bash 复制代码
sudo su -s /bin/bash -c "whoami" service
# 输出:service

方案二:永久修改用户的 Shell(不推荐用于生产环境)

如果您确实需要让该用户能够交互式登录,可以修改其 Shell:

bash 复制代码
# 查看当前 Shell 设置
sudo grep service /etc/passwd

# 修改为 /bin/bash
sudo usermod -s /bin/bash service

# 修改为 /bin/sh(更轻量)
sudo usermod -s /bin/sh service

注意:对于生产环境的服务账户,不建议这样做,因为会降低安全性。

方案三:使用 sudo 直接以服务用户运行命令

对于大多数服务管理场景,您不需要真正「切换」用户,而是以该用户身份运行特定命令:

bash 复制代码
# 以 service 用户运行命令
sudo -u service whoami

# 以 service 用户启动服务
sudo -u service /path/to/your-service

方案四:创建时使用 /sbin/nologin(提供友好提示)

/sbin/nologin/bin/false 类似,但会显示一条拒绝登录的消息:

bash 复制代码
# 创建时使用 nologin
sudo useradd -rs /sbin/nologin service2

# 尝试切换时会看到提示
su service2
# 输出:This account is currently not available.

查看 nologin 的提示信息:

bash 复制代码
cat /etc/nologin.txt  # 如果存在

服务账户管理最佳实践

  1. 创建时明确用途

    bash 复制代码
    # 数据库服务账户
    sudo useradd -r -s /bin/false -d /var/lib/mysql mysql
    
    # Web 服务账户
    sudo useradd -r -s /bin/false -d /var/www/nginx nginx
  2. 设置合适的家目录 :使用 -d 参数指定服务的工作目录。

  3. 使用系统组:将相关服务用户添加到同一个系统组,方便权限管理。

  4. 定期审计:检查系统账户的 Shell 设置是否仍然符合安全要求:

    bash 复制代码
    # 查看所有系统用户的 Shell 设置
    awk -F: '$3 < 1000 {print $1 ": " $7}' /etc/passwd

常见问题解答

Q1:为什么不用 /usr/sbin/nologin?

A:/sbin/nologin/usr/sbin/nologin 是同一个文件的不同路径,取决于发行版。两者功能相同。

Q2:如何检查用户的 Shell 设置?

bash 复制代码
# 方法一:查看 /etc/passwd
sudo grep "^service:" /etc/passwd

# 方法二:使用 finger 命令
finger service

# 方法三:使用 getent
getent passwd service

Q3:Docker 容器中也有这个问题吗?

A:是的,但容器中通常使用 nobody 用户或自定义的 non-root 用户。在 Dockerfile 中:

dockerfile 复制代码
# 创建非登录用户
RUN adduser --disabled-login --gecos "" appuser
USER appuser

Q4:除了 su,还有哪些切换用户的方式?

  • sudo -i -u service:模拟登录环境
  • sudo runuser -u service -- command:使用 runuser
  • sudo -u service /bin/bash -c "command":执行单条命令

总结

useradd -rs /bin/false service 创建的用户无法用 su 切换,这是设计使然 而非错误。/bin/false Shell 专门用于阻止交互式登录,是服务账户安全配置的一部分。

在实际操作中:

  • 调试时 :使用 sudo su -s /bin/bash service
  • 运行服务时 :使用 sudo -u service command
  • 生产环境 :保持 /bin/false/sbin/nologin 设置,不要修改

理解这一点有助于您更好地管理 Linux 系统权限和安全策略。

相关推荐
guo_wen_qiang4 分钟前
mac中docker desktop服务端开启远程访问
运维·服务器·macos·docker
云飞云共享云桌面1 小时前
医疗器械设备研发:多人同时操作 SolidWorks,怎样依靠单台服务器替代多工作站
运维·服务器·网络·数据库·制造
T型码农要学习1 小时前
开源项目5|FileBrowser:免费在线文件管理器!随时随地管控服务器文件
运维·服务器·人工智能·开源
朱 欢 庆1 小时前
云服务器附件备份到本机内网服务器
运维·服务器·前端·经验分享
梦想不只是梦与想1 小时前
Web 服务器网关协议:ASGI 和 WSGI
服务器·python·fastapi
智恒百亿1 小时前
8 卡 RTX 5090 服务器深度实测:256GB 显存能否支撑 70B 模型微调?选型参考
大数据·运维·服务器·人工智能
知行合一。。。6 小时前
RAG--03--Milvus基本用法
数据库·oracle·milvus
TDengine (老段)7 小时前
TDengine 线程模型 — 网络、调度、执行
大数据·数据库·物联网·制造·时序数据库·tdengine·涛思数据
小诗懂技术7 小时前
【网络通信UDP】基础 进程间不同主机的通信
运维·服务器·网络
weixin_440730507 小时前
selenium实战记录-从登陆-首页-进入应用流程用例三种参数化+日志+报告
服务器·selenium·测试工具