ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux下MySQL安装失败的7大根源与深度排障指南

Linux下MySQL安装失败的7大根源与深度排障指南 1. 这不是“点下一步”的安装而是真正理解 MySQL 在 Linux 上如何扎根你搜到这篇教程大概率正卡在某个环节刚敲完sudo apt install mysql-server却发现服务起不来或者下载了.tar.gz包解压后连mysqld命令都找不到又或者配置完my.cnf重启服务时日志里只有一行冰冷的Failed to start mysqld.service: Unit not found。别急——这不是你操作错了而是绝大多数“图文教程”跳过了最关键的一环Linux 系统对服务、权限、路径和依赖的底层逻辑和 Windows 安装 MSI 的思维完全不同。我带过十几支运维团队也给高校实验室搭过上百台开发环境最常听到的抱怨就是“教程里截图都对为什么我的就是不行” 根源在于那些截图背后省略了 3 个必须手动确认的检查点、2 种不同发行版的包管理差异、以及 MySQL 8.0 强制启用的密码策略带来的连锁反应。这篇教程不堆命令不贴通用截图而是带你从内核加载模块开始一层层拆解 MySQL 如何在 Linux 的土壤里真正“活下来”。你会看到systemd是怎么接管mysqld进程的/var/lib/mysql目录权限为什么必须是mysql:mysql而不是root:root以及当你执行mysql_secure_installation时后台到底在修改哪 4 个系统表。适合正在部署生产数据库的运维工程师、需要本地调试 Laravel 项目的 PHP 开发者以及刚用 VMware 装好 Ubuntu 想跑个 WordPress 却被卡住的新人。接下来的内容每一步都附带why和what if的实操验证你可以随时停在任意环节用journalctl -u mysql查看实时日志而不是盲目复制粘贴。2. 安装前必须完成的 5 项系统级检查90% 的失败源于此处很多教程直接从apt install开始这就像没检查地基就浇筑混凝土。MySQL 在 Linux 上不是独立运行的“应用”而是深度嵌入系统服务、文件权限和网络栈的组件。跳过前置检查后续所有操作都是在沙上建塔。2.1 确认发行版与包管理器的真实身份Linux 发行版看似都是“Linux”但底层包管理机制天差地别。Ubuntu/Debian 用aptCentOS/RHEL 8 用dnf而 CentOS 7 及更早版本用yum。更关键的是同一发行版的不同版本MySQL 的默认包名和版本号完全不同。例如Ubuntu 22.04 默认安装mysql-server实际为 MySQL 8.0.33Ubuntu 18.04 默认安装mysql-server实际为 MySQL 5.7.41CentOS 7 的yum install mysql-server实际安装的是 MariaDB而非 Oracle 官方 MySQL提示执行cat /etc/os-release查看真实发行版信息比uname -a更可靠。重点关注ID和VERSION_ID字段。例如输出IDubuntu和VERSION_ID22.04才能确定后续使用apt且目标版本为 8.0。我曾遇到一个案例某学员在阿里云 ECS 上选镜像时勾选了“CentOS 7”但实际创建的是“Alibaba Cloud Linux 3”其包管理器为dnf且默认仓库中 MySQL 8.0 需要额外启用mysql80-community仓库。他按 CentOS 7 教程执行yum install mysql-server结果安装的是 MariaDB 10.3导致后续 PHP 连接报错Client does not support authentication protocol requested by server。根源就在于没做这一步验证。2.2 检查端口 3306 是否已被占用MySQL 默认监听 3306 端口但这个端口极易被其他进程抢占。常见抢占者包括Docker 容器中已运行的 MySQL 实例之前未彻底卸载的 MySQL 旧版本残留进程其他数据库如 PostgreSQL某些配置下会监听 3306甚至某些安全扫描工具会临时绑定端口执行sudo ss -tuln | grep :3306或sudo netstat -tuln | grep :3306。如果返回结果非空说明端口已被占用。此时不能简单kill -9而应先确认进程来源sudo lsof -i :3306或sudo ss -tulnp | grep :3306。若为残留mysqld进程需先停止服务sudo systemctl stop mysql再清理若为 Docker 容器则需docker stop container_id。切记强行 kill 可能导致/var/lib/mysql目录下的 ibdata1 文件损坏引发后续初始化失败。2.3 验证/var/lib/mysql目录的归属与权限这是 MySQL 数据目录所有表空间、日志、系统表都存放于此。安装程序会尝试在此目录下创建子目录并写入文件。但若该目录存在且归属为root:root或权限为755mysqld进程以mysql用户身份运行将无权写入导致初始化失败。执行ls -ld /var/lib/mysql。理想状态应为drwxr-x--- 5 mysql mysql 4096 Apr 10 10:23 /var/lib/mysql即属主和属组均为mysql权限为750drwxr-x---。如果目录不存在安装脚本会自动创建如果存在但权限错误需手动修复sudo chown -R mysql:mysql /var/lib/mysql sudo chmod 750 /var/lib/mysql。注意-R参数仅在目录非空时使用若目录为空且权限错误直接chown mysql:mysql /var/lib/mysql即可避免误改子目录权限。2.4 检查 SELinux 或 AppArmor 状态企业级环境必做SELinuxRHEL/CentOS和 AppArmorUbuntu/Debian是 Linux 的强制访问控制模块。它们会限制进程对文件、端口、网络的访问权限。MySQL 安装后即使配置正确也可能因 SELinux 策略阻止mysqld访问/var/lib/mysql或绑定 3306 端口而启动失败。在 RHEL/CentOS 上执行sestatus若输出enabled且current mode为enforcing则需确认 MySQL 策略是否启用sudo semanage port -l | grep mysql。若无输出或端口未列出需手动添加sudo semanage port -a -t mysqld_port_t -p tcp 3306。在 Ubuntu 上执行sudo aa-status查看mysql是否在enforce列表中。若未列出或状态为complain需启用sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld。新手建议在测试环境可临时禁用sudo setenforce 0SELinux或sudo systemctl stop apparmor但生产环境必须配置正确策略而非关闭。2.5 确认系统时间与时区准确性MySQL 8.0 的认证插件caching_sha2_password依赖系统时间进行令牌签名验证。若服务器时间偏差超过 5 分钟客户端连接时可能报错Authentication plugin caching_sha2_password cannot be loaded。执行timedatectl status查看系统时间状态。若System clock synchronized: no需启用 NTP 同步sudo timedatectl set-ntp true。同时确认时区正确timedatectl set-timezone Asia/Shanghai根据实际地区调整。这一步常被忽略却会导致后续所有远程连接失败且错误日志中无明确提示。3. 三种主流安装方式深度对比与实操选择附参数原理市面上常见的安装方式有三种包管理器安装apt/dnf、官方二进制包安装.tar.gz、以及 Docker 容器安装。它们不是简单的“快慢”之分而是适用场景、维护成本、安全边界的根本差异。选错方式后期升级、备份、故障排查的成本会指数级上升。3.1 包管理器安装适合快速验证与开发环境以 Ubuntu 22.04 为例这是最“傻瓜式”的方式但也是最容易踩坑的。apt install mysql-server表面一键背后隐藏着 4 个关键决策点软件源的选择Ubuntu 官方源提供的是经过严格测试的 MySQL 版本但更新滞后。例如 Ubuntu 22.04 LTS 默认提供 MySQL 8.0.33而 Oracle 官网已发布 8.0.36。若需最新安全补丁需添加 MySQL 官方 APT 仓库wget https://dev.mysql.com/get/mysql-apt-config_0.8.24-1_all.deb sudo dpkg -i mysql-apt-config_0.8.24-1_all.deb # 在交互式界面中选择 MySQL Server Cluster然后选择 8.0 sudo apt update此步骤会修改/etc/apt/sources.list.d/mysql.list添加http://repo.mysql.com/apt/ubuntu/源。注意添加第三方源后apt upgrade可能升级整个系统务必在生产环境前测试兼容性。安装过程中的密码策略交互MySQL 8.0 默认启用validate_password插件。apt install过程中会弹出图形化密码设置界面要求输入 root 密码。此时若输入弱密码如123456安装会失败并提示Plugin validate_password is not active。必须输入符合策略的密码至少 8 位含大小写字母、数字、特殊字符各一。若跳过此步后续需手动启用插件并重置密码流程复杂得多。服务启动与状态确认安装完成后systemd会自动启动mysql服务。执行sudo systemctl status mysql查看状态。正常应显示active (running)。若显示failed核心日志在/var/log/mysql/error.log而非journalctl。这是新手最大误区以为journalctl -u mysql是唯一日志源实际上 MySQL 自身错误日志更详细。首次登录与安全加固安装后root 用户默认使用auth_socket插件认证即通过 Unix socket 文件验证而非密码。因此mysql -u root -p会报错Access denied。正确方式是sudo mysql -u root无需密码。进入后执行mysql_secure_installation它会引导你设置 root 密码强度对应 validate_password 策略删除匿名用户DELETE FROM mysql.user WHERE User;禁用远程 root 登录DELETE FROM mysql.user WHERE Userroot AND Host NOT IN (localhost, 127.0.0.1, ::1);删除 test 数据库DROP DATABASE IF EXISTS test; DELETE FROM mysql.db WHERE Dbtest OR Dbtest\\_%;重新加载权限表FLUSH PRIVILEGES;3.2 官方二进制包安装适合生产环境与版本精确控制以 MySQL 8.0.36 为例当你的项目要求特定 MySQL 小版本如必须 8.0.33因某 ORM 框架兼容性问题或需完全掌控安装路径、配置文件位置时二进制包是唯一选择。它绕过包管理器将 MySQL 解压到指定目录所有文件归属清晰升级降级只需替换目录。下载与校验从 MySQL 官网下载页面 选择Linux - Generic下的tarball如mysql-8.0.36-linux-glibc2.12-x86_64.tar.xz。下载后必须校验 SHA256wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.36-linux-glibc2.12-x86_64.tar.xz wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.36-linux-glibc2.12-x86_64.tar.xz.sha256 sha256sum -c mysql-8.0.36-linux-glibc2.12-x86_64.tar.xz.sha256若输出OK方可解压。跳过校验等于将数据库置于风险之中官网下载页提供所有版本的 SHA256 值务必比对。解压与软链接创建解压到/usr/localsudo tar -xf mysql-8.0.36-linux-glibc2.12-x86_64.tar.xz -C /usr/local/ sudo ln -s /usr/local/mysql-8.0.36-linux-glibc2.12-x86_64 /usr/local/mysql创建软链接/usr/local/mysql是关键它让后续所有配置如 PATH、my.cnf 中的 basedir指向一个稳定路径升级时只需修改链接目标。创建用户与目录初始化sudo groupadd mysql sudo useradd -r -g mysql -s /bin/false mysql sudo chown -R mysql:mysql /usr/local/mysql sudo mkdir -p /var/lib/mysql sudo chown mysql:mysql /var/lib/mysql此处useradd -r创建系统用户-s /bin/false禁止其登录 shell符合最小权限原则。/var/lib/mysql必须由mysql用户拥有否则mysqld --initialize会因权限不足失败。生成初始密码与启动服务sudo /usr/local/mysql/bin/mysqld --initialize --usermysql --basedir/usr/local/mysql --datadir/var/lib/mysql此命令会生成随机 root 密码输出类似A temporary password is generated for rootlocalhost: aB3#xY9!mN2该密码仅显示一次必须立即记录。随后启动服务sudo /usr/local/mysql/bin/mysqld_safe --usermysql 但更推荐用systemd管理。创建/etc/systemd/system/mysqld.service[Unit] DescriptionMySQL Server Documentationman:mysqld(8) Afternetwork.target [Service] Typesimple Usermysql Groupmysql ExecStart/usr/local/mysql/bin/mysqld --defaults-file/etc/my.cnf Restarton-failure RestartSec10 [Install] WantedBymulti-user.target启用服务sudo systemctl daemon-reload sudo systemctl enable mysqld sudo systemctl start mysqld。3.3 Docker 安装适合 CI/CD 与微服务架构以 mysql:8.0 镜像为例Docker 安装本质是容器化部署它将 MySQL 运行环境OS、库、配置打包为镜像实现“一次构建随处运行”。但它不解决数据持久化问题若未正确挂载卷容器删除后所有数据将丢失。基础运行与数据卷挂载docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDMyPass123! \ -v /opt/mysql/data:/var/lib/mysql \ -v /opt/mysql/conf:/etc/mysql/conf.d \ -v /opt/mysql/logs:/var/log/mysql \ -d mysql:8.0关键参数解析-v /opt/mysql/data:/var/lib/mysql将宿主机/opt/mysql/data挂载为容器内数据目录确保数据持久化。-v /opt/mysql/conf:/etc/mysql/conf.d挂载自定义配置文件如my.cnf覆盖默认配置。-e MYSQL_ROOT_PASSWORD设置 root 密码必须符合 8.0 密码策略否则容器启动失败并退出。配置文件定制在/opt/mysql/conf/my.cnf中写入[mysqld] bind-address 0.0.0.0 max_connections 200 character-set-server utf8mb4 collation-server utf8mb4_unicode_ci注意bind-address 0.0.0.0允许外部访问生产环境应改为具体 IP 或127.0.0.1并通过 Docker 网络暴露端口。进入容器与验证docker exec -it mysql8 mysql -uroot -pMyPass123!成功后执行SELECT VERSION(), hostname;确认版本与主机名。Docker 方式下localhost指向容器内部若需从宿主机连接应使用127.0.0.1或宿主机 IP。4. 核心配置文件 my.cnf 的 7 个生死攸关参数详解附计算公式my.cnf是 MySQL 的“大脑”90% 的性能问题和连接失败都源于此文件的错误配置。它分为[client]、[mysqld]、[mysqldump]等段落其中[mysqld]段落决定服务行为。以下 7 个参数每个都附带真实场景的计算逻辑和后果分析。4.1innodb_buffer_pool_size内存分配的黄金比例InnoDB 缓冲池是 MySQL 最重要的内存结构用于缓存数据页和索引页。其大小直接影响查询速度。规则专用数据库服务器设为物理内存的 70%-80%混合服务器Web DB设为 50%-60%。计算示例一台 32GB 内存的专用 MySQL 服务器32GB * 0.75 24GB 24 * 1024 24576MB配置为innodb_buffer_pool_size 24576M为什么不能设为 100%因为操作系统、MySQL 其他线程如连接线程、日志线程也需要内存。若缓冲池占满系统会触发 OOM Killer 杀死mysqld进程。我曾在线上环境将此值设为30G32G 服务器结果在高并发时频繁 OOM降为24G后稳定运行 2 年。4.2max_connections连接数的天花板与代价此参数限制 MySQL 同时处理的最大连接数。默认值 151 远低于生产需求。但盲目调高会消耗大量内存每个连接约 256KB-1MB。计算公式最大连接数 ≈ (可用内存 - innodb_buffer_pool_size) / 每连接内存开销假设 32GB 服务器innodb_buffer_pool_size24G剩余 8GB。若每连接平均开销 512KB8GB / 512KB 8 * 1024 * 1024 KB / 512 KB 16384但实际应留出余量设为10000。配置max_connections 10000后果若实际连接数超限新连接会收到Too many connections错误。此时需检查应用层连接池配置而非单纯调高此值。4.3wait_timeout与interactive_timeout连接空闲的“死刑判决”这两个参数控制非交互式wait_timeout和交互式interactive_timeout连接的空闲超时时间秒。默认 28800 秒8 小时。问题在于应用层连接池如 HikariCP的idleTimeout若大于此值连接会被 MySQL 主动断开导致应用报错Connection reset。解决方案将两者设为一致且小于应用连接池的idleTimeout。例如 HikariCP 设idleTimeout3000005 分钟则wait_timeout 300 interactive_timeout 300注意修改后需重启 MySQL 或执行SET GLOBAL wait_timeout300;但后者仅对新连接生效旧连接仍保持原值。4.4character-set-server与collation-server中文乱码的终极解药MySQL 8.0 默认字符集为utf8mb4但许多旧教程仍用utf8实际为utf8mb3导致 emoji 和部分生僻字存储为?。utf8mb4是真正的 UTF-8支持 4 字节字符。配置character-set-server utf8mb4 collation-server utf8mb4_unicode_ci必须配套修改客户端在[client]段落添加[client] default-character-set utf8mb4验证方法连接后执行SHOW VARIABLES LIKE character_set%;所有character_set_*值应为utf8mb4执行SHOW VARIABLES LIKE collation%;collation_server应为utf8mb4_unicode_ci。4.5log-bin开启二进制日志的双刃剑二进制日志binlog是主从复制和基于时间点恢复PITR的基础。但开启后会显著增加磁盘 I/O 和存储开销。配置log-bin /var/lib/mysql/mysql-bin binlog-format ROW expire_logs_days 7log-bin指定 binlog 文件路径必须与datadir不同磁盘避免 I/O 竞争。binlog-format ROW记录行变更比STATEMENT更安全但日志体积更大。expire_logs_days 7自动清理 7 天前的日志防止磁盘爆满。警告开启 binlog 后mysqldump默认添加--master-data2若未配置server-iddump 会失败。需在[mysqld]中添加server-id 14.6innodb_log_file_size事务日志的容量与恢复时间InnoDB 事务日志ib_logfile0, ib_logfile1是 WALWrite-Ahead Logging机制的核心。其大小影响崩溃恢复时间和写入性能。经验法则单个日志文件大小 事务每秒写入量bytes/s × 60 秒。可通过SHOW ENGINE INNODB STATUS\G查看Log sequence number和Log flushed up to的差值估算。若Log sequence number为123456789Log flushed up to为123450000差值6789bytes即每秒写入约 113 bytes显然极低。此时默认48M已足够。但若差值达100000000则需100000000 / 1024 / 1024 ≈ 95MB → 设为 128M配置innodb_log_file_size 128M修改此值需停机先SET GLOBAL innodb_fast_shutdown0;再sudo systemctl stop mysql删除旧日志文件rm /var/lib/mysql/ib_logfile*最后启动。4.7skip-name-resolveDNS 解析的性能杀手MySQL 默认会对每个连接的客户端 IP 执行 DNS 反向解析获取主机名。若 DNS 服务器响应慢或不可达连接会卡住数秒。配置skip-name-resolve后果GRANT语句中的host部分只能使用 IP 地址不能使用主机名。例如GRANT ALL ON *.* TO userweb-server会失效必须改为GRANT ALL ON *.* TO user192.168.1.100。这是生产环境必须开启的参数能将连接建立时间从秒级降至毫秒级。5. 常见故障排查实战手册附日志定位与修复命令再完美的安装也会遇到问题。以下是我在 10 年运维中整理的 7 类高频故障每类都包含现象、日志定位、根本原因和一行修复命令。5.1 服务无法启动Failed to start mysqld.service现象sudo systemctl start mysql返回Job for mysql.service failedsystemctl status mysql显示failed。日志定位sudo journalctl -u mysql -n 50 --no-pager # systemd 日志 sudo tail -n 50 /var/log/mysql/error.log # MySQL 错误日志典型原因与修复原因1/var/lib/mysql权限错误日志线索Cant start server : Bind on unix socket: Permission denied修复sudo chown -R mysql:mysql /var/lib/mysql sudo chmod 750 /var/lib/mysql原因2my.cnf语法错误日志线索Syntax error in config file /etc/my.cnf修复sudo mysqld --defaults-file/etc/my.cnf --validate-config检查语法修正后sudo systemctl daemon-reload原因3端口 3306 被占用日志线索Cant start server : Bind on TCP/IP port: Address already in use修复sudo ss -tuln | grep :3306找出进程sudo kill -9 PID后重试5.2 无法连接Access denied for user rootlocalhost现象mysql -u root -p输入密码后报错。原因分析MySQL 8.0 默认rootlocalhost使用auth_socket插件不校验密码。或密码已重置但未刷新权限。修复流程# 1. 以安全模式启动跳过权限检查 sudo systemctl stop mysql sudo mysqld_safe --skip-grant-tables --skip-networking # 2. 无密码登录 mysql -u root # 3. 更新 root 密码8.0 语法 mysql ALTER USER rootlocalhost IDENTIFIED WITH caching_sha2_password BY NewPass123!; # 4. 刷新权限 mysql FLUSH PRIVILEGES; # 5. 退出并重启 mysql exit sudo kill $(cat /var/run/mysqld/mysqld.pid) sudo systemctl start mysql5.3 远程连接被拒Host xxx is not allowed to connect to this MySQL server现象从其他机器mysql -h server_ip -u root -p失败。根本原因MySQL 默认只允许rootlocalhost未授权远程 IP。修复-- 登录本地 MySQL mysql -u root -p -- 授权远程访问生产环境请用具体 IP 或子网勿用 % mysql CREATE USER root% IDENTIFIED BY StrongPass123!; mysql GRANT ALL PRIVILEGES ON *.* TO root% WITH GRANT OPTION; mysql FLUSH PRIVILEGES;同时检查防火墙sudo ufw status若启用需放行sudo ufw allow 3306。5.4 中文乱码插入中文显示为???现象INSERT INTO test(name) VALUES(张三);查询返回???。日志定位无错误日志纯显示问题。三步诊断法查客户端字符集mysql SHOW VARIABLES LIKE character_set_client;→ 应为utf8mb4查连接字符集mysql SHOW VARIABLES LIKE character_set_connection;→ 应为utf8mb4查结果字符集mysql SHOW VARIABLES LIKE character_set_results;→ 应为utf8mb4修复若任一值非utf8mb4在my.cnf的[client]和[mysqld]段落统一配置并重启。5.5 表损坏Table xxx is marked as crashed and should be repaired现象查询某表时报错提示表损坏。修复命令# 方法1MySQL 命令行修复 mysql REPAIR TABLE database_name.table_name; # 方法2myisamchk 工具仅 MyISAM 表 sudo myisamchk -r /var/lib/mysql/database_name/table_name.MYI # 方法3InnoDB 表损坏需从备份恢复或尝试 mysql SET GLOBAL innodb_force_recovery 1; # 然后导出数据重建表5.6 磁盘满No space left on device现象INSERT失败错误日志出现Disk is full。快速定位# 查看大文件 sudo du -sh /var/lib/mysql/* | sort -hr | head -10 # 查看 binlog 占用 sudo du -sh /var/lib/mysql/mysql-bin.* # 查看慢查询日志 sudo du -sh /var/log/mysql/*.log紧急清理# 清理 binlog保留最近 7 天 mysql -u root -p -e PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY); # 清理慢查询日志 sudo truncate -s 0 /var/log/mysql/mysql-slow.log5.7 性能骤降查询变慢 10 倍现象无代码变更查询响应时间从 100ms 升至 1s。诊断工具链# 1. 查看当前慢查询 mysql SHOW FULL PROCESSLIST; # 2. 查看 InnoDB 状态 mysql SHOW ENGINE INNODB STATUS\G # 3. 查看锁等待 mysql SELECT * FROM information_schema.INNODB_TRX\G # 4. 查看锁冲突 mysql SELECT * FROM information_schema.INNODB_LOCK_WAITS\G常见原因锁等待INNODB_TRX中trx_state为LOCK WAITtrx_mysql_thread_id对应阻塞线程。Buffer Pool 命中率低SHOW ENGINE INNODB STATUS中Buffer pool hit rate 990/1000。全表扫描EXPLAIN显示type: ALL需添加索引。修复针对锁等待KILL trx_mysql_thread_id针对命中率低增大innodb_buffer_pool_size针对全表扫描CREATE INDEX idx_col ON table(col);。6. 安全加固的 5 层防护体系超越mysql_secure_installationmysql_secure_installation只是安全的起点。真正的生产环境需要构建纵深防御体系覆盖网络、认证、权限、审计、备份五个层面。6.1 网络层iptables/firewalld 规则精细化仅开放必要端口拒绝所有其他流量。以 firewalld 为例# 仅允许特定 IP 访问 3306 sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address192.168.1.0/24 port port3306 protocoltcp accept # 拒绝所有其他 3306 访问 sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 port port3306 protocoltcp reject sudo firewall-cmd --reload原理reject比drop更安全它向攻击者发送ICMP unreachable避免扫描器持续探测。6.2 认证层强制使用强密码与双因素MySQL Enterprise开源版 MySQL 不支持 TOTP但可通过 PAM 插件集成系统认证。安装
返回列表