Linux常用脚本
Salted Fish 2025/9/23 语法
# 1.服务器性能监控脚本
运维的日常离不开对服务器性能的监控,比如CPU、内存、磁盘使用率等。
这个脚本可以快速获取系统资源使用情况,并以清晰的格式输出。
#!/bin/bash
# 获取当前时间
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
# CPU使用率(前1分钟平均负载)
LOADAVG=$(uptime | awk '{print $10,$11,$12}')
# 内存使用情况
MEM_TOTAL=$(free -m | awk '/Mem:/ {print $2}')
MEM_USED=$(free -m | awk '/Mem:/ {print $3}')
MEM_USAGE_PERCENT=$((MEM_USED * 100 / MEM_TOTAL))
# 磁盘使用情况
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}')
# 输出结果
echo"===== 系统性能监控 ($TIMESTAMP) ====="
echo"CPU负载 (1min, 5min, 15min): $LOADAVG"
echo"内存使用率: $MEM_USAGE_PERCENT% ($MEM_USED/$MEM_TOTAL MB)"
echo"根分区磁盘使用率: $DISK_USAGE"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
使用方法:
- 保存为
monitor.sh,赋予执行权限:chmod +x monitor.sh。 - 运行:
./monitor.sh。 - 可结合
crontab定时运行,例如每5分钟记录一次:*/5 * * * * /path/to/monitor.sh >> /var/log/system_monitor.log。
场景:快速排查服务器性能瓶颈,适合初学者或需要临时检查的场景。
# 2.日志清理脚本
日志文件占满磁盘是运维中常见的问题。这个脚本可以自动清理指定目录下超过一定天数的日志文件。
#!/bin/bash
# 根据文件实际修改时间删除过期文件
# saltedFish
# 配置参数
TARGET_DIR="目标目录"
LOG_FILE="日志目录/xxx.log"
THRESHOLD_DAYS=90
DRY_RUN=false # 设置为true进行模拟运行
# 创建日志函数
log() {
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
echo "[$timestamp] $1" | tee -a "$LOG_FILE"
}
# 磁盘空间检查函数
check_disk_space() {
log "磁盘空间检查:"
df -h "$TARGET_DIR" | tee -a "$LOG_FILE"
log "目标目录大小:"
du -sh "$TARGET_DIR" 2>/dev/null | tee -a "$LOG_FILE" || log "无法获取目录大小"
}
# 使用find的-delete选项
clean_old_files() {
log "============== 开始文件清理任务 =============="
log "目标目录: $TARGET_DIR"
log "保留天数: $THRESHOLD_DAYS 天"
if [ "$DRY_RUN" = true ]; then
log "*** 模拟运行模式 - 不会实际删除文件 ***"
fi
# 检查目标目录是否存在
if [ ! -d "$TARGET_DIR" ]; then
log "错误: 目标目录不存在"
return 1
fi
if [ ! -w "$TARGET_DIR" ]; then
log "错误: 对目标目录没有写权限"
return 1
fi
# 记录开始时间
START_TIME=$(date +%s)
if [ "$DRY_RUN" = true ]; then
# 模拟运行:只显示要删除的文件
log "模拟删除以下过期文件:"
find "$TARGET_DIR" -type f -mtime "+$THRESHOLD_DAYS" -exec echo "模拟删除: {}" \;
# 统计文件数量
file_count=$(find "$TARGET_DIR" -type f -mtime "+$THRESHOLD_DAYS" | wc -l)
dir_count=$(find "$TARGET_DIR" -type d -empty | wc -l)
log "将删除 $file_count 个过期文件和 $dir_count 个空目录"
else
# 统计删除前的文件数量
old_file_count=$(find "$TARGET_DIR" -type f | wc -l)
old_dir_count=$(find "$TARGET_DIR" -type d | wc -l)
# 实际删除过期文件
log "开始删除过期文件..."
deleted_files=$(find "$TARGET_DIR" -type f -mtime "+$THRESHOLD_DAYS" -delete -print | wc -l)
log "文件删除完成,删除了 $deleted_files 个文件"
# 删除空目录(忽略错误信息)
log "开始清理空目录..."
deleted_dirs=$(find "$TARGET_DIR" -type d -empty -delete 2>/dev/null | wc -l)
log "空目录清理完成,删除了 $deleted_dirs 个空目录"
# 统计删除后的文件数量
new_file_count=$(find "$TARGET_DIR" -type f | wc -l)
new_dir_count=$(find "$TARGET_DIR" -type d | wc -l)
log "清理前后对比:"
log "文件数量: $old_file_count -> $new_file_count (减少了 $((old_file_count - new_file_count)))"
log "目录数量: $old_dir_count -> $new_dir_count (减少了 $((old_dir_count - new_dir_count)))"
fi
# 记录结束时间和执行时长
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
log "任务执行耗时: ${DURATION} 秒"
log "========================================================="
}
# 创建日志目录
mkdir -p "$(dirname "$LOG_FILE")"
touch "$LOG_FILE"
# 主执行流程
main() {
log "开始文件清理任务"
# 检查磁盘空间(清理前)
check_disk_space
# 执行清理
clean_old_files
# 检查磁盘空间(清理后)
check_disk_space
log "文件清理任务完成"
}
# 执行主函数
main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
使用方法:
- 修改
TARGET_DIR为你的日志目录,THRESHOLD_DAYS为保留天数。 - 保存为
clear_log.sh,赋予执行权限。 - 运行或加入
crontab,如每天凌晨执行:0 0 * * * /path/to/clear_log.sh。
场景:防止日志文件堆积导致磁盘满,适合Web服务器、数据库等场景。
# 3.自动备份脚本
数据备份是运维的生命线。这个脚本可以备份指定目录到目标路径,并压缩以节省空间。
#!/bin/bash
SRC_DIR="/data"
BACKUP_DIR="/backup"
DATE=$(date '+%Y%m%d_%H%M%S')
BACKUP_FILE="backup_$DATE.tar.gz"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 压缩备份
tar -zcf $BACKUP_DIR/$BACKUP_FILE$SRC_DIR
# 删除30天前的备份
find $BACKUP_DIR -name "backup_*.tar.gz" -mtime +30 -exec rm -f {} \;
echo"备份完成: $BACKUP_DIR/$BACKUP_FILE"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
使用方法:
- 修改
SRC_DIR和BACKUP_DIR为实际路径。 - 保存为
backup.sh,赋予执行权限。 - 加入
crontab,如每天凌晨2点备份:0 2 * * * /path/to/backup.sh。
场景:数据库、配置文件或重要目录的定期备份。
# 4.批量检查服务状态
需要快速检查多个服务的运行状态?这个脚本可以批量检查指定服务的状态。
#!/bin/bash
SERVICES=("nginx""mysql""redis")
for SERVICE in"${SERVICES[@]}"; do
systemctl is-active --quiet $SERVICE
if [ $? -eq 0 ]; then
echo"$SERVICE 正在运行"
else
echo"$SERVICE 未运行,尝试重启..."
systemctl restart $SERVICE
if [ $? -eq 0 ]; then
echo"$SERVICE 重启成功"
else
echo"$SERVICE 重启失败,请检查!"
fi
fi
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
使用方法:
- 修改
SERVICES数组,填入需要检查的服务名称。 - 保存为
check_service.sh,赋予执行权限。 - 运行或加入
crontab定时检查。
场景:监控关键服务(如Nginx、MySQL),自动尝试重启。
# 5.批量文件重命名
文件批量重命名在处理日志、备份文件时非常实用。这个脚本可以给指定目录下的文件添加前缀。
#!/bin/bash
DIR="/path/to/files"
PREFIX="backup_"
for FILE in $DIR/*; do
if [ -f "$FILE" ]; then
mv "$FILE" "$DIR/$PREFIX$(basename $FILE)"
fi
done
echo "文件重命名完成!"
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
使用方法:
- 修改
DIR和PREFIX。 - 保存为
rename_files.sh,赋予执行权限。 - 运行:
./rename_files.sh。
场景:批量整理文件名,适合日志归档、数据迁移等。
# 6.磁盘空间告警脚本
磁盘空间不足可能导致服务宕机。这个脚本监控磁盘使用率,超过阈值时发送邮件告警。
#!/bin/bash
THRESHOLD=80
EMAIL="admin@example.com"
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}' | cut -d'%' -f1)
if [ $DISK_USAGE -gt $THRESHOLD ]; then
echo "警告:磁盘使用率达到 $DISK_USAGE%!" | mail -s "磁盘空间告警" $EMAIL
fi
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
使用方法:
- 修改
THRESHOLD和EMAIL。 - 确保服务器已配置邮件服务(如
postfix)。 - 保存为
disk_alert.sh,加入crontab定时运行。
场景:监控关键分区,及时发现磁盘空间问题。
# 7.批量杀死僵尸进程
僵尸进程会占用系统资源,这个脚本可以批量清理。
#!/bin/bash
ZOMBIES=$(ps aux | grep ' Z ' | awk '{print $2}')
if [ -z "$ZOMBIES" ]; then
echo "未发现僵尸进程"
else
for PID in $ZOMBIES; do
kill -9 $PID
echo "已杀死僵尸进程: $PID"
done
fi
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
使用方法:
- 保存为
kill_zombies.sh,赋予执行权限。 - 运行:
./kill_zombies.sh。
场景:清理长期运行的服务器上的僵尸进程。
# 8.批量修改文件权限
批量修改文件权限在多用户环境下很常见。这个脚本可以递归修改指定目录的权限。
#!/bin/bash
DIR="/var/www/html"
PERMISSION="755"
chmod -R $PERMISSION $DIR
echo "已将 $DIR 目录权限设置为 $PERMISSION"
1
2
3
4
5
6
2
3
4
5
6
使用方法:
- 修改
DIR和PERMISSION。 - 保存为
chmod_files.sh,赋予执行权限。 - 运行:
./chmod_files.sh。
场景:Web服务器文件权限统一调整。
# 9.网络连接统计脚本
了解服务器的网络连接状态对排查问题至关重要。这个脚本统计TCP连接状态。
#!/bin/bash
netstat -ant | awk '/^tcp/ {print $6}' | sort | uniq -c | sort -nr
1
2
2
使用方法:
- 保存为
netstat.sh,赋予执行权限。 - 运行:
./netstat.sh。
场景:排查网络瓶颈,分析连接状态。
# 10.自动同步时间
服务器时间不同步可能导致日志混乱或服务异常。这个脚本确保系统时间与NTP服务器同步。
#!/bin/bash
ntpdate pool.ntp.org
if [ $? -eq 0 ]; then
echo "时间同步成功: $(date)"
else
echo "时间同步失败,请检查网络或NTP服务"
fi
1
2
3
4
5
6
7
2
3
4
5
6
7
使用方法:
- 确保安装
ntpdate(yum install ntp或apt install ntp)。 - 保存为
sync_time.sh,赋予执行权限。 - 加入
crontab,如每天同步:0 0 * * * /path/to/sync_time.sh。
场景:保证分布式系统时间一致性。
# 11.系统连接查询
服务器查询相关的连接,如::sockets、远程主机、tcp、udp等等
#! /bin/bash
TCP_Total=$(ss -s | awk '$1=="TCP"{print $2}') #所有TCP连接个数
UDP_Total=$(ss -s | awk '$1=="UDP"{print $2}') #所有UDP连接个数
Unix_sockets_Total=$(ss -ax | awk 'BEGIN{count=0} {count++} END{print count}') #所有UNIX sockets连接个数
TCP_Listen_Total=$(ss -antlpH | awk 'BEGIN{count=0} {count++} END{print count}') #所有处于Listen监听状态的TCP端口个数
TCP_Estab_Total=$(ss -antph | awk 'BEGIN{count=0} /^ESTAB/{count++} END{print count}') #所有处于ESTABLISHED状态TCP连接个数
TCP_SYN_RECV_Total=$(ss -antpH | awk 'BEGIN{count=0} /^SYN-RECV/{count++} END{print count}') #所有处于SYN_RECV状态的TCP连接个数
TCP_TIME_WAIT_Total=$(ss -antpH | awk 'BEGIN{count=0} /^TIME-WAIT/{count++} END{print count}') #所有处于TIME-WAIT状态的TCP连接个数
TCP_TIME_WAIT1_Total=$(ss -antpH | awk 'BEGIN{count=0} /^TIME-WAIT1/{count++} END{print count}') #所有处于TIME-WAIT1状态的TCP连接个数
TCP_TIME_WAIT2_Total=$(ss -antpH | awk 'BEGIN{count=0} /^TIME-WAIT2/{count++} END{print count}') #所有处于TIME-WAIT2状态的TCP连接个数
TCP_Remote_Count=$(ss -antH | awk '$1!~/LISTEN/{IP[$5]++} END{ for(i in IP) {print IP[i],i} }' | sort -nr) #所有远程主机TCP连接次数
TCP_Port_Count=$(ss -antH | sed -r 's/ +/ /g' | awk -F"[ :]" '$1!~/LISTEN/{port[$5]++} END{for(i in port) {print port[i],i}}' | sort -nr) #每个端口被访问次数
#定义输出颜色
SUCCESS="echo -en \\033[1;32m" #绿色
NORMAL="echo -en \\033[0;39m" #黑色
#显示TCP连接总数
tcp_total(){
echo -n "TCP连接总数: "
$SUCCESS
echo "$TCP_Total"
$NORMAL
}
#显示处于LISTEN状态的TCP端口个数
tcp_listen(){
echo -n "处于LISTEN状态的TCP端口个数"
$SUCCESS
echo "$TCP_Listen_Total"
$NORMAL
}
#显示处于ESTABLISHED状态的TCP连接个数
tcp_estab(){
echo -n "处于ESTAB状态的TCP连接个数:"
$SUCCESS
echo "TCP_Estab_Total"
$NORMAL
}
#显示处于SYN-RECV状态的TCP连接个数
tcp_syn_recv(){
echo -n "处于SYN-RECV状态的TCP连接个数:"
$SUCCESS
echo "TCP_SYN_RECV_Total"
$NORMAL
}
#显示处于TIME-WAIT状态的TCP连接个数
tcp_time_wait(){
echo -n "处于TIME-WAIT状态的TCP连接个数:"
$SUCCESS
echo "$TCP_TIME_WAIT_Total"
$NORMAL
}
#显示处于TIME-WAIT1状态的TCP连接个数
tcp_time_wait1(){
echo -n "处于TIME-WAIT1状态的TCP连接个数:"
$SUCCESS
echo "$TCP_TIME_WAIT1_Total"
$NoRMAL
}
#显示处于TIME-WAIT2状态的TCP连接个数
tcp_time_wait2(){
echo -n "处于TIME-WAIT2状态的TCP连接个数:"
$SUCCESS
echo "$TCP_TIME_WAIT2_Total"
$NORMAL
}
#显示UDP连接总数
udp_total(){
echo -n "UDP连接总数:"
$SUCCESS
echo "$UDP_Total"
$NORMAL
}
#显示UNIX sockets连接总数
unix_total(){
echo -n "Unix sockets 连接总数:"
$SUCCESS
echo "$Unix_sockets_Total"
$NORMAL
}
#显示每个远程主机的访问次数
remote_count(){
echo -n "每个远程主机与本机的并发连接数:"
$SUCCESS
echo "$TCP_Remote_Count"
$NORMAL
}
#显示每个端口的并发连接数
port_count(){
echo -n "每个端口的并发连接数:"
$SUCCESS
echo "$TCP_Port_Count"
$NORMAL
}
print_info(){
echo -e "================================================================="
$1
}
print_info tcp_total
print_info tcp_listen
print_info tcp_estab
print_info tcp_syn_recv
print_info tcp_time_wait
print_info tcp_time_wait1
print_info tcp_time_wait2
print_info udp_total
print_info unix_total
print_info remote_count
print_info port_count
echo -e "================================================================="
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131