added:增加Linux-server
This commit is contained in:
1 parent
6fe4e9d23f
commit
d78f3f811b
90 files changed
+16784
-1
No files matched your search
@@ -0,0 +1,114 @@
|
||||
import { spawn, execSync, type ChildProcess } from "child_process";
|
||||
import { BLOG_ROOT } from "./config";
|
||||
|
||||
class HugoManager {
|
||||
private process: ChildProcess | null = null;
|
||||
private ready = false;
|
||||
private starting = false;
|
||||
private healthTimer: NodeJS.Timeout | null = null;
|
||||
|
||||
async start(): Promise<{ ok: boolean; alreadyRunning?: boolean }> {
|
||||
if (this.process && this.ready) {
|
||||
return { ok: true, alreadyRunning: true };
|
||||
}
|
||||
if (this.starting) {
|
||||
return { ok: false };
|
||||
}
|
||||
|
||||
this.starting = true;
|
||||
this.ready = false;
|
||||
|
||||
this.process = spawn("hugo", ["server", "--bind", "0.0.0.0", "--port", "1313", "--disableFastRender", "--noHTTPCache"], {
|
||||
cwd: BLOG_ROOT,
|
||||
shell: true,
|
||||
stdio: "pipe",
|
||||
windowsHide: true,
|
||||
});
|
||||
|
||||
this.process.stdout?.on("data", (d: Buffer) => process.stdout.write(`[hugo] ${d}`));
|
||||
this.process.stderr?.on("data", (d: Buffer) => process.stderr.write(`[hugo] ${d}`));
|
||||
|
||||
this.process.on("exit", (code) => {
|
||||
console.log(`[hugo] exited ${code}`);
|
||||
this.process = null;
|
||||
this.ready = false;
|
||||
this.starting = false;
|
||||
});
|
||||
|
||||
// 等待 Hugo 就绪(最多 15 秒)
|
||||
const ok = await this.waitForReady(15000);
|
||||
this.starting = false;
|
||||
if (ok) {
|
||||
this.ready = true;
|
||||
this.startHealthCheck();
|
||||
console.log("[hugo] ready on 0.0.0.0:1313");
|
||||
}
|
||||
return { ok };
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
this.stopHealthCheck();
|
||||
if (!this.process) return;
|
||||
try {
|
||||
const pid = this.process.pid;
|
||||
if (process.platform === "win32" && pid) {
|
||||
execSync(`taskkill /PID ${pid} /T /F`, { stdio: "ignore" });
|
||||
} else {
|
||||
this.process.kill();
|
||||
}
|
||||
} catch (_e) { /* nothing to kill */ }
|
||||
this.process = null;
|
||||
this.ready = false;
|
||||
this.starting = false;
|
||||
}
|
||||
|
||||
status(): { running: boolean; starting: boolean } {
|
||||
return { running: !!(this.process && this.ready), starting: this.starting };
|
||||
}
|
||||
|
||||
async ensureRunning(): Promise<boolean> {
|
||||
if (this.process && this.ready) return true;
|
||||
const result = await this.start();
|
||||
return result.ok;
|
||||
}
|
||||
|
||||
private async waitForReady(timeoutMs: number): Promise<boolean> {
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < timeoutMs) {
|
||||
if (await this.ping()) return true;
|
||||
await new Promise((r) => setTimeout(r, 1500));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private async ping(): Promise<boolean> {
|
||||
try {
|
||||
const res = await fetch("http://127.0.0.1:1313", { signal: AbortSignal.timeout(1500) });
|
||||
return res.ok || res.status < 500;
|
||||
} catch (_e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private startHealthCheck(): void {
|
||||
this.stopHealthCheck();
|
||||
this.healthTimer = setInterval(async () => {
|
||||
if (!this.process) return;
|
||||
const alive = await this.ping();
|
||||
if (!alive) {
|
||||
console.warn("[hugo] health check failed, marking as not ready");
|
||||
this.ready = false;
|
||||
this.stopHealthCheck();
|
||||
}
|
||||
}, 30_000);
|
||||
}
|
||||
|
||||
private stopHealthCheck(): void {
|
||||
if (this.healthTimer) {
|
||||
clearInterval(this.healthTimer);
|
||||
this.healthTimer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const hugo = new HugoManager();
|
||||
Reference in new issue
Block a user