summarylogtreecommitdiffstats
path: root/1pctl
blob: 1de365b803a1ca60232f74d19f11ad3abc39e500 (plain)
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
#!/bin/bash
action=$1
target=$2
args=$@

BASE_DIR=/var/lib/1p
ORIGINAL_PORT=8888
ORIGINAL_VERSION=
ORIGINAL_ENTRANCE=entrance
ORIGINAL_USERNAME=username
ORIGINAL_PASSWORD=password
# Set the initialize param.
function init_1panel() {
	cat << EOF
 ██╗	██████╗  █████╗ ███╗   ██╗███████╗██╗	 
███║	██╔══██╗██╔══██╗████╗  ██║██╔════╝██║	 
╚██║	██████╔╝███████║██╔██╗ ██║█████╗  ██║	 
 ██║	██╔═══╝ ██╔══██║██║╚██╗██║██╔══╝  ██║	 
 ██║	██║	 ██║  ██║██║ ╚████║███████╗███████╗
 ╚═╝	╚═╝	 ╚═╝  ╚═╝╚═╝  ╚═══╝╚══════╝╚══════╝
EOF
	echo -e "======================== 正在初始化 ========================"
############################################################################
## 准备初始化 1Panel													  ##
############################################################################
	if [[ $EUID -eq 0 ]]; then
		echo "请避免使用ROOT用户执行此命令"
		exit 1
	fi
	if [ "$(ls -A /var/lib/1p/1panel)" ]; then
		echo -e "1Panel已经初始化"
		read -p "您是否需要备份原有的数据后再初始化 [Y/n] " backup
		if [[ $backup != "N" ]] && [[ $backup != "n" ]]; then
			# Get timestamp
			timestamp=$(date +%s)
			echo -e "正在将数据备份到 /var/lib/1p/1panel_$timestamp"
			# Backup files
			sudo mv /var/lib/1p/1panel /var/lib/1p/1panel_$timestamp
		else
			echo -e "请手动备份数据后再次初始化。"
			exit 1
		fi
	else
		echo -e "1Panel尚未初始化,正在准备初始化工作..."
	fi
	if pacman -Ql 1panel &> /dev/null; then
		echo -e "1Panel已经安装,安装途径为ArchLinux软件包。"
	else
		echo -e "\033[31m错误:\033[9m 1Panel尚未安装,请使用AUR安装后重试。"
		echo -e "请访问\033[33m https://aur.archlinux.org/packages/1panel/ \033[0m来安装"
	fi
############################################################################
## 检测 Docker 镜像和 Docker Compose									  ##
############################################################################
	echo -e "检测Docker镜像"
	if pacman -Ql docker >/dev/null 2>&1; then
		echo -e "Docker已安装,正在检测Docker服务..."
		if sudo systemctl status docker >/dev/null 2>&1; then
			echo -e "Docker服务正在运行"
		else
			read -p "Docker服务未运行,是否启动 [Y/n] " start_docker
			if [[ $start_docker != "N" ]] && [[ $start_docker != "n" ]]; then
				sudo systemctl start docker
				echo -e "等待Docker服务启动..."
				for b in {1..30}
				do
					sleep 3
					service_status=`sudo systemctl status docker 2>&1 | grep Active`
					if [[ $service_status == *running* ]];then
						echo -e "Docker服务启动成功"
						break;
					else
						echo -e "Docker服务暂未启动,等待中..."
					fi
				done
			else
				echo -e "Docker将不会启动,您可以手动运行\033[34msudo systemctl enable --now docker.service\033[0m来启动Docker。"
			fi
		fi
	else
		echo -e "Docker未安装,是否需要安装Docker [Y/n] "
		read -r install_docker
		if [[ $install_docker != "N" ]] && [[ $install_docker != "n" ]]; then
			echo -e "正在安装Docker..."
			sudo pacman -Sy docker
		else
			echo -e "\033[33m警告:\033[0m 如果您不安装Docker,1Panel的大部分功能将无法使用!"
		fi
	fi
	echo -e "检测Docker Compose..."
	if sudo docker-compose version >/dev/null 2>&1; then
		echo -e "Docker Compose已安装"
	else
		read -p "Docker Compose尚未安装,是否安装Docker Compose [Y/n] " install_docker_compose
		if [[ $install_docker_compose != "N" ]] && [[ $install_docker_compose != "n" ]]; then
			echo -e "正在安装Docker Compose..."
			sudo pacman -Sy docker-compose
		else
			echo -e "\033[33m警告:\033[0m 如果您不安装Docker Compose,1Panel的核心功能应用商店和容器管理将无法正常使用。"
		fi
	fi
############################################################################
## 设置 1PANEL 端口号													 ##
############################################################################
	DEFAULT_PORT=`expr $RANDOM % 55535 + 10000`
	while true; do
		echo -e "请设置您的1Panel端口号,如果为空,则使用默认端口号: $DEFAULT_PORT"
		echo -n -e "\033[32m端口号: \033[0m"
		read PANEL_PORT

		if [[ "$PANEL_PORT" == "" ]];then
			PANEL_PORT=$DEFAULT_PORT
		fi

		if ! [[ "$PANEL_PORT" =~ ^[1-9][0-9]{0,4}$ && "$PANEL_PORT" -le 65535 ]]; then
			echo "\033[31m错误:\033[0m 端口号必须介于 1 ~ 65535 之间!"
			continue
		fi
		# Check if the port is occupied.
		if ss -lntup | grep -q ":$PANEL_PORT "; then
			echo "\033[31m错误:\033[0m 端口号 $PANEL_PORT 冲突,请重新设置"
			continue
		fi
		echo -e "您的 1Panel 端口号是:$PANEL_PORT 。"
		break
	done
############################################################################
## 检测 1PANEL 防火墙													 ##
############################################################################
	if pacman -Ql firewalld >/dev/null 2>&1; then
		if sudo systemctl status firewalld | grep -q "Active: active" >/dev/null 2>&1;then
			echo -e "防火墙firewalld已放开端口号 $PANEL_PORT。"
			firewall-cmd --zone=public --add-port=$PANEL_PORT/tcp --permanent
			firewall-cmd --reload
		else
			echo -e "防火墙服务firewalld未启用,跳过放开端口。"
		fi
	fi

	if pacman -Ql ufw >/dev/null 2>&1; then
		if sudo systemctl status ufw | grep -q "Active: active" >/dev/null 2>&1;then
			echo -e "防火墙ufw已放开端口号 $PANEL_PORT。"
			ufw reload
		else
			echo -e "防火墙服务ufw未启用,跳过放开端口。"
		fi
	fi
############################################################################
## 设置 1PANEL 用户名													 ##
############################################################################
	DEFAULT_USERNAME=`cat /dev/urandom | head -n 16 | md5sum | head -c 10`
	while true; do
		echo -e "请输入您的1Panel用户名,为空则使用默认用户名 $DEFAULT_USERNAME"
		echo -n -e "\033[32m用户名: \033[0m"
		read PANEL_USERNAME

		if [[ "$PANEL_USERNAME" == "" ]];then
			PANEL_USERNAME=$DEFAULT_USERNAME
		fi

		if [[ ! "$PANEL_USERNAME" =~ ^[a-zA-Z0-9_]{3,30}$ ]]; then
			echo -e "\033[31m错误:\033[0m 1Panel用户名仅支持使用字母、数字和下划线,长度必须介于 3 ~ 30。"
			continue
		fi
		echo -e "您的1Panel用户名是$PANEL_USERNAME"
		break
	done
############################################################################
## 设置 1PANEL 密码													   ##
############################################################################
	DEFAULT_PASSWORD=`cat /dev/urandom | head -n 16 | md5sum | head -c 10`
	echo -e "请设置您的 1Panel 密码,为空则使用默认密码。"
	while true; do
		echo -n -e "\033[32m密码: \033[0m"
		read -s PANEL_PASSWORD
		echo ""
		echo -n -e "\033[32m确认密码: \033[0m"
		read -s PANEL_PASSWORD_CONFIRM
		echo ""
		if [[ "$PANEL_PASSWORD" != "$PANEL_PASSWORD_CONFIRM" ]];then
			echo -e "\033[31m错误:\033[0m 两次输入的密码不一致!"
			continue
		fi
		if [[ "$PANEL_PASSWORD" == "" ]];then
			PANEL_PASSWORD=$DEFAULT_PASSWORD
		fi

		if [[ ! "$PANEL_PASSWORD" =~ ^[a-zA-Z0-9_!@#$%*,.?]{8,30}$ ]]; then
			echo "\033[31m错误:\033[0m 1Panel密码仅支持数字、字母、特殊字符(!@#$%*_,.?),长度为 3 ~ 30。"
			continue
		fi

		break
	done


############################################################################
## 设置 1PANEL 安全入口												   ##
############################################################################
	DEFAULT_ENTRANCE=`cat /dev/urandom | head -n 16 | md5sum | head -c 10`
	while true; do
		echo -e "请设置您的 1Panel 安全入口,为空则使用默认安全入口:$DEFAULT_ENTRANCE。"
		echo -n -e "\033[32m安全入口: \033[0m"
		read PANEL_ENTRANCE
		if [[ "$PANEL_ENTRANCE" == "" ]]; then
			PANEL_ENTRANCE=$DEFAULT_ENTRANCE
		elif [[ ! "$PANEL_ENTRANCE" =~ ^[a-zA-Z0-9_]{5,30}$ ]]; then
			echo "\033[31m错误:\033[0m 1Panel 安全入口仅支持数字、字母和下划线,长度为 length 5 ~ 30。"
			continue
		fi
		echo -e "您的1Panel安全入口为 $PANEL_ENTRANCE。"
		break
	done



############################################################################
## 初始化1Panel 1PANEL													##
############################################################################
	echo -e "正在配置 1Panel 服务..."
	sudo install -vdm 644 /var/lib/1p/1panel
	sudo rm -rvf /var/lib/1p/1panel/*
	sudo sed -i -e "s#ORIGINAL_PORT=.*#ORIGINAL_PORT=${PANEL_PORT}#g" /usr/bin/1pctl
	sudo sed -i -e "s#ORIGINAL_USERNAME=.*#ORIGINAL_USERNAME=${PANEL_USERNAME}#g" /usr/bin/1pctl
	ESCAPED_PANEL_PASSWORD=$(echo "$PANEL_PASSWORD" | sed 's/[!@#$%*_,.?]/\\&/g')
	sudo sed -i -e "s#ORIGINAL_PASSWORD=.*#ORIGINAL_PASSWORD=${ESCAPED_PANEL_PASSWORD}#g" /usr/bin/1pctl
	sudo sed -i -e "s#ORIGINAL_ENTRANCE=.*#ORIGINAL_ENTRANCE=${PANEL_ENTRANCE}#g" /usr/bin/1pctl
	read -p "您想要立即启动 1Panel 服务吗 [Y/n]:" start_1panel
	if [[ $start_1panel != "N" ]] && [[ $start_1panel != "n" ]]; then
		sudo systemctl enable 1panel; sudo systemctl daemon-reload 2>&1

		echo -e "正在启动 1Panel 服务..."
		sudo systemctl start 1panel
		echo -e "等待 1Panel 服务启动..."
		for b in {1..30}
		do
			sleep 3
			service_status=`sudo systemctl status 1panel 2>&1 | grep Active`
			if [[ $service_status == *running* ]];then
				echo -e "1Panel 服务正在运行。"
				break;
			else
				echo -e "\033[31m错误:\033[0m 1Panel 服务尚未运行,等待中..."
				exit 1
			fi
		done
		sed -i -e "s#ORIGINAL_PASSWORD=.*#ORIGINAL_PASSWORD=\*\*\*\*\*\*\*\*\*\*#g" /usr/bin/1pctl
	else
		echo -e "1Panel 服务将不会启动,您可以运行 \033[34msudo systemctl enable --now 1panel.service\033[0m 来手动启动。"
	fi
############################################################################
## 获取 1PANEL IP 地址													##
############################################################################
	echo -e "正在获取 1Panel 本地 IP 地址。"
	active_interface=$(ip route get 8.8.8.8 | awk 'NR==1 {print $5}')
	if [[ -z $active_interface ]]; then
		LOCAL_IP="127.0.0.1"
	else
		LOCAL_IP=`ip -4 addr show dev "$active_interface" | grep -oP '(?<=inet\s)\d+(\.\d+){3}'`
	fi
	echo -e "成功获取 1Panel 本地 IP 地址。"
	echo -e "正在获取 1Panel 公网 IP 地址..."
	PUBLIC_IP=`curl -s https://api64.ipify.org`
	if [[ -z "$PUBLIC_IP" ]]; then
		PUBLIC_IP="N/A"
	fi
	if echo "$PUBLIC_IP" | grep -q ":"; then
		PUBLIC_IP=[${PUBLIC_IP}]
		1panel listen-ip ipv6
	fi
	if [ $PUBLIC_IP != "N/A" ]; then
		echo -e "成功获取 1Panel 公网 IP 地址。"
	else
		echo -e "\033[33m警告:\033[0m 无法获取 1Panel 公网 IP 地址,可能的原因是 1Panel 运行的环境为本地环境而不是云服务器。"
	fi
############################################################################
## 显示 1PANEL 初始化结果												 ##
############################################################################
	echo -e ""
	echo -e "=========================== 感谢您的等待, 1Panel 初始化成功! ============================"
	echo -e ""
	echo -e "现在您可以使用浏览器访问 1Panel:"
	echo -e "公网 IP:	  \033[34m http://$PUBLIC_IP:$PANEL_PORT/$PANEL_ENTRANCE \033[0m"
	echo -e "本地 IP:	   \033[34m http://$LOCAL_IP:$PANEL_PORT/$PANEL_ENTRANCE \033[0m"
	echo -e "1Panel 用户:	 $PANEL_USERNAME"
	if [[ $PANEL_PASSWORD == $DEFAULT_PASSWORD ]]; then
		echo -e "1Panel 密码: $PANEL_PASSWORD"
	else
		echo -e "1Panel 密码: ********"
	fi
	echo -e ""
	echo -e "如果您使用的是云服务器,请前往安全组开启 \033[34m$PANEL_PORT\033[0m 端口号。"
	echo -e ""
	echo -e "为了您的服务器安全,在您离开此界面后您将无法再看到您的密码,请务必牢记您的密码。"
	echo -e ""
	echo -e "==========================================================================================="
}

function usage() {
	echo "1Panel Control Script"
	echo
	echo "Usage: "
	echo "  ./1pctl [COMMAND] [ARGS...]"
	echo "  ./1pctl --help"
	echo
	echo "Commands: "
	echo "  status			  查看 1Panel 服务运行状态"
	echo "  start			   启动 1Panel 服务"
	echo "  stop				停止 1Panel 服务"
	echo "  restart			 重启 1Panel 服务"
	echo "  uninstall		   卸载 1Panel 服务"
	echo "  user-info		   获取 1Panel 用户信息"
	echo "  listen-ip		   切换 1Panel 监听 IP"
	echo "  version			 查看 1Panel 版本信息"
	echo "  update			  修改 1Panel 系统信息"
	echo "  reset			   重置 1Panel 系统信息"
	echo "  restore			 恢复 1Panel 服务及数据"
	echo "  init				初始化 1Panel 服务,在第一次安装后使用"
	echo
	echo "Example: "
	echo "  ./1pctl status"
	echo "  ./1pctl start"
	echo "  ./1pctl stop"
	echo "  ./1pctl restart"
	echo "  ./1pctl uninstall"
	echo "  ./1pctl user-info"
	echo "  ./1pctl listen-ip"
}
function status() {
	systemctl status 1panel.service
}
function start() {
	systemctl start 1panel.service
	status
}
function stop() {
	systemctl stop 1panel.service
	status
}
function restart() {
	systemctl restart 1panel.service
	status
}
function uninstall() {
	read -p "卸载将会完全清除 1Panel 软件包,是否继续 [y/n] : " yn
	if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
		echo -e "================== 开始卸载 1Panel Linux 服务器运维管理面板 =================="
		echo -e ""
		echo -e "1) 停止 1Panel 服务进程..."
		systemctl stop 1panel.service
		systemctl disable 1panel.service >/dev/null 2>&1
	else
		exit 0
	fi

	echo -e "2) 卸载1Panel"

	sudo pacman -R 1panel --noconfirm >/dev/null 2>&1
	if pacman -Ql 1panel-debug &> /dev/null; then
		sudo pacman -R 1panel-debug --noconfirm >/dev/null 2>&1
	fi
	echo -e "3) 重新加载服务配置文件..."
	systemctl daemon-reload
	systemctl reset-failed

	read -p "您是否要删除1Panel的数据文件 [y/n]" yn
	if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
		echo -e "4) 正在删除1Panel的数据文件..."
		sudo rm -rf /var/lib/1p/1panel
	else
		echo -e "4) 请手动备份1Panel数据文件,然后您可以删除/var/lib/1p/1panel目录下的所有文件"
	fi
	echo -e ""
	echo -e "================================== 卸载完成 =================================="
}
function user-info() {
	1panel user-info
}
function listen-ip() {
	1panel listen-ip
}
function listen_ipv4() {
	1panel listen-ip ipv4
	restart
}
function listen_ipv6() {
	1panel listen-ip ipv6
	restart
}
function restore() {
	read -p "1Panel 将会恢复至上一个稳定版本,是否继续 [y/n] : " yn
	if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
		echo -e ""
		1panel restore
		systemctl daemon-reload
		restart
		echo -e ""
		1panel version
	else
		exit 0
	fi
}
function version() {
	1panel version
}
function reset() {
	1panel reset
}
function reset_domain() {
	1panel reset domain
}
function reset_entrance() {
	1panel reset entrance
}
function reset_https() {
	1panel reset https
	restart
}
function reset_ips() {
	1panel reset ips
}
function reset_mfa() {
	1panel reset mfa
}
function update() {
	1panel update
}
function update_username() {
	1panel update username
}
function update_password() {
	1panel update password
}
function update_port() {
	1panel update port
}

function main() {
	case "${action}" in
		status)
			status
			;;
		start)
			start
			;;
		stop)
			stop
			;;
		restart)
			restart
			;;
		restore)
			restore
			;;
		uninstall)
			uninstall
			;;
		user-info)
			user-info
			;;
		listen-ip)
			case "${target}" in
				ipv4)
					listen_ipv4
					;;
				ipv6)
					listen_ipv6
					;;
				*)
					listen-ip
					;;
			esac
			;;
		version)
			version
			;;
		reset)
			case "${target}" in
				domain)
					reset_domain
					;;
				entrance)
					reset_entrance
					;;
				https)
					reset_https
					;;
				ips)
					reset_ips
					;;
				mfa)
					reset_mfa
					;;
				*)
					reset
					;;
			esac
			;;
		update)
			case "${target}" in
				username)
					update_username
					;;
				password)
					update_password
					;;
				port)
					update_port
					;;
				*)
					update
					;;
			esac
			;;
		help)
			usage
			;;
		--help)
			usage
			;;
		"")
			usage
			;;
		*)
		echo "不支持的参数,请使用 help 或 --help 参数获取帮助"
	esac
}
if [ ${action} == 'init' ]; then
	init_1panel
else
	main
fi