常用 Linux Shell 命令

常用 Linux Shell 命令

系统监控与资源排查-快速定位资源瓶颈

查看CPU/内存/根分区

复制代码
# top -b -n 1:非交互模式输出 1 次系统状态,避免进入 top 交互界面
# grep Cpu:过滤 CPU 行,awk提取使用率
# free -h:人性化显示内存,grep Mem聚焦内存行
# df -h | grep /$:只看根分区(避免显示其他挂载点),提取使用率和空闲空间
## 若根分区挂载点不是/(比如特殊系统),需把grep /$改成实际挂载点(如grep /root)

top -b -n 1 | grep Cpu | awk '{print "CPU使用率:"$2"%"}' && free -h | grep Mem | awk '{print "内存使用率:"$3"/"$2"("$7"空闲)"}' && df -h | grep /$ | awk '{print "根分区使用率:"$5"("$4"空闲)"}'

输出
CPU使用率:0.0%
内存使用率:95M/470M(327M空闲)
根分区使用率:20%(6.5G空闲)

CPU/内存排序

复制代码
# ps -eo:自定义输出字段(pid = 进程 ID,ppid = 父进程 ID,% cpu=CPU 占比,% mem = 内存占比,cmd = 进程命令)
# --sort=-%cpu:按 CPU 占比倒序排列(-表示倒序)
## 若想查 "吃内存最多" 的进程,把--sort=-%cpu改成--sort=-%mem
# head -10:只显示前 10 条,避免输出过长

ps -eo pid,ppid,%cpu,%mem,cmd --sort=-%cpu | head -10

输出
   PID   PPID %CPU %MEM CMD
     1      0  0.0  0.7 /usr/lib/systemd/systemd --system --deserialize 16
     2      0  0.0  0.0 [kthreadd]
     3      2  0.0  0.0 [ksoftirqd/0]
     5      2  0.0  0.0 [kworker/0:0H]
     7      2  0.0  0.0 [migration/0]
     8      2  0.0  0.0 [rcu_bh]
     9      2  0.0  0.0 [rcu_sched]
    10      2  0.0  0.0 [lru-add-drain]
    11      2  0.0  0.0 [watchdog/0]

查看大文件

复制代码
# find / -type f -size +100M:从根目录找所有大小超过 100M 的文件(-type f指定文件,避免目录)
## 若想找 "大于 1G" 的文件,把+100M改成+1G
# 2>/dev/null:忽略权限不足的报错(比如/proc目录下的文件)
# xargs du -sh:对找到的文件逐个计算大小(-s单文件,-h人性化显示)
# sort -hr:按大小倒序排列(-h识别 "G/M" 单位,-r倒序)

find / -type f -size +100M 2>/dev/null | xargs du -sh | sort -hr

输出
156M    /var/cache/yum/x86_64/7/updates/gen/primary_db.sqlite
149M    /var/cache/yum/x86_64/7/updates/gen/filelists_db.sqlite
102M    /usr/lib/locale/locale-archive
0       /sys/devices/pci0000:00/0000:00:0f.0/resource1_wc
0       /sys/devices/pci0000:00/0000:00:0f.0/resource1
0       /proc/kcore

磁盘IO

复制代码
# vmstat 1 5:每 1 秒输出 1 次系统 IO 状态,共输出 5 次(避免单次数据不准)
# NR>1:跳过 vmstat 的表头行
# $16:vmstat 输出中 "wa" 字段(IO 等待时间,单位 ms),$17:"st" 字段(等待 IO 的进程数)
## 若 wa 长期超过 20ms,需进一步用iostat -x 1查看具体磁盘的 IO 情况(如sda的 util% 是否接近 100%)

vmstat 1 5 | awk 'NR>1 {print "平均等待IO时间:"$16"ms 等待IO进程数:"$17"个"}'

输出
平均等待IO时间:wams 等待IO进程数:st个
平均等待IO时间:0ms 等待IO进程数:0个
平均等待IO时间:0ms 等待IO进程数:0个
平均等待IO时间:0ms 等待IO进程数:0个
平均等待IO时间:0ms 等待IO进程数:0个
平均等待IO时间:0ms 等待IO进程数:0个

网卡实时流量

复制代码
# sar -n DEV 1 3:每 1 秒输出 1 次网卡流量,共 3 次(-n DEV指定网卡统计)
# grep -v Average:排除最后一行的平均值(只看实时数据)
# awk '/eth0/:只过滤 eth0 网卡的行,$5是接收流量(rxkB/s),$6是发送流量(txkB/s)
## eth0根据实际情况修改

sar -n DEV 1 3 | grep -v Average | awk '/eth0/ {print "网卡eth0:接收"$5"KB/s 发送"$6"KB/s"}'

输出
网卡eth0:接收0.00KB/s 发送0.06KB/s
网卡eth0:接收0.00KB/s 发送0.00KB/s
网卡eth0:接收0.00KB/s 发送0.00KB/s

当前在线的用户

复制代码
# w:查看当前登录用户及操作
# NR>1:跳过 w 的表头
# $1是用户名,$3是登录 IP(若本地登录是localhost),$4是登录时间
## 若想查 "历史登录记录",改用last -n 10(显示最近 10 次登录)

w | awk 'NR>1 {print "登录用户:"$1" 登录IP:"$3" 登录时间:"$4}'

输出
登录用户:USER 登录IP:FROM 登录时间:LOGIN@
登录用户:root 登录IP:15:37 登录时间:45:51
登录用户:root 登录IP:192.168.200.8 登录时间:17:02
登录用户:root 登录IP:192.168.200.8 登录时间:17:18
登录用户:root 登录IP:192.168.200.8 登录时间:18:48
登录用户:root 登录IP:192.168.200.8 登录时间:23:01

日志分析与数据提取-分析日志

正则匹配筛选和统计

复制代码
# grep -i "error":忽略大小写找含 "error" 的行(避免漏 "Error""ERROR")
# grep -E "2025-11-11":用正则匹配指定日期(日志需带时间戳,Nginx 默认日志格式含日期)
# wc -l:统计符合条件的行数(即错误次数)

grep -i "error" /var/log/xxx.log | grep -E "2025-11-11" | wc -l

输出
100

正则匹配筛选和排序

复制代码
# grep "500":过滤状态码为 500 的请求($9是 Nginx 日志的状态码字段)
# awk '{print $1,$7,$9}':提取 IP($1)、URL($7)、状态码($9)
## 使用 head -1 xxx.log 看日志结构,再修改 awk 序号
# sort | uniq -c:按 "IP+URL" 去重并统计次数(uniq -c计数)
# sort -nr:按次数倒序,head -10取前 10

grep "500" /var/log/xxx.log | awk '{print $1,$7,$9}' | sort | uniq -c | sort -nr | head -10

输出
192.168.1.1 /api/info 500
192.168.1.2 /api/info 500

sed筛选和排序

复制代码
# sed -n '/开始时间/,/结束时间/p':提取两个时间戳之间的日志(-n静默模式,p打印匹配内容);
# grep "Exception":过滤含 "Exception" 的异常行
## 根据实际情况修改

sed -n '/2025-11-11 11:00:00/,/2025-11-12 12:00:00/p' /var/log/xxx.log | grep "Exception"

输出
2025-11-11 11:00:00 ERROR [http-nio-8080-exec-1] com.xxx.xxx: NullPointer Exception

awk筛选和排序

复制代码
# awk -F '|':指定字段分隔符为 "|"(默认是空格)
# print $3:提取第 3 个字段(即接口名)
# sort | uniq -c:去重并统计次数,sort -nr倒序,head -5取前 5

awk -F '|' '{print $3}' /var/log/xxx.log | sort | uniq -c | sort -nr | head -5

输出
100 /api/info
50 /api/version

不解压统计关键词

复制代码
# zgrep:直接 grep 压缩文件(支持.gz 格式),避免gunzip解压步骤
# wc -l:统计 timeout 错误次数

zgrep "error" /var/log/log.gz | wc -l

输出
100

实时监控 SSH 登录情况

复制代码
# tail -f:实时跟踪日志文件(新内容会自动输出)
## 部分系统 SSH 日志在/var/log/secure,需把/var/log/messages改成对应路径
# grep --line-buffered "ssh":缓冲每行内容(避免实时输出延迟),过滤含 "ssh" 的行
# awk:区分 "Accepted"(成功登录)和 "Failed"(失败),标注后输出

tail -f /var/log/messages | grep --line-buffered "ssh" | awk '/Accepted/ {print "正常登录:"$0} /Failed/ {print "登录失败:"$0}'

输出
正常登录:Nov 11 12:00:00 ecs-1 sshd-session[1]: Accepted password for root from 192.168.0.1 port 8888 ssh2
正常登录:Nov 11 13:00:00 ecs-2 sshd-session[2]: Accepted password for root from 192.168.0.2 port 8889 ssh2

文件管理与批量操作

查找文件并执行操作

复制代码
# find /data/backup:指定查找目录
# -name "*.tar.gz":只找后缀为.tar.gz 的文件
# -mtime +7:修改时间超过 7 天(+7表示 7 天前,-7是 7 天内)
## 若想按 "访问时间" 查找,把-mtime改成-atime
# -exec rm -f {} \;:对找到的文件执行删除操作({}代表找到的文件,\;结束 exec 命令)

find /var/log -name "*.tar.gz" -mtime +7 -exec rm -f {} \;

输出
a.tar.gz
b.tar.gz

目录文件遍历与执行操作

复制代码
# for file in /var/log/*.log:循环遍历所有.log文件
# date +%Y%m%d:生成当前日期(如 20251111)
# mv "$file" "$file.日期":给每个文件加日期后缀(双引号避免文件名含空格时出错)

for file in /var/log/*.log; do mv "$file" "$file.$(date +%Y%m%d)"; done

输出
a.log.20251111
b.log.20251111

sed替换

复制代码
# sed -i:直接修改文件内容(-i原地替换,不加-i只预览不修改)
# s/旧内容/新内容/g:替换语法(s=substitute,g=global 全局替换,避免只换第一处)
## 若内容含特殊字符(如/),需用\转义,如 s/http:\/\/old.com/http:\/\/new.com/g
# /etc/config/*.conf:指定要修改的文件(所有.conf)

sed -i 's/old_ip=192.168.1.1/old_ip=192.168.1.2/g' /etc/config/*.conf

输出
无

压缩与排除

复制代码
# tar -zcvf:打包压缩(z用 gzip 压缩,c创建包,v显示过程,f指定包名);
# log_$(date +%Y%m%d).tar.gz:备份包名含日期;
# --exclude=/var/log/log2:排除 logs 目录
## 若要排除多个目录,加多个--exclude(如--exclude=log1 --exclude=log2)
## 备份前确认目标目录空间足够(用 df -h /data/backup 查看)

tar -zcvf /var/log/log_$(date +%Y%m%d).tar.gz /var/log --exclude=/var/log/log2

输出
无

scp跨服复制

大文件传输建议用rsync(支持断点续传),命令是
rsync -avz /var/log/*.tar.gz root@192.168.1.1:/var/log/

复制代码
# scp -r:远程拷贝(-r递归拷贝目录,这里虽拷贝文件,但加-r不影响,且支持后续拷贝目录);
# root@192.168.1.1:远程服务器用户名和 IP;
# :/var/log/:远程服务器的目标目录

scp -r /var/log/*.tar.gz root@192.168.1.1:/var/log/

输出
无

查找文件权限

复制代码
# find /data/app:指定查找目录
# -perm 777:只找权限为 777 的文件(777=rwxrwxrwx)
# -type f:只找文件(避免目录,目录 777 风险较低)
# 2>/dev/null:忽略权限不足的报错

find /data/app -perm 777 -type f 2>/dev/null

# 修改为安全权限
chmod 644 /data/app/config/db.conf

输出
120 192.168.1.200
30 10.0.0.5
25 203.0.113.8

查看目录权限

若要给用户加 ACL 权限,用 setfacl -m u:admin:rwx /data/app(给 admin 用户加读写执行权限)

复制代码
# getfacl /data/app:查看目录的 ACL 权限(比ls -l更详细,支持多用户 / 组权限)
# grep -E "user:|group:":只显示用户和组的 ACL 权限(避免其他冗余信息)

getfacl /data/app | grep -E "user:|group:"

输出
user::rwx  # 所有者权限
user:admin:r-x  # admin用户有读执行权限
group::r-x  # 所属组权限
group:dev:---  # dev组无权限(可能是问题原因)

进程与服务管理-管控服务状态

快速查看Nginx服务状态

复制代码
# systemctl status nginx:查看 Nginx 服务状态
## 若系统用service命令(如 centos6),把systemctl status nginx改成service nginx status,日志路径改用/var/log/nginx/error.log
# grep -E "active|inactive|failed":只显示核心状态(active = 运行中,inactive = 停止,failed = 失败)
# journalctl -u nginx:查看 Nginx 的系统日志(-u指定服务单元)
# --since "10 minutes ago":只看最近 10 分钟的日志,tail -20 取最后 20 行

systemctl status nginx | grep -E "active|inactive|failed" && journalctl -u nginx --since "10 minutes ago" | tail -20

输出
...

强制关闭进程

复制代码
# ps -ef | grep nginx:找所有含 "nginx" 的进程
# grep -v grep:排除 "grep nginx" 这个临时进程(避免误杀)
# awk '{print $2}':提取进程 ID($2 是 ps -ef 输出的 PID 字段)
# xargs kill -9:对提取的 PID 执行强制杀死(kill -9是强制终止,kill -15是正常终止,卡死时用-9)

ps -ef | grep nginx | grep -v grep | awk '{print $2}' | xargs kill -9

输出
...

后台启动与日志输出

复制代码
# nohup:忽略挂断信号(no hang up),终端退出后进程继续运行
# > /data/logs/app.log:把标准输出(stdout,脚本的正常输出)重定向到 app.log
## 确保/data/logs目录存在
# 2>&1:把标准错误(stderr,脚本的错误输出)也重定向到 stdout(即一起写入 app.log)
# 最后一个&:把进程放到后台运行

nohup /data/app/start.sh > /data/logs/app.log 2>&1 &

输出 tail -f /data/logs/app.log
...

检查进程与执行脚本

定时任务配置(crontab -e):每 5 分钟检查一次

*/5 * * * * pgrep -f "app.jar" || nohup /data/app/start.sh > /data/logs/app.log 2>&1 &

复制代码
# pgrep -f "app.jar":根据进程名(-f匹配完整命令行)查找进程,找到返回 PID,找不到返回非 0 状态码
# ||:逻辑或,只有前面命令失败(进程不存在)时,才执行后面的启动命令(/data/app/start.sh)
## 检查 app.jar 进程是否存在,不存在则启动

pgrep -f "app.jar" || /data/app/start.sh

输出
...

网络连接与故障排查-快速定位网络问题

端口检查

复制代码
# netstat -tulnp:查看所有监听端口(t=TCP,u=UDP,l= 监听中,n= 显示 IP 和端口(非服务名),p= 显示进程 ID 和名称)
# grep :8080:过滤 8080 端口的监听情况

netstat -tulnp | grep :8080

输出
tcp6       0      0 :::8888                 :::*                    LISTEN      100/java

端口连接排序

Nginx 服务(80 端口)的连接数突然飙升,要 "找出连接 80 端口最多的前 10 个 IP",判断是否有 IP 在恶意发起大量连接(如 CC 攻击)。

复制代码
# ss -antp:查看所有 TCP 连接(a= 所有,n= 显示 IP 端口,t=TCP,p= 显示进程)
# grep :80:过滤 80 端口的连接
# awk '{print $5}':提取客户端 IP 和端口($5是 ss 输出的 "客户端地址:端口" 字段)
# cut -d: -f1:按 ":" 分割,取 IP 部分(去掉端口)
# sort | uniq -c:统计每个 IP 的连接数,sort -nr倒序,head -10取前 10

ss -antp | grep :80 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -10

输出
120 192.168.1.200
30 10.0.0.5
25 203.0.113.8
相关推荐
z202305084 小时前
Linux之vmlinux文件段布局和arm64 的链接脚本vmlinux.lds.S分析
linux·运维·服务器
濊繵5 小时前
Linux网络-Socket 编程 UDP
linux·网络·udp
hhhh明7 小时前
quest2+alvr+steamvr
linux·windows·quest2
dqsh068 小时前
树莓派5+Ubuntu24.04 LTS CH348 / CH9344 驱动安装 保姆级教程
linux·c语言·单片机·嵌入式硬件·iot
menge23339 小时前
Linux DNS域名解析服务器练习
linux·运维·服务器
wsad05329 小时前
CentOS 7 更换腾讯云 yum 源及 EPEL 源
linux·centos·腾讯云
wdfk_prog9 小时前
[Linux]学习笔记系列 -- [kernel]kallsyms
linux·笔记·学习
emiya_saber10 小时前
Linux 进程调度管理
linux·运维·服务器
不脱发的程序猿10 小时前
嵌入式Linux:线程同步(读写锁)
linux·嵌入式