Nginx配置HTTPS,Let's Encrypt免费SSL证书申请
前言
现在网站没个 HTTPS 都不好意思拿出来,浏览器直接标"不安全"。申请 SSL 证书以前要花钱买,现在有了 Let's Encrypt,免费申请,90天有效期,还能自动续期。本文就讲一下怎么用 Let's Encrypt 给 Nginx 配 HTTPS。
前提条件
申请 SSL 证书之前,先确认:
- 域名已经解析到服务器 IP
- 80 端口已经开放(防火墙、安全组都要开)
- Nginx 已经能正常跑 HTTP
这三个条件满足了才能申请成功。
第一步:安装 certbot
certbot 是 Let's Encrypt 官方的证书申请工具。
yum install certbot python2-certbot-nginx -y
这个包会自动装 certbot 和 Nginx 插件。
第二步:申请证书
自动申请并配置
certbot --nginx -d www.example.com -d example.com
参数说明:
--nginx:自动修改 Nginx 配置-d:指定域名,可以写多个
执行过程中会问你:
- 邮箱地址:填你的邮箱,证书过期了会提醒你
- 同意服务条款:输入 A
- 是否接收邮件:输入 N
- 是否把 HTTP 跳转到 HTTPS:选 2(跳转)
等待申请完成,一般几秒钟就好。
第三步:测试 HTTPS
浏览器访问 https://www.example.com,应该能看到小锁标志了。
HTTP 访问 http://www.example.com 会自动跳转到 HTTPS。
证书文件位置
申请完的证书文件都在 /etc/letsencrypt/live/域名/ 目录下:
/etc/letsencrypt/live/www.example.com/
├── cert.pem # 证书
├── chain.pem # 中间证书
├── fullchain.pem # 证书+中间证书(Nginx用这个)
└── privkey.pem # 私钥
Nginx 配置里用的是:
ssl_certificate /etc/letsencrypt/live/域名/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/域名/privkey.pem;
自动续期
Let's Encrypt 证书有效期只有 90 天,需要定期续期。
测试自动续期
certbot renew --dry-run
如果没报错,说明自动续期配置没问题。
自动续期定时任务
certbot 装完会自动加一个定时任务,不用管。可以看看:
crontab -l
或者:
systemctl list-timers | grep certbot
手动配置 HTTPS
如果不想用 certbot 自动改配置,也可以手动写 Nginx 配置。
Nginx HTTPS 配置示例
server {
listen 80;
server_name www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
root /var/www/html/test;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
检查并重载
nginx -t
systemctl reload nginx
常见坑
坑1:域名没解析就申请
域名还没解析到服务器,就开始申请证书,结果申请失败。
解决: 先 ping 一下域名,确认解析到你服务器 IP 了再申请。
坑2:80 端口没开
防火墙或安全组没开 80 端口,Let's Encrypt 验证不了你的域名,申请失败。
解决: 先开 80 端口:
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
云服务器还要在安全组里开 80 端口。
坑3:证书到期了没续期
忘了续期,证书过期了,浏览器报不安全。
解决: certbot 会自动续期,不用管。但要确认自动续期服务在运行:
systemctl status certbot-renew.timer
坑4:HTTPS 配置完了 404
配完 HTTPS 访问 404,一般是 root 目录或者 server_name 写错了。
排查:
- 看 Nginx 配置里的
server_name对不对 - 看
root目录对不对 nginx -t检查配置语法
总结
Nginx 配置 HTTPS 的完整流程:
- 装 certbot:
yum install certbot python2-certbot-nginx -y - 申请证书:
certbot --nginx -d www.example.com - 自动续期:certbot 自动搞定,不用管
- 测试:浏览器访问 HTTPS,看小锁标志
Let's Encrypt 免费证书是现在最流行的方案,不用花钱就能给网站上 HTTPS。
遇到问题加QQ23979811 协助处理
Nginx安装配置完整教程,从安装到运行
前言
刚装好 CentOS 服务器,想跑个网站,第一步就是装 Nginx。Nginx 是目前最流行的 Web 服务器,性能高、占用资源少,还能做反向代理和负载均衡。本文就从安装 Nginx 开始,一步步讲怎么配置一个能跑的网站。
第一步:安装 Nginx
1. 安装 EPEL 源
CentOS7 默认源里的 Nginx 版本比较老,先装 EPEL 源:
yum install epel-release -y
2. 安装 Nginx
yum install nginx -y
3. 启动 Nginx
systemctl start nginx
4. 设置开机自启
systemctl enable nginx
5. 开放防火墙
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
6. 测试
浏览器访问你的服务器 IP,应该能看到 Nginx 默认欢迎页面。
第二步:Nginx 配置文件结构
Nginx 的配置文件都在 /etc/nginx/ 目录下:
/etc/nginx/
├── nginx.conf # 主配置文件
├── conf.d/ # 子配置文件目录
│ └── default.conf # 默认站点配置
├── fastcgi.conf
├── mime.types
└── ...
一般我们写站点配置,都放在 conf.d/ 目录下,每个站点一个文件。
第三步:配置第一个站点
1. 创建网站根目录
mkdir -p /var/www/html/test
2. 写一个测试页面
echo "Hello Nginx" > /var/www/html/test/index.html
3. 创建站点配置文件
vi /etc/nginx/conf.d/test.conf
写入:
server {
listen 80;
server_name www.example.com;
root /var/www/html/test;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
4. 检查配置是否正确
nginx -t
输出 test is successful 就是没问题。
5. 重新加载 Nginx
systemctl reload nginx
6. 测试
浏览器访问 www.example.com,应该能看到 "Hello Nginx"。
注意: 要把域名解析到你服务器的 IP 上,或者在本地 hosts 文件里加一条记录。
常用配置说明
listen 监听端口
listen 80;
监听 80 端口,HTTP 默认端口。
如果要监听 HTTPS 的 443 端口:
listen 443 ssl;
server_name 域名
server_name www.example.com example.com;
可以写多个域名,用空格隔开。
root 网站根目录
root /var/www/html/test;
网站文件放在这个目录下。
index 默认首页
index index.html index.htm;
用户访问网站根目录的时候,默认找哪个文件。
配置 PHP 支持
如果要跑 PHP 网站,还需要配置 PHP-FPM。
1. 安装 PHP-FPM
yum install php-fpm php-mysql -y
2. 启动 PHP-FPM
systemctl start php-fpm
systemctl enable php-fpm
3. 修改 Nginx 配置
在站点配置里加上 PHP 支持:
server {
listen 80;
server_name www.example.com;
root /var/www/html/test;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
4. 重启 Nginx
systemctl restart nginx
5. 测试 PHP
创建一个 info.php 文件:
echo "<?php phpinfo(); ?>" > /var/www/html/test/info.php
浏览器访问 www.example.com/info.php,应该能看到 PHP 信息页面。
常见坑
坑1:403 Forbidden
访问网站报 403,一般是权限问题。
排查:
- 看文件权限是不是 644,目录是不是 755
- 看所有者是不是 nginx
- 看 SELinux 是不是开着
chown -R nginx:nginx /var/www/html/test
chmod -R 755 /var/www/html/test
坑2:502 Bad Gateway
访问网站报 502,说明 Nginx 连不上 PHP-FPM。
排查:
- 看 PHP-FPM 有没有启动:
systemctl status php-fpm - 看配置里的
fastcgi_pass地址对不对
坑3:配置改完不生效
改了 Nginx 配置,没 reload,结果配置没生效。
解决: 改完配置记得 reload:
nginx -t
systemctl reload nginx
坑4:域名解析了还是打不开
域名解析了,但还是打不开。
排查:
- 看防火墙有没有开 80 端口
- 看安全组有没有开 80 端口(云服务器)
- 看域名解析有没有生效:
ping www.example.com
总结
Nginx 安装配置的完整流程:
- 安装 Nginx:
yum install nginx -y - 启动并开机自启:
systemctl start nginx && systemctl enable nginx - 开放防火墙:80 和 443 端口
- 写站点配置:在
conf.d/下创建配置文件 - 检查并重载:
nginx -t && systemctl reload nginx
Nginx 是 Web 服务器的入门必备,装完这个就能跑网站了。
遇到问题加QQ23979811 协助处理
Linux服务管理,systemctl常用命令汇总
前言
CentOS7 装完软件,怎么启动?怎么开机自启?服务挂了怎么查日志?这些都需要用到 systemctl 命令。CentOS7 开始用 systemd 代替了原来的 service 命令,systemctl 就是 systemd 的管理工具。本文就把 systemctl 常用命令汇总一下,日常管理服务够用了。
启动和停止服务
启动服务
systemctl start nginx
停止服务
systemctl stop nginx
重启服务
systemctl restart nginx
重新加载配置
systemctl reload nginx
注意: reload 和 restart 的区别:
reload:不重启进程,重新加载配置,不中断服务restart:重启进程,会短暂中断服务
查看服务状态
查看服务状态
systemctl status nginx
输出会显示服务是不是在运行、PID、内存占用、最近的日志等。
查看服务是不是在运行
systemctl is-active nginx
输出 active 就是在运行,inactive 就是没运行。
查看服务是不是开机自启
systemctl is-enabled nginx
输出 enabled 就是开机自启,disabled 就是不自启。
开机自启管理
设置开机自启
systemctl enable nginx
取消开机自启
systemctl disable nginx
同时启动并设置开机自启
systemctl enable --now nginx
一条命令搞定,不用分两步。
查看日志
查看服务日志
journalctl -u nginx
实时跟踪日志
journalctl -u nginx -f
和 tail -f 类似,实时滚动显示日志。
查看最近100行日志
journalctl -u nginx -n 100
查看今天的日志
journalctl -u nginx --since today
查看指定时间的日志
journalctl -u nginx --since "2026-10-05 10:00:00" --until "2026-10-05 11:00:00"
查看所有服务
列出所有正在运行的服务
systemctl list-units --type=service
列出所有服务(包括没运行的)
systemctl list-unit-files --type=service
按状态过滤
systemctl list-units --type=service --state=running
常用服务管理示例
启动 Nginx 并设置开机自启
systemctl start nginx
systemctl enable nginx
或者一条命令:
systemctl enable --now nginx
重启 Nginx
systemctl restart nginx
查看 Nginx 状态
systemctl status nginx
查看 Nginx 日志
journalctl -u nginx -f
常见坑
坑1:还在用 service 命令
CentOS6 用 service nginx start,CentOS7 开始用 systemctl start nginx。老命令还能用,但新系统推荐用 systemctl。
坑2:改了配置不生效
改了 Nginx 配置,忘了 reload,结果配置没生效。
解决: 改完配置记得 reload:
systemctl reload nginx
坑3:服务启动失败不知道为啥
服务启动失败,只看状态不知道具体原因。
解决: 看日志:
journalctl -u nginx
坑4:重启服务器后服务没自启
装完软件启动了,但没设置开机自启,重启之后服务就没了。
解决: 装完软件记得设置开机自启:
systemctl enable nginx
总结
systemctl 常用命令:
| 命令 | 作用 |
|---|---|
systemctl start 服务名 |
启动服务 |
systemctl stop 服务名 |
停止服务 |
systemctl restart 服务名 |
重启服务 |
systemctl reload 服务名 |
重新加载配置 |
systemctl status 服务名 |
查看服务状态 |
systemctl enable 服务名 |
设置开机自启 |
systemctl disable 服务名 |
取消开机自启 |
systemctl is-active 服务名 |
查看是否在运行 |
systemctl is-enabled 服务名 |
查看是否开机自启 |
journalctl -u 服务名 -f |
实时查看日志 |
记住这几个,CentOS7+ 日常管理服务就够用了。
遇到问题加QQ23979811 协助处理
Linux软件包管理,yum常用命令汇总
前言
CentOS 装软件怎么装?装完怎么卸?找不到某个软件包名怎么办?这些都需要用到 yum 命令。yum 是 CentOS/RHEL 系统的软件包管理器,自动解决依赖关系,比 rpm 好用多了。本文就把 yum 常用命令汇总一下,装软件、卸软件、查软件都能用。
安装软件
安装软件包
yum install nginx -y
-y 表示自动确认,不用手动输 y。
安装多个软件包
yum install nginx mysql php -y
重新安装
yum reinstall nginx -y
软件装坏了想重装,用这个。
卸载软件
卸载软件包
yum remove nginx -y
卸载并删除依赖
yum autoremove nginx -y
把安装 nginx 时自动装上的依赖也一起删掉。
更新软件
更新所有软件
yum update -y
注意: 这个会把所有软件都更新一遍,包括内核。生产环境慎用,可能会把系统搞挂。
更新某个软件
yum update nginx -y
只更新 nginx。
检查哪些软件可以更新
yum check-update
查找软件
搜索软件包
yum search nginx
模糊搜索,输出所有名字或描述里包含 nginx 的包。
查找文件属于哪个包
yum provides /usr/sbin/nginx
你知道某个文件路径,但不知道是哪个包装的,用这个查。
查看软件包信息
yum info nginx
输出软件包的详细信息:版本、大小、描述等。
查看已安装软件
列出所有已安装的包
yum list installed
太多了可以配合 grep:
yum list installed | grep nginx
查看某个软件装没装
yum list installed nginx
仓库管理
查看已启用的仓库
yum repolist
查看所有仓库(包括禁用的)
yum repolist all
清理缓存
yum clean all
yum 下载的包会缓存下来,占磁盘空间。定期清理一下。
重建缓存
yum makecache
常用场景
场景1:装 Nginx
yum install nginx -y
systemctl start nginx
systemctl enable nginx
场景2:不知道软件包名
想装个下载工具,但不知道叫什么。
yum search wget
或者:
yum search curl
场景3:某个命令找不到
输入 ifconfig 提示 command not found,不知道是哪个包装的。
yum provides ifconfig
会告诉你是 net-tools 包提供的,装一下:
yum install net-tools -y
场景4:软件版本太旧
CentOS7 自带的软件版本都比较老,比如 Nginx 是 1.20。想用新版本,需要加第三方源。
装 EPEL 源:
yum install epel-release -y
装完 EPEL 源之后,就能装更多软件包了。
常见坑
坑1:yum install 不加 -y
不加 -y 的话,安装到一半会停下来问你 Is this ok [y/d/N],自动化脚本里很容易卡在这里。
解决: 命令后面加 -y:
yum install nginx -y
坑2:yum update 把系统搞挂了
生产环境跑了 yum update -y,结果内核更新了,重启之后服务起不来。
解决: 生产环境不要随便 yum update,要更新就单独更新某个软件:
yum update nginx -y
坑3:找不到软件包
用默认源搜不到某个软件,比如 Docker、Node.js 这些。
解决: 加第三方源,比如 EPEL:
yum install epel-release -y
坑4:yum 缓存满了
yum 缓存的包占了很多磁盘空间。
解决: 定期清理:
yum clean all
总结
yum 常用命令:
| 命令 | 作用 |
|---|---|
yum install 包名 -y |
安装软件 |
yum remove 包名 -y |
卸载软件 |
yum update 包名 -y |
更新软件 |
yum search 关键词 |
搜索软件 |
yum provides 文件路径 |
查文件属于哪个包 |
yum info 包名 |
查看软件包信息 |
yum list installed |
列出已安装的包 |
yum repolist |
查看仓库列表 |
yum clean all |
清理缓存 |
记住这几个,CentOS 日常装软件就够用了。
遇到问题加QQ23979811 协助处理
Linux文件权限详解,chmod和chown命令使用
前言
Nginx 报 403 Forbidden?文件改完了不生效?权限不对导致各种奇怪问题?Linux 的文件权限是新手最容易搞混的地方。什么是 rwx?755 和 644 有什么区别?chown 和 chmod 分别是干嘛的?本文就把 Linux 文件权限讲明白,让你一看就懂。
查看文件权限
用 ls -l 查看文件详细信息:
ls -l /var/www/html/index.html
输出示例:
-rw-r--r-- 1 nginx nginx 1234 Oct 5 10:30 /var/www/html/index.html
权限字符串详解
最开头的 -rw-r--r-- 就是权限,拆解一下:
- rw- r-- r--
① ② ③ ④
- ① 文件类型:
-是普通文件,d是目录,l是链接 - ② 所有者权限(user):
rw-= 可读可写,不可执行 - ③ 所属组权限(group):
r--= 只读 - ④ 其他人权限(other):
r--= 只读
rwx 含义
| 字符 | 含义 | 数字 |
|---|---|---|
r |
读(read) | 4 |
w |
写(write) | 2 |
x |
执行(execute) | 1 |
所以:
rwx= 4+2+1 = 7rw-= 4+2+0 = 6r--= 4+0+0 = 4r-x= 4+0+1 = 5
常用权限数字
| 数字 | 权限 | 说明 |
|---|---|---|
| 755 | rwxr-xr-x | 所有者可读写执行,其他人可读执行(常用目录、脚本) |
| 644 | rw-r--r-- | 所有者可读写,其他人只读(常用文件) |
| 700 | rwx------ | 只有所有者能读写执行(私密文件) |
| 600 | rw------- | 只有所有者能读写(私密文件) |
| 777 | rwxrwxrwx | 所有人都能读写执行(不安全,尽量别用) |
记住两个最常用的:
- 目录用
755 - 文件用
644
chmod 修改权限
数字方式
chmod 755 /var/www/html
把目录权限改成 755。
chmod 644 /var/www/html/index.html
把文件权限改成 644。
递归修改
chmod -R 755 /var/www/html/
把目录下所有文件和子目录都改成 755。
注意: 递归修改的时候要小心,一般文件应该是 644,目录是 755。如果全部改成 755,文件就能执行了,不安全。
字母方式
chmod u+x script.sh
给所有者加执行权限。
chmod g+w file.txt
给所属组加写权限。
chmod o-r file.txt
去掉其他人的读权限。
u:所有者g:所属组o:其他人+:加权限-:减权限
chown 修改所有者
修改文件所有者
chown nginx /var/www/html/index.html
把文件所有者改成 nginx。
修改所有者和所属组
chown nginx:nginx /var/www/html/index.html
所有者改成 nginx,所属组也改成 nginx。
递归修改
chown -R nginx:nginx /var/www/html/
把整个目录的所有者和所属组都改成 nginx。
实际应用场景
场景1:Nginx 报 403
Nginx 访问网站报 403 Forbidden,一般是权限不对。
ls -l /var/www/html/index.html
看所有者和权限。如果文件是 root 的,Nginx 进程读不到,就会 403。
chown nginx:nginx /var/www/html/index.html
chmod 644 /var/www/html/index.html
场景2:脚本不能执行
写了个 shell 脚本,运行提示 Permission denied。
chmod +x script.sh
加执行权限就能跑了。
场景3:目录权限不对
网站目录权限不对,上传的图片打不开。
chmod -R 755 /var/www/html/
chown -R nginx:nginx /var/www/html/
常见坑
坑1:chmod 777 解决一切
很多人一遇到权限问题就 chmod 777,这是最懒也最不安全的做法。777 意味着所有人都能读写执行,黑客上传个木马就直接跑了。
正确做法: 文件用 644,目录用 755,所有者设成运行服务的用户。
坑2:只改权限不改所有者
权限对了,但所有者不对,服务还是读不到文件。
解决: 权限和所有者都要对。比如 Nginx 运行用户是 nginx,文件所有者也要是 nginx。
坑3:递归 chmod 把文件也改成 755
chmod -R 755 把所有文件都改成可执行了,不安全。
正确做法: 目录用 755,文件用 644。可以用 find 分开改:
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
坑4:改了权限不生效
改了权限但还是不对,看看是不是有 SELinux 在捣乱。
解决: 先临时关掉 SELinux 测试:
setenforce 0
如果关了就好了,说明是 SELinux 的问题。
总结
Linux 文件权限核心:
- rwx = 4+2+1
- 目录用 755,文件用 644
- chmod 改权限,chown 改所有者
- 不要随便用 777
记住两个最常用的:目录 755,文件 644。遇到权限问题先 ls -l 看看,再改,别上来就 777。
遇到问题加QQ23979811 协助处理
Linux用户和组管理,useradd和groupadd命令使用
前言
服务器上需要给开发人员开个账号?或者给不同的人分配不同的权限?这就需要用到 Linux 的用户和组管理。Linux 是多用户系统,每个用户有自己的家目录和权限。学会用户和组管理,是运维的基本功。本文就讲一下怎么创建、删除、修改用户和组。
创建用户
基本创建
useradd testuser
这样就创建了一个叫 testuser 的用户。默认会:
- 创建一个同名的组
- 创建家目录
/home/testuser - 指定 shell 为
/bin/bash
设置密码
passwd testuser
输入两次密码就好了。注意: 新建的用户默认是不能登录的,必须设密码才能登录。
创建用户时指定参数
useradd -m -s /bin/bash -G wheel testuser
参数说明:
-m:自动创建家目录-s /bin/bash:指定默认 shell-G wheel:把用户加入 wheel 组(可以用 sudo)
查看用户信息
id testuser
输出用户的 UID、GID、所属组。
cat /etc/passwd
查看所有用户。
删除用户
userdel testuser
这样只删用户,不删家目录。
如果要连家目录一起删:
userdel -r testuser
注意: -r 会把用户的家目录和邮件都删掉,小心操作。
修改用户
修改用户名
usermod -n newname oldname
修改用户的家目录
usermod -d /home/newhome testuser
把用户加入某个组
usermod -aG wheel testuser
-aG 表示追加到组,不要只用 -G,不然会把原来的组都覆盖掉。
锁定用户
usermod -L testuser
锁定后用户不能登录。
解锁用户
usermod -U testuser
组管理
创建组
groupadd developers
删除组
groupdel developers
查看用户属于哪些组
groups testuser
把用户加入组
usermod -aG developers testuser
从组里删除用户
gpasswd -d testuser developers
sudo 权限
把用户加入 wheel 组(CentOS 默认支持 sudo 的组)
usermod -aG wheel testuser
这样 testuser 就可以用 sudo 执行 root 命令了。
编辑 sudoers 文件
visudo
在文件里添加:
testuser ALL=(ALL) ALL
这样 testuser 也有 sudo 权限。
注意: 一定要用 visudo 编辑,不要直接改 /etc/sudoers,改坏了 sudo 就用不了了。
查看登录历史
谁在线
w
历史登录记录
last
谁在执行 sudo
lastcomm
实际应用场景
场景1:给开发人员开账号
useradd -m -s /bin/bash dev01
passwd dev01
usermod -aG developers dev01
场景2:给运维开 sudo 权限
useradd -m -s /bin/bash ops01
passwd ops01
usermod -aG wheel ops01
场景3:删除离职员工账号
userdel -r olduser
常见坑
坑1:userdel 没加 -r,家目录还在
只删了用户,家目录 /home/testuser 还在,占着磁盘空间。
解决: 删用户的时候加 -r:
userdel -r testuser
坑2:usermod -G 把原来的组覆盖了
用 -G 而不是 -aG,结果用户原来的组都没了,只剩新的组。
解决: 追加组用 -aG:
usermod -aG developers testuser
坑3:新建用户不能登录
创建了用户,但没设密码,结果不能登录。
解决: 创建完用户一定要设密码:
passwd testuser
坑4:visudo 改错了
直接用 vi 改 /etc/sudoers,改错了导致 sudo 用不了。
解决: 一定要用 visudo 命令编辑,它会检查语法。
总结
用户和组管理的核心命令:
- useradd:创建用户
- passwd:设置密码
- userdel -r:删除用户(连家目录)
- usermod -aG:把用户加入组
- groupadd:创建组
- groups:查看用户属于哪些组
- visudo:编辑 sudo 权限
用户管理是 Linux 安全的基础,每个用户用自己的账号,不要所有人都用 root。
遇到问题加QQ23979811 协助处理
Linux查看和修改系统时间,date和timedatectl命令
前言
服务器时间不对?日志时间戳对不上?定时任务不准?这些问题都和系统时间有关。Linux 服务器的时间很重要,日志、定时任务、证书过期时间都依赖系统时间。时间不准会出各种奇怪的问题。本文就讲一下怎么查看和修改 Linux 系统时间,以及怎么设置时区。
查看系统时间
方法一:date 命令
date
输出示例:
Mon Oct 5 10:30:45 CST 2026
CST 就是中国标准时间(China Standard Time)。
方法二:timedatectl 命令(推荐)
timedatectl
输出示例:
Local time: Mon 2026-10-05 10:30:45 CST
Universal time: Mon 2026-10-05 02:30:45 UTC
RTC time: Mon 2026-10-05 02:30:46
Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
这个命令显示的信息更全:本地时间、UTC时间、硬件时间、时区、是否同步、NTP服务状态。
设置时区
查看当前时区
timedatectl
看 Time zone 那行。
查看所有可用时区
timedatectl list-timezones
或者:
ls /usr/share/zoneinfo/
设置时区为上海
timedatectl set-timezone Asia/Shanghai
这是最常用的,国内服务器一般都设成这个。
验证
timedatectl
看 Time zone 那行是不是变成了 Asia/Shanghai。
手动设置时间
不推荐手动设置
一般情况下,时间不准了应该用 NTP 自动同步,不要手动设。手动设的时间过一段时间又会不准。
但如果确实需要手动设:
设置日期和时间
date -s "2026-10-05 10:30:45"
只设置时间
date -s "10:30:45"
只设置日期
date -s "2026-10-05"
NTP 时间同步
安装 NTP 服务
CentOS7 用 chronyd:
yum install chrony -y
启动并设置开机自启
systemctl start chronyd
systemctl enable chronyd
查看同步状态
timedatectl
看 System clock synchronized: yes 就是同步成功了。
手动同步一次
chronyc makestep
常见时间格式
date 命令可以格式化输出:
输出年月日
date +%Y-%m-%d
输出:
2026-10-05
输出时分秒
date +%H:%M:%S
输出完整日期时间
date +"%Y-%m-%d %H:%M:%S"
时间戳
date +%s
输出 Unix 时间戳(秒数)。
从时间戳转换
date -d @1728100000
实际应用场景
场景1:日志时间不对
看日志发现时间戳不对,先查系统时间:
date
如果时间不对,改时区:
timedatectl set-timezone Asia/Shanghai
场景2:定时任务不准
crontab 定时任务执行时间不对,先看系统时间:
date
时间不对就同步 NTP。
场景3:证书过期时间不对
SSL 证书过期时间对不上,也是系统时间的问题。
场景4:脚本里用到时间戳
写脚本的时候需要获取当前时间戳:
now=$(date +%s)
常见坑
坑1:时区不对导致日志时间差8小时
服务器装完默认是 UTC 时区,比北京时间晚8小时。
解决: 设置成上海时区:
timedatectl set-timezone Asia/Shanghai
坑2:改了时间但硬件时间没同步
手动改了系统时间,重启之后又变回去了,因为硬件时间(RTC)没改。
解决: 用 NTP 同步就不用管这个,NTP 会自动同步硬件时间。
坑3:NTP 服务没启动
装了 NTP 但没启动,时间还是不同步。
解决:
systemctl start chronyd
systemctl enable chronyd
坑4:手动设时间后过一会儿又不准了
手动设的时间不准,因为系统时钟会漂移。
解决: 用 NTP 自动同步,不要手动设。
总结
查看和修改系统时间的核心命令:
- date:快速看当前时间
- timedatectl:看完整时间信息(时区、NTP同步状态)
- timedatectl set-timezone Asia/Shanghai:设置时区
- chronyd:NTP时间同步服务
服务器时间一定要准,用 NTP 自动同步,不要手动设。国内服务器时区设成 Asia/Shanghai。
遇到问题加QQ23979811 协助处理
Linux添加Swap交换分区,解决内存不足问题
前言
服务器内存不够用了?MySQL 启动就报内存不足?或者运行着运行着就被 OOM Killer 杀进程了?这时候除了加内存条,还有个应急办法——加 Swap 交换分区。Swap 就是把磁盘的一部分当内存用,虽然慢,但能救急。本文就讲一下怎么在 Linux 下添加 Swap 交换分区。
什么是 Swap
Swap 交换分区,就是把磁盘的一部分空间当作内存来用。当物理内存不够的时候,系统会把不常用的内存数据换到磁盘上,腾出物理内存给正在用的进程。
注意: Swap 只是应急方案,不能当内存用。磁盘比内存慢几百倍,如果频繁使用 Swap,系统会非常卡。
第一步:查看当前 Swap 情况
先看看现在有没有 Swap,多大:
free -h
输出示例:
total used free shared buff/cache available
Mem: 1.8Gi 1.2Gi 200Mi 50Mi 400Mi 300Mi
Swap: 0B 0B 0B
上面的例子里 Swap 是 0B,说明没有配置 Swap。
也可以看:
swapon -s
第二步:创建 Swap 文件
我们用文件的方式创建 Swap,比分区方式灵活,随时可以删。
1. 创建一个 2G 的 Swap 文件
dd if=/dev/zero of=/swapfile bs=1M count=2048
参数说明:
if=/dev/zero:输入源,零设备of=/swapfile:输出文件bs=1M:块大小1Mcount=2048:2048块,也就是2G
2. 设置文件权限
chmod 600 /swapfile
必须设置成 600,不然系统不认。
3. 格式化成 Swap
mkswap /swapfile
输出会显示:
Setting up swapspace version 1, size = 2097151 KiB
no label, UUID=xxxx-xxxx
第三步:启用 Swap
swapon /swapfile
查看是否启用成功:
free -h
现在应该能看到 Swap 那行有数值了。
第四步:配置开机自动挂载
写入 /etc/fstab,重启后自动启用。
vi /etc/fstab
在最后一行添加:
/swapfile swap swap defaults 0 0
第五步:调整 Swap 使用优先级
Linux 默认是尽量用物理内存,Swap 只用在内存不够的时候。这个策略一般不用改。
如果想调整 Swap 的使用倾向,可以改 /etc/sysctl.conf:
vm.swappiness = 10
swappiness 值范围是 0~100:
0:尽量不用 Swap100:积极使用 Swap10:推荐值,内存不够才用 Swap
改完执行:
sysctl -p
常见操作
查看 Swap 使用情况
swapon -s
关闭 Swap
swapoff /swapfile
删除 Swap
swapoff /swapfile
rm /swapfile
然后把 /etc/fstab 里那行也删掉。
实际应用场景
场景1:MySQL 启动报内存不足
MySQL 启动的时候需要加载很多数据到内存,如果内存不够会直接启动失败。加个 Swap 就能启动了。
场景2:临时跑大任务
有时候要临时跑个大任务,内存不够,加个 Swap 救急。
场景3:防止 OOM Killer 杀进程
内存不够的时候,系统会用 OOM Killer 杀掉占内存最多的进程。加个 Swap 能缓冲一下,避免直接被杀。
常见坑
坑1:Swap 文件权限不对
创建完 Swap 文件之后忘了 chmod 600,结果 swapon 报错。
解决: 一定要先设置权限:
chmod 600 /swapfile
坑2:/etc/fstab 写错了
和挂载硬盘一样,/etc/fstab 写错了重启会进不去系统。
解决: 改完先执行 swapon -a 测试一下。
坑3:Swap 太大了影响性能
Swap 不是越大越好。如果 Swap 用得很频繁,系统会非常卡,因为磁盘比内存慢几百倍。
建议: Swap 大小设成物理内存的 0.5~2 倍就够了。比如 2G 内存,Swap 设 2~4G 就行。
坑4:SSD 上放 Swap 还好,机械硬盘上放 Swap 很卡
如果是机械硬盘,频繁读写 Swap 会非常卡。SSD 还好一点。
总结
添加 Swap 的完整流程:
- dd 创建 Swap 文件
- chmod 600 设置权限
- mkswap 格式化
- swapon 启用
- 写 /etc/fstab 开机自动挂载
- 调整 swappiness 优先级
Swap 只是应急方案,真正解决内存不足还是要加物理内存。但应急的时候,Swap 确实能救一命。
遇到问题加QQ23979811 协助处理
Linux添加新硬盘并挂载,fdisk和mkfs分区格式化
前言
服务器磁盘满了,加了一块新硬盘,但不知道怎么用?新硬盘插上去之后,Linux 是不能直接用的,需要先分区、格式化、挂载,最后还要配置开机自动挂载。整个流程看起来复杂,其实就几步。本文就以 CentOS7 为例,完整讲一下新硬盘从插入到挂载的全过程。
第一步:查看新硬盘有没有识别到
加完硬盘之后,先看看系统有没有识别到。
fdisk -l
输出会列出所有磁盘设备。一般系统盘是 /dev/sda,新硬盘就是 /dev/sdb、/dev/sdc 这样。
找到新硬盘,大小和你加的硬盘一致的那个就是。比如新硬盘是100G,找大小100G的那个设备。
注意: 千万别搞错设备名!格式化错了盘,数据就全没了。一定要确认大小对得上。
第二步:给新硬盘分区
用 fdisk 命令给新硬盘分区。这里我们分一个主分区,用完全部空间。
fdisk /dev/sdb
进入 fdisk 交互界面,按以下步骤操作:
1. 输入 n 创建新分区
Command (m for help): n
2. 选择主分区
Select (default p): p
3. 分区号选默认1
Partition number (1-4, default 1): 1
4. 起始扇区选默认
直接回车:
First sector (2048-209715199, default 2048): 回车
5. 结束扇区选默认(用完全部空间)
直接回车:
Last sector, +sectors or +size{K,M,G} (2048-209715199, default 209715199): 回车
6. 输入 w 保存退出
Command (m for help): w
这样就分好区了,分区设备是 /dev/sdb1。
第三步:格式化分区
分完区之后,需要格式化成文件系统。一般用 ext4 或 xfs。
CentOS7 默认用 xfs:
mkfs.xfs /dev/sdb1
如果要用 ext4:
mkfs.ext4 /dev/sdb1
等待格式化完成,一般很快,几十秒就好。
第四步:创建挂载目录
先创建一个目录用来挂载新硬盘:
mkdir /data
第五步:挂载分区
把分区挂载到刚才创建的目录:
mount /dev/sdb1 /data
查看挂载结果:
df -h
输出里应该能看到 /dev/sdb1 挂载在 /data 目录。
第六步:配置开机自动挂载
上面的挂载重启之后就没了,需要写入 /etc/fstab 才能开机自动挂载。
1. 查看分区的 UUID
blkid /dev/sdb1
输出示例:
/dev/sdb1: UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" TYPE="xfs"
复制这个 UUID。
2. 编辑 /etc/fstab
vi /etc/fstab
在最后一行添加:
UUID=刚才复制的UUID /data xfs defaults 0 0
各字段含义:
- 第一列:设备UUID
- 第二列:挂载点
- 第三列:文件系统类型(xfs 或 ext4)
- 第四列:挂载参数(defaults 就够了)
- 第五列:dump备份标记(0表示不备份)
- 第六列:开机检查顺序(0表示不检查)
3. 测试配置是否正确
mount -a
如果没有报错,说明配置正确。如果报错了,千万别重启!重启可能进不去系统。
常见坑
坑1:格式化错了盘
这是最危险的坑!格式化错了盘,数据就全没了。
解决: 格式化之前一定要确认设备名是对的,用 fdisk -l 看大小,确认大小和你加的新硬盘一致再操作。
坑2:/etc/fstab 写错了,重启进不去系统
如果 /etc/fstab 写错了,重启的时候会卡在挂载界面,进不去系统。
解决: 改完 /etc/fstab 之后一定要先跑 mount -a 测试,确认没报错再重启。
坑3:挂载目录里有文件
如果挂载目录里已经有文件了,挂载之后原来的文件就看不到了(不是删了,是被覆盖了)。
解决: 挂载之前确认挂载目录是空的,或者先把原来的文件移走。
坑4:用设备名写 fstab,重启后变了
如果用 /dev/sdb1 写 fstab,下次重启之后硬盘顺序变了,可能就挂载错了。
解决: 用 UUID 写 fstab,UUID 是唯一的,不会变。
总结
新硬盘挂载的完整流程:
- fdisk -l:确认新硬盘设备名
- fdisk /dev/sdb:分区
- mkfs.xfs /dev/sdb1:格式化
- mkdir /data:创建挂载目录
- mount /dev/sdb1 /data:临时挂载
- blkid 查UUID:获取UUID
- 写 /etc/fstab:配置开机自动挂载
- mount -a:测试配置
整个流程走一遍以后,加硬盘就是熟练活了。
遇到问题加QQ23979811 协助处理
Linux查看系统版本和内核信息,cat /etc/os-release和uname命令
前言
刚拿到一台服务器,第一步就是看看是什么系统、什么版本、内核是多少。不同的系统版本配置方法不一样,CentOS7 和 CentOS8 的防火墙命令都不一样,Ubuntu 和 CentOS 的包管理器也不一样。所以第一件事就是确认系统版本。本文就讲一下怎么查看 Linux 系统版本和内核信息。
查看系统版本
方法一:cat /etc/os-release(推荐)
这是最通用的方法,所有现代 Linux 发行版都有这个文件:
cat /etc/os-release
CentOS7 输出示例:
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"
Ubuntu 输出示例:
NAME="Ubuntu"
VERSION="20.04.6 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.6 LTS"
VERSION_ID="20.04"
重点看 NAME、VERSION、VERSION_ID 这几行。
方法二:cat /etc/redhat-release(CentOS/RHEL专用)
CentOS 和 RHEL 系统可以直接看这个文件:
cat /etc/redhat-release
输出:
CentOS Linux release 7.9.2009 (Core)
方法三:lsb_release -a
lsb_release -a
输出:
Distributor ID: CentOS
Description: CentOS Linux release 7.9.2009 (Core)
Release: 7.9.2009
Codename: Core
注意: 有些系统默认没装 lsb_release,需要先安装:
yum install redhat-lsb -y
方法四:hostnamectl
hostnamectl
输出会显示系统信息,包括操作系统和内核版本:
Static hostname: localhost.localdomain
Icon name: computer-vm
Chassis: vm
Machine ID: xxxxxxxx
Boot ID: xxxxxxxx
Virtualization: kvm
Operating System: CentOS Linux 7 (Core)
CPE OS Name: cpe:/o:centos:centos:7
Kernel: Linux 3.10.0-1160.el7.x86_64
Architecture: x86-64
这个命令同时显示系统版本和内核版本,很方便。
查看内核版本
方法一:uname -a(最常用)
uname -a
输出示例:
Linux localhost 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:58 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
各段含义:
Linux:内核名localhost:主机名3.10.0-1160.el7.x86_64:内核版本#1 SMP ...:编译信息x86_64 x86_64 x86_64:硬件架构、处理器类型、操作系统类型
方法二:uname -r
只看内核版本号:
uname -r
输出:
3.10.0-1160.el7.x86_64
内核版本号拆解:
3:主版本10:次版本0:修订版本1160:RHEL补丁号el7:Enterprise Linux 7x86_64:64位
方法三:cat /proc/version
cat /proc/version
输出:
Linux version 3.10.0-1160.el7.x86_64 (mockbuild@x86-01.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) ) #1 SMP Mon Oct 19 16:18:58 UTC 2020
查看系统架构
uname -m
输出:
x86_64
说明是64位系统。如果输出 i686 就是32位。
或者用:
arch
实际应用场景
场景1:刚拿到服务器,先确认系统版本
cat /etc/os-release
uname -r
确认是 CentOS7 还是 Ubuntu,内核版本是多少。
场景2:安装软件前确认版本
不同版本的系统安装方法不一样,CentOS7 用 yum,Ubuntu 用 apt。先确认版本再装软件。
场景3:排查内核兼容性问题
有些软件要求特定内核版本,先看看当前内核版本够不够。
uname -r
场景4:确认是32位还是64位
uname -m
常见坑
坑1:cat /etc/issue 不准
很多老教程说用 cat /etc/issue 看系统版本,但这个文件可能被改过,不一定准。推荐用 /etc/os-release。
坑2:把内核版本和系统版本搞混
内核版本是 uname -r 显示的,系统版本是 /etc/os-release 显示的。这两个不一样,别搞混了。
坑3:CentOS 各小版本不影响大版本
CentOS7.9 和 CentOS7.6 都是 CentOS7,大部分操作是一样的。只要大版本对就行,不用纠结小版本号。
总结
查看系统版本和内核信息的核心命令:
- cat /etc/os-release:看系统版本(最通用)
- cat /etc/redhat-release:CentOS/RHEL 专用
- uname -a:看内核版本和系统架构
- uname -r:只看内核版本号
- hostnamectl:同时看系统版本和内核版本
拿到一台新服务器,先跑这几个命令确认系统环境,再开始做其他操作。
遇到问题加QQ23979811 协助处理
Linux查看进程启动时间,ps和lsof命令使用
前言
想知道某个进程跑了多久?或者想知道哪个进程打开了某个文件?这时候就需要用到 ps 和 lsof 两个命令了。ps 用来查看进程信息,包括启动时间、运行状态等;lsof 用来查看进程打开了哪些文件。这两个命令是运维排查问题的必备工具。本文就详细讲一下这两个命令的使用。
ps 命令
基本用法
ps aux
输出所有进程的详细信息。
输出示例:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 128000 5000 ? Ss Oct01 0:05 /usr/lib/systemd/systemd
root 123 0.0 0.2 150000 10000 ? Ss Oct01 0:10 /usr/sbin/sshd
nginx 4567 0.0 0.3 200000 15000 ? S Oct05 0:02 nginx: worker process
各列含义
| 列 | 含义 |
|---|---|
USER |
进程所属用户 |
PID |
进程ID |
%CPU |
CPU占用百分比 |
%MEM |
内存占用百分比 |
VSZ |
虚拟内存大小 |
RSS |
物理内存大小 |
TTY |
终端 |
STAT |
进程状态 |
START |
启动时间 |
TIME |
累计CPU时间 |
COMMAND |
启动命令 |
查看进程启动时间
ps -p PID -o lstart
比如查看PID为123的进程的启动时间:
ps -p 123 -o lstart
输出:
STARTED
Mon Oct 1 10:30:45 2026
查看某个进程的详细信息
ps aux | grep nginx
按CPU占用排序
ps aux --sort=-%cpu | head -10
按内存占用排序
ps aux --sort=-%mem | head -10
lsof 命令
lsof = list open files,用来查看进程打开了哪些文件。
基本用法
lsof
列出所有进程打开的所有文件。
查看某个进程打开的文件
lsof -p PID
比如查看PID为123的进程打开了哪些文件:
lsof -p 123
查看某个文件被哪个进程占用
lsof 文件路径
比如查看 /var/log/nginx/access.log 被哪个进程占用:
lsof /var/log/nginx/access.log
查看某个端口被哪个进程占用
lsof -i :80
查看80端口被哪个进程占用。
查看某个用户打开的文件
lsof -u nginx
查看nginx用户打开的所有文件。
查看某个目录下被打开的文件
lsof +D /var/log/
查看 /var/log/ 目录下所有被打开的文件。
实际排查案例
案例1:磁盘空间没释放
删了一个大文件,但磁盘空间没释放。这是因为还有进程在写这个文件。
lsof | grep deleted
输出所有已删除但还被进程占用的文件。找到对应的PID,重启那个进程就能释放空间了。
案例2:端口被占用
启动Nginx的时候报错"Address already in use",说明80端口被占用了。
lsof -i :80
看是哪个进程占了80端口,杀掉或者换个端口。
案例3:进程启动时间不对
怀疑某个服务被重启过,看看启动时间。
ps -ef | grep nginx
或者更详细的:
ps -p PID -o lstart
案例4:找出谁在写日志
想知道哪个进程在写某个日志文件。
lsof /var/log/messages
常见坑
坑1:删了文件磁盘空间没释放
这是最常见的坑。删了大文件,但磁盘空间没释放,因为还有进程在写这个文件。
解决: 用 lsof | grep deleted 找到还在写这个文件的进程,重启那个进程,或者直接清空文件内容:
> /var/log/nginx/access.log
坑2:ps aux 和 ps -ef 搞混了
ps aux 和 ps -ef 输出格式不一样,但信息基本一样。aux 是BSD格式,-ef 是System V格式。看个人习惯。
坑3:lsof 输出太多
lsof 不加参数会输出一大堆,根本看不过来。一定要加参数过滤:-p、-i、-u、+D 等。
总结
查看进程信息的核心命令:
- ps aux:看所有进程的基本信息
- ps -p PID -o lstart:看某个进程的启动时间
- lsof -p PID:看某个进程打开了哪些文件
- lsof -i :端口:看某个端口被哪个进程占用
- lsof | grep deleted:看哪些已删除文件还被进程占用
ps 和 lsof 是运维排查问题的基本功,遇到问题先跑一遍这两个命令,大部分问题都能定位到方向。
遇到问题加QQ23979811 协助处理
Linux查看网络连接数,ss和netstat命令统计
前言
服务器被攻击了?网站访问量突然暴涨?想看看当前有多少人在连接你的服务器?这时候就需要查看网络连接数了。ss 和 netstat 是两个最常用的网络连接查看命令,ss 是新版,速度更快,推荐优先用。本文就讲一下怎么用这两个命令统计网络连接数、排查网络问题。
ss 命令(推荐)
ss 是 iproute2 包自带的,比 netstat 快很多,尤其是连接数很多的时候。
基本用法
ss
显示所有TCP和UDP连接。
统计各状态连接数
ss -s
输出示例:
Total: 120
TCP: 80 (estab 30, closed 40, orphaned 0, timewait 20)
Transport Total IP IPv6
RAW 0 0 0
UDP 5 3 2
TCP 80 60 20
INET 85 63 22
FRAG 0 0 0
这就是全局统计,一眼就能看出当前有多少连接。
查看TCP连接
ss -t
只显示TCP连接。
查看所有监听端口
ss -tlnp
参数说明:
-t:TCP-l:只显示监听状态的-n:不解析域名,直接显示IP和端口-p:显示进程名
统计某个端口的连接数
比如统计80端口的连接数:
ss -tn | grep :80 | wc -l
统计各状态的TCP连接数
ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn
输出示例:
40 ESTAB
30 TIME-WAIT
10 LISTEN
5 CLOSE-WAIT
netstat 命令
netstat 是老牌命令,很多老脚本还在用。
基本用法
netstat -tlnp
查看监听的TCP端口。
统计各状态连接数
netstat -an | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
统计某个端口的连接数
netstat -an | grep :80 | wc -l
查看哪个进程在监听某个端口
netstat -tlnp | grep :80
连接状态详解
TCP连接有很多状态,常见的:
| 状态 | 含义 |
|---|---|
ESTABLISHED |
已建立连接,正在通信 |
LISTEN |
监听中,等待连接 |
TIME_WAIT |
主动关闭方等待,防止旧包干扰新连接 |
CLOSE_WAIT |
被动关闭方等待,说明程序没正确关闭连接 |
FIN_WAIT1 |
主动关闭方,等待对方回应 |
FIN_WAIT2 |
主动关闭方,已经收到对方回应 |
重点关注:
ESTABLISHED多:说明当前活跃连接多,正常TIME_WAIT多:说明短连接很多,正常但要注意CLOSE_WAIT多:说明程序有bug,没正确关闭连接
实际排查案例
案例1:看看当前有多少人访问网站
ss -tn | grep :80 | grep ESTAB | wc -l
统计80端口已建立连接的数量。
案例2:看看哪个IP连接最多
ss -tn state established '( sport = :80 )' | awk '{print $4}' | awk -F: '{print $1}' | sort | uniq -c | sort -rn | head -10
输出连接最多的前10个IP。
案例3:看看是不是被攻击了
如果突然有大量 TIME_WAIT 或 CLOSE_WAIT,可能是被攻击了。
ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn
常见坑
坑1:连接数多就是被攻击了
连接数多不一定是被攻击。如果是正常的网站访问量上涨,连接数多是正常的。要看连接来源IP分布和连接状态。
坑2:TIME_WAIT 多就优化
TIME_WAIT 是TCP协议的正常机制,不需要太紧张。除非 TIME_WAIT 数量特别多(几万几十万),影响了性能,再考虑优化。
坑3:CLOSE_WAIT 多不处理
CLOSE_WAIT 多说明你的程序有bug,没有正确关闭连接。时间长了会把文件句柄用完,导致新连接建不起来。这是程序问题,要改代码。
总结
查看网络连接数的核心命令:
- ss -s:快速看全局统计
- ss -tlnp:看监听端口和对应进程
- ss -tan | awk '{print $1}' | sort | uniq -c:统计各状态连接数
- netstat:老命令,兼容性好,但慢
推荐用 ss,比 netstat 快很多,尤其是连接数很多的时候。
遇到问题加QQ23979811 协助处理
Linux查看磁盘I/O性能,iostat命令详解
前言
服务器变慢了,CPU不高、内存也够,但就是卡。这时候就要看看是不是磁盘I/O瓶颈了。很多时候系统慢不是CPU不够,而是磁盘读写太慢,CPU一直在等磁盘。iostat 就是专门用来查看磁盘I/O性能的工具,配合 vmstat 一起用,能快速定位I/O问题。本文就详细讲一下 iostat 命令的使用。
安装 iostat
CentOS7 默认可能没装 iostat,先装一下:
yum install sysstat -y
iostat 属于 sysstat 包,装完就有了。
基本用法
直接输入:
iostat
输出示例:
Linux 3.10.0-1160.el7.x86_64 (localhost) 10/05/2026 _x86_64_ (2 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
5.00 0.00 2.00 1.00 0.00 92.00
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 10.00 50.00 100.00 500000 1000000
输出详解
CPU 部分
avg-cpu: %user %nice %system %iowait %steal %idle
5.00 0.00 2.00 1.00 0.00 92.00
| 列 | 含义 |
|---|---|
%user |
用户态CPU占用 |
%nice |
改变过优先级的进程占用 |
%system |
内核态CPU占用 |
%iowait |
等待磁盘I/O的CPU占比(重点看这个) |
%steal |
被虚拟机偷走的CPU |
%idle |
空闲CPU |
重点看 %iowait: 如果这个值很高(比如超过20%),说明磁盘I/O是瓶颈,CPU大部分时间在等磁盘读写。
磁盘部分
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 10.00 50.00 100.00 500000 1000000
| 列 | 含义 |
|---|---|
Device |
设备名 |
tps |
每秒传输次数(IOPS) |
kB_read/s |
每秒读取的数据量 |
kB_wrtn/s |
每秒写入的数据量 |
kB_read |
总共读取的数据量 |
kB_wrtn |
总共写入的数据量 |
实时监控
每2秒刷新一次
iostat 2
按 Ctrl+C 退出。
每2秒刷新一次,总共刷新5次
iostat 2 5
只看磁盘部分,不看CPU
iostat -d 2
更详细的磁盘统计
显示扩展统计信息
iostat -x
输出会多出很多列,这才是真正分析磁盘性能的关键:
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 5.00 1.00 9.00 50.00 100.00 30.00 0.10 5.00 2.00 6.00 1.00 1.00
重点列说明:
| 列 | 含义 | 判断标准 |
|---|---|---|
await |
平均I/O等待时间(毫秒) | 超过20ms就要注意,超过100ms说明磁盘很慢 |
svctm |
平均I/O服务时间(毫秒) | 越小越好 |
%util |
磁盘利用率 | 接近100%说明磁盘跑满了 |
avgqu-sz |
平均I/O队列长度 | 越大说明排队越严重 |
最重要的两个指标:
%util:如果接近100%,说明磁盘已经跑满了await:如果很大,说明每次I/O等待时间很长,磁盘很慢
常用参数组合
实时监控磁盘性能
iostat -x 2
每2秒刷新一次,显示扩展信息。
只看某个磁盘
iostat -x sda 2
以MB为单位显示
iostat -m
显示设备映射关系
iostat -N
实际排查案例
案例1:系统变慢,怀疑磁盘I/O
vmstat 1
看 wa 列,如果很高(超过20%),说明磁盘I/O是瓶颈。
然后用 iostat 详细看:
iostat -x 2
看 %util 是不是接近100%,await 是不是很大。
案例2:哪个磁盘跑得最忙
iostat -x 2
看 %util 列,哪个磁盘的 %util 最高,就是哪个磁盘是瓶颈。
案例3:读写比例
iostat -x 2
看 r/s 和 w/s,是读多还是写多,针对性优化。
常见坑
坑1:%util 100% 就以为磁盘坏了
%util 100% 说明磁盘在处理I/O请求,但不一定是磁盘性能不行。可能是I/O请求量太大,也可能是磁盘确实慢。要结合 await 一起看。
坑2:只看 tps 不看 await
tps 高不一定是问题,要看每次I/O的等待时间 await。如果 await 很小,说明磁盘处理得很快,tps高也没关系。
坑3:把 iowait 当成CPU问题
%iowait 高说明CPU在等磁盘,不是CPU不够用。这时候加CPU没用,要优化磁盘I/O。
总结
查看磁盘I/O性能的核心命令:
- iostat:快速看磁盘整体读写情况
- iostat -x 2:实时监控,重点看
%util和await - vmstat 1:看
wa列,确认是不是I/O瓶颈
记住两个关键指标:
%util接近100%:磁盘跑满了await超过20ms:磁盘响应慢了
遇到问题加QQ23979811 协助处理
Linux查看内存使用情况,free和vmstat命令详解
前言
服务器卡了,第一反应就是看看内存够不够用。很多人一看到 free 很少就慌了,觉得内存不够要扩容。其实 Linux 的内存管理和 Windows 不一样,free 少不代表内存真的不够。本文就讲一下怎么用 free 和 vmstat 两个命令正确查看内存使用情况。
free 命令
基本用法
直接输入:
free
输出示例:
total used free shared buff/cache available
Mem: 8165036 4000000 2000000 50000 2165036 4000000
Swap: 2097148 0 2097148
输出详解
| 列 | 含义 |
|---|---|
total |
总内存大小 |
used |
已使用的内存 |
free |
完全空闲的内存 |
shared |
共享内存 |
buff/cache |
缓存和缓冲区占用的内存 |
available |
真正可用的内存(重点看这列) |
重点:available 才是真正可用的内存
很多人只看 free 列,看到只剩几百M就慌了。其实 Linux 会把空闲内存都用来做缓存(buff/cache),这些缓存是可以随时回收的。
看 available 列才是真正可用的内存。 比如上面的例子,free 只有2G,但 available 有4G,说明还有4G内存可以用。
free 常用参数
free -h
以人类可读的格式显示(自动用G/M/K单位):
total used free shared buff/cache available
Mem: 7.8Gi 3.8Gi 1.9Gi 50Mi 2.1Gi 3.8Gi
Swap: 2.0Gi 0B 2.0Gi
free -m
以MB为单位显示。
free -g
以GB为单位显示。
free -s 5
每5秒刷新一次。
free -c 3
总共显示3次后退出。
vmstat 命令
基本用法
直接输入:
vmstat
输出示例:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 2000000 50000 2100000 0 0 10 20 100 50 5 2 92 1 0
输出详解
procs 进程部分:
r:等待运行的进程数b:处于不可中断睡眠的进程数
memory 内存部分:
swpd:已用的交换分区大小free:空闲内存buff:缓冲区大小cache:缓存大小
swap 交换分区部分:
si:从磁盘交换到内存的速度(KB/s)so:从内存交换到磁盘的速度(KB/s)
io 磁盘I/O部分:
bi:从磁盘读取的速度(块/s)bo:写入磁盘的速度(块/s)
cpu CPU部分:
us:用户态CPU占用sy:内核态CPU占用id:空闲CPUwa:等待I/O的CPUst:被虚拟机偷走的CPU
vmstat 常用参数
vmstat 1
每秒刷新一次,按 Ctrl+C 退出。
vmstat 1 5
每秒刷新一次,总共刷新5次。
vmstat -s
显示内存统计信息。
怎么判断内存够不够用
看 available 够不够
free -h
看 available 列,如果 available 还有几百M以上,说明内存够用。
看 swap 用了多少
free -h
如果 Swap 的 used 列有数值,说明物理内存不够用了,系统在把内存数据换到磁盘上。这时候性能会大幅下降。
看 si 和 so
vmstat 1
如果 si 和 so 列长期不为0,说明系统在频繁换页,内存不够用了。
实际排查案例
案例1:内存够不够
free -h
看 available 列,如果还有几个G,说明内存够用。
案例2:系统变慢,怀疑内存不足
vmstat 1
看 si 和 so 是不是很高,如果很高说明在频繁换页,内存不够。
案例3:哪个进程占内存最多
top
按 M 键按内存排序,看哪个进程占的内存最多。
常见坑
坑1:把 free 少当成内存不足
Linux 的内存管理机制和 Windows 不一样,空闲内存都用来做缓存了,buff/cache 那部分是可以随时回收的。看 available 列才是真正可用的内存。
坑2:看到 swap 用了就慌
如果 swap 用了一点,但 si 和 so 都是0,说明那是历史遗留的,不影响性能。只有当 si 和 so 长期不为0的时候才是问题。
坑3:内存不够就随便扩容
内存不够的原因可能有很多:
- 某个程序内存泄漏
- 数据库缓存配置太大
- 日志缓存没配置
先找出原因,再决定要不要扩容。
总结
查看内存使用情况的核心命令:
- free -h:快速看内存总览,重点看
available列 - vmstat 1:实时监控内存和换页情况,看
si和so - top 按M:看哪个进程占内存最多
记住一个原则:Linux 的 free 少不是问题,available 少才是问题。
遇到问题加QQ23979811 协助处理
Linux查看系统运行时间,uptime和w命令使用
前言
想知道服务器已经连续运行了多少天?现在有多少人在线?系统负载怎么样?这些问题用 uptime 和 w 两个命令就能搞定。这两个命令虽然简单,但都是运维日常最常用的,一个看运行时间和负载,一个看谁在线。本文就把这两个命令讲透。
uptime 命令
基本用法
直接输入:
uptime
输出示例:
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分钟的平均值 |
负载怎么看
负载(load average)是衡量系统繁忙程度的指标。数值越高说明越忙。
判断标准:
- 负载数值和CPU核心数有关
- 比如4核CPU,负载4.0才算跑满
- 一般来说,负载不要超过CPU核心数的70%
- 比如4核CPU,负载在2.8以下算正常
uptime 常用参数
uptime -V
查看版本号。
uptime -h
查看帮助。
w 命令
基本用法
直接输入:
w
输出示例:
10:30:45 up 30 days, 2:15, 1 user, load average: 0.50, 0.40, 0.30
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 192.168.1.100 10:20 5.00s 0.05s 0.00s w
输出详解
第一行和 uptime 完全一样:系统时间、运行时间、在线用户数、负载。
下面是当前登录的用户列表:
| 列 | 含义 |
|---|---|
USER |
登录用户名 |
TTY |
终端类型(pts/0 表示远程SSH连接) |
FROM |
登录来源IP |
LOGIN@ |
登录时间 |
IDLE |
空闲时间 |
JCPU |
该终端所有进程占用的CPU时间 |
PCPU |
当前进程占用的CPU时间 |
WHAT |
当前正在运行的命令 |
w 常用参数
w -h
不显示第一行标题,只显示用户列表。
w -s
精简模式,不显示 JCPU 和 PCPU 列。
w root
只查看某个用户的登录信息。
who 命令
除了 uptime 和 w,还有个 who 命令,更简单:
who
输出:
root pts/0 2026-10-05 10:20 (192.168.1.100)
只显示谁在线、从哪来、什么时候登录的。
last 命令
想知道历史登录记录,用 last:
last
输出最近的登录记录,包括:
- 谁登录的
- 从哪个IP登录的
- 什么时候登录的
- 登录了多久
last -10
只看最近10条。
实际应用场景
场景1:服务器重启过没有
用 uptime 看运行时间,如果才几天,说明最近重启过。
uptime
场景2:谁在登录我的服务器
用 w 看当前有谁在线,来源IP是哪里。如果有不认识的IP,可能是被入侵了。
w
场景3:系统负载高不高
用 uptime 看 load average,如果负载很高,再用 top 看是哪个进程占的。
uptime
top
场景4:排查登录历史
用 last 看历史登录记录,有没有异常登录。
last
常见坑
坑1:负载高就以为CPU不够
负载高不一定是CPU的问题。负载包括所有等待CPU的进程,也包括等待I/O的进程。可能是磁盘I/O瓶颈,也可能是大量进程在排队。要结合 top 一起看。
坑2:把在线用户数看得很重要
1 user 这个数字只是当前登录的用户数,不代表系统性能。一个用户也可能把系统跑满,100个用户也可能很空闲。
坑3:last 显示的是历史记录,不是实时状态
last 是看历史登录记录的,现在谁在线要用 w 或 who。两者别搞混了。
总结
uptime 和 w 是最基础的系统监控命令:
- uptime:看系统运行时间和负载
- w:看谁在线、从哪来、在干嘛
- who:更简单的在线用户查看
- last:看历史登录记录
这几个命令都是秒出结果,排查问题的时候先跑一遍,快速了解系统基本状态。
遇到问题加QQ23979811 协助处理
Linux日志过大占用磁盘,logrotate日志切割配置
前言
服务器跑了几个月,突然磁盘满了,一查发现是日志文件占了几十G。Nginx的access.log、MySQL的慢查询日志、系统日志……这些日志文件只会越来越大,不会自己变小。手动删了吧,又怕删出问题;不删吧,磁盘迟早满。Linux 自带了 logrotate 工具,专门用来自动切割和清理日志,配置一次以后就不用管了。本文就详细讲一下怎么用 logrotate 管理日志。
什么是 logrotate
logrotate 是 Linux 系统自带的日志管理工具,可以自动完成:
- 切割日志:把大日志文件按天/按大小切成多个小文件
- 压缩日志:旧的日志自动 gzip 压缩
- 删除日志:保留指定天数后自动删除
- 通知服务:切割完后通知 Nginx/MySQL 等服务重新打开日志文件
系统默认每天运行一次 logrotate,你只需要写好配置文件就行。
logrotate 配置文件结构
全局配置
vi /etc/logrotate.conf
这是全局配置文件,一般不用改。里面定义了默认的行为:
weekly # 默认每周切割一次
rotate 4 # 保留4个日志文件
create # 切割后创建新的空日志文件
dateext # 用日期作为扩展名
include /etc/logrotate.d # 包含这个目录下的所有配置
单个服务的配置
每个服务的日志配置放在 /etc/logrotate.d/ 目录下:
ls /etc/logrotate.d/
比如 nginx、mysql、syslog 都有各自的配置文件。
实战:配置 Nginx 日志切割
我们以 Nginx 为例,写一个完整的 logrotate 配置。
1. 创建配置文件
vi /etc/logrotate.d/nginx
2. 写入配置
/var/log/nginx/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 nginx nginx
postrotate
/usr/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endpostrotate
}
3. 参数说明
| 参数 | 作用 |
|---|---|
/var/log/nginx/*.log |
要切割的日志文件路径 |
daily |
每天切割一次 |
rotate 30 |
保留30个日志文件 |
compress |
旧日志用gzip压缩 |
delaycompress |
延迟压缩,新切割的当天不压缩 |
missingok |
日志文件不存在不报错 |
notifempty |
空文件不切割 |
create 644 nginx nginx |
创建新文件,权限644,属主nginx |
postrotate...endpostrotate |
切割后执行的命令,通知Nginx重新打开日志文件 |
常用切割策略
按天切割,保留30天
/var/log/nginx/*.log {
daily
rotate 30
compress
missingok
notifempty
create 644 nginx nginx
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endpostrotate
}
按大小切割,超过100M就切
/var/log/nginx/access.log {
size 100M
rotate 10
compress
missingok
notifempty
create 644 nginx nginx
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endpostrotate
}
同时按天+按大小
/var/log/nginx/*.log {
daily
size 100M
rotate 30
compress
missingok
notifempty
create 644 nginx nginx
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endpostrotate
}
意思是每天检查一次,如果日志超过100M就切割。
手动测试 logrotate
配置完之后,可以用 debug 模式测试一下,不会真正执行:
logrotate -d /etc/logrotate.d/nginx
参数说明:
-d:debug模式,只显示会做什么,不真正执行
如果没问题,手动执行一次:
logrotate -f /etc/logrotate.d/nginx
-f:强制切割,不管到没到时间
常见坑
坑1:切割了但服务还在写旧文件
很多人配置完 logrotate,发现日志切完了,但磁盘空间没释放。这是因为 Nginx 还在往旧的日志文件里写(虽然名字改了,但文件句柄还在)。
解决: 一定要配置 postrotate 脚本,通知服务重新打开日志文件。对于 Nginx,就是发送 USR1 信号:
postrotate
/bin/kill -USR1 `cat /run/nginx.pid`
endpostrotate
坑2:压缩延迟没开,旧日志还占着空间
如果不加 delaycompress,切割完立刻就压缩,但服务可能还在写旧文件,导致压缩失败或者压缩不完整。
解决: 加上 delaycompress,让新切割的日志第二天再压缩。
坑3:日志文件权限不对
切割完创建的新日志文件,如果属主不对,Nginx 就写不进去。
解决: 用 create 644 nginx nginx 指定新文件的属主和权限。
坑4:logrotate 不执行
配置写完了,但日志从来没切割过。检查一下:
# 看logrotate的cron任务有没有
cat /etc/cron.daily/logrotate
# 手动执行一次看有没有报错
logrotate -d /etc/logrotate.d/nginx
总结
logrotate 配置的核心步骤:
- 在
/etc/logrotate.d/下创建配置文件 - 指定日志路径、切割频率、保留数量
- 加上
postrotate通知服务重新打开日志 - 用
logrotate -d测试配置 - 系统每天自动执行,不用管了
日志切割是服务器运维的基本功,配好了以后磁盘永远不会被日志撑满。
遇到问题加QQ23979811 协助处理
服务器被暴力ssh爆破,如何防护与封禁IP
前言
刚装好的服务器没几天,一看登录日志吓一跳——全是各种IP在尝试SSH登录,用户名猜遍了root、admin、test,密码也是暴力破解。这就是典型的SSH暴力破解攻击。如果你的服务器密码又简单,很容易被破解进来。本文就讲一下怎么发现暴力破解、怎么封禁恶意IP,以及怎么从根本上防护。
第一步:查看SSH登录日志
先看看有没有被爆破。CentOS7 的SSH日志在 /var/log/secure:
tail -100 /var/log/secure
如果看到大量类似这样的记录,就是被爆破了:
Failed password for root from 1.2.3.4 port 12345 ssh2
Failed password for admin from 5.6.7.8 port 23456 ssh2
统计一下尝试登录的次数最多的IP:
grep "Failed password" /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -rn | head -10
输出会列出尝试登录次数最多的10个IP。
防护方案一:使用 fail2ban 自动封禁
手动封禁太慢了,用 fail2ban 可以自动检测并封禁恶意IP。
1. 安装 EPEL 源
yum install epel-release -y
2. 安装 fail2ban
yum install fail2ban -y
3. 配置 fail2ban
vi /etc/fail2ban/jail.local
写入以下内容:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/secure
maxretry = 3
bantime = 86400
findtime = 600
参数说明:
enabled = true:启用这个规则maxretry = 3:最多尝试3次bantime = 86400:封禁24小时(单位秒)findtime = 600:10分钟内的失败次数
4. 启动 fail2ban
systemctl start fail2ban
systemctl enable fail2ban
5. 查看封禁状态
fail2ban-client status sshd
防护方案二:手动封禁恶意IP
如果不想装 fail2ban,也可以手动用 firewall-cmd 封禁IP:
封禁单个IP
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='1.2.3.4' reject"
firewall-cmd --reload
查看已封禁的规则
firewall-cmd --list-rich-rules
解除封禁
firewall-cmd --permanent --remove-rich-rule="rule family='ipv4' source address='1.2.3.4' reject"
firewall-cmd --reload
防护方案三:修改SSH默认端口
SSH默认端口是22,所有人都知道,扫端口的机器人都会先扫22。改成一个不常见的端口能挡住90%的自动扫描。
1. 编辑SSH配置
vi /etc/ssh/sshd_config
找到 #Port 22,改成:
Port 22222
2. 防火墙开放新端口
firewall-cmd --permanent --add-port=22222/tcp
firewall-cmd --reload
3. 重启SSH服务
systemctl restart sshd
注意: 改完端口后,连接时要指定新端口:ssh -p 22222 root@你的服务器IP。千万不要关掉当前SSH窗口!新开一个窗口测试,确认新端口能连上了再关旧窗口。
防护方案四:禁止root密码登录,改用密钥登录
最彻底的防护就是不让密码登录,只用SSH密钥登录。
1. 生成SSH密钥对
在你本地电脑上执行:
ssh-keygen -t rsa -b 4096
一路回车,会生成两个文件:
~/.ssh/id_rsa:私钥,放在你本地~/.ssh/id_rsa.pub:公钥,上传到服务器
2. 上传公钥到服务器
ssh-copy-id -p 22222 root@你的服务器IP
3. 配置SSH禁用密码登录
vi /etc/ssh/sshd_config
找到并修改:
PasswordAuthentication no
PermitRootLogin yes
PubkeyAuthentication yes
4. 重启SSH服务
systemctl restart sshd
注意: 改之前一定要确认密钥登录能正常用!不然改完就连不上了。
防护方案五:限制只允许特定IP登录
如果你自己的IP是固定的,可以只允许自己的IP登录SSH:
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='你的IP/24' port protocol='tcp' port='22' accept"
firewall-cmd --permanent --remove-port=22/tcp
firewall-cmd --reload
这样只有你指定的IP段才能连SSH,其他IP直接拒绝。
常见坑
坑1:改了SSH端口忘了开防火墙
改完SSH端口后,忘了在防火墙里开放新端口,结果新端口连不上,旧端口也关了,直接把自己锁在外面。
解决: 改完端口后,一定要先开防火墙再重启SSH,而且要新开窗口测试。
坑2:用fail2ban把自己封了
测试的时候故意输错几次密码,结果被fail2ban封了自己的IP。
解决: 把自己的IP加到 fail2ban 的忽略列表里:
ignoreip = 127.0.0.1/8 你的IP
坑3:禁用密码登录前没测试密钥
直接就把 PasswordAuthentication no 了,结果密钥没配好,连不上服务器了。
解决: 先测试密钥登录能正常用,再禁用密码登录。千万不要关当前窗口,新开窗口测试。
总结
SSH暴力破解防护的优先级:
- 改SSH端口:从22改成其他端口,挡住大部分自动扫描
- 用fail2ban:自动封禁多次失败的IP
- 用密钥登录:禁用密码登录,这是最彻底的防护
- 限制IP:只允许自己的IP段登录
防护措施不是越多越好,够用就行。最推荐的组合是:改端口 + fail2ban + 密钥登录,这一套下来基本就很安全了。
遇到问题加QQ23979811 协助处理
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:进程IDUSER:进程所属用户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 运维最常用的监控工具,记住几个关键点:
- 看负载:
load average,和CPU核心数对比 - 看CPU:
%us高说明用户进程吃CPU,%wa高说明磁盘I/O瓶颈 - 看内存:看
avail Mem,不要只看free - 排序:按
P看CPU占用,按M看内存占用 - 杀进程:按
k输入PID
日常排查服务器问题,先打开 top 看一眼,大部分问题都能定位到方向。
遇到问题加QQ23979811 协助处理
服务器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 连接慢的排查步骤:
- 先确认是不是 DNS 反向解析的问题
- 修改
/etc/ssh/sshd_config,加UseDNS no和GSSAPIAuthentication no - 重启 sshd 服务
- 再连接测试,应该秒连
这是 Linux 服务器最常见的优化之一,改完立竿见影。如果你的服务器 SSH 连接慢,先试试这个方法,90% 的情况都能解决。
遇到问题加QQ23979811 协助处理
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 不执行的排查顺序:
- 先确认 crond 服务启动了没
- 检查 crontab 语法格式对不对
- 脚本有没有执行权限
- 脚本里的命令是不是都用了绝对路径
- 看
/var/log/cron日志有没有执行记录 - 看
/var/spool/mail/root有没有错误信息 - 检查 SELinux 是不是拦截了
按这个顺序排查,基本都能找到原因。记住 crontab 的环境变量和你手动登录时不一样,所有命令都用绝对路径,能避免 80% 的问题。
遇到问题加QQ23979811 协助处理