麒麟系统服务调优实战:安全禁用不必要服务的完整指南
1. 为什么“禁用不必要的服务”是系统调优的第一刀很多人拿到一台新装好的系统第一反应是装软件、配环境、跑业务很少有人会先去翻一遍后台到底开了多少服务。我刚开始接触系统运维那几年也是这样觉得“默认开着就开着呗又不影响我用”。直到有一次在一台配置不算低的机器上跑一个本地数据处理任务CPU 和内存都够但响应就是慢半拍排查了半天才发现后台跑着十几个根本用不到的服务光是一个打印相关的守护进程就在那儿反复轮询。把它们关掉之后同样的任务耗时直接降了将近两成。从那以后我养成了一个习惯任何系统交付到我手上第一件事就是过一遍服务列表。“麒麟系统禁用不必要的服务”这件事说白了就是给系统做减法。它不是什么高深的技术但它是性价比最高的调优手段之一。你不需要改内核参数不需要重新编译只需要搞清楚哪些服务是当前场景真正需要的哪些是“装了但永远用不上”的然后把后者关掉。带来的好处是实打实的内存占用下降、启动速度变快、后台 CPU 抖动减少、潜在的攻击面收窄。尤其是最后一点很多人忽略——每一个正在运行的服务都是一个监听端口、一个进程、一份可能被利用的代码关掉它就等于少了一扇可能被撬开的门。这篇文章适合谁看如果你是刚接手麒麟系统的运维新手或者是在国产化环境里做适配的开发者又或者只是想让自己的开发机跑得更清爽一点那这篇内容都能直接拿去用。我会把“怎么判断一个服务该不该关”“怎么关才安全”“关错了怎么救回来”这些实操层面的东西讲透而不是只给你一条命令就完事。因为我自己踩过的坑告诉我禁用服务最大的风险不是关不掉而是关错了导致系统起不来或者某个功能莫名其妙失效所以“怎么安全地关”比“怎么关”重要得多。在展开之前先明确一个前提麒麟系统有多个版本分支桌面版和服务器版的服务集合差别很大不同版本之间默认开启的服务也不完全一样。所以下面讲的方法论是通用的但具体到某个服务名你需要结合自己机器上的实际情况来判断。我不会给你一份“万能禁用清单”因为那种清单在不同场景下可能是灾难——比如你把一台打印服务器的打印服务关了那这台机器就废了。判断的标准永远是“这台机器要干什么”而不是“别人关了我也关”。2. 动手之前先搞清楚系统里到底跑着什么2.1 用 systemctl 摸清服务全貌麒麟系统底层用的是 systemd 作为初始化系统所以管理服务的主力工具就是systemctl。第一步不是急着关而是先看。你得知道现在有哪些服务在跑、哪些是开机自启的、哪些是激活状态但没在跑的。最基础的一条命令systemctl list-units --typeservice --staterunning这条命令列出当前所有正在运行的 service 单元。输出里你会看到 UNIT服务名、LOAD是否加载、ACTIVE活跃状态、SUB子状态、DESCRIPTION描述。重点关注 ACTIVE 是active且 SUB 是running的那些这些就是实打实占着资源的。但光看运行中的还不够因为有些服务现在是停的但开机自启重启之后又会起来。所以要再看一眼开机自启列表systemctl list-unit-files --typeservice --stateenabled这条命令列出所有enabled状态的服务单元文件也就是开机自动启动的。把这两条命令的输出结合起来看你才能得到完整的画面哪些现在在跑哪些将来会跑。我一般会把这两个输出重定向到文件里方便对比systemctl list-units --typeservice --staterunning /tmp/running_services.txt systemctl list-unit-files --typeservice --stateenabled /tmp/enabled_services.txt然后慢慢看。别嫌麻烦这一步花十分钟后面能省你几个小时。2.2 看懂服务之间的依赖关系这是最容易翻车的地方。systemd 的服务不是孤立的它们之间有依赖关系。你关掉一个服务可能会连带影响另一个你需要的服务。比如某些网络管理服务和网络配置工具之间存在依赖你关了前者后者可能就起不来了。查看一个服务的依赖关系systemctl list-dependencies 服务名这条命令会以树状结构展示该服务依赖了哪些其他单元以及哪些单元依赖了它。注意默认展示的是“正向依赖”它需要谁加上--reverse参数可以看到“反向依赖”谁需要它systemctl list-dependencies --reverse 服务名提示在禁用任何服务之前务必先跑一遍反向依赖检查。如果发现有其他你需要的服务依赖它那就不能直接禁用得想别的办法。举个例子假设你想关掉某个和蓝牙相关的服务但你的桌面环境里某个输入设备管理组件依赖它那你关了之后可能发现键盘上的多媒体键失灵了。这种问题不会报错只会让你觉得“怎么突然不好使了”排查起来很费劲。所以依赖检查这一步绝对不能跳过。2.3 区分“服务”和“套接字”“定时器”systemd 管理的单元类型不止 service 一种还有 socket、timer、target 等。有些功能是通过 socket 激活的也就是说服务本身没在跑但对应的 socket 在监听一旦有连接进来就拉起服务。这种情况下你只禁用 service 是不够的还得处理对应的 socket。查看所有 socket 单元systemctl list-units --typesocket --stateactive同理定时器systemctl list-units --typetimer --stateactive我遇到过一种情况明明把某个服务禁用了重启之后发现它又跑起来了查了半天才发现是对应的 socket 单元把它拉起来的。所以禁用服务时要连它的 socket 和 timer 一起看该禁的一块禁掉。3. 判断标准哪些服务可以关哪些碰不得3.1 按使用场景分类判断这是最实用的判断方法。先问自己这台机器是干什么用的如果是桌面办公机那打印服务、蓝牙服务、音频服务、显示管理服务这些通常都要保留因为你日常要用。但像一些服务器端的守护进程、数据库服务、Web 服务如果这台机器不承担这些角色就可以考虑关掉。如果是服务器那桌面相关的服务基本都可以关显示管理器、桌面环境组件、音频服务、打印服务、蓝牙服务这些在服务器上纯属浪费资源。但网络服务、日志服务、安全审计服务这些要保留。如果是开发测试机那要看你在开发什么。做嵌入式的可能保留串口相关服务做 Web 开发的保留网络和数据库服务做数据处理的保留存储和计算相关服务。我整理了一个粗略的判断表供参考服务类别桌面机服务器开发机判断依据显示管理器保留禁用按需服务器无需图形界面打印服务保留禁用按需无打印需求即可关蓝牙服务保留禁用按需无蓝牙设备即可关音频服务保留禁用按需服务器无音频硬件网络管理保留保留保留网络是基础功能日志服务保留保留保留排查问题必需数据库服务按需按需按需看是否本地跑数据库Web 服务按需按需按需看是否本地跑 Web这张表不是绝对的只是一个思考框架。核心逻辑是这台机器上有没有对应的硬件、有没有对应的使用需求。没有硬件支撑的服务开着也是白开没有使用需求的服务开着就是浪费。3.2 通过资源占用反推如果你不确定某个服务要不要关可以看看它占了多少资源。用下面这条命令按内存占用排序查看所有服务systemctl status 服务名或者更直接一点用ps配合排序ps aux --sort-%mem | head -20这条命令列出内存占用最高的 20 个进程。如果某个服务进程排在前列而你又确实用不到它那关掉它的收益就很明显。CPU 占用也是类似ps aux --sort-%cpu | head -20不过要注意CPU 占用是动态的有些服务平时不占 CPU但会定期唤醒做检查这种“间歇性抖动”用ps不一定看得出来。可以用top或者htop观察一段时间看看哪些进程在反复出现。提示不要只看瞬时占用。有些服务内存占用不大但会频繁唤醒 CPU导致功耗上升、响应变慢。这种“隐形消耗”更值得关注。3.3 安全视角减少攻击面从安全角度来说每一个监听网络端口的服务都是一个潜在入口。查看当前监听的端口ss -tlnp或者netstat -tlnp输出里会显示哪些端口在监听、对应哪个进程。然后逐个问自己这个端口需要对外开放吗这个服务需要监听在 0.0.0.0 上吗有些服务默认监听在所有网卡上但实际上只需要本地访问。这种情况下与其关掉服务不如改配置让它只监听 127.0.0.1。但如果是完全用不到的服务那直接关掉更干净。我个人的原则是能不监听就不监听能只监听本地就不监听外部能关掉的服务就不留着。每少一个监听端口就少一份风险。4. 实操安全禁用服务的完整流程4.1 标准操作三步走禁用一个服务标准流程是三步停止、禁用、确认。第一步停止当前运行的服务sudo systemctl stop 服务名第二步禁止开机自启sudo systemctl disable 服务名第三步确认状态systemctl status 服务名如果输出显示inactive (dead)并且Loaded那一行显示disabled那就说明操作成功了。但这里有个细节disable只是取消了开机自启的符号链接服务单元文件本身还在。如果你想更彻底一点可以用mask把它彻底屏蔽sudo systemctl mask 服务名mask会创建一个指向/dev/null的符号链接这样即使有其他服务试图拉起它也拉不起来。适用于那些你确定永远不需要、而且可能被其他服务间接唤醒的服务。对应的取消屏蔽sudo systemctl unmask 服务名注意mask比disable更狠用之前一定要确认这个服务真的永远不需要。我有一次手滑 mask 了一个网络相关的服务结果重启之后网络直接起不来只能进恢复模式救回来。4.2 批量处理时的注意事项如果你要关的服务比较多可以写个脚本批量处理。但批量操作风险更高因为一旦关错了影响面更大。我的建议是分批操作每批不超过三到五个服务每批之后重启验证一次。一个简单的批量停止脚本示例#!/bin/bash SERVICES(服务名1 服务名2 服务名3) for svc in ${SERVICES[]}; do echo 正在处理: $svc sudo systemctl stop $svc sudo systemctl disable $svc systemctl status $svc --no-pager | head -5 echo --- done这个脚本会逐个停止并禁用服务然后打印状态供你确认。注意我加了--no-pager避免systemctl status进入分页模式卡住脚本。但脚本只是提高效率的工具判断哪些服务该关仍然需要你人工来做。不要在网上随便找一份“禁用清单”就照着跑那些清单往往是针对特定场景的放到你的机器上可能完全不适用。4.3 重启验证最关键的一步禁用完服务之后一定要重启验证。因为有些服务之间存在隐式依赖你不重启是发现不了的。sudo reboot重启之后检查系统是否正常启动、网络是否正常、你需要的功能是否正常。然后再次运行systemctl list-units --typeservice --staterunning对比一下重启前后的运行服务列表确认你禁用的服务确实没有起来同时没有意外的服务被连带影响。如果重启之后发现某个功能不正常了别慌进恢复模式或者用 Live 环境挂载硬盘把对应的服务重新启用即可。这也是为什么我建议每次只动少量服务——出问题了容易定位是哪个服务导致的。5. 常见问题与排查技巧实录5.1 禁用后服务又自动起来了这是最常见的问题。原因通常有三种第一种存在 socket 激活。服务本身被禁用了但对应的 socket 还在监听有连接进来时 systemd 会自动拉起服务。解决办法是连 socket 一起禁用sudo systemctl stop 服务名.socket sudo systemctl disable 服务名.socket第二种被其他服务依赖拉起。用前面讲的list-dependencies --reverse检查找到是哪个服务拉起了它然后决定是处理上游服务还是保留这个服务。第三种有定时器在触发。检查对应的 timer 单元systemctl list-timers --all找到相关的定时器后禁用掉。5.2 关错了导致系统异常如果关掉某个服务后发现系统行为异常最快的恢复方式是重新启用并启动sudo systemctl enable 服务名 sudo systemctl start 服务名如果已经严重到进不了系统那就需要进恢复模式。麒麟系统通常可以在启动时通过引导菜单进入恢复模式或者用安装介质启动后挂载根分区进行修复。提示在进行大规模服务禁用之前建议先给系统做一个快照或者备份。虚拟机的话直接打快照物理机的话至少备份一下/etc/systemd/system目录和/etc下的相关配置。5.3 常见问题速查表问题现象可能原因排查命令解决方法服务禁用后自动重启socket 激活systemctl list-units --typesocket禁用对应 socket服务禁用后自动重启被其他服务依赖systemctl list-dependencies --reverse处理上游依赖服务禁用后自动重启定时器触发systemctl list-timers --all禁用对应 timer系统功能异常关错了关键服务journalctl -xe重新启用服务网络不通网络管理服务被关systemctl status NetworkManager重新启用网络服务无法登录图形界面显示管理器被关systemctl status display-manager重新启用显示管理器5.4 我踩过的几个坑第一个坑有一次我把一个看起来“没用”的服务关了结果发现它是某个硬件驱动的依赖导致触摸板失灵。这种问题不会报错只会让你觉得“怎么突然不好使了”。教训是不确定的服务先查资料再动手别凭感觉。第二个坑用mask屏蔽了一个服务后来需要用到时忘了自己 mask 过enable怎么都不生效折腾了半天才想起来要unmask。教训是mask 操作要记下来最好在系统里留个备注文件。第三个坑批量禁用服务后没有重启验证直接交付了。结果客户重启后发现某个功能不可用又来找我。教训是重启验证是必须的不能省。6. 进阶让服务管理更规范6.1 用 preset 管理默认状态systemd 提供了 preset 机制可以定义一组服务的默认启用/禁用状态。查看当前 presetsystemctl preset-all --dry-run这条命令会显示如果应用 preset 规则哪些服务会被启用、哪些会被禁用。你可以根据自己的需求定制 preset 文件放在/etc/systemd/system-preset/目录下。这样做的好处是当你需要批量部署多台机器时可以用同一套 preset 规则保证所有机器的服务状态一致。对于运维来说一致性比省那点资源更重要因为不一致意味着每次排查问题都要考虑“这台机器是不是和别人不一样”。6.2 记录你的变更每次禁用服务都应该记录下来什么时候、禁用了什么、为什么禁用、验证结果如何。可以简单记在一个文本文件里echo $(date %Y-%m-%d %H:%M) 禁用 服务名 原因无打印需求 /root/service_changes.log这个习惯看起来不起眼但当你几个月后回头看或者需要把机器交接给别人的时候这份记录就是救命稻草。我见过太多“前人关了服务没记录后人排查半天”的情况。6.3 定期复查服务需求不是一成不变的。今天不需要的服务明天可能因为业务变化就需要了。所以建议每隔一段时间比如一个季度复查一次服务列表看看有没有需要调整的。复查的时候重点看两件事一是有没有新装的服务默认自启了但你没注意二是有没有之前禁用的服务现在需要重新启用。保持服务列表和实际需求同步才是长久之道。7. 我个人的经验总结做系统调优这么多年我越来越觉得“禁用不必要的服务”这件事技术含量不高但判断含量很高。命令就那几条谁都会敲难的是知道什么该关、什么不该关、什么时候关、关了之后怎么验证。这需要你对系统有整体的理解对业务场景有清晰的认知还需要一点“宁可保守也不要激进”的谨慎。我的建议是新手先从最明显的、最没有争议的服务开始关比如服务器上的蓝牙、打印、音频这些。积累经验之后再逐步深入到网络服务、日志服务这些影响面更大的领域。每次操作都做好记录、做好验证、留好退路。不要追求一次到位追求的是每次操作都可控、可回退。另外不要迷信任何“优化清单”。包括我这篇内容里提到的所有判断都只是参考框架最终决策一定要结合你自己的实际情况。你的机器你最了解别人的清单再详细也不如你自己跑一遍systemctl list-units看得清楚。最后分享一个小技巧如果你不确定某个服务是干什么的可以用systemctl cat 服务名查看它的单元文件内容里面通常有描述信息和启动命令能帮你判断它的用途。再配合man手册和系统日志基本上没有搞不清楚的服务。