很多刚开始接触 Linux 的朋友都有过这种经历:命令背了一堆,ls、cd、cp、mv 用得滚瓜烂熟,可真到了线上服务器上,遇到"机器负载突然飙高""某个服务莫名其妙起不来""远程连不上机器"这三类问题,还是不知道从哪下手。凑巧的是,这三类问题对应的正好是 Linux 运维里最基础也最高频的三项能力:负载监控、服务管理、SSH 工具使用。
我把它们放到一篇文章里讲,是因为在实际工作中这三件事从来不是割裂的。你几乎总是先通过 SSH 连上远程服务器,然后用各种工具观察系统负载,定位到服务异常之后,再用服务管理命令去处理,最后回到 SSH 查看结果。这就是一个完整的远程运维闭环。这篇文章适合刚入行的运维、经常和 Linux 服务器打交道的开发同学,以及自学 Linux 想系统性补基本功的人。我会按自己平时实际操作的顺序来讲,包括一些命令为什么这么选、哪些坑我踩过,尽量不写那些"看起来正确但实际用不上"的废话。
1. 负载监控:先把"负载高"三个字拆开看
1.1 load average 的三个数字,很多人其实没读懂
几乎每篇讲负载监控的文章,都会让你先敲一个命令:
bash复制$ uptime
10:35:22 up 3 days, 4:12, 2 users, load average: 0.82, 0.65, 0.43
load average 后面那三个数字,分别代表过去 1 分钟、5 分钟、15 分钟的系统平均负载。我第一次看到这个输出时以为 0.82 是个"负载百分比",后来才发现完全不是一回事。
准确地说,load average 统计的是处于运行态和不可中断睡眠态的进程数量的时间平均值。通俗讲就是:这段时间里平均有多少个进程在排队等着系统给它们分配资源。这个资源可能是 CPU,也可能是磁盘 IO、锁等待等。所以看到 0.82 时,正确理解是"过去一段时间里平均有 0.82 个进程在排队",而不是"系统负载用了 82%"。
判断负载是否异常,最常见的经验是拿负载值和 CPU 核心数对比。4 核的机器负载长期在 4 左右,基本说明 CPU 被排满;到 8 就意味着排队很严重了。但这个判断有个前提——负载高确实是由 CPU 造成的时候才成立。如果瓶颈在磁盘 IO 或者内存交换,这个对比就没那么直接。这也是我一再强调的原因:load average 只能当"报警器",真正找问题必须往下一层扒。
再补充一点,很多人不知道 /proc/loadavg 这个文件:
bash复制$ cat /proc/loadavg
0.82 0.65 0.43 1/456 3210
前三个数跟 uptime 输出一致;第四列的分子是当前正在运行的进程数,分母是系统总进程数;第五列是最近创建进程的 PID。日常手动看负载用 uptime 就够,但如果你要写监控脚本、做告警采集,很多方案底层读的就是这个文件,知道格式会有帮助。
1.2 看负载的三件套:top、vmstat、iostat怎么配合
刚才说 load average 只是报警器,那真正的"显微镜"是什么?我日常最常用的三个命令是 top、vmstat、iostat,它们各管一段,配合起来基本能覆盖 90% 的负载排查场景。
top 是最直观的动态监控工具。进去之后重点看两个区域:顶部几行的系统汇总,包括 uptime、进程数、CPU 时间占比、内存占用;下面是按资源占用排序的进程列表。我实际排查时会这样操作:
- 按
P键按 CPU 占用排序,看谁在烧 CPU; - 按
M键按内存占用排序,看谁在吃内存; - 按数字
1展开每个 CPU 核心的使用率,判断是不是单核被打满; - 按
z开高亮,按x高亮当前排序列,方便盯关键进程。
top 里特别需要养成习惯看的一个字段是 %wa(IO wait),表示 CPU 等待磁盘 IO 完成的时间占比。这个值如果长期在 30% 以上,基本可以断定磁盘 IO 是当前瓶颈。这时候你死盯着 CPU 占用是找不到答案的,因为 CPU 可能在"干等"。
vmstat 是被很多人低估的命令,它用一行数字就能把系统整体状态说清楚:
bash复制$ vmstat 2 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
3 1 0 120000 30000 5200000 0 0 10 20 100 200 15 10 70 5 0
命令含义是每 2 秒采样一次,一共采样 5 次。我主要看这么几列:
r:运行队列中的进程数,长期大于 CPU 核数说明 CPU 不够用;b:不可中断睡眠状态的进程数,通常和磁盘 IO 强相关;si/so:swap 换入换出的量,持续非零说明内存吃紧,系统在频繁换页;bi/bo:块设备每秒读入/写出的块数,判断磁盘读写压力的直接指标;us/sy:用户态和系统态 CPU 占用,sy 长期超过 20% 就要留意是不是内核层面出问题;wa:CPU 等待 IO 的时间占比,这个数字高配合b列非零,基本坐实 IO 瓶颈。
iostat 则是在确认 IO 有问题之后做进一步细化的工具,能把每块磁盘、每个分区的情况列出来。重点看 %util 和 await。%util 表示磁盘在处理 IO 的时间占比,新手容易以为到 100% 才算满,但如果是 SSD,60% 以上就可能明显影响性能了,因为 SSD 的内部排队和延迟特性和机械盘完全不同。await 是每次 IO 请求的平均处理时间,机械盘正常应该在几毫秒到二十毫秒之间,如果飙到几百毫秒,这盘基本就是"废"了,该考虑换盘或者排查是什么进程在疯狂读写。
1.3 顺着数字往下挖:CPU、内存、IO 的定位思路
光会敲命令还不够,得有一套分析流程把信息串起来。我在实际排障中总结了一个判断顺序,按这个顺序走基本不会乱:
- 先看
uptime确认负载现状,以及 1 分钟、5 分钟、15 分钟的趋势——1 分钟远大于 15 分钟说明是刚突发的问题,三个数都高说明已经持续了一段时间; - 用
vmstat 2 5看全局,重点盯r、b、si/so、wa; - 再用
free -h看内存,确认是不是 swap 在频繁换页; - 顺着上面的指向用
top找具体进程; - 如果疑似磁盘问题,用
iostat -x 1确认是哪块盘、什么指标异常。
这里我想专门说一个特别容易误判的场景:内存问题经常披着"负载高"的外衣。物理内存不够时,系统会启用 swap,而 swap 的读写本质就是磁盘 IO,于是你会看到 si/so 非零、wa 升高、load average 飙升,但 CPU 占用反而不高。这时候从 CPU 方向排查,查多久都是白费。正确思路是看内存占用最大的进程,多半是某个应用内存泄漏把 swap 打满了。这类案例我接手过好几起,最后都靠 top 按 M 排序定位到元凶。
如果你需要看历史趋势而不是当下快照,一定要用 sar。绝大多数发行版都装了 sysstat 包,Debian/Ubuntu 上执行 apt install sysstat,CentOS/RHEL 上执行 yum install sysstat。开启后系统会在后台定时采集数据,之后就能用 sar -q 看历史负载、sar -r 看历史内存、sar -d 看历史磁盘。这个工具对"事后复盘昨天下午服务器为什么卡"非常有用——很多问题发生的时候你不在现场,光靠回忆是还原不出当时的场景的。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 服务管理:用 systemd 把服务装进"笼子"里
2.1 从 service 到 systemctl,命令变化背后的逻辑
这些年 Linux 服务管理最大的变化,就是从 SysVinit 过渡到了 systemd。早年间管理服务靠的是 /etc/init.d/ 下的脚本,起服务用 service nginx start,设开机自启用 chkconfig nginx on,每个脚本自己写一堆 start、stop、restart 的分支逻辑。现在主流发行版基本都用 systemd 了,systemctl 一家通吃。
这个变化的本质,是从"脚本驱动"变成"配置驱动"。SysVinit 时代,每个服务就是一坨 shell 脚本,怎么启停全靠脚本作者自由发挥;systemd 里,每个服务是一个 .service 文件,用声明式配置来描述"这个服务怎么启动、依赖什么东西、崩了要不要拉起来"。systemd 本身作为系统的 1 号进程统一管理所有这些单元,好处是依赖关系清晰、可以并行启动、程序崩溃能自动拉起。理解了这个背景,你就明白为什么现在写服务配置的方式和以前完全不一样了。
2.2 日常操作清单:启动、停止、自启、状态
这里给一份我每天都会用到的 systemctl 操作清单,可以直接收藏。
| 操作 | 命令 |
|---|---|
| 启动服务 | systemctl start nginx |
| 停止服务 | systemctl stop nginx |
| 重启服务 | systemctl restart nginx |
| 重新加载配置 | systemctl reload nginx |
| 设置开机自启 | systemctl enable nginx |
| 取消开机自启 | systemctl disable nginx |
| 查看运行状态 | systemctl status nginx |
| 查看是否开机自启 | systemctl is-enabled nginx |
| 列出失败单元 | systemctl --failed |
| 查看服务日志 | journalctl -u nginx |
有四个细节,是新人最容易掉坑的地方。
第一,reload 和 restart 不是一回事。Nginx、sshd 这类服务支持 reload,让主进程重新读取配置文件,不中断现有连接;restart 是彻底停掉再启动,必然造成短暂中断。生产环境改配置,能 reload 就不要 restart,这是基本素养。
第二,enable 和 start 是两个独立操作。很多人执行完 systemctl start nginx 就以为服务开机自启了,完全不对。enable 才是设置开机自启,start 只是"现在启动这一次"。
第三,systemd 有一套 --user 用户级服务体系。systemctl --user start xxx 是把服务跑在普通用户级别,随用户登录启动、随退出停止。首次使用前要执行 loginctl enable-linger 用户名 开启驻留,否则用户退出登录,服务就跟着停了。这个机制很适合跑个人定时任务、同步脚本这类不需要 root 权限的东西。
第四,systemctl status 显示 active (running) 不代表业务就正常。进程还活着但端口没监听、主进程僵死、子进程变成孤儿,这些情况 status 有时是看不出来的。所以我判断服务是否真的可用,都会再补一句 ss -lntp | grep 端口 确认端口在监听。
2.3 自定义一个 service 文件,把脚本变成受管服务
运维里经常遇到这种需求:"我这个脚本想随系统自启""这个进程崩了能不能自动拉起来"。最干净的做法是写一个 .service 文件,把事情交给 systemd,而不是往 rc.local 里乱塞命令。
假设我们有一个 Python 写的小服务,启动命令是 /usr/local/bin/myapp --config /etc/myapp.conf,那么在 /etc/systemd/system/myapp.service 里写:
ini复制[Unit]
Description=My Custom Application
After=network.target
[Service]
Type=simple
User=myapp
WorkingDirectory=/opt/myapp
ExecStart=/usr/local/bin/myapp --config /etc/myapp.conf
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
几个关键字段说明一下原因。
After=network.target:声明这个服务在网络就绪后再启动,避免脚本一启动就访问网络结果网络还没好。Type=simple:告诉 systemd,ExecStart 启动的这个进程就是主进程。如果程序会先 fork 再脱离终端,则要改成Type=forking并配合PIDFile指定 pid 文件,否则 systemd 跟踪不到主进程,服务状态会乱。User=myapp:指定用普通用户运行,我强烈建议不要把应用直接跑在 root 下,权限太大,出问题影响面也大。Restart=on-failure:进程异常退出时自动拉起,RestartSec=5是重启前等 5 秒。注意不要随手写Restart=always,如果程序因为配置文件错误反复崩溃,它会无限循环重启,把日志打满。WantedBy=multi-user.target:表示在多用户模式下启用,配合systemctl enable生成开机自启的软链接。
写完文件后,一定先执行 systemctl daemon-reload,再 start 和 enable。这个命令漏掉的后果是 systemd 还用旧的配置缓存,你改的字段全都不生效,然后你盯着文件看半天找不到问题。这个"改了没反应"的现象,几乎每个玩 systemd 的人都经历过。
2.4 服务管理里最容易踩的两个坑
第一个坑就是上面说的 daemon-reload,不重复讲了,只说结论:改完 service 文件不 reload,后面所有操作都基于旧配置。
第二个坑是"服务状态 active 但业务就是访问不了"。进程还活着,但监听端口没了,或者主进程已经僵死,这种时候 systemctl status 不一定暴露。我的习惯是第一时间用 ss -lntp 看端口,如果进程在但端口没监听,多半是程序主循环挂了,这时候 systemctl restart 一般能救回来,但一定要去翻 journalctl -u 服务名 -n 100 --no-pager 的日志找根本原因,不能只顾着"重启大法"。
第三个坑和 systemd 无关,但经常被放在一起遇到:journald 日志默认会占用 /var/log/journal 下的磁盘空间,长期不清可能把根分区撑满。我自己会限制 journal 大小,在 /etc/systemd/journald.conf 里设置:
ini复制SystemMaxUse=500M
然后 systemctl restart systemd-journald。限制在 500M 基本够排查问题用了,还能避免日志把系统拖垮。磁盘满导致的"服务起不来""登录卡顿",很多时候根源就是没管住日志。
3. SSH 工具使用:连接、免密、传输、加固一条龙
3.1 SSH 连接的基础姿势与端口参数
SSH 大概是 Linux 运维里使用频率最高的工具,它既是一套协议,也是一组命令行工具。最基本的连接姿势:
bash复制ssh 用户名@主机地址
首次连接时,终端会显示主机指纹并让你确认。输入 yes 后,对方公钥会被记录到本机的 ~/.ssh/known_hosts 里,之后再连就不会询问。这一步其实是整个 SSH 信任链的起点,作用是防止中间人攻击——你确认过的指纹,下次连接时如果变了,SSH 会立刻报警。
如果服务端改了端口,比如 2222,要加 -p:
bash复制ssh -p 2222 用户名@主机地址
刚学的时候我经常把 SSH 和 scp 的端口参数搞混:SSH 的小写 -p 是指定端口,而 scp 里小写 -p 是保留时间戳,scp 指定端口要用大写 -P。这个反人性设定坑了无数人,直到现在我写 scp 还会多看一眼参数。
实际工作中,我不建议长期用裸密码登录,原因下面展开。另外一句题外话,在 Windows 上做开发的同学常用的 VSCode Remote-SSH,本质上就是把本地编辑器连到远程服务器上,底层走的还是这套 SSH 机制。你理解了 ssh 命令,也就理解了它为什么需要你配置密钥、为什么要处理 known_hosts 提示。
3.2 SSH 密钥登录:为什么推荐,以及完整配置流程
密码登录有两个大问题:一是密码容易被暴力破解,二是每次连接都要输入,麻烦且容易被习惯性偷懒简化(比如设个弱密码)。密钥登录的本质,是用一对公私钥做身份认证:公钥放在服务器上,私钥留在本地,连接时服务器拿公钥验证你是否有对应的私钥。私钥本身不通过网络传输,安全性远高于密码。
配置流程并不复杂,我一步步说。
第一步,在本地生成密钥对:
bash复制$ ssh-keygen -t ed25519 -C "your_email@example.com"
一路回车,会在 ~/.ssh/ 下生成 id_ed25519(私钥)和 id_ed25519.pub(公钥)。我推荐优先用 ed25519,密钥短、生成快、安全性不低于 RSA 4096。只有老系统或特殊设备(比如某些交换机和老版本 OpenSSH)不支持时,才退回去用 -t rsa -b 4096。
第二步,把公钥传到服务器:
bash复制$ ssh-copy-id 用户名@主机地址
这个命令会提示输入一次密码,然后把你的公钥追加到服务器 ~/.ssh/authorized_keys 里。如果环境里没有 ssh-copy-id,手动操作也行:把 id_ed25519.pub 内容复制到服务器的 ~/.ssh/authorized_keys,一行一个公钥,注意文件权限最好是 600,目录权限 700。
第三步,再次登录验证。如果还是提示要密码,优先查三件事:authorized_keys 和 ~/.ssh 目录权限是否过宽,~ 目录本身权限是否过宽,SELinux 是否开启。我自己遇到最多的就是目录权限 777,sshd 出于安全考虑会拒绝加载 authorized_keys,表现就是密钥明明放对了,但就是连不上。在 CentOS 这类开了 SELinux 的系统上,修复权限后可能还需要 restorecon -Rv ~/.ssh 恢复上下文。
配置完成后,日常登录不再需要密码,同时还能顺手把 root 密码登录关掉,安全等级直接上一档。这里顺便提一下 Git 使用场景:GitHub、GitLab、Gitee 这类代码平台配置 SSH 免密,走的也是同一套流程,你生成一对新密钥,把公钥贴到平台后台,本地把私钥配给 SSH agent 就行。会了服务器密钥登录,代码平台的 SSH 配置也就自然通了。
3.3 用 ~/.ssh/config 告别长命令,顺便实现批量操作
管理的机器一多,每次 ssh user@ip -p 2222 这种长命令很快就让人烦躁。SSH 支持在 ~/.ssh/config 里定义主机别名,比如:
code复制Host web-prod
HostName 192.168.1.10
Port 22
User deploy
IdentityFile ~/.ssh/id_ed25519
Host db-1
HostName 192.168.1.20
Port 2222
User root
IdentityFile ~/.ssh/db_key
配置完后直接:
bash复制$ ssh web-prod
命令会自动带上 HostName、Port、User 和指定的 IdentityFile。我建议所有经常连服务器的朋友都维护这个文件,它带来的好处不只是省事。同一台机器有多个身份、多把密钥,直接在对应的 Host 配置下写不同 IdentityFile 即可,互不干扰。VSCode Remote-SSH 的配置文件也可以指向同一个文件,改一处全生效。
配合 for 循环,还能实现一个轻量的"批量登录执行命令"效果。比如三台配置相同的服务器别名分别是 node1、node2、node3,想批量看磁盘占用:
bash复制for h in node1 node2 node3; do echo "=== $h ==="; ssh $h 'df -h'; done
几台机器的场景下,这个方式比引入 Ansible 等配置管理工具轻量太多。机器数量超过一定规模,需要批量修改配置了,再考虑上正式的批量工具不迟。
3.4 scp 与 rsync:远程文件传输到底怎么选
SSH 不仅用于执行命令,远程传文件也是高频操作。最基础的是 scp:
bash复制# 本地文件传到服务器
scp ./local_file.txt user@host:/tmp/
# 服务器文件拉到本地
scp user@host:/var/log/nginx/access.log ./nginx_access.log
# 指定端口(注意是大写 -P)
scp -P 2222 ./local_file.txt user@host:/tmp/
传目录加 -r:
bash复制scp -r ./my_dir user@host:/tmp/
但 scp 有个明显短板:不支持增量。文件多、目录大的时候速度堪忧。这种情况我都是用 rsync,它走 SSH 通道,支持增量传输,只同步差异部分:
bash复制rsync -avz --progress ./my_dir/ user@host:/tmp/my_dir/
参数说明:-a 归档模式,保留权限、时间戳、软链接等;-v 显示过程;-z 传输时压缩;--progress 显示进度。尾部目录带不带斜杠意义不同——源目录带斜杠表示同步目录内容,不带斜杠会把目录本身也带过去,这个细节曾经让我多传了一层目录,花了半天才意识到。
图形化 SSH 工具(比如 Bitvise SSH Client、Xshell、FinalShell 这类)一般都自带 SFTP 文件面板,底层同样是 SSH 加密通道,喜欢 GUI 的同学可以用。但我还是建议把 scp/rsync 练熟,因为服务器排障现场往往只有命令行可用,不可能给你一个漂亮的图形界面。
3.5 服务端安全收尾:把入口管住
SSH 服务端核心配置在 /etc/ssh/sshd_config,改完执行 systemctl reload sshd 生效。以下几项是我建议能开就开的安全配置:
ini复制PermitRootLogin prohibit-password
PasswordAuthentication no
PubkeyAuthentication yes
AllowGroups wheel
MaxAuthTries 3
逐个讲下我的理解。
PermitRootLogin prohibit-password 表示 root 只能通过密钥登录,禁止密码登录,但不是彻底禁止 root,兼顾安全性和管理便利。PasswordAuthentication no 是全员禁密码、只认密钥,这是防暴力破解最有效的一招,比换个稀奇古怪的端口管用得多。AllowGroups wheel 进一步限定只有 wheel 组的用户才能 SSH 进来,即使普通用户有密钥也进不来,这就是"设置只有 wheel 组的用户可以 ssh 远程登录"的标准做法。MaxAuthTries 3 限制单次连接尝试次数,增加暴力破解成本。
修改 sshd_config 之前,我有个习惯:先保留一条可用的密钥登录入口,改完用 sshd -t 检查语法无误再 reload。这个命令没有输出就代表配置语法正确。如果不小心把配置写错导致 sshd 起不来,你至少还能走物理控制台或者原有连接进去修复,不至于把自己锁在门外。这个经验真是花了代价换回来的。
另外,群晖 NAS 这类设备上配置 SSH 密钥、欧拉系统离线安装或升级 OpenSSH 包的场景,底层逻辑和上面完全一致,只是包管理器命令不同。理解了这套流程,换什么发行版都是一通百通。
4. 三件套串成一条线:一次远程负载异常的完整排查
4.1 一个真实场景:告警说负载高,但开发说 CPU 没事
假设一个特别常见的场景:晚上九点,监控告警说某台应用服务器 load average 超过 10,开发同事在群里反馈"我上去看了,CPU 没跑满啊,是不是监控误报"。这时候你手上只有 SSH 访问权限,怎么一步步定位?
我不会一上来就 top,而是会走一条完整的链路:连接、看负载、看全局、看细节、定位进程、处理服务、确认恢复。你会发现,这正好把前面讲的 SSH、负载监控、服务管理全部串了起来。
4.2 排查链路逐步演示
第一步,连接。我是配了 config 别名的,直接 ssh web-prod 进服务器。没有配的,就是 ssh user@ip。假设这台机器平时用密钥登录,这一步不会卡在密码上。
第二步,uptime 确认当前负载和趋势。重点比较三个数字。如果 1 分钟值是 8、5 分钟是 5、15 分钟是 3,说明负载是在上涨、刚发生的问题;如果三个值都稳定在 10 以上,说明已经持续一段时间了,可能是某个进程稳定跑满资源。这个趋势判断直接影响后面的处理优先级——突发问题要立刻止损,持续问题可以更从容地定位。
第三步,vmstat 2 5 看全局。我会特别在意 r、b、si/so、wa 这几列。r 高、wa 低说明 CPU 队列问题;b 高、wa 也高说明磁盘 IO 卡住了进程;si/so 持续非零说明内存不够,swap 在拼命换页。这一步已经把排查方向收敛到了 CPU、内存、IO 三者之一,后面就是顺着方向挖细节。
第四步,按方向细化。CPU 方向用 top 看具体进程;内存方向用 free -h 加 top 的 M 排序看大内存占用者;IO 方向用 iostat -x 1 看具体磁盘的 %util 和 await。绝大多数情况下,到这里就能看到元凶了——比如某个 Java 进程 CPU 占用 800%,或者某个日志写入进程把磁盘 %util 打满。
第五步,找到元凶后用服务管理命令处理。如果是一个 systemd 管理的应用进程,我会先 journalctl -u 应用名 -n 100 --no-pager 看最近日志里有没有报错,再决定 restart 还是调整配置。直接 restart 是最快的止损手段,但如果根因是配置不当或者内存泄漏,restart 之后很快会复发,所以日志一定要看。
第六步,确认恢复情况。处理完不要立刻就走,等几分钟再跑一次 uptime 和 vmstat,确认负载降下来了,再 systemctl status 应用名 看服务状态。我见过太多"重启完就溜,第二天又告警"的案例,都在处理完没有做验证环节。
4.3 收尾动作:记录、沉淀、调整监控
排障结束不等于事情结束。我一般会做三个收尾动作。第一,把排查思路和结论记下来,哪怕是简单几行字,下次遇到类似问题直接翻记录,省去重新排查的时间。第二,如果根因是配置问题,把修改后的配置提交到版本库,避免机器重装后"经验消失"。第三,如果问题是突发且难以根治的,先把监控告警阈值调整到合理区间——阈值设得太敏感,半夜全是低频告警,真出事时反而没人注意;阈值太迟钝又起不到预警作用。这个平衡需要结合你自己的业务情况来调。
5. 被线上环境教育出来的几个习惯
5.1 关于负载监控,我学到的三件事
第一,永远不要单看 load average,它只是信号不是答案。第二,看负载指标要连续采样,vmstat 至少间隔 2 秒采十几次,单次输出没有参考价值。第三,把 sar 的历史数据采集打开,事后复盘的价值一点都不比现场抢救低,很多问题当时看不出规律,回头翻历史数据反而一目了然。另外,看 free 的时候要看 available 而不是 free,因为系统会回收 cached/buffered 内存来应急,free 偏低不代表真的内存不足,available 才是真正可用的估算值。
5.2 关于服务管理,我保留的几个底线
修改任何 service 文件后先 daemon-reload,这已经成肌肉记忆了。生产环境能 reload 就不 restart,先把正在服务的连接保住,再谈配置更新。给服务配置重启策略时,on-failure 比 always 稳妥,避免配置错误时无限重启。journald 日志必须配限额,不然日志写满根分区只是时间问题。这三条我用吃亏的经历换回来,写在这里,希望你不用再踩一遍。
5.3 关于 SSH,我最想强调的一点
密钥认证不是锦上添花,而是远程管理的基本盘。禁密码、密钥登录、限定用户组、定期更新 OpenSSH 版本,这四件事做齐了,远程入口才算是基本封闭。把 sshd_config 改好之后,记得开个新终端窗口验证一遍再退出当前会话,确认新配置没问题之前,永远别急着断开你手里那根"安全绳"。这个习惯救过我很多次。
这三项基本功——负载监控、服务管理、SSH 工具使用——是 Linux 服务器日常操作的骨架。它们各自都不难,难的是在真实场景里把它们顺畅地组合起来。多在自己搭的实验环境里模拟几遍"远程登录、发现负载异常、定位进程、处理服务、确认恢复"的完整循环,等真正上了生产环境,你会感谢当初练过这套连招的自己。
