1. Linux 用户被锁后解锁失败faillog 与 usermod 排查全流程Linux 用户被锁这件事表面看只是「登录不上」实际背后可能是两套完全不同的机制在起作用一套是 PAM 的失败计数pam_tally / pam_faillock另一套是 usermod 手动把密码字段加了锁标记。很多人一上来就usermod -U结果发现解锁后还是登不进去原因就是锁的来源根本没找对。这篇内容面向日常做 Linux 运维、被「用户被锁了但解锁命令没效果」卡住的同学从 faillog 日志、pam 配置、usermod 参数三个方向拆开讲最后再补一段用 TaoToken 统一 Key 通道验证 API 调用是否正常的操作把「系统层解锁」和「应用层鉴权」两件事分开定位。先说清楚这两个机制的区别不然后面命令会看晕。PAM 失败计数锁当用户连续输错密码达到阈值比如 deny3PAM 模块会把这次失败写进/var/log/faillog并在计数超限后拒绝该用户认证。这种锁的特点是——密码本身没变只是认证入口被拦了。解锁要用faillog -u 用户名 -r重置计数。usermod 密码锁usermod -L 用户名会在/etc/shadow的密码字段前面加一个!让密码哈希失效。这种锁的特点是——账号还在但密码验证永远失败。解锁要用usermod -U 用户名把!去掉。问题就出在这里如果用户是被 PAM 计数锁的你敲usermod -U是没用的因为密码字段本来就没被锁反过来如果用户是被usermod -L锁的你敲faillog -r也白搭。所以排查第一步永远是——先确认锁的类型。我一般按这个顺序走# 1. 看 faillog 里有没有失败记录 faillog -u alice # 2. 看 shadow 里密码字段有没有被加锁标记 sudo grep ^alice: /etc/shadow # 3. 看 pam 配置里有没有启用失败计数 grep -r pam_tally\|pam_faillock /etc/pam.d/第 2 步的输出很关键。正常密码字段长这样alice:$6$xxxxx...:19000:0:99999:7:::被usermod -L锁之后会变成alice:!$6$xxxxx...:19000:0:99999:7:::注意那个!它就在第二个冒号后面、哈希开头的位置。如果看到!!或者!*说明密码压根没设置过或者被彻底禁用那又是另一种情况了。第 1 步的faillog -u alice输出大概是这样Username Failures Maximum Latest alice 5 3 Wed Jan 8 10:23:11 0800 2025Failures 是累计失败次数Maximum 是阈值Latest 是最后一次失败时间。如果 Failures 已经超过 Maximum那基本可以确定是 PAM 计数锁。第 3 步是确认系统到底用的是哪个模块。老系统CentOS 6 时代用pam_tally.so新系统CentOS 7、Ubuntu 18.04基本都换成了pam_faillock.so。这两个模块的配置写法不一样解锁命令也略有差别后面会分别讲。把这三步跑完你就能判断出用户到底是被哪种机制锁的。判断清楚了解锁就是一条命令的事判断错了敲十条命令也没用。这也是为什么很多人觉得「Linux 解锁很玄学」——不是命令不对是没定位到锁源。2. TaoToken 统一 Key 前置准备把 API 鉴权从系统账号里剥出来排查用户锁定的过程中有个容易被忽略的坑你以为用户在系统层被锁了其实真正拦住他的是应用层的 API 鉴权失败。尤其是现在很多运维脚本、CI 任务、Agent 工具都要调大模型接口一旦 Key 配错或者额度用尽表现和「账号被锁」几乎一样——任务跑不动、日志报 401、用户反馈「登不进去」。所以我在排查系统账号的同时会顺手用 TaoToken 的统一 Key 通道验证一下 API 调用是否正常。这样做的好处是系统层和应用层的鉴权问题能一次性分开不用来回猜。TaoToken 是一个统一的大模型 API 接入通道官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。它的核心价值是——你只需要一个 Key就能调用多个模型不用为每个模型单独申请账号、单独配 Key。对运维场景来说这意味着脚本里的鉴权配置可以统一管理出问题时只需要检查一个地方。前置准备分三步第一步拿到统一 Key。登录控制台在 API Keys 页面创建一个新 Key。地址是 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。创建的时候建议给 Key 起个能认出来的名字比如ops-check-2025方便后面排查时知道这个 Key 是干嘛用的。第二步确认你要调的模型 ID。不同模型的 ID 不一样比如 Claude 系列、GPT 系列各有各的写法。可以在模型对话页面先试一下地址是 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 选一个模型发条消息确认能通再把这个模型 ID 记下来。第三步把 Base URL、Key、Model ID 三件套准备好。这三样是后面所有配置的基础缺一不可。Base URL 统一用https://taotoken.net/apiKey 就是刚才创建的那串Model ID 是第二步确认的。这里要提醒一句TaoToken 的 Key 和 Linux 系统账号是两套完全独立的鉴权体系。系统账号被锁不影响 API Key 使用API Key 失效也不代表系统账号有问题。排查的时候一定要分开看别把两件事混在一起。如果你用的是 Claude Code 这类工具配置会更集中一些。Claude Code 的配置文件通常在~/.claude/settings.json或者项目级的.claude/settings.json里面需要填 Base URL、API Key、Model ID。具体路径和字段名以你实际安装的版本为准配置前先确认一下文件位置。对于长期跑编码任务或者 Agent 的场景可以考虑用 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 它更适合需要持续调用、额度稳定的情况。临时排查用普通 Key 就够了。把这三步做完你手里就有了一个可用的 API 鉴权通道。接下来无论是验证系统解锁是否成功还是排查应用层报错都有了一个干净的对照基准。3. 可复制配置faillog 解锁命令与 usermod 参数完整写法这一节直接给可复制的命令和配置片段你照着改用户名就能用。分三块PAM 失败计数解锁、usermod 密码锁解锁、以及 API 鉴权的 JSON 配置。3.1 PAM 失败计数解锁pam_tally / pam_faillock先看老系统的pam_tally.so配置。在/etc/pam.d/login或者/etc/pam.d/system-auth里通常会有这两行auth required pam_tally.so onerrfail no_magic_root account required pam_tally.so deny3 no_magic_root resetdeny3是失败阈值reset表示登录成功后重置计数。如果你要调整阈值改这个数字就行。改完不需要重启下次认证就生效。解锁命令# 查看指定用户的失败记录 faillog -u alice # 重置指定用户的失败计数 sudo faillog -u alice -r # 重置所有用户的失败计数慎用 sudo faillog -r新系统用的是pam_faillock.so配置一般在/etc/security/faillock.conf或者/etc/pam.d/system-auth里auth required pam_faillock.so preauth silent deny3 unlock_time600 auth required pam_faillock.so authfail deny3 unlock_time600 account required pam_faillock.sounlock_time600表示锁 600 秒后自动解锁。如果你不想等手动解锁命令是# 查看失败记录 faillock --user alice # 重置失败计数 sudo faillock --user alice --reset注意faillock和faillog是两个不同命令别敲混了。faillog读的是/var/log/faillogfaillock读的是/var/run/faillock/下的文件。新系统上如果faillog没输出大概率是系统已经切到pam_faillock了改用faillock命令。3.2 usermod 密码锁解锁先确认密码字段状态sudo grep ^alice: /etc/shadow如果看到!开头说明被锁了。解锁# 解锁密码 sudo usermod -U alice # 再次确认! 应该消失了 sudo grep ^alice: /etc/shadow如果要主动锁定某个用户sudo usermod -L alice-L和-U是成对的一个加锁一个解锁。注意usermod -L只是让密码失效用户如果已经登录的会话不会立刻断开。要强制踢下线还得配合pkill -u alice或者loginctl terminate-user alice。还有一个容易踩的坑如果用户密码字段本来就是!!表示从未设置密码你敲usermod -U是没用的因为-U只能去掉一个!去不掉两个。这种情况得先用passwd alice设置密码。3.3 API 鉴权 JSON 配置如果你用 Claude Code 或者类似工具配置文件里需要填三件套。以settings.json为例{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的Key, ANTHROPIC_MODEL: claude-sonnet-4-20250514 } }字段名可能因工具版本不同而有差异但核心就是 Base URL、Key、Model ID 这三样。Base URL 固定用https://taotoken.net/apiKey 从控制台拿Model ID 从模型对话页面确认。如果你用的是 Codex 类的工具配置可能在~/.codex/auth.json{ base_url: https://taotoken.net/api, api_key: sk-你的Key, model: gpt-4o }同样三件套只是字段名不一样。配置完保存重启工具或者重新加载配置。3.4 一键排查脚本把上面的检查串起来写成一个脚本排查时直接跑#!/bin/bash USER$1 echo 1. faillog 记录 faillog -u $USER 2/dev/null || echo faillog 无记录或命令不存在 echo 2. faillock 记录 faillock --user $USER 2/dev/null || echo faillock 无记录或命令不存在 echo 3. shadow 密码字段 sudo grep ^$USER: /etc/shadow | cut -d: -f1,2 echo 4. PAM 配置 grep -r pam_tally\|pam_faillock /etc/pam.d/ 2/dev/null echo 5. 账号状态 passwd -S $USERpasswd -S的输出会告诉你账号是 L锁定、P正常密码、NP无密码还是其他状态。这个命令比手动看 shadow 更直观。把用户名作为参数传进去比如./check_user.sh alice五步输出一目了然。哪一步有异常就往哪个方向深入。4. 验证请求确认解锁成功与 API 调用正常解锁命令敲完不代表事情结束得验证。验证分两层系统层确认用户能登录应用层确认 API 调用能通。4.1 系统层验证最直接的方式是su切换用户su - alice如果能正常切换进去说明系统层解锁成功。如果提示认证失败回到第 3 节重新检查锁源。另一个方式是看passwd -S的状态sudo passwd -S alice正常输出是alice P 01/08/2025 0 99999 7 -1第二列的P表示密码可用。如果是L说明还被锁着。还可以看faillog或faillock的计数是否归零faillog -u alice # Failures 应该变成 0 faillock --user alice # 应该没有失败记录4.2 API 层验证系统层通了之后用 TaoToken 的 Key 发一个测试请求确认 API 通道正常。用 curl 最简单curl -X POST https://taotoken.net/api/v1/messages \ -H Content-Type: application/json \ -H x-api-key: sk-你的Key \ -H anthropic-version: 2023-06-01 \ -d { model: claude-sonnet-4-20250514, max_tokens: 100, messages: [ {role: user, content: 回复 OK 两个字母即可} ] }如果返回类似这样的结构说明 API 通道正常{ id: msg_xxx, type: message, role: assistant, content: [ {type: text, text: OK} ] }重点看content数组里有没有文本返回。如果有说明 Base URL、Key、Model ID 三件套都配对了。如果返回 401说明 Key 有问题返回 404说明 Base URL 或路径不对返回 400 且提示 model 相关说明 Model ID 写错了。这些错误码和系统层的「用户被锁」是两回事别混在一起排查。4.3 把两层验证串起来实际排查时我一般按这个顺序先跑系统层验证确认su - alice能进。能进说明系统账号没问题问题在应用层。不能进回到第 3 节继续查系统锁。系统层通了之后跑 API 验证。API 通了说明整条链路都正常。API 不通看错误码定位是 Key、URL 还是 Model 的问题。这样分层验证的好处是——你不会在一个层面上反复试错。系统层的问题用系统命令解决应用层的问题用 API 工具解决各管各的。如果你用的是 Claude Code 这类工具验证方式更简单直接在工具里发一条消息看能不能收到回复。能收到说明配置正确报错的话看错误信息里提到的是认证问题还是网络问题再对应排查。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth这一节把排查过程中最常见的几类报错列出来对照着看。5.1 401 Unauthorized这是 API 鉴权失败最典型的报错。可能原因有三个Key 写错了。检查配置文件里的 Key 是不是完整复制了有没有多余空格。Key 一般以sk-开头复制的时候别漏字符。Key 被删了或者过期了。去控制台 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 确认这个 Key 还在不在状态是不是 active。请求头字段名写错了。不同 API 的鉴权头不一样Anthropic 风格用x-api-keyOpenAI 风格用Authorization: Bearer。用错字段名也会 401。5.2 local proxy failed这个报错通常出现在工具配置了本地代理但代理没起来或者端口不对。检查配置文件里有没有proxy相关的字段如果有确认代理地址和端口是否正确。如果不需要代理把相关配置删掉。注意这里说的代理是工具自身的网络配置不是系统层的账号问题。别把local proxy failed和用户被锁混为一谈。5.3 reading choices 相关报错这类报错一般出现在调用返回结构解析失败的时候。可能原因是返回的不是预期的 JSON 结构。比如你期望 OpenAI 格式的choices数组但实际返回的是 Anthropic 格式的content数组。检查你用的 Model ID 和请求格式是否匹配。返回了错误信息但被当成正常响应解析。比如 401 的响应体里没有choices字段解析时就报reading choices失败。这种情况要先看原始返回内容确认是不是鉴权问题。5.4 OAuth 相关报错如果你用的是需要 OAuth 登录的工具报错可能和 token 过期有关。检查 OAuth token 是否还有效必要时重新登录。OAuth 报错和 API Key 报错是两套体系。OAuth 是登录态API Key 是调用凭证。排查时先确认你用的是哪种鉴权方式再对应检查。5.5 系统层常见错usermod -U后还是登不进去。大概率是 PAM 计数锁没解跑faillog -u 用户名 -r或faillock --user 用户名 --reset。faillog命令没输出。新系统可能已经切到pam_faillock改用faillock命令。passwd -S显示L但usermod -U没效果。检查密码字段是不是!!这种情况得先用passwd设置密码。用户能登录但 SSH 还是拒绝。检查/etc/ssh/sshd_config里有没有DenyUsers或AllowUsers限制这又是另一层控制了。5.6 排查顺序建议遇到报错先别急着改配置按这个顺序走第一步确认报错来自哪一层。系统命令报错看系统层API 请求报错看应用层。第二步系统层先看passwd -S和faillog/faillock确认锁源。第三步应用层先看错误码401 查 Key404 查 URL400 查 Model ID。第四步改完配置重新验证别一次改多个地方不然出问题不知道是哪个改动导致的。6. 长期编码与 Agent 场景用 Coding Plan 统一管理调用系统账号解锁是一次性的事但 API 调用是长期的。如果你日常要跑编码任务、Agent 工作流或者多个脚本都要调大模型接口建议把调用通道统一管理起来。TaoToken 的 Coding Plan 就是为这种场景准备的地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。它的特点是额度稳定、适合持续调用不用每次担心 Key 的额度问题。配置方式和普通 Key 一样还是三件套Base URL 用https://taotoken.net/apiKey 从控制台拿Model ID 按需选。区别在于 Coding Plan 的额度更适合长期跑不会因为临时调用量上来就断。对于 Claude Code 用户接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有详细的配置步骤和字段说明。Claude Code 的专属入口是 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude_codeutm_campaignrewrite 需要的话可以直接看这个页面。实际用下来统一 Key 通道最大的好处是排查方便。以前每个模型一个 Key出问题要挨个检查现在只有一个 Key401 就是 Key 的问题404 就是 URL 的问题定位路径短了很多。回到用户锁定这个场景系统层的锁用 faillog 和 usermod 解决应用层的鉴权用统一 Key 验证。两层分开排查互不干扰。这套方法我用了挺久比一上来就瞎敲命令高效得多。最后留一个实用技巧把第 3.4 节的排查脚本存到/usr/local/bin/check_user.sh加个执行权限以后遇到用户被锁直接跑脚本五步输出看完就知道问题在哪。脚本里的用户名用参数传别写死这样哪个用户出问题都能查。
阅读完成 · 觉得有帮助?