用函数式思维写 shell 之 unban_the_ip 脚本
shell 练习:用函数式思维写 shell,以服务器安全-封锁 ip/解封 ip 作为示例。
unban_the_ip 脚本代码
bash
#!/bin/bash
# desc: 解禁 ip(即:黑名单数据删除操作)
# author: echoxu
# 功能:
# 1. 命令行中添加要解禁的 ip,支持批量操作
# 2: 可解禁指定文件里的 ip,支持批量操作
. lib/common
. lib/firewall
. lib/nginx
. lib/blacklist
args_arr=()
# 组成非第一个参数外的所有参数列表
analysis_args(){
args=$@
for arg in $args
do
args_arr[${#args_arr[*]}]=${arg}
done
unset args_arr[0] # 删除第一个元素,即传入的 flag 的值
}
# 重启 nginx/firewalld 的 handler 函数
relaod_handler(){
block_ip_type=$(get_section_value_from_config_path block_ip_type)
code=$?
print_return_code_message_of_get_section_path $code
case "$block_ip_type" in
firewalld)
block_ip_type=firewalld_reload
;;
nginx)
block_ip_type=reload_nginx
;;
esac
echo $block_ip_type
}
# 统计返回值,当返回值为 0 的个数大于 1 时才能重启防火墙
# 也可以通过判断 blacklist 或者 blockip.conf 文件是否被修改来决定是否重启
reload_of_block_ip_type(){
succeed_code_count=0
for i in `cat /tmp/add_ip_to_blacklist_return_code`
do
if [ $i -eq 0 ];then
let succeed_code_count++
fi
done
if [ $succeed_code_count -gt 0 ];then
reload_res=$(relaod_handler)
$reload_res
fi
}
# 将操作记录到日志中
record_logs_of_unban_ip(){
to_log=$1
log_path=$2
echo "$(date +'%F-%T') 解禁ip: $to_log " >> $log_path
}
# handler 函数
get_block_ip_type_of_unban_ip_handler(){
block_ip_type_input=$1
case "$block_ip_type_input" in
firewalld)
block_ip_type_input=firewall_op_with_remove
;;
nginx)
block_ip_type_input=nginx_record_remove
;;
esac
echo $block_ip_type_input
}
# 从命令行中解封一个或多个 ip
unban_the_ip(){
for arg in ${args_arr[*]}
do
is_ip_result=$(isip_from_input $arg)
code=$?
if [ $code != 0 ];then
err_code $code "$arg 不符合 ip 格式,请确认后再操作..."
echo $code >> /tmp/add_ip_to_blacklist_return_code
continue
else
arg=$is_ip_result
fi
if [ "$block_ip_type" = "firewalld" ];then
delete_ip_from_blacklist $arg
code=$?
if [ $code -eq 144 ];then
err_code $code "IP: $arg 在黑名单文件中不存在..."
continue
fi
fi
$block_ip_type_result $arg
code=$?
echo $code >> /tmp/add_ip_to_blacklist_return_code
if [ $code = 0 ];then
record_logs_of_unban_ip $arg $log_path
fi
done
}
# 批量解封 ip: 从文件中获取待解禁的 ip
unban_the_ip_from_file(){
unban_ip_file_path=$1
real_path=$(get_real_path $unban_ip_file_path)
is_file_res=$(vaild_is_path_from_input $real_path)
code=$?
if [ $code != 0 ];then
print_message_of_vaild_is_path_from_input $code $real_path
else
unban_ip_file_path=$is_file_res
fi
for ip_from_file in `cat $unban_ip_file_path`
do
is_ip_result=$(isip_from_input $ip_from_file)
code=$?
if [ $code != 0 ];then
err_code $code "$ip_from_file 不符合 ip 格式,请重新输入..."
echo $code >> /tmp/add_ip_to_blacklist_return_code
continue
fi
if [ "$block_ip_type" = "firewalld" ];then
delete_ip_from_blacklist $ip_from_file
code=$?
if [ $code -eq 144 ];then
err_code $code "IP: $ip_from_file 在黑名单文件中不存在..."
continue
fi
fi
$block_ip_type_result $ip_from_file
code=$?
echo $code >> /tmp/add_ip_to_blacklist_return_code
if [ $code = 0 ];then
record_logs_of_unban_ip $ip_from_file $log_path
fi
done
}
# 路由函数
unban_the_ip_router(){
args=$@
flag=$1
args_number=$#
to_unban_filepath=$2
# 清空返回值
cat /dev/null > /tmp/add_ip_to_blacklist_return_code
# 获取 封禁/解禁 ip 的方式
block_ip_type=$(get_section_value_from_config_path block_ip_type)
code=$?
print_return_code_message_of_get_section_path $code
block_ip_type_result=$(get_block_ip_type_of_unban_ip_handler $block_ip_type)
# 防火墙状态检查
if [[ $block_ip_type_result == "firewall_op_with_remove" ]];then
firewall_status=$(check_firewall_status)
code=$?
print_message_of_check_firewall_status $code
fi
# 获取日志文件存储路径(获取一次即可,所以写在这里)
log_path=$(get_section_value_from_config_path server_secure_log_path)
code=$?
print_return_code_message_of_get_section_path $code
# 判断参数
case "$flag" in
-u)
# 指定这个 flag 时,总参数个数不能小于 2
if [ $args_number -lt 2 ];then
echo -e "${Error}: 总参数个数不能小于 2"
exit 1
fi
analysis_args $@
unban_the_ip
;;
-f)
# 指定这个 flag 时,总参数个数不能大于 2
if [[ $args_number -gt 2 || $args_number -lt 2 ]];then
echo -e "${Error}: 总参数个数不能小于 2 且不能大于 3"
exit 1
fi
unban_the_ip_from_file $to_unban_filepath
;;
*)
echo -e "${Error}: Usage: $0 -u 单个或多个 ip|-f 文件路径"
echo -e "${Info}: -u: 解封单个或多个 ip"
echo -e "${Info}: -f: 从指定的文件里读取 ip 并解封"
exit 1
;;
esac
reload_of_block_ip_type
}
unban_the_ip_router $@
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238