@sfmc-bds/bds-tools 0.1.0 → 0.2.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bds-manager.d.ts.map +1 -1
- package/dist/bds-manager.js +236 -263
- package/dist/bds-manager.js.map +7 -1
- package/dist/changelog.js +39 -50
- package/dist/changelog.js.map +7 -1
- package/dist/check-update.d.ts +2 -2
- package/dist/check-update.d.ts.map +1 -1
- package/dist/check-update.js +361 -401
- package/dist/check-update.js.map +7 -1
- package/dist/cli-pack-manager.d.ts +10 -6
- package/dist/cli-pack-manager.d.ts.map +1 -1
- package/dist/cli-pack-manager.js +226 -135
- package/dist/cli-pack-manager.js.map +7 -1
- package/dist/fsx.js +86 -100
- package/dist/fsx.js.map +7 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +166 -185
- package/dist/http.js.map +7 -1
- package/dist/is-main.d.ts +17 -0
- package/dist/is-main.d.ts.map +1 -0
- package/dist/is-main.js +32 -0
- package/dist/is-main.js.map +7 -0
- package/dist/log.d.ts +2 -4
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +12 -19
- package/dist/log.js.map +7 -1
- package/dist/logger.js +6 -10
- package/dist/logger.js.map +7 -1
- package/dist/pack-manager.d.ts +88 -24
- package/dist/pack-manager.d.ts.map +1 -1
- package/dist/pack-manager.js +280 -245
- package/dist/pack-manager.js.map +7 -1
- package/dist/paths.d.ts +8 -3
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +53 -39
- package/dist/paths.js.map +7 -1
- package/dist/qqutil.d.ts.map +1 -1
- package/dist/qqutil.js +90 -87
- package/dist/qqutil.js.map +7 -1
- package/dist/recovery.js +26 -37
- package/dist/recovery.js.map +7 -1
- package/dist/rollback.d.ts +1 -1
- package/dist/rollback.js +55 -74
- package/dist/rollback.js.map +7 -1
- package/dist/server-properties.d.ts +12 -0
- package/dist/server-properties.d.ts.map +1 -0
- package/dist/server-properties.js +28 -0
- package/dist/server-properties.js.map +7 -0
- package/dist/taskbar.d.ts +2 -0
- package/dist/taskbar.d.ts.map +1 -1
- package/dist/taskbar.js +51 -82
- package/dist/taskbar.js.map +7 -1
- package/dist/types.js +1 -5
- package/dist/types.js.map +7 -1
- package/dist/update-result.d.ts +12 -0
- package/dist/update-result.d.ts.map +1 -0
- package/dist/update-result.js +15 -0
- package/dist/update-result.js.map +7 -0
- package/dist/upstream.js +94 -108
- package/dist/upstream.js.map +7 -1
- package/dist/version.js +63 -81
- package/dist/version.js.map +7 -1
- package/dist/world-packs.d.ts +112 -0
- package/dist/world-packs.d.ts.map +1 -0
- package/dist/world-packs.js +335 -0
- package/dist/world-packs.js.map +7 -0
- package/dist/zipx.d.ts +10 -0
- package/dist/zipx.d.ts.map +1 -0
- package/dist/zipx.js +48 -0
- package/dist/zipx.js.map +7 -0
- package/package.json +17 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bds-manager.d.ts","sourceRoot":"","sources":["../src/bds-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"bds-manager.d.ts","sourceRoot":"","sources":["../src/bds-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQ3C,MAAM,WAAW,UAAU;IACzB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,IAAI,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAqED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,CA0K5E;AAED,eAAO,MAAM,SAAS,EAAE,YAAiC,CAAC;AAC1D,eAAO,MAAM,iBAAiB,QAAO,IAA2C,CAAC"}
|
package/dist/bds-manager.js
CHANGED
|
@@ -1,294 +1,267 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* bds-manager.ts — BDS 进程管理器
|
|
3
|
-
*
|
|
4
|
-
* 改进:
|
|
5
|
-
* - 优雅 stop (发送 stop 命令 → 等待退出 → SIGTERM → SIGKILL)
|
|
6
|
-
* - watchdog (崩溃自动重启)
|
|
7
|
-
* - 单例事件发射器
|
|
8
|
-
* - 完全异步 (fs/promises)
|
|
9
|
-
*/
|
|
10
1
|
import { spawn, exec } from "node:child_process";
|
|
11
2
|
import { promisify } from "node:util";
|
|
12
3
|
import fs from "node:fs";
|
|
13
4
|
import path from "node:path";
|
|
14
5
|
import { EventEmitter } from "node:events";
|
|
15
|
-
import {
|
|
6
|
+
import { isMainModule } from "./is-main.js";
|
|
7
|
+
import { ensureStateDir, loadConfig, PID_FILE } from "./paths.js";
|
|
16
8
|
import { log } from "./log.js";
|
|
9
|
+
import { ensureEmitServerTelemetry } from "./server-properties.js";
|
|
17
10
|
const execAsync = promisify(exec);
|
|
18
11
|
let cached = null;
|
|
19
12
|
function readPid() {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
13
|
+
try {
|
|
14
|
+
return parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10) || 0;
|
|
15
|
+
} catch {
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
26
18
|
}
|
|
27
19
|
function writePid(pid) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
20
|
+
try {
|
|
21
|
+
ensureStateDir();
|
|
22
|
+
fs.writeFileSync(PID_FILE, String(pid));
|
|
23
|
+
} catch {
|
|
24
|
+
}
|
|
34
25
|
}
|
|
35
26
|
function clearPid() {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
catch {
|
|
41
|
-
/* ignore */
|
|
42
|
-
}
|
|
27
|
+
try {
|
|
28
|
+
if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);
|
|
29
|
+
} catch {
|
|
30
|
+
}
|
|
43
31
|
}
|
|
44
32
|
async function isAlive(pid) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return stdout.includes(String(pid));
|
|
51
|
-
}
|
|
52
|
-
process.kill(pid, 0);
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
return false;
|
|
33
|
+
if (!pid) return false;
|
|
34
|
+
try {
|
|
35
|
+
if (process.platform === "win32") {
|
|
36
|
+
const { stdout } = await execAsync(`tasklist /fi "PID eq ${pid}" /nh`, { windowsHide: true });
|
|
37
|
+
return stdout.includes(String(pid));
|
|
57
38
|
}
|
|
39
|
+
process.kill(pid, 0);
|
|
40
|
+
return true;
|
|
41
|
+
} catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
58
44
|
}
|
|
59
45
|
function ensureProc() {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return cached;
|
|
46
|
+
if (cached) return cached;
|
|
47
|
+
const cfg = loadConfig();
|
|
48
|
+
const bds_path = path.resolve(cfg.bds_path || process.cwd());
|
|
49
|
+
const exePath = path.join(bds_path, "bedrock_server.exe");
|
|
50
|
+
cached = {
|
|
51
|
+
process: null,
|
|
52
|
+
isManualStop: false,
|
|
53
|
+
crashRestart: cfg.crash_restart !== false,
|
|
54
|
+
crashDelayMs: (cfg.crash_restart_delay ?? 5) * 1e3,
|
|
55
|
+
exePath,
|
|
56
|
+
bdsPath: bds_path
|
|
57
|
+
};
|
|
58
|
+
return cached;
|
|
74
59
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
catch {
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
log.warn("BDS 由外部启动,无法发送命令到 stdin");
|
|
60
|
+
function createBdsManager(options = {}) {
|
|
61
|
+
const events = new EventEmitter();
|
|
62
|
+
events.setMaxListeners(100);
|
|
63
|
+
const sendCommand = (cmd) => {
|
|
64
|
+
const p = ensureProc();
|
|
65
|
+
const pid = readPid();
|
|
66
|
+
if (!pid || !isAlive(pid)) {
|
|
67
|
+
log.warn("BDS \u672A\u8FD0\u884C");
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
if (p.process && p.process.pid === pid && p.process.stdin) {
|
|
71
|
+
try {
|
|
72
|
+
p.process.stdin.write(cmd + "\n");
|
|
73
|
+
log.info(`\u5DF2\u53D1\u9001\u547D\u4EE4: ${cmd}`);
|
|
74
|
+
return true;
|
|
75
|
+
} catch {
|
|
96
76
|
return false;
|
|
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
|
-
setTimeout(resolve, 5000);
|
|
124
|
-
}, 30_000)),
|
|
125
|
-
]);
|
|
126
|
-
if (p.process && p.process.exitCode === null) {
|
|
127
|
-
log.warn("强制结束进程...");
|
|
128
|
-
try {
|
|
129
|
-
p.process.kill("SIGKILL");
|
|
130
|
-
}
|
|
131
|
-
catch { }
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
// 外部启动的 BDS — fallback 使用 taskkill / pkill
|
|
136
|
-
log.info("BDS 由外部启动,使用 taskkill...");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
log.warn("BDS \u7531\u5916\u90E8\u542F\u52A8\uFF0C\u65E0\u6CD5\u53D1\u9001\u547D\u4EE4\u5230 stdin");
|
|
80
|
+
return false;
|
|
81
|
+
};
|
|
82
|
+
const stop = async () => {
|
|
83
|
+
const p = ensureProc();
|
|
84
|
+
const pid = readPid();
|
|
85
|
+
if (!pid || !await isAlive(pid)) {
|
|
86
|
+
log.info("BDS \u672A\u8FD0\u884C");
|
|
87
|
+
clearPid();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (p.process && p.process.pid === pid && p.process.stdin) {
|
|
91
|
+
p.isManualStop = true;
|
|
92
|
+
log.info("\u6B63\u5728\u5173\u95ED BDS...");
|
|
93
|
+
try {
|
|
94
|
+
p.process.stdin.write("stop\n");
|
|
95
|
+
} catch (e) {
|
|
96
|
+
log.warn(`\u53D1\u9001 stop \u547D\u4EE4\u5931\u8D25: ${e.message}`);
|
|
97
|
+
}
|
|
98
|
+
await Promise.race([
|
|
99
|
+
new Promise((resolve) => p.process?.once("exit", () => resolve())),
|
|
100
|
+
new Promise(
|
|
101
|
+
(resolve) => setTimeout(() => {
|
|
102
|
+
log.warn("30s \u8D85\u65F6\uFF0C\u5F3A\u5236\u7EC8\u6B62...");
|
|
137
103
|
try {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
await execAsync("pkill -f bedrock_server", { windowsHide: true });
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
catch {
|
|
146
|
-
/* ignore */
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
clearPid();
|
|
150
|
-
p.process = null;
|
|
151
|
-
log.info("BDS 已停止");
|
|
152
|
-
};
|
|
153
|
-
const start = async () => {
|
|
154
|
-
const p = ensureProc();
|
|
155
|
-
const existing = readPid();
|
|
156
|
-
if (existing && (await isAlive(existing))) {
|
|
157
|
-
log.info("BDS 已在运行中");
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
if (!fs.existsSync(p.exePath)) {
|
|
161
|
-
log.error(`未找到 ${p.exePath}`);
|
|
162
|
-
throw new Error(`bedrock_server.exe 不存在: ${p.exePath}`);
|
|
163
|
-
}
|
|
164
|
-
log.info("正在启动 BDS...");
|
|
165
|
-
const child = spawn(p.exePath, [], {
|
|
166
|
-
cwd: p.bdsPath,
|
|
167
|
-
stdio: options.detached ? "ignore" : ["pipe", "pipe", "pipe"],
|
|
168
|
-
detached: options.detached,
|
|
169
|
-
windowsHide: true,
|
|
170
|
-
});
|
|
171
|
-
if (options.detached)
|
|
172
|
-
child.unref();
|
|
173
|
-
p.process = child;
|
|
174
|
-
writePid(child.pid ?? 0);
|
|
175
|
-
log.info(`BDS 已启动 (PID: ${child.pid})`);
|
|
176
|
-
child.stdout?.on("data", (chunk) => {
|
|
177
|
-
const text = chunk.toString();
|
|
178
|
-
events.emit("output", text);
|
|
179
|
-
if (require.main === module)
|
|
180
|
-
process.stdout.write(text);
|
|
181
|
-
});
|
|
182
|
-
child.stderr?.on("data", (chunk) => {
|
|
183
|
-
const text = `[STDERR] ${chunk.toString()}`;
|
|
184
|
-
events.emit("output", text);
|
|
185
|
-
if (require.main === module)
|
|
186
|
-
process.stderr.write(text);
|
|
187
|
-
});
|
|
188
|
-
child.on("exit", (code) => {
|
|
189
|
-
log.info(`BDS 已退出 (code: ${code})`);
|
|
190
|
-
clearPid();
|
|
191
|
-
p.process = null;
|
|
192
|
-
if (!p.isManualStop && p.crashRestart && isMain()) {
|
|
193
|
-
log.info(`BDS 意外退出,${p.crashDelayMs / 1000}s 后自动重启...`);
|
|
194
|
-
setTimeout(() => {
|
|
195
|
-
start().catch((e) => log.error(`自动重启失败: ${e.message}`));
|
|
196
|
-
}, p.crashDelayMs);
|
|
104
|
+
p.process?.kill("SIGTERM");
|
|
105
|
+
} catch {
|
|
197
106
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
107
|
+
setTimeout(resolve, 5e3);
|
|
108
|
+
}, 3e4)
|
|
109
|
+
)
|
|
110
|
+
]);
|
|
111
|
+
if (p.process && p.process.exitCode === null) {
|
|
112
|
+
log.warn("\u5F3A\u5236\u7ED3\u675F\u8FDB\u7A0B...");
|
|
113
|
+
try {
|
|
114
|
+
p.process.kill("SIGKILL");
|
|
115
|
+
} catch {
|
|
206
116
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
log.info("BDS \u7531\u5916\u90E8\u542F\u52A8\uFF0C\u4F7F\u7528 taskkill...");
|
|
120
|
+
try {
|
|
121
|
+
if (process.platform === "win32") {
|
|
122
|
+
await execAsync("taskkill /f /im bedrock_server.exe", { windowsHide: true });
|
|
123
|
+
} else {
|
|
124
|
+
await execAsync("pkill -f bedrock_server", { windowsHide: true });
|
|
210
125
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
126
|
+
} catch {
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
clearPid();
|
|
130
|
+
p.process = null;
|
|
131
|
+
log.info("BDS \u5DF2\u505C\u6B62");
|
|
132
|
+
};
|
|
133
|
+
const start = async () => {
|
|
134
|
+
const p = ensureProc();
|
|
135
|
+
const existing = readPid();
|
|
136
|
+
if (existing && await isAlive(existing)) {
|
|
137
|
+
log.info("BDS \u5DF2\u5728\u8FD0\u884C\u4E2D");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (!fs.existsSync(p.exePath)) {
|
|
141
|
+
log.error(`\u672A\u627E\u5230 ${p.exePath}`);
|
|
142
|
+
throw new Error(`bedrock_server.exe \u4E0D\u5B58\u5728: ${p.exePath}`);
|
|
143
|
+
}
|
|
144
|
+
ensureEmitServerTelemetry(p.bdsPath, log);
|
|
145
|
+
log.info("\u6B63\u5728\u542F\u52A8 BDS...");
|
|
146
|
+
const child = spawn(p.exePath, [], {
|
|
147
|
+
cwd: p.bdsPath,
|
|
148
|
+
stdio: options.detached ? "ignore" : ["pipe", "pipe", "pipe"],
|
|
149
|
+
detached: options.detached,
|
|
150
|
+
windowsHide: true
|
|
151
|
+
});
|
|
152
|
+
if (options.detached) child.unref();
|
|
153
|
+
p.process = child;
|
|
154
|
+
writePid(child.pid ?? 0);
|
|
155
|
+
log.info(`BDS \u5DF2\u542F\u52A8 (PID: ${child.pid})`);
|
|
156
|
+
child.stdout?.on("data", (chunk) => {
|
|
157
|
+
const text = chunk.toString();
|
|
158
|
+
events.emit("output", text);
|
|
159
|
+
if (isMain()) process.stdout.write(text);
|
|
160
|
+
});
|
|
161
|
+
child.stderr?.on("data", (chunk) => {
|
|
162
|
+
const text = `[STDERR] ${chunk.toString()}`;
|
|
163
|
+
events.emit("output", text);
|
|
164
|
+
if (isMain()) process.stderr.write(text);
|
|
165
|
+
});
|
|
166
|
+
child.on("exit", (code) => {
|
|
167
|
+
log.info(`BDS \u5DF2\u9000\u51FA (code: ${code})`);
|
|
168
|
+
clearPid();
|
|
169
|
+
p.process = null;
|
|
170
|
+
if (!p.isManualStop && p.crashRestart && isMain()) {
|
|
171
|
+
log.info(`BDS \u610F\u5916\u9000\u51FA\uFF0C${p.crashDelayMs / 1e3}s \u540E\u81EA\u52A8\u91CD\u542F...`);
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
start().catch((e) => log.error(`\u81EA\u52A8\u91CD\u542F\u5931\u8D25: ${e.message}`));
|
|
174
|
+
}, p.crashDelayMs);
|
|
175
|
+
}
|
|
176
|
+
p.isManualStop = false;
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
const status = async () => {
|
|
180
|
+
const pid = readPid();
|
|
181
|
+
const alive = pid > 0 && await isAlive(pid);
|
|
182
|
+
if (alive) {
|
|
183
|
+
console.log(`BDS \u8FD0\u884C\u4E2D (PID: ${pid})`);
|
|
184
|
+
} else {
|
|
185
|
+
console.log("BDS \u672A\u8FD0\u884C");
|
|
186
|
+
clearPid();
|
|
187
|
+
}
|
|
188
|
+
return alive;
|
|
189
|
+
};
|
|
190
|
+
const watch = async () => {
|
|
191
|
+
log.info("\u542F\u52A8\u76D1\u62A4\u6A21\u5F0F...");
|
|
192
|
+
while (true) {
|
|
193
|
+
const pid = readPid();
|
|
194
|
+
if (!pid || !await isAlive(pid)) {
|
|
195
|
+
try {
|
|
196
|
+
await start();
|
|
197
|
+
} catch (e) {
|
|
198
|
+
log.error(`\u81EA\u52A8\u542F\u52A8\u5931\u8D25: ${e.message}`);
|
|
226
199
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
200
|
+
}
|
|
201
|
+
await new Promise((r) => setTimeout(r, 5e3));
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
const getPid = () => {
|
|
205
|
+
const p = ensureProc();
|
|
206
|
+
return p.process?.pid ?? readPid();
|
|
207
|
+
};
|
|
208
|
+
return {
|
|
209
|
+
start,
|
|
210
|
+
stop,
|
|
211
|
+
status,
|
|
212
|
+
sendCommand,
|
|
213
|
+
watch,
|
|
214
|
+
events,
|
|
215
|
+
isManualStop: false,
|
|
216
|
+
getPid
|
|
217
|
+
};
|
|
242
218
|
}
|
|
243
|
-
|
|
244
|
-
|
|
219
|
+
const bdsEvents = new EventEmitter();
|
|
220
|
+
const bdsEvents_enabled = () => {
|
|
221
|
+
bdsEvents.setMaxListeners(100);
|
|
222
|
+
};
|
|
245
223
|
bdsEvents_enabled();
|
|
246
|
-
/** 判断当前是否作为 CLI 主入口运行 */
|
|
247
224
|
function isMain() {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
// 兼容 CJS 编译产物的 require.main 不等于当前 module 场景
|
|
251
|
-
// 若 process.argv[1] 指向本文件 → 主入口
|
|
252
|
-
const entry = process.argv[1] ?? "";
|
|
253
|
-
return entry.endsWith("bds-manager.js") || entry.endsWith("bds-manager.ts");
|
|
225
|
+
if (process.env.SFMC_SERVICE === "manager") return true;
|
|
226
|
+
return isMainModule(import.meta.url);
|
|
254
227
|
}
|
|
255
|
-
// CLI 入口
|
|
256
228
|
if (isMain()) {
|
|
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
|
-
status 检查状态
|
|
290
|
-
send <cmd> 发送命令
|
|
291
|
-
watch 监护模式(崩溃自动重启)`);
|
|
292
|
-
}
|
|
229
|
+
const cmd = process.argv[2];
|
|
230
|
+
const bds = createBdsManager();
|
|
231
|
+
const args = process.argv.slice(3);
|
|
232
|
+
switch (cmd) {
|
|
233
|
+
case "start":
|
|
234
|
+
bds.start().catch((e) => log.error(`\u542F\u52A8\u5931\u8D25: ${e.message}`));
|
|
235
|
+
break;
|
|
236
|
+
case "stop":
|
|
237
|
+
bds.stop().catch((e) => log.error(`\u505C\u6B62\u5931\u8D25: ${e.message}`));
|
|
238
|
+
break;
|
|
239
|
+
case "restart":
|
|
240
|
+
bds.stop().then(() => bds.start()).catch((e) => log.error(`\u91CD\u542F\u5931\u8D25: ${e.message}`));
|
|
241
|
+
break;
|
|
242
|
+
case "status":
|
|
243
|
+
bds.status();
|
|
244
|
+
break;
|
|
245
|
+
case "send":
|
|
246
|
+
if (args[0]) bds.sendCommand(args.join(" "));
|
|
247
|
+
else console.log("\u7528\u6CD5: node bds-manager.js send <command>");
|
|
248
|
+
break;
|
|
249
|
+
case "watch":
|
|
250
|
+
bds.watch().catch((e) => log.error(`\u76D1\u62A4\u5F02\u5E38: ${e.message}`));
|
|
251
|
+
break;
|
|
252
|
+
default:
|
|
253
|
+
console.log(`\u7528\u6CD5:
|
|
254
|
+
start \u542F\u52A8 BDS
|
|
255
|
+
stop \u505C\u6B62
|
|
256
|
+
restart \u91CD\u542F
|
|
257
|
+
status \u68C0\u67E5\u72B6\u6001
|
|
258
|
+
send <cmd> \u53D1\u9001\u547D\u4EE4
|
|
259
|
+
watch \u76D1\u62A4\u6A21\u5F0F\uFF08\u5D29\u6E83\u81EA\u52A8\u91CD\u542F\uFF09`);
|
|
260
|
+
}
|
|
293
261
|
}
|
|
294
|
-
|
|
262
|
+
export {
|
|
263
|
+
bdsEvents,
|
|
264
|
+
bdsEvents_enabled,
|
|
265
|
+
createBdsManager
|
|
266
|
+
};
|
|
267
|
+
//# sourceMappingURL=bds-manager.js.map
|
package/dist/bds-manager.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/bds-manager.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * bds-manager.ts \u2014 BDS \u8FDB\u7A0B\u7BA1\u7406\u5668\n *\n * \u6539\u8FDB:\n * - \u4F18\u96C5 stop (\u53D1\u9001 stop \u547D\u4EE4 \u2192 \u7B49\u5F85\u9000\u51FA \u2192 SIGTERM \u2192 SIGKILL)\n * - watchdog (\u5D29\u6E83\u81EA\u52A8\u91CD\u542F)\n * - \u5355\u4F8B\u4E8B\u4EF6\u53D1\u5C04\u5668\n * - \u5B8C\u5168\u5F02\u6B65 (fs/promises)\n */\n\nimport { spawn, exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { EventEmitter } from \"node:events\";\nimport { isMainModule } from \"./is-main.js\";\nimport { ensureStateDir, loadConfig, PID_FILE } from \"./paths.js\";\nimport { log } from \"./log.js\";\nimport { ensureEmitServerTelemetry } from \"./server-properties.js\";\n\nconst execAsync = promisify(exec);\n\nexport interface BdsManager {\n start(): Promise<void>;\n stop(): Promise<void>;\n status(): Promise<boolean>;\n sendCommand(cmd: string): boolean;\n watch(): Promise<void>;\n events: EventEmitter;\n isManualStop: boolean;\n getPid(): number;\n}\n\nexport interface BdsManagerOptions {\n detached?: boolean;\n}\n\ninterface CachedProc {\n process: ReturnType<typeof spawn> | null;\n isManualStop: boolean;\n crashRestart: boolean;\n crashDelayMs: number;\n exePath: string;\n bdsPath: string;\n}\n\nlet cached: CachedProc | null = null;\n\nfunction readPid(): number {\n try {\n return parseInt(fs.readFileSync(PID_FILE, \"utf-8\").trim(), 10) || 0;\n } catch {\n return 0;\n }\n}\n\nfunction writePid(pid: number): void {\n try {\n ensureStateDir();\n fs.writeFileSync(PID_FILE, String(pid));\n } catch {\n /* ignore */\n }\n}\n\nfunction clearPid(): void {\n try {\n if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);\n } catch {\n /* ignore */\n }\n}\n\nasync function isAlive(pid: number): Promise<boolean> {\n if (!pid) return false;\n try {\n if (process.platform === \"win32\") {\n const { stdout } = await execAsync(`tasklist /fi \"PID eq ${pid}\" /nh`, { windowsHide: true });\n return stdout.includes(String(pid));\n }\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction ensureProc(): CachedProc {\n if (cached) return cached;\n const cfg = loadConfig();\n const bds_path = path.resolve(cfg.bds_path || process.cwd());\n const exePath = path.join(bds_path, \"bedrock_server.exe\");\n\n cached = {\n process: null,\n isManualStop: false,\n crashRestart: cfg.crash_restart !== false,\n crashDelayMs: (cfg.crash_restart_delay ?? 5) * 1000,\n exePath,\n bdsPath: bds_path,\n };\n return cached;\n}\n\nexport function createBdsManager(options: BdsManagerOptions = {}): BdsManager {\n const events = new EventEmitter();\n events.setMaxListeners(100);\n\n const sendCommand = (cmd: string): boolean => {\n const p = ensureProc();\n const pid = readPid();\n if (!pid || !isAlive(pid)) {\n log.warn(\"BDS \u672A\u8FD0\u884C\");\n return false;\n }\n if (p.process && p.process.pid === pid && p.process.stdin) {\n try {\n p.process.stdin.write(cmd + \"\\n\");\n log.info(`\u5DF2\u53D1\u9001\u547D\u4EE4: ${cmd}`);\n return true;\n } catch {\n return false;\n }\n }\n log.warn(\"BDS \u7531\u5916\u90E8\u542F\u52A8\uFF0C\u65E0\u6CD5\u53D1\u9001\u547D\u4EE4\u5230 stdin\");\n return false;\n };\n\n const stop = async (): Promise<void> => {\n const p = ensureProc();\n const pid = readPid();\n if (!pid || !(await isAlive(pid))) {\n log.info(\"BDS \u672A\u8FD0\u884C\");\n clearPid();\n return;\n }\n\n if (p.process && p.process.pid === pid && p.process.stdin) {\n p.isManualStop = true;\n log.info(\"\u6B63\u5728\u5173\u95ED BDS...\");\n try {\n p.process.stdin.write(\"stop\\n\");\n } catch (e) {\n log.warn(`\u53D1\u9001 stop \u547D\u4EE4\u5931\u8D25: ${(e as Error).message}`);\n }\n\n await Promise.race([\n new Promise<void>((resolve) => p.process?.once(\"exit\", () => resolve())),\n new Promise<void>((resolve) =>\n setTimeout(() => {\n log.warn(\"30s \u8D85\u65F6\uFF0C\u5F3A\u5236\u7EC8\u6B62...\");\n try { p.process?.kill(\"SIGTERM\"); } catch {}\n setTimeout(resolve, 5000);\n }, 30_000)\n ),\n ]);\n\n if (p.process && p.process.exitCode === null) {\n log.warn(\"\u5F3A\u5236\u7ED3\u675F\u8FDB\u7A0B...\");\n try { p.process.kill(\"SIGKILL\"); } catch {}\n }\n } else {\n // \u5916\u90E8\u542F\u52A8\u7684 BDS \u2014 fallback \u4F7F\u7528 taskkill / pkill\n log.info(\"BDS \u7531\u5916\u90E8\u542F\u52A8\uFF0C\u4F7F\u7528 taskkill...\");\n try {\n if (process.platform === \"win32\") {\n await execAsync(\"taskkill /f /im bedrock_server.exe\", { windowsHide: true });\n } else {\n await execAsync(\"pkill -f bedrock_server\", { windowsHide: true });\n }\n } catch {\n /* ignore */\n }\n }\n\n clearPid();\n p.process = null;\n log.info(\"BDS \u5DF2\u505C\u6B62\");\n };\n\n const start = async (): Promise<void> => {\n const p = ensureProc();\n const existing = readPid();\n if (existing && (await isAlive(existing))) {\n log.info(\"BDS \u5DF2\u5728\u8FD0\u884C\u4E2D\");\n return;\n }\n\n if (!fs.existsSync(p.exePath)) {\n log.error(`\u672A\u627E\u5230 ${p.exePath}`);\n throw new Error(`bedrock_server.exe \u4E0D\u5B58\u5728: ${p.exePath}`);\n }\n\n // \u542F\u52A8\u524D\u5E42\u7B49\u786E\u4FDD\u9065\u6D4B\u5F00\u5173\uFF08\u5B89\u88C5\u9636\u6BB5\u4E5F\u4F1A\u5199\uFF1B\u65E7\u76EE\u5F55\u9996\u6B21\u542F\u52A8\u65F6\u8865\u4E0A\uFF09\n ensureEmitServerTelemetry(p.bdsPath, log);\n\n log.info(\"\u6B63\u5728\u542F\u52A8 BDS...\");\n const child = spawn(p.exePath, [], {\n cwd: p.bdsPath,\n stdio: options.detached ? \"ignore\" : [\"pipe\", \"pipe\", \"pipe\"],\n detached: options.detached,\n windowsHide: true,\n });\n\n if (options.detached) child.unref();\n\n p.process = child;\n writePid(child.pid ?? 0);\n log.info(`BDS \u5DF2\u542F\u52A8 (PID: ${child.pid})`);\n\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n const text = chunk.toString();\n events.emit(\"output\", text);\n if (isMain()) process.stdout.write(text);\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n const text = `[STDERR] ${chunk.toString()}`;\n events.emit(\"output\", text);\n if (isMain()) process.stderr.write(text);\n });\n\n child.on(\"exit\", (code) => {\n log.info(`BDS \u5DF2\u9000\u51FA (code: ${code})`);\n clearPid();\n p.process = null;\n if (!p.isManualStop && p.crashRestart && isMain()) {\n log.info(`BDS \u610F\u5916\u9000\u51FA\uFF0C${p.crashDelayMs / 1000}s \u540E\u81EA\u52A8\u91CD\u542F...`);\n setTimeout(() => {\n start().catch((e) => log.error(`\u81EA\u52A8\u91CD\u542F\u5931\u8D25: ${e.message}`));\n }, p.crashDelayMs);\n }\n p.isManualStop = false;\n });\n };\n\n const status = async (): Promise<boolean> => {\n const pid = readPid();\n const alive = pid > 0 && (await isAlive(pid));\n if (alive) {\n console.log(`BDS \u8FD0\u884C\u4E2D (PID: ${pid})`);\n } else {\n console.log(\"BDS \u672A\u8FD0\u884C\");\n clearPid();\n }\n return alive;\n };\n\n const watch = async (): Promise<void> => {\n log.info(\"\u542F\u52A8\u76D1\u62A4\u6A21\u5F0F...\");\n while (true) {\n const pid = readPid();\n if (!pid || !(await isAlive(pid))) {\n try { await start(); }\n catch (e) { log.error(`\u81EA\u52A8\u542F\u52A8\u5931\u8D25: ${(e as Error).message}`); }\n }\n await new Promise((r) => setTimeout(r, 5_000));\n }\n };\n\n const getPid = (): number => {\n const p = ensureProc();\n return p.process?.pid ?? readPid();\n };\n\n return {\n start,\n stop,\n status,\n sendCommand,\n watch,\n events,\n isManualStop: false,\n getPid,\n };\n}\n\nexport const bdsEvents: EventEmitter = new EventEmitter();\nexport const bdsEvents_enabled = (): void => { bdsEvents.setMaxListeners(100); };\nbdsEvents_enabled();\n\n/** \u5224\u65AD\u5F53\u524D\u662F\u5426\u4F5C\u4E3A CLI \u4E3B\u5165\u53E3\u8FD0\u884C\uFF08\u88AB check-update \u7B49 import \u65F6\u4E3A false\uFF09 */\nfunction isMain(): boolean {\n // sfmc supervisor \u901A\u8FC7 SFMC_SERVICE \u62C9\u8D77\u5B50\u8FDB\u7A0B\u65F6\u4F18\u5148\u5224\u5B9A\uFF08\u4E0E check-update \u5BF9\u79F0\uFF09\n if (process.env.SFMC_SERVICE === \"manager\") return true;\n return isMainModule(import.meta.url);\n}\n\n// CLI \u5165\u53E3\nif (isMain()) {\n const cmd = process.argv[2];\n const bds = createBdsManager();\n const args = process.argv.slice(3);\n\n switch (cmd) {\n case \"start\":\n bds.start().catch((e) => log.error(`\u542F\u52A8\u5931\u8D25: ${e.message}`));\n break;\n case \"stop\":\n bds.stop().catch((e) => log.error(`\u505C\u6B62\u5931\u8D25: ${e.message}`));\n break;\n case \"restart\":\n bds.stop()\n .then(() => bds.start())\n .catch((e) => log.error(`\u91CD\u542F\u5931\u8D25: ${e.message}`));\n break;\n case \"status\":\n bds.status();\n break;\n case \"send\":\n if (args[0]) bds.sendCommand(args.join(\" \"));\n else console.log(\"\u7528\u6CD5: node bds-manager.js send <command>\");\n break;\n case \"watch\":\n bds.watch().catch((e) => log.error(`\u76D1\u62A4\u5F02\u5E38: ${e.message}`));\n break;\n default:\n console.log(`\u7528\u6CD5:\n start \u542F\u52A8 BDS\n stop \u505C\u6B62\n restart \u91CD\u542F\n status \u68C0\u67E5\u72B6\u6001\n send <cmd> \u53D1\u9001\u547D\u4EE4\n watch \u76D1\u62A4\u6A21\u5F0F\uFF08\u5D29\u6E83\u81EA\u52A8\u91CD\u542F\uFF09`);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|