麒麟系统服务启动失败不能仅看“failed”,须四层验证:先用getstatus确认kysec execcontrol是否enforcing,再查service文件user/group与路径权限匹配性,接着用journalctl -u -p err..emerg和ausearch抓取真实拒绝日志,最后sudo -u模拟执行复现原始错误。

麒麟系统服务因权限问题启动失败时,无法仅靠 systemctl status 的“failed”字样判断根源,必须结合 KySec 安全模块、SELinux 策略、文件属主与执行上下文四层权限机制交叉验证。
第一步:确认是否被 KySec 拦截
麒麟 V10 SP1 及后续版本默认启用 KySec 内核安全模块,exec control = enforcing 会直接拒绝非白名单路径下的脚本或二进制执行,且错误提示极隐蔽——不是 Permission denied,而是“解释器错误: 权限不够”或“KYSEC: 权限不够”。
执行 getstatus KySec,检查输出中 execcontrol 是否为 enforcing。
若确认是 enforcing 模式,立即验证该服务的 ExecStart 路径是否在 KySec 白名单内:【KySec 默认白名单不含 /home、/opt/service、/usr/local/bin 等常见自定义路径】。例如,若 service 文件中写的是 ExecStart=/home/appuser/myapp/start.sh,该路径几乎必然被拦。
临时绕过验证:sudo security-switch --set custom --list apparmor(关闭 KySec exec 控制),再 systemctl start 服务。若此时成功,则 100% 确认为 KySec 权限拦截。
第二步:检查服务单元文件中的权限相关配置
方法一:查看 Unit 段是否禁用权限隔离
执行 systemctl cat servicename.service,重点检查 [Unit] 和 [Service] 段。
若存在 NoNewPrivileges=yes 或 ProtectSystem=strict,会导致服务进程无法提升权限访问关键资源;若存在 RestrictSUIDSGID=yes,可能使 setuid 程序失效。
方法二:确认 User 和 Group 设置是否匹配实际文件属主
若服务配置了 User=appuser,但 /opt/myapp 目录属主是 root:root 且无 group 读写权限,则 appuser 进程将无法加载配置或写日志。运行 ls -ld /opt/myapp 验证属主与权限位是否匹配。
方法三:检查 ExecStart 调用链是否隐含权限陷阱
比如 ExecStart=/bin/bash -c 'java -jar /opt/app.jar' —— 此写法会让 bash 进程以服务指定用户身份执行,但 java 二进制本身若在 /usr/lib/jvm/ 下权限收紧(如 750 且 group 不含 appuser),就会触发 Permission denied。应改用绝对路径调用且确保 java 文件对目标用户可执行。
第三步:提取并过滤真实权限拒绝日志
① 执行 journalctl -u servicename -b -p err..emerg,聚焦 error 至 emerg 级别日志。
② 若看到 “Permission denied” 字样,立即追加 -o verbose 查看完整上下文,重点关注 MESSAGE 字段后的 _EXE、_COMM、_UID 字段值。
③ 特别注意以下三类典型报错:
— “openat(AT_FDCWD, \"/etc/myapp/config.yml\", O_RDONLY) = -1 EACCES (Permission denied)”:说明进程 UID 对该配置文件无读权限;
— “chown(\"/var/log/myapp\", 1001, 1001) = -1 EPERM (Operation not permitted)”:说明进程缺少 CAP_CHOWN 能力,或运行在受限命名空间中;
— “execve(\"/home/appuser/bin/start.sh\", [...], [...]) = -1 EACCES (Permission denied)”:这不是脚本没 x 权限,而是 KySec 或 SELinux 明确拒绝 execve 系统调用。
④ 若 journalctl 无有效线索,执行 ausearch -m avc -ts recent | grep servicename(需先确保 auditd 运行),捕获 SELinux 拒绝事件。
第四步:模拟服务执行环境做最小化复现
进入服务配置中指定的 User 和 WorkingDirectory,用相同 UID/GID 手动执行 ExecStart 命令全路径。
例如,若 service 中定义 User=appuser、WorkingDirectory=/opt/myapp、ExecStart=/usr/bin/java -jar app.jar,则切换后执行:
sudo -u appuser -i bash -c 'cd /opt/myapp && /usr/bin/java -jar app.jar'。
这一步能绕过 systemd 的沙箱限制,暴露出原始权限错误——比如 java 命令找不到(PATH 缺失)、jar 包不可读(umask 导致创建时权限为 600)、或 JVM 自身因 /tmp 权限不足无法创建临时目录。
【关键点:systemd 启动的服务不继承用户 ~/.bashrc 中的 PATH,必须在 service 文件中显式声明 Environment=PATH=/usr/local/bin:/usr/bin:/bin】











