-
Notifications
You must be signed in to change notification settings - Fork 8
/
server-setup.sh
1335 lines (1176 loc) · 42.4 KB
/
server-setup.sh
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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
# 检查是否具有足够的权限
if [ "$(id -u)" != "0" ]; then
echo "需要管理员权限,请使用sudo运行此脚本。"
exit 1
fi
# 获取操作系统信息
get_os_info() {
# 忽略大小写匹配
if [ -f /etc/os-release ]; then
source /etc/os-release
if [[ $ID == "debian" || $ID == "ubuntu" ]]; then
echo "Debian/Ubuntu"
elif [ $ID == "centos" ]; then
echo "CentOS"
elif [ $ID == "fedora" ]; then
echo "Fedora"
elif [ $ID == "arch" ]; then
echo "Arch"
# 添加更多的操作系统判断
# elif [ $ID == "some-other-os" ]; then
# echo "Some Other OS"
else
echo "Unknown"
fi
elif [ -f /etc/centos-release ]; then
echo "CentOS"
elif [ -f /etc/fedora-release ]; then
echo "Fedora"
elif [ -f /etc/arch-release ]; then
echo "Arch"
else
echo "Unknown"
fi
}
# 检查IP地址是否在中国
set_mirror() {
local IP=$(curl -s ipinfo.io/ip)
local COUNTRY=$(curl -s ipinfo.io/country)
if [ "$COUNTRY" = "CN" ]; then
YES_CN="https://mirror.ghproxy.com/"
ACC="--mirror AzureChinaCloud"
else
YES_CN=""
ACC=""
fi
}
set_mirror
# 检查已安装的防火墙类型
check_firewall() {
if command -v ufw &>/dev/null; then
echo "ufw" # 返回 ufw 表示安装了 ufw 防火墙
elif command -v firewalld &>/dev/null; then
echo "firewalld" # 返回 firewalld 表示安装了 firewalld 防火墙
elif command -v iptables &>/dev/null; then
echo "iptables" # 返回 iptables 表示安装了 iptables 防火墙
elif command -v nft &>/dev/null; then
echo "nftables" # 返回 nftables 表示安装了 nftables 防火墙
else
echo "unknown" # 返回 unknown 表示未安装支持的防火墙工具
fi
}
# 根据已安装的防火墙显示当前开放的端口
display_open_ports() {
firewall=$(check_firewall)
case $firewall in
"ufw")
echo "当前开放的防火墙端口 (TCP):"
ufw status | grep "ALLOW" | grep -oP '\d+/tcp' | sort -u
echo "当前开放的防火墙端口 (UDP):"
ufw status | grep "ALLOW" | grep -oP '\d+/udp' | sort -u
;;
"firewalld")
echo "当前开放的防火墙端口 (TCP):"
firewall-cmd --list-ports | grep "tcp"
echo "当前开放的防火墙端口 (UDP):"
firewall-cmd --list-ports | grep "udp"
;;
"iptables")
echo "当前开放的防火墙端口 (TCP):"
iptables-legacy -L INPUT -n --line-numbers | grep "tcp" | grep -oP '\d+' | sort -u
echo "当前开放的防火墙端口 (UDP):"
iptables-legacy -L INPUT -n --line-numbers | grep "udp" | grep -oP '\d+' | sort -u
;;
"nftables")
echo "当前开放的防火墙端口 (TCP):"
nft list ruleset | grep "tcp" | grep -oP '\d+' | sort -u
echo "当前开放的防火墙端口 (UDP):"
nft list ruleset | grep "udp" | grep -oP '\d+' | sort -u
;;
*)
echo "找不到支持的防火墙。"
return 1
;;
esac
}
# 安装必要组件
install_components() {
echo "是否需要安装必要组件?(y/n)"
echo "docker docker-compose fail2ban vim curl"
read choice
if [ "$choice" != "y" ] && [ "$choice" != "Y" ]; then
echo "取消安装。"
return 1
fi
echo "正在安装必要组件..."
# 获取操作系统信息
os_type=$(get_os_info)
case $os_type in
Debian/Ubuntu)
# 更新软件包列表,如果失败则退出
apt -y update || {
echo "更新软件包列表失败"
return 1
}
# 安装组件,如果失败则退出
apt -y install fail2ban vim curl || {
echo "安装组件失败"
return 1
}
;;
CentOS)
# 更新软件包列表,如果失败则退出
yum -y update || {
echo "更新软件包列表失败"
return 1
}
# 安装组件,如果失败则退出
yum -y install fail2ban vim curl || {
echo "安装组件失败"
return 1
}
;;
Fedora)
# 更新软件包列表,如果失败则退出
dnf -y update || {
echo "更新软件包列表失败"
return 1
}
# 安装组件,如果失败则退出
dnf -y install fail2ban vim curl || {
echo "安装组件失败"
return 1
}
;;
Arch)
# 更新软件包列表,如果失败则退出
pacman -Syu --noconfirm || {
echo "更新软件包列表失败"
return 1
}
# 安装组件,如果失败则退出
pacman -S --noconfirm fail2ban vim curl || {
echo "安装组件失败"
return 1
}
;;
*)
echo "无法确定操作系统类型,无法安装组件。"
return 1
;;
esac
echo "其他组件安装成功,现在开始安装Docker和Docker Compose。"
local docker_url
if [ -n "${ACC}" ]; then
docker_url="https://get.docker.com ${ACC}"
else
docker_url="https://get.docker.com"
fi
echo "使用以下地址安装: ${docker_url}"
bash <(wget -qO - "${docker_url}") || {
echo "安装Docker失败"
return 1
}
echo "Docker和Docker Compose安装成功。"
echo "所有组件安装完成。"
}
# 添加要登记设备的公钥
add_public_key() {
local public_key authorized_keys_file backup_file
authorized_keys_file="${HOME}/.ssh/authorized_keys"
backup_file="${authorized_keys_file}.bak"
echo "请输入公钥:"
read -r public_key
# 检查公钥是否为空
if [[ -z "$public_key" ]]; then
echo "错误: 公钥不能为空。" >&2
return 1
fi
# 确保 .ssh 目录存在并设置正确的权限
mkdir -p "${HOME}/.ssh" && chmod 700 "${HOME}/.ssh" || {
echo "错误: 无法创建或设置 .ssh 目录权限。" >&2
return 1
}
# 如果 authorized_keys 文件不存在,创建它并设置正确的权限
[[ -f "$authorized_keys_file" ]] || {
touch "$authorized_keys_file" && chmod 600 "$authorized_keys_file" || {
echo "错误: 无法创建或设置 authorized_keys 文件权限。" >&2
return 1
}
}
# 检查公钥是否已存在
if grep -qF -- "$public_key" "$authorized_keys_file"; then
echo "警告: 该公钥已存在于 authorized_keys 文件中。"
return 0
fi
# 备份 authorized_keys 文件
cp -f "$authorized_keys_file" "$backup_file" || {
echo "错误: 无法创建备份文件。" >&2
return 1
}
# 追加公钥到 authorized_keys 文件
if echo "$public_key" >>"$authorized_keys_file"; then
echo "成功: 公钥已添加。"
else
echo "错误: 无法添加公钥。" >&2
mv -f "$backup_file" "$authorized_keys_file"
return 1
fi
# 验证公钥是否成功添加
if ! grep -qF -- "$public_key" "$authorized_keys_file"; then
echo "错误: 公钥添加失败,未在 authorized_keys 文件中找到。" >&2
mv -f "$backup_file" "$authorized_keys_file"
return 1
fi
# 删除备份文件
rm -f "$backup_file"
return 0
}
# 关闭SSH密码登录
disable_ssh_password_login() {
echo "正在关闭SSH密码登录..."
# 备份原始sshd_config文件
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
# 检查是否存在sshd_config文件
if [ -f /etc/ssh/sshd_config ]; then
chmod 600 ~/.ssh/authorized_keys
sed -i 's/#\?PasswordAuthentication\s\+yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
systemctl restart sshd
if [ $? -eq 0 ]; then
echo "SSH密码登录已关闭。"
else
echo "SSH密码登录关闭失败。"
# 恢复备份的sshd_config文件
mv /etc/ssh/sshd_config.bak /etc/ssh/sshd_config
return 1
fi
else
echo "sshd_config 文件不存在"
return 1
fi
}
# 添加docker工具脚本
add_docker_tools() {
echo "你是否希望安装docker工具箱?(包括常用的docker命令和自定义脚本)"
echo "-----------------------------------"
echo "docker工具箱,添加便捷指令."
echo "功能1、nginx命令=docker nginx"
echo "功能2、dlogs命令=查看docker容器日志"
echo "功能3、dclogs命令=查看docker-compose容器日志"
echo "功能4、dspa命令=清理不再使用的 docker 镜像、容器和网络"
echo "功能5、dc命令=docker-compose"
echo "功能6、dcs命令=查看docker-compose容器状态"
echo "功能7、dcps命令=查看docker-compose容器"
echo "功能9、dcip命令=查看容器ip,并添加到宿主机hosts中"
echo "功能9、dr命令=重启指定容器"
echo "功能10、dcr命令=重启指定compose"
echo "工具脚本保存在"/root/.docker_tools"文件夹中,请勿删除"
echo "-----------------------------------"
read -p "是否安装,请输入 y 或 n:" install_choice
case $install_choice in
y | Y)
# 检查是否已经存在.bashrc文件
if [ -e "/root/.bashrc" ]; then
# 备份原始.bashrc文件
cp /root/.bashrc /root/.bashrc.bak
fi
# 创建存放工具脚本的文件夹
tools_folder="/root/.docker_tools"
mkdir -p "$tools_folder"
# 下载脚本
wget -qO "$tools_folder/docker_compose_utils.sh" "${YES_CN}https://raw.githubusercontent.com/SuperNG6/linux-setup.sh/main/docker_tools/docker_compose_utils.sh"
wget -qO "$tools_folder/dlogs.sh" "${YES_CN}https://raw.githubusercontent.com/SuperNG6/linux-setup.sh/main/docker_tools/dlogs.sh"
wget -qO "$tools_folder/dcip.sh" "${YES_CN}https://raw.githubusercontent.com/SuperNG6/linux-setup.sh/main/docker_tools/dcip.sh"
wget -qO "$tools_folder/dclogs.sh" "${YES_CN}https://raw.githubusercontent.com/SuperNG6/linux-setup.sh/main/docker_tools/dclogs.sh"
wget -qO "$tools_folder/dc.sh" "${YES_CN}https://raw.githubusercontent.com/SuperNG6/linux-setup.sh/main/docker_tools/dc.sh"
wget -qO "$tools_folder/drestart.sh" "${YES_CN}https://raw.githubusercontent.com/SuperNG6/linux-setup.sh/main/docker_tools/drestart.sh"
wget -qO "$tools_folder/dcrestart.sh" "${YES_CN}https://raw.githubusercontent.com/SuperNG6/linux-setup.sh/main/docker_tools/dcrestart.sh"
wget -qO "$tools_folder/dcps.sh" "${YES_CN}https://raw.githubusercontent.com/SuperNG6/linux-setup.sh/main/docker_tools/dcps.sh"
wget -qO "$tools_folder/dcstats.sh" "${YES_CN}https://raw.githubusercontent.com/SuperNG6/linux-setup.sh/main/docker_tools/dcstats.sh"
wget -qO "$tools_folder/docker_aliases.sh" "${YES_CN}https://raw.githubusercontent.com/SuperNG6/linux-setup.sh/main/docker_tools/docker_aliases.sh"
find "$tools_folder" -name "*.sh" -exec chmod +x {} \;
echo "下载成功"
# 检查是否已经存在别名,避免重复添加
if grep -q "docker_aliases.sh" /root/.bashrc; then
echo "别名已存在,正在更新中……"
else
# 追加alias到.bashrc文件
cat <<EOF >/root/.bashrc
if [ -f /root/.docker_tools/docker_aliases.sh ]; then
. /root/.docker_tools/docker_aliases.sh
fi
EOF
fi
echo "docker工具箱已成功安装。"
;;
n | N)
echo "取消安装docker工具箱。"
;;
*)
echo "无效的选项,取消安装docker工具箱。"
;;
esac
}
# 删除所有 swap 文件和分区
remove_all_swap() {
# 获取所有 swap 文件的列表
swap_files=$(swapon -s | awk '{if($1!~"^Filename"){print $1}}')
# 获取所有 swap 分区的列表
swap_partitions=$(grep -E '^\S+\s+\S+\sswap\s+' /proc/swaps | awk '{print $1}')
# 遍历并禁用、删除每个 swap 文件和分区
for item in $swap_files $swap_partitions; do
echo "正在禁用并删除 swap :$item"
swapoff "$item"
rm -f "$item"
echo "已删除 swap :$item"
done
echo "所有 swap 文件和分区已删除。"
}
# 清理 swap 缓存
cleanup_swap() {
echo "正在检查当前交换空间..."
echo "=========================================="
# 获取所有交换空间文件的列表
swap_files=$(swapon -s | awk '{if($1!~"^Filename"){print $1}}')
# 获取所有交换分区的列表
swap_partitions=$(grep -E '^\S+\s+\S+\sswap\s+' /proc/swaps | awk '{print $1}')
# 获取物理内存和已使用的物理内存
total_memory=$(free -m | awk 'NR==2{print $2}')
used_memory=$(free -m | awk 'NR==2{print $3}')
# 获取已使用的交换空间
used_swap=$(free -m | awk 'NR==3{print $3}')
# 计算已使用的物理内存和虚拟内存占物理内存的百分比
used_memory_percent=$(((used_memory) * 100 / total_memory))
total_used_percent=$(((used_memory + used_swap) * 100 / total_memory))
if [ -n "$swap_files" ]; then
echo "当前交换空间大小如下:"
swapon --show
echo "=========================================="
echo "物理内存使用率:$used_memory_percent% ( $used_memory MB/ $total_memory MB )"
echo "已使用的物理内存和虚拟内存占物理内存的百分比: $total_used_percent% ( $((used_memory + used_swap)) MB / $total_memory MB )"
# 检测是否可以清理 swap 缓存
if [ $total_used_percent -gt 80 ]; then
echo "不建议清理 swap 缓存,因为物理内存使用量和 swap 使用量总和已经超过物理内存的80%。"
echo "如果清理 swap 缓存,可能导致系统内存不足,影响性能和稳定性。"
else
echo "是否要清理 swap 缓存"
read -p "请输入 y 或 n:" cleanup_choice
case $cleanup_choice in
y | Y)
# 遍历并清理每个交换空间文件和分区
for item in $swap_files $swap_partitions; do
echo "正在清理 swap 缓存:$item"
swapoff "$item"
echo "已清理 swap 缓存:$item"
swapon "$item"
done
echo "所有的 swap 缓存已清理。"
;;
n | N)
echo "不需要清理 swap 缓存"
;;
*)
echo "无效的选项,保留已存在的交换空间。"
;;
esac
fi
fi
}
# 设置虚拟内存
set_virtual_memory() {
echo "正在检查当前 swap ..."
swap_files=$(swapon -s | awk '{if($1!~"^Filename"){print $1}}')
if [ -n "$swap_files" ]; then
echo "当前 swap 大小如下:"
swapon --show
echo "是否要删除已存在的 swap ?"
read -p "请输入 y 或 n:" remove_choice
case $remove_choice in
y | Y)
# 调用函数以删除所有 swap 文件和分区
remove_all_swap
;;
n | N)
echo "保留已存在的 swap 。"
;;
*)
echo "无效的选项,保留已存在的 swap 。"
;;
esac
fi
echo "请选择虚拟内存的大小或手动输入值:"
echo "1. 256M"
echo "2. 512M"
echo "3. 1GB"
echo "4. 2GB"
echo "5. 4GB"
echo "6. 手动输入值"
read -p "请输入选项数字(按q退出):" choice
case $choice in
1)
swap_size="256M"
;;
2)
swap_size="512M"
;;
3)
swap_size="1G"
;;
4)
swap_size="2G"
;;
5)
swap_size="4G"
;;
6)
read -p "请输入虚拟内存大小(例如:256M、1G、2G等):" swap_size_input
swap_size="$swap_size_input"
;;
q | Q)
echo "返回主菜单..."
return 1
;;
*)
echo "无效的选项。"
return 1
;;
esac
echo "正在设置虚拟内存..."
# 检查是否已经存在交换文件
if [ -n "$swap_files" ]; then
echo "已经存在交换文件。删除现有的交换文件..."
# 调用函数以删除所有 swap 文件和分区
remove_all_swap
fi
# 将单位转换为KB
case $swap_size in
*M)
swap_size_kb=$((${swap_size//[^0-9]/} * 1024)) # Convert MB to KB
;;
*G)
swap_size_kb=$((${swap_size//[^0-9]/} * 1024 * 1024)) # Convert GB to KB
;;
*)
echo "无效的虚拟内存大小单位。"
return 1
;;
esac
# 使用dd创建交换文件
dd if=/dev/zero of=/swap bs=1k count=$swap_size_kb
if [ $? -eq 0 ]; then
chmod 600 /swap
mkswap /swap
swapon /swap
if [ $? -eq 0 ]; then
echo "/swap swap swap defaults 0 0" >>/etc/fstab
echo "虚拟内存设置成功。"
echo "当前 swap 大小如下:"
swapon -s | grep '/swap'
else
echo "交换文件创建成功,但启用交换失败,请检查命令是否执行成功。"
return 1
fi
else
echo "创建交换文件失败,请检查命令是否执行成功。"
return 1
fi
}
# 修改swap使用阈值
modify_swap_usage_threshold() {
echo "当前系统的vm.swappiness值:$(cat /proc/sys/vm/swappiness)"
echo "正在修改swap使用阈值..."
read -p "请输入要设置的vm.swappiness值(0-100之间):" swap_value
# 检查输入是否为数字且在0-100范围内
if ! [[ "$swap_value" =~ ^[0-9]+$ ]] || [ "$swap_value" -lt 0 ] || [ "$swap_value" -gt 100 ]; then
echo "无效的输入,请输入0-100之间的数字。"
return 1
fi
# 备份原始配置文件
cp /etc/sysctl.conf /etc/sysctl.conf.bak
# 检查是否存在vm.swappiness设置
if grep -q "^vm.swappiness" /etc/sysctl.conf; then
# 更新现有的vm.swappiness值
sed -i "s/^vm.swappiness=.*/vm.swappiness=$swap_value/" /etc/sysctl.conf
else
# 追加vm.swappiness值到/etc/sysctl.conf
echo "vm.swappiness=$swap_value" >>/etc/sysctl.conf
fi
# 重新加载系统设置
sysctl -p
# 检查修改是否成功
if grep -q "^vm.swappiness=$swap_value" /etc/sysctl.conf; then
echo "swap使用阈值修改成功。"
echo "vm.swappiness值已设置为 $swap_value"
else
echo "swap使用阈值修改失败,请检查配置文件。"
# 恢复备份文件
mv /etc/sysctl.conf.bak /etc/sysctl.conf
return 1
fi
}
# 优化内核参数
optimize_kernel_parameters() {
# 询问用户是否继续
read -p "您确定要优化内核参数吗?(y/n): " choice
case $choice in
y | Y)
echo "正在备份原始内核参数..."
cp /etc/sysctl.conf /etc/sysctl.conf.bak
echo "正在优化内核参数..."
# 定义需要设置的参数
parameters=(
"fs.inotify.max_user_watches=524288"
"net.core.rmem_max=33554432"
"net.core.wmem_max=33554432"
"net.core.somaxconn = 4096"
"net.ipv4.tcp_max_syn_backlog = 4096"
"net.ipv4.tcp_rmem=4096 87380 23068672"
"net.ipv4.tcp_wmem=4096 16384 23068672"
"net.ipv4.udp_rmem_min=8192"
"net.ipv4.udp_wmem_min=8192"
"net.ipv4.tcp_timestamps = 1"
"net.ipv4.ip_forward = 1"
"net.ipv4.tcp_sack=1"
"net.ipv4.tcp_fack=1"
"net.ipv4.tcp_window_scaling=1"
"net.ipv4.tcp_adv_win_scale=1"
"net.ipv4.tcp_moderate_rcvbuf=1"
"net.ipv4.ip_forward = 1"
"net.core.default_qdisc=fq"
"net.ipv4.tcp_congestion_control=bbr"
)
# 注释掉 net.ipv4.tcp_fastopen=3
sed -i 's/^net.ipv4.tcp_fastopen=3/#net.ipv4.tcp_fastopen=3/' /etc/sysctl.conf
# 设置或更新参数
for param in "${parameters[@]}"; do
key="${param%=*}"
value="${param#*=}"
if grep -q "^$key" /etc/sysctl.conf; then
sed -i "s/^$key=.*/$param/" /etc/sysctl.conf
else
echo "$param" >>/etc/sysctl.conf
fi
done
# 重新加载系统设置
sysctl -p
echo "内核参数优化完成。"
;;
n | N)
echo "取消内核参数优化。"
;;
*)
echo "无效的选项。"
return 1
;;
esac
}
# 安装XanMod内核
install_xanmod_kernel() {
echo "当前内核版本:$(uname -r)"
# 检查 CPU 支持的指令集级别
cpu_support_info=$(/usr/bin/awk -f <(wget -qO - "${YES_CN}https://raw.githubusercontent.com/SuperNG6/linux-setup.sh/main/docker_tools/check_x86-64_psabi.sh"))
if [[ $cpu_support_info == "CPU supports x86-64-v"* ]]; then
cpu_support_level=${cpu_support_info#CPU supports x86-64-v}
echo "你的CPU支持XanMod内核,级别为 x86-64-v$cpu_support_level"
else
echo "你的CPU不受XanMod内核支持,无法安装。"
return 1
fi
read -p "是否继续下载并安装XanMod内核? (y/n): " continue_choice
case $continue_choice in
y | Y)
echo "正在从GitHub下载XanMod内核..."
echo "XanMod内核官网 https://xanmod.org"
echo "内核来自 https://sourceforge.net/projects/xanmod/files/releases/lts/"
# 创建临时文件夹
temp_folder=$(mktemp -d)
cd $temp_folder
# 根据CPU支持级别选择下载的内核
case $cpu_support_level in
2)
headers_file="linux-headers-6.1.46-x64v2-xanmod1_6.1.46-x64v2-xanmod1-0.20230816.g11dcd23_amd64.deb"
image_file="linux-image-6.1.46-x64v2-xanmod1_6.1.46-x64v2-xanmod1-0.20230816.g11dcd23_amd64.deb"
headers_md5="45c85d1bcb07bf171006a3e34b804db0"
image_md5="63c359cef963a2e9f1b7181829521fc3"
;;
3)
headers_file="linux-headers-6.1.46-x64v3-xanmod1_6.1.46-x64v3-xanmod1-0.20230816.g11dcd23_amd64.deb"
image_file="linux-image-6.1.46-x64v3-xanmod1_6.1.46-x64v3-xanmod1-0.20230816.g11dcd23_amd64.deb"
headers_md5="6ae3e253a8aeabd80458df4cb4da70cf"
image_md5="d6ea43a2a6686b86e0ac23f800eb95a4"
;;
4)
headers_file="linux-headers-6.1.46-x64v4-xanmod1_6.1.46-x64v4-xanmod1-0.20230816.g11dcd23_amd64.deb"
image_file="linux-image-6.1.46-x64v4-xanmod1_6.1.46-x64v4-xanmod1-0.20230816.g11dcd23_amd64.deb"
headers_md5="9c41a4090a8068333b7dd56b87dd01df"
image_md5="7d30eef4b9094522fc067dc19f7cc92e"
;;
*)
echo "你的CPU不受XanMod内核支持,无法安装。"
return 1
;;
esac
# 下载内核文件
wget "${YES_CN}https://github.com/SuperNG6/linux-setup.sh/releases/download/0816/$headers_file"
wget "${YES_CN}https://github.com/SuperNG6/linux-setup.sh/releases/download/0816/$image_file"
# 校验 MD5 值
if [ "$(md5sum $headers_file | awk '{print $1}')" != "$headers_md5" ]; then
echo "下载的 $headers_file MD5 值不匹配,可能文件已被篡改。"
return 1
fi
if [ "$(md5sum $image_file | awk '{print $1}')" != "$image_md5" ]; then
echo "下载的 $image_file MD5 值不匹配,可能文件已被篡改。"
return 1
fi
# 安装内核
dpkg -i linux-image-*xanmod*.deb linux-headers-*xanmod*.deb
# 检查安装是否成功
if [ $? -eq 0 ]; then
echo "XanMod内核安装成功。"
read -p "是否需要更新grub引导配置? (y/n): " update_grub_choice
case $update_grub_choice in
y | Y)
update-grub
echo "Grub引导配置已更新,重启后生效。"
echo "若需要开启BBRv3,请重启后执行脚本-内核优化选项"
;;
n | N)
echo "跳过Grub引导配置更新。"
;;
*)
echo "无效的选项,跳过Grub引导配置更新。"
;;
esac
else
echo "XanMod内核安装失败。"
fi
# 清理下载的deb文件
rm -f linux-image-*xanmod*.deb linux-headers-*xanmod*.deb
;;
n | N)
echo "取消下载和安装XanMod内核。"
;;
*)
echo "无效的选项,取消下载和安装XanMod内核。"
;;
esac
}
# 卸载XanMod内核并恢复原有内核,并更新Grub引导配置
uninstall_xanmod_kernel() {
echo "正在检查当前内核...$(uname -r)"
# 获取当前内核的版本号
current_kernel_version=$(uname -r)
# 检查是否为XanMod内核
if [[ $current_kernel_version == *-xanmod* ]]; then
echo "当前内核为 XanMod 内核:$current_kernel_version"
# 显示卸载提示
read -p "确定要卸载XanMod内核并恢复原有内核吗?(y/n): " confirm
if [[ $confirm == [yY] ]]; then
echo "正在卸载XanMod内核并恢复原有内核..."
# 卸载XanMod内核
apt-get purge linux-image-*xanmod* linux-headers-*xanmod* -y
apt-get autoremove -y
# 更新Grub引导配置
update-grub
echo "XanMod内核已卸载并恢复原有内核。Grub引导配置已更新,重启后生效。"
else
echo "取消卸载操作。"
fi
else
echo "当前内核不是XanMod内核,无法执行卸载操作。"
fi
}
# 安装 Debian Cloud 内核
install_debian_cloud_kernel() {
echo "INFO" "开始安装 Debian Cloud 内核"
echo "正在更新软件包列表..."
apt update -y
echo "当前系统内核版本:"
dpkg -l | grep linux-image
echo "查找最新的 Cloud 内核版本..."
latest_cloud_kernel=$(apt-cache search linux-image | grep -E 'linux-image-[0-9]+\.[0-9]+\.[0-9]+-[0-9]+-cloud-amd64 ' | grep -v unsigned | sort -V | tail -n 1 | awk '{print $1}')
latest_cloud_headers=${latest_cloud_kernel/image/headers}
if [ -z "$latest_cloud_kernel" ]; then
log "ERROR" "未找到可用的 Cloud 内核版本"
echo "未找到可用的 Cloud 内核版本。"
return 1
fi
echo "找到最新的 Cloud 内核版本:$latest_cloud_kernel"
read -p "是否安装此版本?(y/n): " install_choice
if [[ $install_choice == [yY] ]]; then
echo "正在安装 Cloud 内核..."
apt install $latest_cloud_headers $latest_cloud_kernel -y
if [ $? -eq 0 ]; then
echo "更新 GRUB..."
update-grub
log "INFO" "Debian Cloud 内核安装成功"
echo "Debian Cloud 内核安装成功。请重启系统以使用新内核。"
else
log "ERROR" "Debian Cloud 内核安装失败"
echo "Debian Cloud 内核安装失败。"
fi
else
echo "取消安装 Cloud 内核。"
fi
}
# 卸载 Debian Cloud 内核
uninstall_debian_cloud_kernel() {
echo "INFO" "开始卸载 Debian Cloud 内核"
echo "当前系统内核版本:"
dpkg -l | grep linux-image
cloud_kernels=$(dpkg -l | grep -E 'linux-image-[0-9]+\.[0-9]+\.[0-9]+-[0-9]+-cloud-amd64' | awk '{print $2}')
cloud_headers=$(echo "$cloud_kernels" | sed 's/image/headers/g')
if [ -z "$cloud_kernels" ]; then
echo "未检测到已安装的 Cloud 内核。"
return
fi
echo "检测到以下 Cloud 内核:"
echo "$cloud_kernels"
echo "对应的 headers:"
echo "$cloud_headers"
read -p "是否卸载这些 Cloud 内核并恢复原有内核?(y/n): " uninstall_choice
if [[ $uninstall_choice == [yY] ]]; then
echo "正在卸载 Cloud 内核..."
apt remove $cloud_kernels $cloud_headers -y
apt autoremove -y
if [ $? -eq 0 ]; then
echo "更新 GRUB..."
update-grub
log "INFO" "Debian Cloud 内核卸载成功"
echo "Debian Cloud 内核卸载成功。请重启系统以使用原有内核。"
else
log "ERROR" "Debian Cloud 内核卸载失败"
echo "Debian Cloud 内核卸载失败。"
fi
else
echo "取消卸载 Cloud 内核。"
fi
}
# 修改SSH端口号
modify_ssh_port() {
current_port=$(grep -oP '^Port \K\d+' /etc/ssh/sshd_config)
if [ -z "$current_port" ]; then
echo "当前SSH端口号未设置(被注释),请输入要设置的新SSH端口号:"
else
echo "当前SSH端口号:$current_port,请输入新的SSH端口号:"
fi
read -p "新SSH端口号:" new_port
if ! [[ "$new_port" =~ ^[0-9]+$ ]]; then
echo "无效的输入,请输入有效的端口号。"
return 1 # 返回非零退出状态码表示错误
fi
if [ -z "$current_port" ]; then
# 添加新的端口号配置
sed -i "/^#Port/a Port $new_port" /etc/ssh/sshd_config
else
# 更新现有的端口号配置
sed -i "s/^Port .*/Port $new_port/" /etc/ssh/sshd_config
fi
chmod 644 /etc/ssh/sshd_config
systemctl restart sshd
echo "SSH端口号已修改为:$new_port"
# 开放新端口号根据不同的防火墙
firewall=$(check_firewall)
case $firewall in
"ufw")
ufw allow $new_port/tcp
echo "开放防火墙SSH端口 $new_port"
;;
"firewalld")
firewall-cmd --add-port=$new_port/tcp --permanent
firewall-cmd --reload
echo "开放防火墙SSH端口 $new_port"
;;
"iptables")
iptables -A INPUT -p tcp --dport $new_port -j ACCEPT
service iptables save
service iptables restart
echo "开放防火墙SSH端口 $new_port"
;;
"nftables")
nft add rule ip filter input tcp dport $new_port accept
echo "开放防火墙SSH端口 $new_port"
;;
*)
echo "不支持的防火墙或找不到防火墙。"
;;
esac
}
# 设置防火墙端口
set_firewall_ports() {
firewall=$(check_firewall)
case $firewall in
"ufw")
firewall_cmd="ufw"
;;
"firewalld")
firewall_cmd="firewall-cmd"
;;
"iptables")
firewall_cmd="iptables-legacy"
;;
"nftables")
firewall_cmd="nft"
;;
*)
echo "找不到支持的防火墙。"
return 1
;;
esac
echo "当前系统安装的防火墙为:$(check_firewall)"
echo "=========================================="
display_open_ports
echo -e "============================================="
echo "请选择要执行的操作:"
echo -e "============================================="
echo "1. 开放防火墙端口"
echo "2. 关闭防火墙端口"
echo "q. 返回主菜单"
read -p "请输入操作选项 (1/2): " action
case $action in
1)
echo -e "============================================="
echo -e "','逗号为分隔符,支持一次输入多个tcp,udp端口"
echo -e "============================================="
read -p "请输入要开放的新防火墙端口,如80t,443t,53u(t代表TCP,u代表UDP):" new_ports_input
# 设置 IFS(内部字段分隔符)为逗号,将输入字符串按逗号分割成数组
IFS=',' read -ra new_ports <<<"$new_ports_input"
for port_input in "${new_ports[@]}"; do
if [[ ! "$port_input" =~ ^[0-9]+[tu]$ ]]; then
echo "无效的输入,请按照格式输入端口号和协议缩写(例如:80t 或 443u)。"
return 1
fi
port="${port_input%[tu]}"
case "${port_input: -1}" in
t)
protocol="tcp"
;;
u)
protocol="udp"
;;
*)
echo "无效的协议缩写。"
return 1
;;
esac
$firewall_cmd allow $port/$protocol
echo "开放 $protocol 端口 $port 成功。"
done
;;
2)
echo -e "============================================="
echo -e "','逗号为分隔符,支持一次输入多个tcp,udp端口"
echo -e "============================================="
read -p "请输入要关闭的防火墙端口,如80t,53u(t代表TCP,u代表UDP):" ports_to_close_input
# 设置 IFS(内部字段分隔符)为逗号,将输入字符串按逗号分割成数组
IFS=',' read -ra ports_to_close <<<"$ports_to_close_input"
for port_input in "${ports_to_close[@]}"; do
if [[ ! "$port_input" =~ ^[0-9]+[tu]$ ]]; then
echo "无效的输入,请按照格式输入端口号和协议缩写(例如:80t 或 443u)。"
return 1
fi
port="${port_input%[tu]}"