forked from eishare/Paper
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPaperBootstrap.java
More file actions
135 lines (117 loc) · 5.04 KB
/
PaperBootstrap.java
File metadata and controls
135 lines (117 loc) · 5.04 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
package io.papermc.paper;
import java.io.*;
import java.nio.file.*;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import org.yaml.snakeyaml.Yaml;
public final class PaperBootstrap {
private static final AtomicBoolean running = new AtomicBoolean(true);
private static Process tuicProcess;
private static Process hy2Process;
private static Process realityProcess;
// 固定配置参数(按要求设置)
private static final String FIXED_UUID = "1ed3bd45-6943-405d-8e08-3e0431cb5f4d";
private static final String FIXED_TUIC_PORT = "65462";
private static final String FIXED_HY2_PORT = "8195";
private static Map<String, String> config;
private PaperBootstrap() {}
public static void main(String[] args) {
try {
loadConfig();
startNodes();
scheduleDailyRestart();
Runtime.getRuntime().addShutdownHook(new Thread(PaperBootstrap::stopAllNodes));
System.out.println("🎉 TUIC + Hysteria2 + Reality 启动完成!");
} catch (Exception e) {
e.printStackTrace();
System.err.println("❌ 节点启动失败:" + e.getMessage());
stopAllNodes();
System.exit(1);
}
}
private static void loadConfig() throws IOException {
Path configPath = Paths.get("config.yml");
if (!Files.exists(configPath)) {
throw new FileNotFoundException("config.yml 不存在,请先创建!");
}
Yaml yaml = new Yaml();
try (InputStream in = Files.newInputStream(configPath)) {
config = yaml.load(in);
}
// 仅校验 reality_port(其他关键参数已固定,无需从配置读取)
if (!config.containsKey("reality_port")) {
throw new IllegalArgumentException("config.yml 缺少必要字段(reality_port)");
}
System.out.println("✅ 配置文件读取完成!");
}
private static void startNodes() throws IOException {
startTuic();
startHy2(); // 修正原代码多余的 "uuid" 拼写错误
startReality();
}
private static void startTuic() throws IOException {
// 使用固定端口和UUID,无需从配置读取
ProcessBuilder pb = new ProcessBuilder("./tuic-server",
"-p", FIXED_TUIC_PORT,
"-u", FIXED_UUID
);
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectErrorStream(true);
tuicProcess = pb.start();
System.out.println("✅ TUIC 启动端口: " + FIXED_TUIC_PORT);
}
private static void startHy2() throws IOException {
// 使用固定端口和UUID,无需从配置读取
ProcessBuilder pb = new ProcessBuilder("./hy2-server",
"-p", FIXED_HY2_PORT,
"-u", FIXED_UUID
);
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectErrorStream(true);
hy2Process = pb.start();
System.out.println("✅ Hysteria2 启动端口: " + FIXED_HY2_PORT);
}
private static void startReality() throws IOException {
String realityPort = config.get("reality_port");
String sni = config.getOrDefault("sni", "www.bing.com");
// 假设 xray 已上传到当前目录 ./xray
ProcessBuilder pb = new ProcessBuilder("./xray",
"run",
"-c", "xray.json"
);
Map<String, String> env = pb.environment();
env.put("UUID", FIXED_UUID); // 传入固定UUID
env.put("REALITY_PORT", realityPort);
env.put("SNI", sni);
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectErrorStream(true);
realityProcess = pb.start();
System.out.println("✅ VLESS Reality 启动端口: " + realityPort);
}
private static void stopAllNodes() {
if (tuicProcess != null && tuicProcess.isAlive()) tuicProcess.destroy();
if (hy2Process != null && hy2Process.isAlive()) hy2Process.destroy();
if (realityProcess != null && realityProcess.isAlive()) realityProcess.destroy();
System.out.println("🛑 所有节点已停止");
}
private static void scheduleDailyRestart() {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Runnable restartTask = () -> {
System.out.println("🔄 定时重启服务器(北京时间0点)");
stopAllNodes();
try {
startNodes();
} catch (IOException e) {
e.printStackTrace();
}
};
// 计算距离北京时间0点的延迟
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime nextMidnight = now.truncatedTo(ChronoUnit.DAYS).plusDays(1);
long initialDelay = Duration.between(now, nextMidnight).getSeconds();
scheduler.scheduleAtFixedRate(restartTask, initialDelay, 24 * 3600, TimeUnit.SECONDS);
}
}