Linux查看CPU、内存负载,top命令详解

前言

服务器变慢了?网站卡了?第一反应就是看看 CPU 和内存是不是跑满了。Linux 下最常用的查看系统负载的命令就是 top,相当于 Windows 的任务管理器。但很多人打开 top 后看得一头雾水,不知道各个数字代表什么意思。本文就把 top 命令的输出详解一遍,让你一眼就能看出服务器哪里出了问题。

启动 top 命令

直接在终端输入:

top

就能看到实时的系统监控界面。按 q 键退出。

top 输出详解

top 的输出分为两部分:上面是系统整体信息,下面是各个进程的详细列表。

第一行:系统概况

top - 10:30:45 up 30 days,  2:15,  1 user,  load average: 0.50, 0.40, 0.30
  • 10:30:45:当前系统时间
  • up 30 days, 2:15:系统已经运行了30天2小时15分钟
  • 1 user:当前有1个用户登录
  • load average: 0.50, 0.40, 0.30:系统负载,分别是1分钟、5分钟、15分钟的平均负载

负载怎么看? 负载数值和 CPU 核心数有关。比如4核CPU,负载4.0才算跑满;如果负载超过 CPU 核心数的70%就需要注意了。

第二行:任务进程

Tasks: 120 total,   1 running, 119 sleeping,   0 stopped,   0 zombie
  • 120 total:总共有120个进程
  • 1 running:1个正在运行
  • 119 sleeping:119个休眠中
  • 0 stopped:0个停止
  • 0 zombie:0个僵尸进程

僵尸进程多了要注意,说明有进程没正常退出。

第三行:CPU 使用情况

%Cpu(s):  5.0 us,  2.0 sy,  0.0 ni, 92.0 id,  0.5 wa,  0.0 hi,  0.5 si,  0.0 st
  • us:用户态CPU占用百分比
  • sy:内核态CPU占用百分比
  • ni:改变过优先级的进程占用
  • id:空闲CPU百分比
  • wa:等待I/O的CPU百分比
  • hi:硬中断占用
  • si:软中断占用
  • st:被虚拟机偷走的CPU时间

重点看 us 和 id: 如果 us 很高说明用户进程占了大量CPU;如果 wa 很高说明磁盘I/O是瓶颈。

第四行:内存使用

KiB Mem :  8165036 total,  2000000 free,  4000000 used,  2165036 buff/cache
  • total:总内存
  • free:空闲内存
  • used:已用内存
  • buff/cache:缓存占用

注意: Linux 的内存管理机制和 Windows 不一样,free 很少不代表内存不够用,因为很多内存被用作缓存(buff/cache),需要的时候可以释放出来。

第五行:交换分区

KiB Swap:  2097148 total,  2097148 free,        0 used.  4000000 avail Mem
  • total:交换分区总大小
  • free:空闲交换分区
  • used:已用交换分区
  • avail Mem:可用内存(包括可回收的缓存)

如果 Swap 用了很多,说明物理内存不够用了,系统在把内存数据换到磁盘上,这时候性能会大幅下降。

进程列表

下面是各个进程的详细列表,各列含义:

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
1234 root      20   0  100000  20000   5000 S   5.0  0.2   1:23.45 nginx
  • PID:进程ID
  • USER:进程所属用户
  • PR:进程优先级
  • NI:nice值,负值优先级高
  • VIRT:虚拟内存占用
  • RES:物理内存占用(常驻内存)
  • SHR:共享内存
  • S:进程状态(R运行/S睡眠/D不可中断睡眠/Z僵尸)
  • %CPU:CPU占用百分比
  • %MEM:内存占用百分比
  • TIME+:累计CPU时间
  • COMMAND:进程名

top 常用快捷键

在 top 界面里,可以按这些键进行交互:

按键 功能
P 按CPU占用排序(默认)
M 按内存占用排序
N 按PID排序
1 显示每个CPU核心的详细信息
k 杀掉指定PID的进程
q 退出top
h 显示帮助
d 刷新间隔时间(秒)
u 只显示指定用户的进程
c 显示完整命令行

实际排查案例

案例1:CPU 占用很高

打开 top,按 P 键按CPU排序,看哪个进程占的CPU最多。如果是某个异常进程,按 k 输入PID杀掉。

案例2:内存占用很高

按 M 键按内存排序,看哪个进程占的内存最多。如果是数据库占的内存多,那是正常的(数据库会把数据缓存到内存里)。

案例3:系统负载高但CPU不高

如果 load average 很高,但 %us 和 %sy 都不高,看看 %wa 是不是很高。如果 wa 高,说明是磁盘I/O瓶颈,CPU在等磁盘读写。

常见坑

坑1:把 buff/cache 当成已用内存

很多人看到 free 很少就慌了,觉得内存不够用。其实 Linux 把空闲内存都用来做缓存了,buff/cache 那部分是可以随时回收的。看 avail Mem 那列才是真正可用的内存。

坑2:load average 高就以为CPU不够

负载高不一定是CPU的问题。可能是磁盘I/O瓶颈(%wa高),也可能是大量进程在等待资源。要结合CPU使用率一起看。

坑3:杀进程杀错了

用 k 杀进程的时候一定要确认PID是不是对的,别把系统关键进程杀了。杀错了可能直接导致系统挂掉。

总结

top 命令是 Linux 运维最常用的监控工具,记住几个关键点:

  1. 看负载:load average,和CPU核心数对比
  2. 看CPU:%us 高说明用户进程吃CPU,%wa 高说明磁盘I/O瓶颈
  3. 看内存:看 avail Mem,不要只看 free
  4. 排序:按 P 看CPU占用,按 M 看内存占用
  5. 杀进程:按 k 输入PID

日常排查服务器问题,先打开 top 看一眼,大部分问题都能定位到方向。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-5 07:30 

服务器ssh连接慢,DNS反向解析问题解决办法

前言

有没有遇到过这种情况:SSH 登录服务器的时候,输入密码之前要等好几秒甚至十几秒才出密码提示框?服务器性能明明没问题,网络也不差,但 SSH 就是连得慢。这十有八九是 SSH 在做 DNS 反向解析拖慢了速度。本文就讲一下这个问题的原因和解决办法。

问题现象

正常情况下,SSH 连接服务器应该秒连。但如果你遇到的是这样的情况:

$ ssh root@192.168.1.100
# 这里卡住了 5-10 秒
root@192.168.1.100's password:

输入完 ssh 命令后,要等好几秒才出密码提示,那就大概率是 DNS 反向解析的问题。

为什么会这样

SSH 默认会做一件事:当客户端连接过来时,服务器会根据客户端的 IP 地址反查它的域名(PTR 记录)。这个过程叫反向 DNS 解析。

如果你的服务器 DNS 配置有问题,或者客户端的 IP 没有反向解析记录,这个反查过程就会卡住,直到超时才继续。这就是 SSH 连接慢的根本原因。

解决办法:关闭反向解析

修改 SSH 配置文件,禁用反向 DNS 解析。

1. 编辑 sshd_config

vi /etc/ssh/sshd_config

2. 找到或添加这两行

UseDNS no
GSSAPIAuthentication no
  • UseDNS no:关闭反向 DNS 解析
  • GSSAPIAuthentication no:关闭 GSSAPI 认证(这也会拖慢连接)

3. 重启 SSH 服务

systemctl restart sshd

CentOS7 上是 sshd,Debian/Ubuntu 上是 ssh,别搞混了。

4. 验证

再用 SSH 连一下,应该秒连了。

其他可能导致 SSH 慢的原因

除了 DNS 反向解析,还有几个常见原因也会导致 SSH 连接慢:

1. 反向解析超时时间太长

默认的反向解析超时时间比较长。除了直接关闭 UseDNS,也可以改短超时时间:

UseDNS no

直接关掉是最简单的。

2. GSSAPI 认证

有些系统默认开启了 GSSAPI 认证,这个认证过程也很慢。关掉它:

GSSAPIAuthentication no

3. DNS 服务器配置不对

如果你的服务器 /etc/resolv.conf 里配的 DNS 服务器不通或者很慢,反向解析就会超时。可以改成公共 DNS:

vi /etc/resolv.conf

改成:

nameserver 8.8.8.8
nameserver 114.114.114.114

4. 主机名解析问题

如果服务器的主机名在 /etc/hosts 里没有配置,SSH 启动时可能会卡住。把主机名加到 hosts 文件里:

vi /etc/hosts

加上一行:

127.0.0.1   localhost localhost.localdomain
192.168.1.100   your-hostname

怎么确认是不是 DNS 反向解析的问题

改完配置之前,可以先验证一下是不是这个原因。

方法1:查看 SSH 调试日志

在客户端用 -v 参数连接,看详细日志:

ssh -v root@192.168.1.100

如果日志里有类似这样的输出,就是在做反向解析:

debug1: Remote: /root/.ssh/rc: line 1: message: command not found
debug1: channel 0: free: client-session, nchannels 1

中间如果有停顿,就是在反查 DNS。

方法2:在服务器端看日志

在服务器上看 SSH 日志:

tail -f /var/log/secure

连接的时候如果有 reverse mapping 或 dns 相关的字样,就是 DNS 问题。

常见坑

坑1:改完配置忘了重启 sshd

改完 /etc/ssh/sshd_config 后必须重启 SSH 服务才生效:

systemctl restart sshd

很多人改完就直接测试,发现没效果,以为没改对,其实就是忘了重启。

坑2:把 UseDNS 写成了 UseDns

大小写敏感!必须是 UseDNS no,D 和 N 都要大写。写成 UseDns 或者 usedns 都不生效。

坑3:改完配置连不上了

如果改完 SSH 配置后连不上了,可能是配置写错了。千万不要关掉当前 SSH 窗口!新开一个窗口测试,确认没问题了再关旧窗口。

总结

SSH 连接慢的排查步骤:

  1. 先确认是不是 DNS 反向解析的问题
  2. 修改 /etc/ssh/sshd_config,加 UseDNS no 和 GSSAPIAuthentication no
  3. 重启 sshd 服务
  4. 再连接测试,应该秒连

这是 Linux 服务器最常见的优化之一,改完立竿见影。如果你的服务器 SSH 连接慢,先试试这个方法,90% 的情况都能解决。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-5 07:29 

Linux crontab定时任务不执行常见原因与排查

前言

配置好了 crontab 定时任务,时间也写对了,但到点就是不执行?这是很多新手都会遇到的坑。crontab 不执行的原因五花八门,从最基础的语法错误到环境变量问题,再到 SELinux 拦截,排查起来很费时间。本文把常见的 crontab 不执行原因都整理出来,按排查顺序一步步来,基本能解决 90% 的问题。

第一步:确认 crond 服务是否运行

最基础也是最容易忽略的——定时任务服务本身有没有启动。

systemctl status crond

如果显示 inactive (dead),说明服务没启动,先启动它:

systemctl start crond
systemctl enable crond

CentOS7 上定时服务叫 crond,Debian/Ubuntu 上叫 cron,别搞混了。

第二步:检查 crontab 语法是否正确

1. 查看当前用户的定时任务

crontab -l

2. crontab 时间格式

* * * * * 命令
- - - - -
| | | | |
| | | | ----- 星期几 (0 - 7) (0和7都是周日)
| | | ------- 月份 (1 - 12)
| | --------- 日期 (1 - 31)
| ----------- 小时 (0 - 23)
------------- 分钟 (0 - 59)

3. 常见语法错误

错误1:分钟写在最前面

# 错误:每天9点执行(错的)
0 9 * * * /root/backup.sh

# 正确:每天9点执行
0 9 * * * /root/backup.sh

等等,这个其实是对的。真正容易错的是:

错误2:命令路径用了相对路径

# 错误:crontab 里找不到 mysql 命令
0 9 * * * mysql -u root -p123456 dbname < /root/backup.sql

# 正确:用绝对路径
0 9 * * * /usr/bin/mysql -u root -p123456 dbname < /root/backup.sql

crontab 的环境变量和你手动登录时不一样! 它的 PATH 很精简,很多命令找不到。所以要么用绝对路径,要么在脚本里先 source 环境变量。

第三步:检查脚本本身有没有执行权限

很多人写了脚本,但忘了加执行权限:

ls -l /root/backup.sh

如果没有 x 权限,加上:

chmod +x /root/backup.sh

第四步:检查脚本内容有没有问题

1. 脚本里用了相对路径

# 错误:相对路径在 crontab 里会出问题
cd /var/www/html
tar -zcf backup.tar.gz .

# 正确:用绝对路径
cd /var/www/html
tar -zcf /root/backup.tar.gz .

2. 脚本里用了交互式命令

比如 read、ssh 需要交互输入的命令,在 crontab 里是跑不了的,因为没有终端。

3. 脚本开头没写 shebang

# 正确的 shebang
#!/bin/bash

如果脚本没有 shebang,或者 shebang 写错了,执行就会失败。

第五步:检查日志

crontab 的执行日志默认在 /var/log/cron 里:

tail -100 /var/log/cron

如果日志里显示任务被执行了,但结果不对,那就是脚本本身的问题。

如果日志里压根没有这个任务的记录,那就是 crontab 服务本身的问题或者任务格式不对。

第六步:检查环境变量问题

这是最隐蔽的坑。你手动跑脚本没问题,但 crontab 里就是不行,十有八九是环境变量的问题。

排查方法:在脚本开头加上环境变量

#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

或者直接在 crontab 里指定:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
0 9 * * * /root/backup.sh

第七步:检查 SELinux 是不是拦截了

如果 SELinux 开着,可能会拦截 crontab 的操作。查看日志:

tail -100 /var/log/audit/audit.log | grep crontab

如果看到 denied 字样,就是 SELinux 拦截了。

第八步:检查邮箱通知

crontab 默认会把执行结果(包括错误信息)发到执行用户的邮箱里:

mail

或者看 /var/spool/mail/root 文件:

tail -100 /var/spool/mail/root

这里面通常会有具体的错误信息,是排查的好帮手。

常见坑

坑1:环境变量缺失

这是最常见的坑。你手动跑脚本能成,crontab 里就不行,因为 crontab 的环境变量和你登录 shell 的不一样。

解决: 在脚本开头加上 export PATH=...,或者所有命令都用绝对路径。

坑2:脚本没有执行权限

写完脚本忘了 chmod +x,crontab 当然跑不了。

坑3:重定向丢了

crontab 默认会把输出发到邮箱,如果你不想收邮件,可以重定向:

0 9 * * * /root/backup.sh > /dev/null 2>&1

> /dev/null 是丢弃标准输出,2>&1 是把错误输出也重定向到标准输出。

坑4:时间格式写错了

比如把 * * * * * 写成了 * * * *,少了一个字段,直接就不执行。

坑5:用户写错了

你用 root 用户写的 crontab,但实际是别的用户需要跑,当然不执行。用 crontab -u 用户名 -l 查看对应用户的任务。

总结

crontab 不执行的排查顺序:

  1. 先确认 crond 服务启动了没
  2. 检查 crontab 语法格式对不对
  3. 脚本有没有执行权限
  4. 脚本里的命令是不是都用了绝对路径
  5. 看 /var/log/cron 日志有没有执行记录
  6. 看 /var/spool/mail/root 有没有错误信息
  7. 检查 SELinux 是不是拦截了

按这个顺序排查,基本都能找到原因。记住 crontab 的环境变量和你手动登录时不一样,所有命令都用绝对路径,能避免 80% 的问题。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-5 07:27 

Linux磁盘占用100%怎么排查,大文件查找清理方法

前言

服务器跑着跑着突然网站打不开了,SSH 也反应变慢,一查磁盘使用率 100%。这是运维中非常常见的问题。磁盘满了不仅影响服务正常运行,还可能导致数据丢失、日志写不进去等严重后果。本文就手把手教你怎么快速定位磁盘占用大的文件,以及怎么安全清理。

第一步:查看整体磁盘使用情况

先用 df 命令看看哪个分区满了:

df -h

参数说明:

  • -h:以人类可读的方式显示(G、M)

输出示例:

Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G   38G  2.0G  95% /
devtmpfs        7.8G     0  7.8G   0% /dev
tmpfs           7.8G     0  7.8G   0% /dev/shm
tmpfs           7.8G  480M  7.8G   6% /run
tmpfs           7.8G     0  7.8G   0% /sys/fs/cgroup

看 Use% 那一列,如果哪个分区到了 100% 或者 90% 以上,那就是问题所在。比如上面 /dev/vda1 用了 95%,根分区快满了。

第二步:定位哪个目录占用最大

知道哪个分区满了,接下来找是哪个目录占了最多空间。用 du 命令:

1. 查看根目录下各目录的大小

du -sh /* 2>/dev/null

参数说明:

  • -s:只显示总计,不显示每个子目录
  • -h:人类可读格式
  • 2>/dev/null:忽略权限不足的报错信息

输出示例:

0       /bin
100M    /boot
...
15G     /home
20G     /var
3G      /usr

从输出可以看出 /var 目录占了 20G,是大头。

2. 继续往下查 /var 目录

du -sh /var/* 2>/dev/null | sort -rh | head -10

参数说明:

  • sort -rh:按大小倒序排列
  • head -10:只显示前10个最大的

输出示例:

15G     /var/log
3G      /var/lib
1G      /var/cache
...

继续往下查,直到找到具体是哪个文件最大。

第三步:查找最大的单个文件

如果目录太大不好定位,直接找整个系统里最大的文件:

1. 查找大于100M的文件

find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | awk '{print $5, $9}'

参数说明:

  • -type f:只找文件,不找目录
  • -size +100M:找大于100M的文件
  • 2>/dev/null:忽略权限报错

2. 按大小排序显示前20个最大文件

find / -type f -size +10M -exec ls -lh {} \; 2>/dev/null | sort -k5 -rh | head -20

这样就能列出系统里最大的20个文件,一目了然。

常见的磁盘占用大户

根据经验,Linux 磁盘占用大通常是这几个地方:

1. 日志文件(/var/log)

这是最常见的。服务跑久了日志文件会越来越大,尤其是:

  • Nginx 访问日志、错误日志
  • MySQL 慢查询日志、错误日志
  • 系统日志 messages、syslog

排查方法:

du -sh /var/log/* | sort -rh | head -10

2. 已删除但仍被进程占用的文件

有时候你删掉了大文件,但磁盘空间没释放,因为还有进程在占用这个文件的句柄。

排查方法:

lsof | grep deleted

如果看到很多 deleted 状态的文件,说明有进程占用着已删除的文件。重启对应的进程就能释放空间。

3. 缓存文件(/var/cache)

yum 下载的缓存包、APT 的缓存都在这里,时间久了会积累很多。

清理方法:

yum clean all

4. Docker 镜像和容器

如果用了 Docker,镜像、容器、日志都会占很多空间。

排查方法:

docker system df

清理方法:

docker system prune -a

安全清理方法

找到大文件后,不要直接 rm -rf 删了就完事,要注意安全:

1. 日志文件:清空而不是删除

如果是日志文件,不要删文件本身,而是清空内容:

> /var/log/nginx/access.log

或者:

echo "" > /var/log/nginx/access.log

这样文件还在,但内容清空了,不会影响正在写入的进程。

2. 大文件:先确认再删除

删之前一定要确认这个文件是不是真的不需要了:

ls -lh /path/to/file
head -20 /path/to/file  # 看看内容是什么

确认没问题再删:

rm -f /path/to/file

3. 已删除但被占用的文件

如果删掉文件后空间没释放,找到占用的进程并重启:

lsof | grep deleted
# 找到对应的 PID,重启服务
systemctl restart nginx

常见坑

坑1:用 du 查到的大小和 df 不一致

有时候 df 显示磁盘满了,但 du -sh /* 加起来远没到那个数。这通常是因为:

  • 有已删除但仍被进程占用的文件
  • 挂载点下还有其他挂载

解决: 用 lsof | grep deleted 找被占用的已删除文件,重启对应进程释放空间。

坑2:删了文件空间没释放

这就是上面说的坑——文件被进程占用着,虽然删了但空间没释放。必须重启进程才能释放。

坑3:直接删日志文件导致服务异常

很多人直接 rm -f /var/log/nginx/access.log,结果 Nginx 还在往这个已经不存在的文件里写,日志就丢了。正确做法是清空内容而不是删除文件:> /var/log/nginx/access.log。

总结

排查磁盘占用的标准流程:

  1. df -h 看哪个分区满了
  2. du -sh /* | sort -rh 找最大的目录
  3. find / -type f -size +100M 找最大的文件
  4. 确认文件用途后再清理
  5. 日志文件清空内容,不要直接删文件

日常运维建议配置 logrotate 自动切割日志,避免日志越积越大。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-5 07:26 

CentOS7 关闭SELinux详细步骤,临时+永久关闭

前言

刚装完 CentOS7,部署网站的时候老是遇到各种权限问题:文件明明权限对了还是访问不了,端口也开了就是连不上。排查半天发现是 SELinux 在捣乱。SELinux 是 CentOS 自带的强制访问控制安全机制,安全性很高,但对新手来说确实不太友好。本文详细讲一下怎么临时和永久关闭 SELinux,以及关闭前需要知道的注意事项。

什么是 SELinux

SELinux(Security-Enhanced Linux)是 Linux 内核的一个安全模块,提供强制访问控制(MAC)机制。它比传统的自主访问控制(DAC)更严格,不仅看文件权限,还看进程和文件的安全上下文(SELinux 标签)。

CentOS7 默认开启 SELinux,这也是为什么很多新手部署完网站各种报错的原因——Nginx、PHP、MySQL 的进程和文件上下文不匹配,SELinux 直接拦截。

查看 SELinux 状态

在关闭之前,先看看 SELinux 当前是什么状态:

getenforce

输出可能是:

  • Enforcing:强制模式,SELinux 正在拦截违规操作
  • Permissive:宽容模式,只记录警告不拦截
  • Disabled:已关闭

也可以用这个命令看更详细的信息:

sestatus

输出示例:

SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed

临时关闭 SELinux(重启后失效)

如果你只是临时测试一下,不想改配置文件,可以用这个方法:

setenforce 0

setenforce 0 表示切换到 Permissive 宽容模式,SELinux 不会再拦截操作,但会在日志里记录。这个命令立即生效,不需要重启。

验证一下:

getenforce

应该输出 Permissive。

注意: 这种方式重启服务器后 SELinux 会重新开启,所以只是临时生效。

永久关闭 SELinux(重启后依然关闭)

要永久关闭,需要修改配置文件:

1. 编辑 SELinux 配置文件

vi /etc/selinux/config

2. 修改 SELINUX 的值

找到这一行:

SELINUX=enforcing

改成:

SELINUX=disabled

3. 保存退出,重启服务器

reboot

重启后再验证一下:

getenforce

应该输出 Disabled。

三种模式说明

SELinux 有三种模式,大家可以根据需求选择:

模式 说明
enforcing 强制模式,SELinux 强制执行策略,违规操作直接拦截
permissive 宽容模式,只记录警告日志,不拦截操作
disabled 完全关闭 SELinux

建议: 如果只是临时调试,可以用 permissive 模式,既能放行所有操作,又能通过日志看到哪些操作被 SELinux 拦截了。生产环境如果实在搞不懂 SELinux,再考虑完全关闭。

常见坑

坑1:改了配置文件没重启就以为关了

很多朋友改完 /etc/selinux/config 文件,马上用 getenforce 查看,发现还是 Enforcing,就以为没改成功。其实配置文件改了之后必须重启服务器才会生效。临时生效用 setenforce 0,永久生效必须重启。

坑2:改了 SELINUX=disabled 但还有问题

有时候即使把 SELinux 关了,之前设置的安全上下文标签还在,可能会导致一些奇怪的问题。如果遇到这种情况,可以重启服务器彻底解决。

坑3:生产环境直接关闭有安全风险

SELinux 是一道安全防线,生产环境直接完全关闭会降低系统安全性。建议先尝试把模式改成 permissive,看看日志里哪些操作被拦截了,再针对性地调整上下文标签,而不是直接全部关掉。

总结

CentOS7 关闭 SELinux 的两种方式:

临时关闭(立即生效,重启失效):

setenforce 0

永久关闭(重启后生效):

  1. 编辑 /etc/selinux/config
  2. 把 SELINUX=enforcing 改成 SELINUX=disabled
  3. 重启服务器

新手刚部署完服务器,先临时关了跑通业务,后面再慢慢研究 SELinux 的配置,别一上来就跟它死磕。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-5 07:25 

Linux查看服务器开放端口,netstat和ss命令使用教程

前言

部署完网站后,经常需要确认某个端口是否真的开放了,或者排查服务有没有正常监听。Linux 下最常用的两个工具就是 netstat 和 ss。netstat 是老经典,几乎所有系统都自带;ss 是 iproute2 套件里的新工具,性能更好、信息更全。本文把这两个命令的常用用法都整理出来,新手照着抄就行。

netstat 命令用法

1. 查看所有监听端口

netstat -tlnp

参数说明:

  • -t:只显示 TCP 连接
  • -l:只显示监听状态的端口
  • -n:以数字形式显示端口号,不做域名解析
  • -p:显示占用端口的进程名和 PID

输出示例:

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1234/sshd
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      5678/nginx
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      5678/nginx

2. 查看 UDP 端口

netstat -ulnp

把 -t 换成 -u 就是查看 UDP 端口。

3. 查看所有端口(TCP+UDP)

netstat -tulnp

4. 查看指定端口是否被占用

netstat -tlnp | grep 80

如果 80 端口被占用,会输出对应的进程信息。

5. 查看所有网络连接(不只是监听)

netstat -an

-a 表示显示所有连接,不只是监听状态的。

ss 命令用法

ss 是 netstat 的替代品,在服务器上性能更好,尤其是连接数很多的时候。

1. 查看所有监听端口

ss -tlnp

参数和 netstat 基本一样:

  • -t:TCP
  • -l:监听状态
  • -n:数字形式
  • -p:显示进程

2. 查看 UDP 端口

ss -ulnp

3. 查看所有端口(TCP+UDP)

ss -tulnp

4. 查看指定端口

ss -tlnp | grep 443

5. 查看所有已建立的连接

ss -tn state established

可以用来统计当前服务器有多少个活跃连接。

6. 查看某个IP的连接

ss -tn dst 192.168.1.100

查看和 192.168.1.100 之间的所有连接。

两个命令的区别

对比项 netstat ss
性能 连接数多的时候很慢 非常快
来源 net-tools 包 iproute2 包
兼容性 几乎所有 Linux 都有 新系统默认自带
功能 基础网络查询 更丰富的过滤功能

建议: 日常排查用 ss 更高效,老系统上找不到 ss 再用 netstat。

常见坑

坑1:看不到进程信息

执行 netstat -tlnp 或 ss -tlnp 时,如果看不到 PID/Program name 那一列,说明你不是 root 用户。加上 sudo 再执行:

sudo netstat -tlnp
sudo ss -tlnp

坑2:端口显示是 :: 而不是 0.0.0.0

0.0.0.0:80 表示监听所有 IPv4 地址的 80 端口;:::80 表示监听所有 IPv6 地址的 80 端口(同时也兼容 IPv4)。这两种都能从外网访问,不用担心。

坑3:查不到端口但服务明明启动了

检查一下服务是不是只监听了 127.0.0.1。如果 Local Address 显示的是 127.0.0.1:80,那外网是访问不了的,只能本机访问。需要修改服务配置监听 0.0.0.0。

总结

查看 Linux 开放端口记住这几个核心命令就够了:

  • 常用查看:ss -tlnp 或 netstat -tlnp
  • 查指定端口:ss -tlnp | grep 端口号
  • 查UDP端口:ss -ulnp

日常排查优先用 ss,速度快信息全;老系统没 ss 再用 netstat。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-5 07:24 

CentOS7 firewalld开放80、443端口永久生效命令

前言

刚装好 CentOS7 服务器,部署完 Nginx 网站后,外网却访问不了?十有八九是防火墙没放行端口。CentOS7 默认用 firewalld 代替了旧版的 iptables,很多刚接触的朋友不太熟悉操作。本文就详细讲解如何在 CentOS7 上永久开放 80、443 等常用端口,以及操作中容易踩的坑。

操作步骤

1. 检查 firewalld 运行状态

首先确认防火墙服务是否正在运行:

systemctl status firewalld

如果显示 active (running) 说明防火墙已启动。如果没启动,先启动它:

systemctl start firewalld
systemctl enable firewalld

2. 查看当前已开放的端口

firewall-cmd --list-ports

这个命令会列出当前防火墙放行的所有端口。

3. 永久开放 80 端口

firewall-cmd --permanent --add-port=80/tcp

参数说明:

  • --permanent:永久生效,不加这个参数重启防火墙后就失效
  • --add-port=80/tcp:开放 80 端口,协议为 TCP

4. 永久开放 443 端口

firewall-cmd --permanent --add-port=443/tcp

5. 同时开放多个端口

如果需要一次性开放多个端口,可以这样写:

firewall-cmd --permanent --add-port=80/tcp --add-port=443/tcp --add-port=8080/tcp

6. 开放端口范围

如果要开放一整段端口,比如 3000 到 4000:

firewall-cmd --permanent --add-port=3000-4000/tcp

7. 重载防火墙使配置生效

修改完规则后,必须重载才能生效:

firewall-cmd --reload

8. 验证端口是否开放成功

firewall-cmd --list-ports

如果输出里能看到 80/tcp 443/tcp 就说明开放成功了。

9. 移除开放的端口(如果需要)

firewall-cmd --permanent --remove-port=8080/tcp
firewall-cmd --reload

常见坑

坑1:忘了加 --permanent 参数

很多朋友执行了 firewall-cmd --add-port=80/tcp,当时测试是通的,但重启服务器或者重启防火墙后就又不通了。原因就是没加 --permanent,这种方式只是临时生效,重启后规则丢失。

解决: 开放端口时一定要加 --permanent 参数,然后执行 firewall-cmd --reload 重载配置。

坑2:改完规则忘了 reload

执行完 --add-port 后,规则只是写入了配置文件,还没有真正生效。必须执行 firewall-cmd --reload 才能让新规则生效。

坑3:以为开放了端口就一定能访问

防火墙只是第一道关卡。如果网站还是访问不了,还要检查:

  1. Nginx/Apache 是否启动并监听了对应端口
  2. 安全组(云服务器)是否也放行了端口
  3. 服务器内部的应用是否正常运行

坑4:用了 iptables 命令却不生效

CentOS7 默认是 firewalld 管理防火墙,如果你用 iptables 命令添加规则,firewalld 重启后会把规则覆盖掉。要么用 firewalld 命令,要么先关掉 firewalld 再用 iptables。

总结

CentOS7 开放端口的核心命令就是三步:

  1. firewall-cmd --permanent --add-port=端口号/tcp 添加规则
  2. firewall-cmd --reload 重载生效
  3. firewall-cmd --list-ports 验证结果

记住 --permanent 和 --reload 这两个关键点,90% 的问题都能解决。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-5 07:23 

Nginx报502 Bad Gateway完整排查思路(PHP-FPM场景)

Nginx 出现 502 Bad Gateway 是最常见的报错之一,90% 的情况都是 PHP-FPM 出了问题。下面是完整的排查思路,按顺序一步步来,基本都能解决。

1. 先看 PHP-FPM 是否在运行

systemctl status php-fpm

如果显示 failed 或 inactive,直接重启:

systemctl restart php-fpm

注意:CentOS 7 一般是 php-fpm,Ubuntu 可能是 php7.4-fpm 之类的,看你装的版本。

2. 看 Nginx 错误日志(最关键)

tail -f /var/log/nginx/error.log

常见错误信息:

错误1:connect() failed (111: Connection refused) while connecting to upstream
说明 PHP-FPM 没启动,或者监听地址不对。

错误2:upstream timed out
PHP 脚本执行超时了,或者 PHP-FPM 进程不够用。

错误3:Primary script unknown
Nginx 配置里的 SCRIPT_FILENAME 路径不对,找不到 PHP 文件。

3. 检查 Nginx 配置是否正确

nginx -t

如果显示 test is successful 说明配置语法没问题。

重点检查 fastcgi_pass 这一行:

location ~ \.php$ {
    fastcgi_pass   127.0.0.1:9000;  # 或者 unix:/run/php-fpm/www.sock
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

常见问题:

  • fastcgi_pass 地址和 PHP-FPM 实际监听地址不一致
  • SCRIPT_FILENAME 路径写错了

4. 检查 PHP-FPM 监听地址

netstat -tlnp | grep php-fpm

或者:

ss -tlnp | grep php-fpm

看 PHP-FPM 是监听在 9000 端口还是 unix sock 文件,然后和 Nginx 配置里的 fastcgi_pass 对应上。

5. 检查 PHP-FPM 进程数是否够

看 PHP-FPM 配置:

vi /etc/php-fpm.d/www.conf

重点参数:

pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30

如果访问量大,进程数不够就会 502。

6. 检查 PHP 错误日志

tail -f /var/log/php-fpm/www-error.log

有时候 PHP 代码本身报错,也会导致 502。

7. 其他常见原因

磁盘满了

df -h

内存不够

free -h

如果内存不足,PHP-FPM 进程会被杀掉,也会 502。

SELinux 没关
参考我之前的文章,关掉 SELinux 试试。

排查顺序总结

  1. 重启 PHP-FPM → 看能不能恢复
  2. 看 Nginx 错误日志 → 定位具体错误
  3. 检查 Nginx 配置 → fastcgi_pass 和 SCRIPT_FILENAME
  4. 检查 PHP-FPM 状态 → 监听地址、进程数
  5. 检查系统资源 → 磁盘、内存
  6. 检查 SELinux

遇到服务器、Nginx、MySQL 报错,可以加微信远程协助排查问题。


emer 发布于  2026-10-4 19:27 

CentOS7 firewalld开放80、443端口永久生效命令

CentOS 7 默认使用 firewalld 作为防火墙管理工具。很多新手搭建网站后发现外网访问不了,90% 都是因为 80、443 端口没开放。下面是完整的操作步骤,照抄就能用。

1. 先确认防火墙状态

systemctl status firewalld

如果显示 active (running) 说明防火墙正在运行,需要继续下面的操作。如果是 inactive 那就是防火墙没开,问题不在这里。

2. 开放 80 端口(HTTP)

firewall-cmd --zone=public --add-port=80/tcp --permanent

参数说明:

  • --zone=public:作用域为公共区域
  • --add-port=80/tcp:开放 80 端口,TCP 协议
  • --permanent:永久生效,不加这个重启服务器就失效了

3. 开放 443 端口(HTTPS)

firewall-cmd --zone=public --add-port=443/tcp --permanent

4. 一次性开放多个端口

如果需要同时开放多个端口,可以一条命令搞定:

firewall-cmd --zone=public --add-port=80/tcp --add-port=443/tcp --permanent

5. 重载防火墙使配置生效

⚠️ 重点:开放端口后必须重载,否则不生效!

firewall-cmd --reload

6. 查看已开放的端口

确认一下端口有没有真正开放成功:

firewall-cmd --list-ports

正常会输出类似:

80/tcp 443/tcp

7. 常用其他端口开放命令

SSH 端口(默认22,建议改成别的):

firewall-cmd --zone=public --add-port=22/tcp --permanent

MySQL 端口(如果需要远程连接数据库):

firewall-cmd --zone=public --add-port=3306/tcp --permanent

Redis 端口:

firewall-cmd --zone=public --add-port=6379/tcp --permanent

8. 移除/关闭已开放的端口

如果某个端口不需要了,想关掉:

firewall-cmd --zone=public --remove-port=8080/tcp --permanent
firewall-cmd --reload

常见坑

  1. 加了 --permanent 还是不生效?
    忘记 firewall-cmd --reload 了。永久配置写入后必须重载才会加载到运行时。

  2. 端口开放了还是访问不了?
    检查云服务商的安全组(阿里云/腾讯云/华为云都有这个东西),防火墙和安全组是两层,都要开。

  3. firewalld 命令找不到?
    CentOS 7 最小化安装可能没装,执行 yum install firewalld -y 安装。

  4. 临时开放端口(重启就失效)
    去掉 --permanent 参数就是临时开放,重启或 reload 后自动关闭。


遇到服务器、Nginx、MySQL 报错,可以加微信远程协助排查问题。


emer 发布于  2026-10-4 19:22 

MySQL 索引优化技巧

MySQL 索引优化技巧

索引是数据库性能的关键,加对了查询快十倍,加错了反而更慢。

1. 索引类型

主键索引:主键自带索引,一张表只能一个。

普通索引:最基本的索引,加速查询。

CREATE INDEX idx_name ON user(name);

唯一索引:字段值不能重复。

CREATE UNIQUE INDEX idx_email ON user(email);

联合索引:多个字段组合的索引。

CREATE INDEX idx_name_age ON user(name, age);

2. 索引失效的情况

1)like 以 % 开头

-- 索引失效
SELECT * FROM user WHERE name LIKE '%张';

-- 索引生效
SELECT * FROM user WHERE name LIKE '张%';

2)对字段做函数运算

-- 索引失效
SELECT * FROM user WHERE LEFT(name,1) = '张';

-- 索引生效
SELECT * FROM user WHERE name LIKE '张%';

3)联合索引不满足最左前缀

联合索引 (name, age):

-- 生效
SELECT * FROM user WHERE name = '张三';

-- 生效
SELECT * FROM user WHERE name = '张三' AND age = 25;

-- 失效
SELECT * FROM user WHERE age = 25;

4)隐式类型转换

-- phone 是 varchar
-- 索引失效
SELECT * FROM user WHERE phone = 13800001111;

-- 索引生效
SELECT * FROM user WHERE phone = '13800001111';

3. 查看索引使用情况

-- 查看执行计划
EXPLAIN SELECT * FROM user WHERE name = '张三';

-- 重点看 type 字段:
-- system > const > eq_ref > ref > range > index > ALL
-- 最差是 ALL(全表扫描)

4. 索引优化原则

  • 为高频查询加索引:不要乱加
  • 区分度高的字段优先:性别这种区分度低的不加
  • 联合索引把最常用的放左边
  • 索引不是越多越好:增删改会变慢
  • 避免索引冗余:(a,b) 包含了 (a)

5. 慢查询排查

-- 开启慢查询
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 2;

-- 查看慢查询日志
SHOW VARIABLES LIKE 'slow_query_log_file';

总结

MySQL 索引优化核心:

  • 联合索引满足最左前缀
  • like 不要以 % 开头
  • 不要对字段做函数运算
  • 用 EXPLAIN 看执行计划
  • 慢查询找出来再优化

搞懂这些,数据库性能提升一大截。


emer 发布于  2026-10-4 11:12 

Git 常用命令汇总

Git 常用命令汇总

Git 是现在开发必备工具,整理一份常用命令清单,收藏备用。

1. 初始化和克隆

# 初始化新仓库
git init

# 克隆远程仓库
git clone https://github.com/user/repo.git

# 克隆指定分支
git clone -b dev https://github.com/user/repo.git

2. 查看状态

# 查看工作区状态
git status

# 查看提交历史
git log

# 查看简洁历史
git log --oneline --graph

# 查看文件改动
git diff

3. 添加和提交

# 添加所有文件到暂存区
git add .

# 添加指定文件
git add file.php

# 提交到本地仓库
git commit -m "修复bug"

# 提交并跳过验证
git commit --no-verify -m "修复bug"

4. 分支操作

# 查看本地分支
git branch

# 查看所有分支(包括远程)
git branch -a

# 创建新分支
git branch dev

# 切换分支
git checkout dev

# 创建并切换分支
git checkout -b dev

# 删除分支
git branch -d dev

# 强制删除分支
git branch -D dev

5. 远程操作

# 拉取远程更新
git pull

# 推送本地提交
git push

# 推送本地新分支到远程
git push -u origin dev

# 删除远程分支
git push origin --delete dev

6. 撤销操作

# 撤销工作区修改
git checkout -- file.php

# 撤销暂存区
git reset HEAD file.php

# 回退到上一个版本
git reset --hard HEAD^

# 回退到指定版本
git reset --hard commit_id

# 撤销上次提交(保留修改)
git reset --soft HEAD^

7. 合并和变基

# 合并分支
git merge dev

# 变基
git rebase master

# 取消合并
git merge --abort

8. 标签操作

# 打标签
git tag v1.0.0

# 查看标签
git tag

# 推送标签
git push origin v1.0.0

# 推送所有标签
git push origin --tags

总结

Git 常用命令核心:

  • 查看:status / log / diff
  • 提交:add / commit
  • 分支:branch / checkout / merge
  • 远程:pull / push
  • 撤销:reset / checkout

记住这些,日常 Git 操作基本够用了。


emer 发布于  2026-10-4 11:11 

Nginx 日志分析技巧

Nginx 日志分析技巧

Nginx 日志是排查问题、分析流量的重要工具。学会看日志,网站问题排查效率翻倍。

1. 日志位置

# 默认访问日志
/var/log/nginx/access.log

# 默认错误日志
/var/log/nginx/error.log

可以在 nginx.conf 里自定义:

access_log /var/log/nginx/www.access.log;
error_log /var/log/nginx/www.error.log;

2. 日志格式

默认日志格式:

127.0.0.1 - - [04/Oct/2026:10:00:00 +0800] "GET / HTTP/1.1" 200 612 "https://www.baidu.com/" "Mozilla/5.0..."

各字段含义:

  • IP 地址
  • 请求时间
  • 请求方法和路径
  • 状态码
  • 响应大小
  • 来源页面
  • User-Agent

3. 常用分析命令

# 查看访问量前10的IP
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head 10

# 查看访问量前10的页面
awk '{print $7}' access.log | sort | uniq -c | sort -nr | head 10

# 查看状态码分布
awk '{print $9}' access.log | sort | uniq -c | sort -nr

# 查看 404 请求
grep ' 404 ' access.log

# 查看 502 错误
grep ' 502 ' access.log

4. 排查问题

排查 502 错误:

grep ' 502 ' access.log | tail 20

排查慢请求:
开启慢日志:

slow_request_log /var/log/nginx/slow.log;
slow_request_time 5s;

排查爬虫:

grep 'Baiduspider' access.log
grep 'Googlebot' access.log

5. 流量统计

# 今天总访问量
grep '04/Oct/2026' access.log | wc -l

# 今天总流量
grep '04/Oct/2026' access.log | awk '{sum+=$10} END {print sum/1024/1024 " MB"}'

# 每小时访问量
awk '{print $4}' access.log | cut -d: -f2 | uniq -c

6. 日志切割

日志太大要切割,用 logrotate:

# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    missingok
    rotate 30
    compress
    notifempty
    create 0640 nginx adm
    postrotate
        systemctl reload nginx
    endscript
}

7. 常用工具

  • GoAccess:实时日志分析工具
  • ELK:Elasticsearch + Logstash + Kibana
  • Zabbix:监控告警

总结

Nginx 日志分析核心:

  • 位置:/var/log/nginx/
  • 命令:awk + sort + uniq
  • 排查:看状态码、看慢请求
  • 切割:用 logrotate

学会这些,日常日志分析基本够用了。


emer 发布于  2026-10-4 11:08 

Docker 常用命令大全

Docker 常用命令大全

Docker 命令不多,但记不住还是很麻烦。整理一份常用命令清单,收藏备用。

1. 镜像命令

# 拉取镜像
docker pull nginx:latest

# 查看本地镜像
docker images

# 删除镜像
docker rmi nginx:latest

# 搜索镜像
docker search nginx

# 导出镜像
docker save -o nginx.tar nginx:latest

# 导入镜像
docker load -i nginx.tar

2. 容器命令

# 启动容器(后台运行)
docker run -d --name mynginx -p 80:80 nginx

# 查看运行中的容器
docker ps

# 查看所有容器(包括停止的)
docker ps -a

# 停止容器
docker stop mynginx

# 启动已停止的容器
docker start mynginx

# 重启容器
docker restart mynginx

# 删除容器
docker rm mynginx

# 强制删除运行中的容器
docker rm -f mynginx

3. 进入容器

# 进入容器(bash)
docker exec -it mynginx bash

# 进入容器(sh)
docker exec -it mynginx sh

# 查看容器日志
docker logs mynginx

# 实时查看日志
docker logs -f mynginx

# 查看容器详情
docker inspect mynginx

4. 文件操作

# 从容器复制文件到宿主机
docker cp mynginx:/etc/nginx/nginx.conf ./

# 从宿主机复制文件到容器
docker cp ./index.html mynginx:/usr/share/nginx/html/

5. 端口和网络

# 查看容器端口映射
docker port mynginx

# 查看容器 IP
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mynginx

6. 清理命令

# 停止所有容器
docker stop $(docker ps -q)

# 删除所有停止的容器
docker container prune

# 删除所有未使用的镜像
docker image prune

# 删除所有未使用的资源(危险操作)
docker system prune -a

7. Docker Compose 常用命令

# 启动所有服务
docker-compose up -d

# 停止所有服务
docker-compose down

# 查看服务状态
docker-compose ps

# 查看日志
docker-compose logs -f

# 重启某个服务
docker-compose restart nginx

总结

Docker 常用命令核心:

  • 镜像:pull / images / rmi
  • 容器:run / ps / stop / start / rm
  • 进入:exec -it
  • 日志:logs -f
  • 清理:prune

记住这些,日常 Docker 操作基本够用了。


emer 发布于  2026-10-4 11:07 

PHP Composer 入门指南

PHP Composer 入门指南

Composer 是 PHP 的依赖管理工具,现在做 PHP 开发不用 Composer 几乎不可能。

1. 安装 Composer

# Linux/Mac
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

# Windows 直接下载安装包
# https://getcomposer.org/Composer-Setup.exe

验证安装:

composer -V

2. 换国内镜像(必须)

官方镜像太慢,一定要换国内镜像:

# 阿里云镜像
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

# 腾讯云镜像
composer config -g repo.packagist composer https://mirrors.tencent.com/composer/

3. 初始化项目

# 进入项目目录
cd myproject

# 初始化 composer.json
composer init

或者手动创建 composer.json:

{
    "name": "my/project",
    "require": {
        "monolog/monolog": "^2.0"
    }
}

4. 常用命令

# 安装依赖
composer install

# 更新依赖
composer update

# 安装某个包
composer require monolog/monolog

# 卸载某个包
composer remove monolog/monolog

# 自动加载
composer dump-autoload

5. 自动加载

// 引入自动加载文件
require __DIR__ . '/vendor/autoload.php';

// 然后就可以直接用第三方库了
$log = new Monolog\Logger('name');

6. composer.json 详解

{
    "name": "项目名",
    "description": "项目描述",
    "type": "project",
    "require": {
        "php": ">=7.4",
        "monolog/monolog": "^2.0",
        "guzzlehttp/guzzle": "^7.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

7. 版本号说明

  • ^2.0:兼容 2.0 到 3.0(不包含 3.0)
  • ~2.0:兼容 2.0 到 2.1(不包含 2.1)
  • *:任意版本
  • 2.0.*:2.0.x 版本

总结

Composer 核心:

  • 安装:一行命令
  • 换镜像:必须换国内源
  • 常用:install / update / require / remove
  • 自动加载:require vendor/autoload.php

搞懂这些,Composer 日常开发就够用了。


emer 发布于  2026-10-4 11:06 

MySQL 事务隔离级别

MySQL 事务隔离级别详解

事务是数据库并发控制的基础,搞懂四个隔离级别,才能解决脏读、幻读问题。

1. 事务 ACID 特性

  • 原子性(Atomicity):要么全成功,要么全回滚
  • 一致性(Consistency):事务前后数据一致
  • 隔离性(Isolation):事务之间互不干扰
  • 持久性(Durability):提交后永久保存

2. 四种隔离级别

MySQL 有四种隔离级别,从上到下越来越严格:

读未提交(READ UNCOMMITTED)

  • 可以读到别人还没提交的数据
  • 会出现脏读
  • 几乎没人用

读提交(READ COMMITTED)

  • 只能读到别人已经提交的数据
  • 解决了脏读,但会出现不可重复读
  • Oracle、SQL Server 默认级别

可重复读(REPEATABLE READ)

  • 同一个事务里,读多次结果都一样
  • 解决了脏读、不可重复读
  • MySQL InnoDB 默认级别
  • InnoDB 用间隙锁解决了幻读

串行化(SERIALIZABLE)

  • 事务一个一个排队执行
  • 最安全,但性能最差
  • 几乎没人用

3. 三种读问题

脏读:读到了别人还没提交的数据,别人回滚了,你读到的就是脏数据。

不可重复读:同一个事务里,两次读同一行数据,结果不一样(别人中间改了并提交了)。

幻读:同一个事务里,两次查同一个范围,行数不一样(别人中间插了新行)。

4. 查看和设置隔离级别

-- 查看当前隔离级别
SELECT @@global.tx_isolation;
SELECT @@session.tx_isolation;

-- 设置全局隔离级别
SET GLOBAL tx_isolation = 'READ-COMMITTED';

-- 设置当前会话隔离级别
SET SESSION tx_isolation = 'READ-COMMITTED';

5. 实际应用建议

  • 默认就好:MySQL 默认的可重复读已经够用
  • 高并发场景:可以降到读提交,提升并发性能
  • 金融级场景:用串行化,绝对安全
  • 大多数业务:默认级别就行,不用折腾

6. 代码示例

// PDO 事务示例
try {
    $pdo->beginTransaction();

    $pdo->exec("UPDATE account SET money = money - 100 WHERE id = 1");
    $pdo->exec("UPDATE account SET money = money + 100 WHERE id = 2");

    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    echo "转账失败:" . $e->getMessage();
}

总结

MySQL 事务隔离级别核心:

  • 读未提交:脏读
  • 读提交:不可重复读
  • 可重复读:默认级别,解决幻读
  • 串行化:最安全最慢

大多数业务用默认的可重复读就够了。


emer 发布于  2026-10-4 11:05 

PHP 字符串处理技巧

PHP 字符串处理常用技巧

字符串处理是 PHP 开发最常用的操作,掌握这些函数,写代码效率翻倍。

1. 截取字符串

// 截取前 5 个字符
substr("hello world", 0, 5); // hello

// 截取从第 6 个开始到结尾
substr("hello world", 6); // world

// 中文字符串截取(用 mb_)
mb_substr("你好世界", 0, 2, "UTF-8"); // 你好

注意:中文要用 mb_substr,不能用 substr,否则会乱码。

2. 替换字符串

//  str_replace(替换所有)
str_replace("world", "PHP", "hello world"); // hello PHP

//  str_ireplace(不区分大小写)
str_ireplace("WORLD", "PHP", "hello world");

//  preg_replace(正则替换)
preg_replace("/\d/", "", "abc123def"); // abcdef

3. 查找字符串

// 查找位置(找不到返回 false)
strpos("hello world", "world"); // 6

// 查找最后出现位置
strrpos("hello world hello", "hello"); // 12

// 判断是否包含(PHP 8+)
str_contains("hello world", "world"); // true

// 判断开头
str_starts_with("hello world", "hello"); // true

// 判断结尾
str_ends_with("hello world", "world"); // true

4. 格式化字符串

// 去除首尾空格
trim("  hello  "); // hello

// 只去左边/右边
ltrim("  hello"); // hello
rtrim("hello  "); // hello

// 转小写/大写
strtolower("Hello"); // hello
strtoupper("hello"); // HELLO

// 首字母大写
ucfirst("hello"); // Hello

// 每个单词首字母大写
ucwords("hello world"); // Hello World

5. 字符串和数组转换

// 字符串转数组
explode(",", "a,b,c"); // ["a","b","c"]

// 数组转字符串
implode(",", ["a","b","c"]); // a,b,c

// 重复字符串
str_repeat("ab", 3); // ababab

// 字符串长度
strlen("hello"); // 5
mb_strlen("你好", "UTF-8"); // 2

6. 常用技巧

// 生成随机字符串
substr(md5(time()), 0, 8);

// 脱敏手机号
substr_replace("13812345678", "****", 3, 4); // 138****5678

// 截取摘要(带省略号)
mb_strlen($text) > 10 ? mb_substr($text, 0, 10) . "..." : $text;

// 清除 HTML 标签
strip_tags("<p>hello</p>"); // hello

总结

PHP 字符串处理核心函数:

  • 截取:substr / mb_substr
  • 替换:str_replace / preg_replace
  • 查找:strpos / str_contains
  • 格式化:trim / strtolower / ucwords
  • 转换:explode / implode

记住这些,日常开发基本够用了。


emer 发布于  2026-10-4 11:04 

Linux 防火墙配置技巧

Linux 防火墙配置技巧

服务器安全第一步就是配好防火墙,只开需要的端口,其他全关。

1. firewalld(CentOS 7+ 默认)

# 查看状态
firewall-cmd --state

# 查看已开放端口
firewall-cmd --list-ports

# 开放端口
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=443/tcp

# 开放多个端口
firewall-cmd --permanent --add-port=8000-9000/tcp

# 开放指定 IP 访问
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.100' port protocol='tcp' port=3306 accept"

# 重载配置(必须重载才生效)
firewall-cmd --reload

# 删除端口
firewall-cmd --permanent --remove-port=8080/tcp

2. ufw(Ubuntu 默认)

# 查看状态
ufw status

# 开启防火墙
ufw enable

# 允许 SSH
ufw allow 22

# 允许 80 和 443
ufw allow 80
ufw allow 443

# 允许指定 IP
ufw allow from 192.168.1.100 to any port 3306

# 拒绝某个 IP
ufw deny from 1.2.3.4

# 删除规则
ufw delete allow 8080

3. iptables(经典)

# 查看规则
iptables -L -n

# 允许 22 端口
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 允许 80 端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT

# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 默认拒绝其他
iptables -P INPUT DROP

# 保存规则(CentOS)
service iptables save

4. 安全建议

  • 只开必要端口:SSH、HTTP、HTTPS,其他全关
  • SSH 改端口:不要用默认 22,改成其他端口
  • 限制 SSH 登录 IP:只允许你的 IP 登录 SSH
  • 数据库不对外暴露:MySQL、Redis 只允许本地访问
  • 定期查看日志:/var/log/secure 看有没有暴力破解

5. 常用端口速查

  • 22:SSH
  • 80:HTTP
  • 443:HTTPS
  • 3306:MySQL
  • 6379:Redis
  • 8080:应用端口

总结

Linux 防火墙核心:

  • CentOS 用 firewalld
  • Ubuntu 用 ufw
  • 只开必要端口
  • 数据库不对外暴露
  • SSH 限制 IP 访问

配好防火墙,服务器安全提升一大截。


emer 发布于  2026-10-4 10:52 

Nginx 负载均衡配置

Nginx 负载均衡配置实战

网站流量大了,单台服务器扛不住,就得用负载均衡。Nginx 做负载均衡很简单,几行配置就行。

1. 基本配置

http {
    upstream backend {
        server 192.168.1.101:80;
        server 192.168.1.102:80;
        server 192.168.1.103:80;
    }

    server {
        listen 80;
        server_name www.example.com;

        location / {
            proxy_pass http://backend;
        }
    }
}

默认是轮询(round robin),请求轮流分到三台服务器。

2. 四种分配策略

轮询(默认):一个一个来。

权重(weight):按比例分配,性能好的服务器多分担。

upstream backend {
    server 192.168.1.101 weight=3;
    server 192.168.1.102 weight=2;
    server 192.168.1.103 weight=1;
}

3:2:1 的比例,第一台分一半请求。

ip_hash:同一个 IP 固定分到同一台服务器,解决 session 问题。

upstream backend {
    ip_hash;
    server 192.168.1.101;
    server 192.168.1.102;
}

least_conn:最少连接数优先,分给当前最闲的服务器。

upstream backend {
    least_conn;
    server 192.168.1.101;
    server 192.168.1.102;
}

3. 健康检查

upstream backend {
    server 192.168.1.101 max_fails=3 fail_timeout=30s;
    server 192.168.1.102 max_fails=3 fail_timeout=30s;
}

一台服务器挂了,自动从列表里摘掉,恢复了再加回来。

4. 常用参数

  • max_fails:失败几次算挂了,默认1次
  • fail_timeout:挂了多久再重试,默认10秒
  • down:标记服务器下线,不分配请求
  • backup:备用服务器,其他都挂了才用

5. 完整示例

upstream backend {
    server 192.168.1.101 weight=3 max_fails=3 fail_timeout=30s;
    server 192.168.1.102 weight=2 max_fails=3 fail_timeout=30s;
    server 192.168.1.103 backup;
}

server {
    listen 80;
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

总结

Nginx 负载均衡核心:

  • upstream 定义服务器组
  • 四种策略:轮询、权重、ip_hash、最少连接
  • 健康检查自动摘除故障节点
  • 生产环境用权重 + 健康检查就够了

搞懂这些,多台服务器集群就跑起来了。


emer 发布于  2026-10-4 10:51 

Redis 数据结构详解

Redis 五种数据结构详解

Redis 不只是缓存,它的五种数据结构各有各的用处,搞懂了才能用对地方。

1. String(字符串)

最基础的数据结构,存字符串、数字都行。

SET name "张三"
GET name
INCR count
SET token "abc123" EX 3600

应用场景:缓存用户信息、计数器、分布式锁、会话存储。

2. Hash(哈希)

存键值对,适合存对象。

HSET user:1 name "张三" age 25 city "北京"
HGET user:1 name
HGETALL user:1

应用场景:存用户信息、商品信息,比 String 存 JSON 更省空间。

3. List(列表)

有序列表,可以从头或尾加元素。

LPUSH messages "hello"
LPUSH messages "world"
LRANGE messages 0 -1

应用场景:消息队列、最新消息列表、朋友圈时间线。

4. Set(集合)

无序不重复集合。

SADD tags "PHP"
SADD tags "MySQL"
SMEMBERS tags
SISMEMBER tags "PHP"

应用场景:标签、共同好友、去重。

5. ZSet(有序集合)

每个元素带分数,按分数排序。

ZADD rank 100 "张三"
ZADD rank 90 "李四"
ZREVRANGE rank 0 9 WITHSCORES

应用场景:排行榜、计分板、优先级队列。

总结

五种数据结构各有用处:

  • String:简单缓存、计数器
  • Hash:存对象
  • List:队列、时间线
  • Set:去重、标签
  • ZSet:排行榜

选对数据结构,性能才能发挥出来。


emer 发布于  2026-10-4 10:50 

PHP 数组操作技巧

PHP 数组操作技巧

数组是 PHP 最常用的数据结构,掌握这些技巧,写代码效率翻倍。

1. 数组合并

// 索引数组合并
$arr1 = [1, 2];
$arr2 = [3, 4];
$result = array_merge($arr1, $arr2); // [1,2,3,4]

// 关联数组合并,后面覆盖前面
$arr1 = ['a' => 1, 'b' => 2];
$arr2 = ['b' => 3, 'c' => 4];
$result = array_merge($arr1, $arr2); // ['a'=>1, 'b'=>3, 'c'=>4]

2. 数组去重

// 一维数组去重
$arr = [1, 2, 2, 3, 3, 3];
$result = array_unique($arr); // [1,2,3]

// 二维数组按字段去重
$users = [
    ['id' => 1, 'name' => '张三'],
    ['id' => 2, 'name' => '李四'],
    ['id' => 1, 'name' => '张三'],
];
$ids = array_column($users, 'id');
$unique = array_unique($ids);

3. 数组排序

// 升序
sort($arr);

// 降序
rsort($arr);

// 按键排序
ksort($arr);

// 按值排序,保留键
asort($arr);

4. 数组过滤

// 过滤空值
$arr = [1, 0, '', null, 'a'];
$result = array_filter($arr); // [1, 'a']

// 自定义过滤
$result = array_filter($arr, function($value) {
    return $value > 2;
});

5. 数组取值

// 取某一列
$names = array_column($users, 'name');

// 取交集
$arr1 = [1, 2, 3];
$arr2 = [2, 3, 4];
$result = array_intersect($arr1, $arr2); // [2,3]

// 取差集
$result = array_diff($arr1, $arr2); // [1]

6. 常用技巧

// 判断键是否存在
isset($arr['key']);
array_key_exists('key', $arr);

// 随机取一个
$value = array_rand($arr);

// 打乱数组
shuffle($arr);

// 数组合并成字符串
$str = implode(',', $arr);

// 字符串转数组
$arr = explode(',', $str);

总结

PHP 数组函数非常丰富,常用的就这些:合并、去重、排序、过滤、取值。把这些记熟,日常开发基本够用了。


emer 发布于  2026-10-4 10:48 
'); })();