-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathinstall.sh
More file actions
486 lines (447 loc) · 16.4 KB
/
install.sh
File metadata and controls
486 lines (447 loc) · 16.4 KB
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
#!/bin/bash
# ===========================
# PPanel One-Click Deployment Script
# ===========================
# Supports selecting different service combinations for installation,
# automatically sets NEXT_PUBLIC_API_URL (default to server IP + 8080),
# clears other environment variables.
# Prompts user to modify ppanel.yaml and corresponding Docker Compose files
# when deploying the server and one-click deployment.
# Checks if the user is already in the ppanel-script directory.
# Supports English and Chinese prompts.
# Added an "Update services" option that functions similarly to "Restart services".
# ===========================
# Color Definitions
# ===========================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
UNDERLINE='\033[4m'
NC='\033[0m' # No Color
# ===========================
# Output Functions
# ===========================
log() {
echo -e "$1"
}
error() {
echo -e "${RED}$1${NC}"
}
prompt() {
echo -ne "${BOLD}$1${NC}"
}
info() {
echo -e "${GREEN}$1${NC}"
}
warning() {
echo -e "${YELLOW}$1${NC}"
}
bold_echo() {
echo -e "${BOLD}$1${NC}"
}
# ===========================
# Helper Function: Set NEXT_PUBLIC_API_URL
# ===========================
set_next_public_api_url_in_yml() {
# Default API URL is server IP + 8080 port
DEFAULT_API_URL="http://$SERVER_IP:8080"
if [ "$LANGUAGE" == "CN" ]; then
prompt "请输入 NEXT_PUBLIC_API_URL (默认为:$DEFAULT_API_URL):"
else
prompt "Please enter NEXT_PUBLIC_API_URL (default: $DEFAULT_API_URL): "
fi
read api_url
if [ -z "$api_url" ]; then
api_url="$DEFAULT_API_URL"
if [ "$LANGUAGE" == "CN" ]; then
warning "$api_url"
else
warning "No input detected. Using default NEXT_PUBLIC_API_URL: $api_url"
fi
fi
yml_file=$1
# Backup the original yml file
cp "$yml_file" "${yml_file}.bak"
# Create a temporary file
temp_file=$(mktemp)
# Initialize flag
in_environment_section=0
while IFS= read -r line || [[ -n "$line" ]]; do
# Check if entering the environment section
if [[ $line =~ ^[[:space:]]*environment: ]]; then
echo "$line" >> "$temp_file"
in_environment_section=1
continue
fi
# If in the environment section
if [[ $in_environment_section -eq 1 ]]; then
# Check if it's the next top-level key (no indentation)
if [[ $line =~ ^[[:space:]]{0,2}[a-zA-Z0-9_-]+: ]]; then
in_environment_section=0
elif [[ $line =~ ^([[:space:]]*)(NEXT_PUBLIC_API_URL): ]]; then
indentation="${BASH_REMATCH[1]}"
var_name="${BASH_REMATCH[2]}"
# Set NEXT_PUBLIC_API_URL to user-provided value
echo "${indentation}${var_name}: $api_url" >> "$temp_file"
continue
fi
fi
# Copy other lines
echo "$line" >> "$temp_file"
done < "$yml_file"
# Replace the original yml file with the modified one
mv "$temp_file" "$yml_file"
}
generate_guid_password() {
# 生成16字节随机数并格式化为UUID风格
local hex=$(openssl rand -hex 16)
local uuid=$(echo $hex | sed -E 's/(.{8})(.{4})(.{4})(.{4})(.{12})/\1-\2-\3-\4-\5/')
# 生成最终密码(md5(uuid-时间戳))
local password=$(echo -n "${uuid}-$(date +%s)" | md5sum | awk '{print $1}')
echo "$password"
}
input_admin_account() {
# Default admin email is admin@ppanel.dev
DEFAULT_ADMIN_EMAIL="admin@ppanel.dev"
while true; do
if [ "$LANGUAGE" == "CN" ]; then
prompt "请输入管理员账号邮箱 (默认为: $DEFAULT_ADMIN_EMAIL): "
else
prompt "Please enter administrator email (default: $DEFAULT_ADMIN_EMAIL): "
fi
read admin_email
if [ -z "$admin_email" ]; then
admin_email="$DEFAULT_ADMIN_EMAIL"
if [ "$LANGUAGE" == "CN" ]; then
warning "$admin_email"
else
warning "No input detected. Using default administrator email: $admin_email"
fi
fi
# 简单邮箱格式校验
if [[ "$admin_email" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]]; then
# 生成密码
admin_password=$(generate_guid_password)
# 只修改 Administrator.Password
if grep -q '^ Password:' config/ppanel.yaml; then
sed -i.bak "/^Administrator:/,/^[^ ]/ s/^ Password:.*/ Password: $admin_password/" config/ppanel.yaml
fi
# 只修改 Administrator.Email
if grep -q '^ Email:' config/ppanel.yaml; then
sed -i.bak "/^Administrator:/,/^[^ ]/ s/^ Email:.*/ Email: $admin_email/" config/ppanel.yaml
fi
break
else
if [ "$LANGUAGE" == "CN" ]; then
warning "请输入有效的邮箱地址."
else
warning "Please enter a valid email address."
fi
fi
done
}
# ===========================
# Main Function
# ===========================
main() {
# Display language selection menu
echo -e "${CYAN}==================================================${NC}"
echo -e "${BOLD}Please select your language / 请选择语言:${NC}"
echo -e "${CYAN}==================================================${NC}"
echo -e "1) English"
echo -e "2) 中文"
echo -e "${CYAN}==================================================${NC}"
prompt "Please enter a number (1-2) [1]: "
read lang_choice
# Default to English if no input
if [ -z "$lang_choice" ]; then
lang_choice=1
fi
# Set LANGUAGE variable based on user choice
case $lang_choice in
1)
LANGUAGE="EN"
;;
2)
LANGUAGE="CN"
;;
*)
warning "Invalid selection. Defaulting to English."
LANGUAGE="EN"
;;
esac
# Check if running as root
if [ "$EUID" -ne 0 ]; then
if [ "$LANGUAGE" == "CN" ]; then
error "请以 root 用户运行此脚本。"
else
error "Please run this script as root."
fi
exit 1
fi
# Update system package index
if [ "$LANGUAGE" == "CN" ]; then
info "更新系统包索引..."
else
info "Updating system package index..."
fi
apt-get update -y
# Install necessary packages
# Check if curl is installed
if command -v curl >/dev/null 2>&1; then
if [ "$LANGUAGE" == "CN" ]; then
warning "检测到 curl 已安装,跳过安装步骤。"
else
warning "curl is already installed. Skipping installation."
fi
else
if [ "$LANGUAGE" == "CN" ]; then
info "正在安装 curl..."
else
info "Installing curl..."
fi
apt-get install -y curl
fi
# Check if Docker is installed
if command -v docker >/dev/null 2>&1; then
if [ "$LANGUAGE" == "CN" ]; then
warning "检测到 Docker 已安装,跳过安装步骤。"
else
warning "Docker is already installed. Skipping installation."
fi
else
# Install Docker
if [ "$LANGUAGE" == "CN" ]; then
info "正在安装 Docker..."
else
info "Installing Docker..."
fi
curl -fsSL https://get.docker.com | bash -s -- -y
fi
# Check if git is installed
if command -v git >/dev/null 2>&1; then
if [ "$LANGUAGE" == "CN" ]; then
warning "检测到 git 已安装,跳过安装步骤。"
else
warning "git is already installed. Skipping installation."
fi
else
if [ "$LANGUAGE" == "CN" ]; then
info "正在安装 git..."
else
info "Installing git..."
fi
apt-get install -y git
fi
# Check if in ppanel-script directory
CURRENT_DIR=${PWD##*/}
if [ "$CURRENT_DIR" != "ppanel-script" ]; then
# Clone PPanel script repository
if [ "$LANGUAGE" == "CN" ]; then
info "正在克隆 PPanel 脚本仓库..."
else
info "Cloning PPanel script repository..."
fi
git clone https://github.com/perfect-panel/ppanel-script.git
cd ppanel-script
else
if [ "$LANGUAGE" == "CN" ]; then
warning "检测到已在 ppanel-script 目录中,跳过克隆步骤。"
else
warning "Detected that you are already in the ppanel-script directory, skipping clone step."
fi
fi
# Get server IP address
SERVER_IP=$(hostname -I | awk '{print $1}')
# Display service component selection menu
bold_echo "=================================================="
if [ "$LANGUAGE" == "CN" ]; then
bold_echo "请选择您要执行的操作:"
else
bold_echo "Please select the action you want to perform:"
fi
bold_echo "=================================================="
if [ "$LANGUAGE" == "CN" ]; then
echo -e "1) 一键部署(全部组件)"
echo -e "2) 更新服务"
echo -e "3) 重启服务"
echo -e "4) 查看日志"
echo -e "5) 退出"
else
echo -e "1) One-click deployment (All components)"
echo -e "2) Update services"
echo -e "3) Restart services"
echo -e "4) View logs"
echo -e "5) Exit"
fi
bold_echo "=================================================="
# Prompt user for selection
if [ "$LANGUAGE" == "CN" ]; then
prompt "请输入一个数字 (1-5) [1]: "
else
prompt "Please enter a number (1-5) [1]: "
fi
read choice
# If the user does not input, default to 1
if [ -z "$choice" ]; then
choice=1
fi
# Handle user selection
case $choice in
1)
if [ "$LANGUAGE" == "CN" ]; then
info "开始一键部署所有组件..."
else
info "Starting one-click deployment of all components..."
fi
# Set NEXT_PUBLIC_API_URL and update related yml files
set_next_public_api_url_in_yml "compose.yaml"
input_admin_account
docker compose up -d
;;
2)
if [ "$LANGUAGE" == "CN" ]; then
info "正在更新正在运行的服务..."
else
info "Updating running services..."
fi
# Get a list of running containers and their compose project names
mapfile -t running_projects < <(docker ps --format '{{.Label "com.docker.compose.project"}}' | sort | uniq)
if [ ${#running_projects[@]} -eq 0 ]; then
if [ "$LANGUAGE" == "CN" ]; then
warning "未检测到正在运行的服务。"
else
warning "No running services detected."
fi
else
for project in "${running_projects[@]}"; do
if [ -z "$project" ]; then
continue
fi
if [ "$LANGUAGE" == "CN" ]; then
info "正在更新项目中的服务:$project"
else
info "Updating services in project: $project"
fi
docker compose -p "$project" pull
docker compose -p "$project" up -d
done
if [ "$LANGUAGE" == "CN" ]; then
info "所有正在运行的服务已更新。"
else
info "All running services have been updated."
fi
fi
;;
3)
if [ "$LANGUAGE" == "CN" ]; then
info "正在重启正在运行的服务..."
else
info "Restarting running services..."
fi
# Get a list of running containers and their compose project names
mapfile -t running_projects < <(docker ps --format '{{.Label "com.docker.compose.project"}}' | sort | uniq)
if [ ${#running_projects[@]} -eq 0 ]; then
if [ "$LANGUAGE" == "CN" ]; then
warning "未检测到正在运行的服务。"
else
warning "No running services detected."
fi
else
for project in "${running_projects[@]}"; do
if [ -z "$project" ]; then
continue
fi
if [ "$LANGUAGE" == "CN" ]; then
info "正在重启项目中的服务:$project"
else
info "Restarting services in project: $project"
fi
docker compose -p "$project" restart
done
if [ "$LANGUAGE" == "CN" ]; then
info "所有正在运行的服务已重启。"
else
info "All running services have been restarted."
fi
fi
;;
4)
if [ "$LANGUAGE" == "CN" ]; then
info "查看日志..."
warning "您可以按 Ctrl+C 退出日志查看。"
else
info "Viewing logs..."
warning "You can press Ctrl+C to exit log viewing."
fi
docker compose logs -f
;;
5)
if [ "$LANGUAGE" == "CN" ]; then
info "退出安装脚本。"
else
info "Exiting the installation script."
fi
exit 0
;;
*)
if [ "$LANGUAGE" == "CN" ]; then
error "无效的选项,请重新运行脚本并选择正确的数字(1-5)。"
else
error "Invalid option, please rerun the script and select a valid number (1-5)."
fi
exit 1
;;
esac
# 部署完成信息(仅一键部署时显示)
if [[ "$choice" -eq 1 ]]; then
if [ "$LANGUAGE" == "CN" ]; then
info "部署完成!"
else
info "Deployment completed!"
fi
# Prompt access addresses
echo ""
if [ "$LANGUAGE" == "CN" ]; then
bold_echo "请使用以下地址访问已部署的服务:"
echo -e "服务端(API):${CYAN}http://$SERVER_IP:8080${NC}"
echo -e "管理端:${CYAN}http://$SERVER_IP:3001${NC}"
echo -e "用户端:${CYAN}http://$SERVER_IP:3002${NC}"
else
bold_echo "Please use the following addresses to access the deployed services:"
echo -e "Server (API): ${CYAN}http://$SERVER_IP:8080${NC}"
echo -e "Admin Dashboard: ${CYAN}http://$SERVER_IP:3001${NC}"
echo -e "User Dashboard: ${CYAN}http://$SERVER_IP:3002${NC}"
fi
# Display default admin account information
echo ""
if [ "$LANGUAGE" == "CN" ]; then
bold_echo "默认管理员账户:"
admin_email=$(awk '/^Administrator:/ {flag=1; next} /^[^ ]/ {flag=0} flag && /Email:/ {print $2}' config/ppanel.yaml | head -n1 | tr -d '\r\n')
admin_password=$(awk '/^Administrator:/ {flag=1; next} /^[^ ]/ {flag=0} flag && /Password:/ {print $2}' config/ppanel.yaml | head -n1 | tr -d '\r\n')
echo -e "用户名: ${CYAN}${admin_email}${NC}"
echo -e "密码: ${CYAN}${admin_password}${NC}"
else
bold_echo "Default Admin Account:"
admin_email=$(awk '/^Administrator:/ {flag=1; next} /^[^ ]/ {flag=0} flag && /Email:/ {print $2}' config/ppanel.yaml | head -n1 | tr -d '\r\n')
admin_password=$(awk '/^Administrator:/ {flag=1; next} /^[^ ]/ {flag=0} flag && /Password:/ {print $2}' config/ppanel.yaml | head -n1 | tr -d '\r\n')
echo -e "Username: ${CYAN}${admin_email}${NC}"
echo -e "Password: ${CYAN}${admin_password}${NC}"
fi
# Display service status
echo ""
if [ "$LANGUAGE" == "CN" ]; then
bold_echo "您可以使用以下命令查看服务运行状态:"
else
bold_echo "You can check the service status using the following command:"
fi
echo -e "${CYAN}docker compose ps${NC}"
fi
}
# ===========================
# Execute the Main Function
# ===========================
main