magalh 1.0.16 → 1.0.18
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/bin/mgl.js +75 -207
- package/msh.js +1 -1
- package/package.json +1 -1
package/bin/mgl.js
CHANGED
|
@@ -26,15 +26,6 @@ function warn(message) {
|
|
|
26
26
|
console.warn(`[magalh] ${message}`);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function fail(message, exitCode = 1) {
|
|
30
|
-
try {
|
|
31
|
-
process.stderr.write(`[magalh] ${message}\n`);
|
|
32
|
-
} catch {
|
|
33
|
-
console.error(`[magalh] ${message}`);
|
|
34
|
-
}
|
|
35
|
-
process.exit(exitCode);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
29
|
function isRootOnLinux() {
|
|
39
30
|
return typeof process.getuid === "function" && process.getuid() === 0;
|
|
40
31
|
}
|
|
@@ -51,13 +42,17 @@ function isWindowsAdminLike() {
|
|
|
51
42
|
}
|
|
52
43
|
}
|
|
53
44
|
|
|
54
|
-
function
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
45
|
+
function printHelp() {
|
|
46
|
+
process.stdout.write(
|
|
47
|
+
[
|
|
48
|
+
"magalh - Magala Media Server",
|
|
49
|
+
"",
|
|
50
|
+
"Usage:",
|
|
51
|
+
" magalh [--help]",
|
|
52
|
+
" magalh --install-service",
|
|
53
|
+
"",
|
|
54
|
+
].join("\n"),
|
|
55
|
+
);
|
|
61
56
|
}
|
|
62
57
|
|
|
63
58
|
function runCommand(command, commandArgs, options = {}) {
|
|
@@ -67,11 +62,10 @@ function runCommand(command, commandArgs, options = {}) {
|
|
|
67
62
|
});
|
|
68
63
|
}
|
|
69
64
|
|
|
70
|
-
function
|
|
65
|
+
function safeRunCommand(command, commandArgs, options = {}) {
|
|
71
66
|
try {
|
|
72
67
|
return execFileSync(command, commandArgs, {
|
|
73
68
|
stdio: "pipe",
|
|
74
|
-
encoding: "utf8",
|
|
75
69
|
...options,
|
|
76
70
|
});
|
|
77
71
|
} catch {
|
|
@@ -79,45 +73,26 @@ function runCommandQuiet(command, commandArgs, options = {}) {
|
|
|
79
73
|
}
|
|
80
74
|
}
|
|
81
75
|
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
"
|
|
86
|
-
"",
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
" magalh --install-service",
|
|
91
|
-
" magalh --uninstall-service",
|
|
92
|
-
" magalh --service-status",
|
|
93
|
-
"",
|
|
94
|
-
"Notes:",
|
|
95
|
-
" - The server starts normally with: magalh",
|
|
96
|
-
" - Service installation is explicit only; it is never done automatically.",
|
|
97
|
-
"",
|
|
98
|
-
].join("\n"),
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function getCliBin() {
|
|
103
|
-
return path.join(rootDir, "bin", "mgl.js");
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function getLinuxServiceFile() {
|
|
107
|
-
return `/etc/systemd/system/${SERVICE_NAME}.service`;
|
|
108
|
-
}
|
|
76
|
+
function installLinuxService() {
|
|
77
|
+
if (!isRootOnLinux()) {
|
|
78
|
+
log(
|
|
79
|
+
"Skipping systemd setup (not running as root).\n" +
|
|
80
|
+
" To install manually: sudo npm install -g magalh",
|
|
81
|
+
);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
109
84
|
|
|
110
|
-
|
|
111
|
-
if (!
|
|
112
|
-
|
|
85
|
+
const systemdDir = "/etc/systemd/system";
|
|
86
|
+
if (!fs.existsSync(systemdDir)) {
|
|
87
|
+
log("Skipping systemd setup (systemd not found).");
|
|
88
|
+
return;
|
|
113
89
|
}
|
|
114
|
-
}
|
|
115
90
|
|
|
116
|
-
|
|
91
|
+
const serviceFile = path.join(systemdDir, `${SERVICE_NAME}.service`);
|
|
117
92
|
const nodeBin = process.execPath;
|
|
118
|
-
const cliBin =
|
|
93
|
+
const cliBin = path.join(rootDir, "bin", "mgl.js");
|
|
119
94
|
|
|
120
|
-
|
|
95
|
+
const serviceContent = [
|
|
121
96
|
"[Unit]",
|
|
122
97
|
`Description=${SERVICE_DISPLAY_NAME}`,
|
|
123
98
|
"After=network-online.target",
|
|
@@ -137,37 +112,10 @@ function getLinuxServiceContent() {
|
|
|
137
112
|
"WantedBy=multi-user.target",
|
|
138
113
|
"",
|
|
139
114
|
].join("\n");
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function isLinuxServiceInstalled() {
|
|
143
|
-
return fileExists(getLinuxServiceFile());
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function isWindowsServiceInstalled() {
|
|
147
|
-
const out = runCommandQuiet("sc", ["query", SERVICE_NAME]);
|
|
148
|
-
return typeof out === "string" && out.includes("SERVICE_NAME");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function installLinuxService() {
|
|
152
|
-
if (!isRootOnLinux()) {
|
|
153
|
-
fail("Linux service installation requires root. Run: sudo magalh --install-service");
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const systemdDir = "/etc/systemd/system";
|
|
157
|
-
if (!fileExists(systemdDir)) {
|
|
158
|
-
fail("systemd directory not found. Service install is not supported on this Linux system.");
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const cliBin = getCliBin();
|
|
162
|
-
if (!fileExists(cliBin)) {
|
|
163
|
-
fail(`CLI file not found: ${cliBin}`);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const serviceFile = getLinuxServiceFile();
|
|
167
|
-
const content = getLinuxServiceContent();
|
|
168
115
|
|
|
169
116
|
try {
|
|
170
|
-
fs.writeFileSync(serviceFile,
|
|
117
|
+
fs.writeFileSync(serviceFile, serviceContent, { mode: 0o644 });
|
|
118
|
+
|
|
171
119
|
log(`Service file written -> ${serviceFile}`);
|
|
172
120
|
|
|
173
121
|
runCommand("systemctl", ["daemon-reload"]);
|
|
@@ -180,66 +128,26 @@ function installLinuxService() {
|
|
|
180
128
|
` Logs : journalctl -u ${SERVICE_NAME} -f`,
|
|
181
129
|
);
|
|
182
130
|
} catch (error) {
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function uninstallLinuxService() {
|
|
188
|
-
if (!isRootOnLinux()) {
|
|
189
|
-
fail("Linux service removal requires root. Run: sudo magalh --uninstall-service");
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const serviceFile = getLinuxServiceFile();
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
runCommandQuiet("systemctl", ["stop", SERVICE_NAME]);
|
|
196
|
-
runCommandQuiet("systemctl", ["disable", SERVICE_NAME]);
|
|
197
|
-
|
|
198
|
-
if (fileExists(serviceFile)) {
|
|
199
|
-
fs.unlinkSync(serviceFile);
|
|
200
|
-
log(`Removed service file -> ${serviceFile}`);
|
|
201
|
-
} else {
|
|
202
|
-
log("Service file does not exist. Nothing to remove.");
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
runCommand("systemctl", ["daemon-reload"]);
|
|
206
|
-
log("Linux service removed.");
|
|
207
|
-
} catch (error) {
|
|
208
|
-
fail(`Linux service removal failed: ${error.message || String(error)}`);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function printLinuxServiceStatus() {
|
|
213
|
-
if (!isLinuxServiceInstalled()) {
|
|
214
|
-
log("Linux service is not installed.");
|
|
215
|
-
process.exit(0);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
log(`Linux service file exists -> ${getLinuxServiceFile()}`);
|
|
219
|
-
const status = runCommandQuiet("systemctl", ["status", SERVICE_NAME, "--no-pager"]);
|
|
220
|
-
if (status) {
|
|
221
|
-
process.stdout.write(`${status}\n`);
|
|
222
|
-
} else {
|
|
223
|
-
warn("Could not read systemd status output.");
|
|
131
|
+
warn(`Warning: systemd setup failed: ${error.message || String(error)}`);
|
|
224
132
|
}
|
|
225
133
|
}
|
|
226
134
|
|
|
227
135
|
function installWindowsService() {
|
|
228
136
|
if (!isWindowsAdminLike()) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
fail(`CLI file not found: ${cliBin}`);
|
|
137
|
+
log(
|
|
138
|
+
"Skipping Windows service setup (not running as Administrator).\n" +
|
|
139
|
+
" To install manually: run npm install -g magalh as Administrator.",
|
|
140
|
+
);
|
|
141
|
+
return;
|
|
235
142
|
}
|
|
236
143
|
|
|
237
144
|
const nodeBin = process.execPath;
|
|
145
|
+
const cliBin = path.join(rootDir, "bin", "mgl.js");
|
|
238
146
|
const binPath = `"${nodeBin}" "${cliBin}"`;
|
|
239
147
|
|
|
240
148
|
try {
|
|
241
|
-
|
|
242
|
-
|
|
149
|
+
safeRunCommand("sc", ["stop", SERVICE_NAME]);
|
|
150
|
+
safeRunCommand("sc", ["delete", SERVICE_NAME]);
|
|
243
151
|
|
|
244
152
|
runCommand("sc", [
|
|
245
153
|
"create",
|
|
@@ -276,83 +184,21 @@ function installWindowsService() {
|
|
|
276
184
|
" Logs : Event Viewer -> Windows Logs -> Application",
|
|
277
185
|
);
|
|
278
186
|
} catch (error) {
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
function uninstallWindowsService() {
|
|
284
|
-
if (!isWindowsAdminLike()) {
|
|
285
|
-
fail("Windows service removal requires Administrator privileges.");
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
try {
|
|
289
|
-
runCommandQuiet("sc", ["stop", SERVICE_NAME]);
|
|
290
|
-
runCommandQuiet("sc", ["delete", SERVICE_NAME]);
|
|
291
|
-
log("Windows service removed.");
|
|
292
|
-
} catch (error) {
|
|
293
|
-
fail(`Windows service removal failed: ${error.message || String(error)}`);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function printWindowsServiceStatus() {
|
|
298
|
-
if (!isWindowsServiceInstalled()) {
|
|
299
|
-
log("Windows service is not installed.");
|
|
300
|
-
process.exit(0);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
const status = runCommandQuiet("sc", ["query", SERVICE_NAME]);
|
|
304
|
-
if (status) {
|
|
305
|
-
process.stdout.write(`${status}\n`);
|
|
306
|
-
} else {
|
|
307
|
-
warn("Could not read Windows service status output.");
|
|
187
|
+
warn(`Warning: Windows service setup failed: ${error.message || String(error)}`);
|
|
308
188
|
}
|
|
309
189
|
}
|
|
310
190
|
|
|
311
191
|
function installService() {
|
|
312
192
|
if (process.platform === "linux") {
|
|
313
193
|
installLinuxService();
|
|
314
|
-
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
if (process.platform === "win32") {
|
|
194
|
+
} else if (process.platform === "win32") {
|
|
318
195
|
installWindowsService();
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
fail(`Service installation is not supported on platform: ${process.platform}`);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
function uninstallService() {
|
|
326
|
-
if (process.platform === "linux") {
|
|
327
|
-
uninstallLinuxService();
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
if (process.platform === "win32") {
|
|
332
|
-
uninstallWindowsService();
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
fail(`Service removal is not supported on platform: ${process.platform}`);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
function printServiceStatus() {
|
|
340
|
-
if (process.platform === "linux") {
|
|
341
|
-
printLinuxServiceStatus();
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
if (process.platform === "win32") {
|
|
346
|
-
printWindowsServiceStatus();
|
|
347
|
-
return;
|
|
196
|
+
} else {
|
|
197
|
+
log(`Service install is not supported on platform: ${process.platform}`);
|
|
348
198
|
}
|
|
349
|
-
|
|
350
|
-
log(`Service status is not supported on platform: ${process.platform}`);
|
|
351
199
|
}
|
|
352
200
|
|
|
353
201
|
function startMainProcess() {
|
|
354
|
-
ensureEntryFileExists();
|
|
355
|
-
|
|
356
202
|
const child = spawn(process.execPath, [entryFile, ...args], {
|
|
357
203
|
cwd: rootDir,
|
|
358
204
|
env: process.env,
|
|
@@ -364,13 +210,44 @@ function startMainProcess() {
|
|
|
364
210
|
if (signal) {
|
|
365
211
|
process.exit(1);
|
|
366
212
|
}
|
|
213
|
+
process.exit(typeof code === "number" ? code : 0);
|
|
367
214
|
});
|
|
368
215
|
|
|
369
216
|
child.on("error", (error) => {
|
|
370
|
-
|
|
217
|
+
try {
|
|
218
|
+
process.stderr.write(
|
|
219
|
+
`Failed to start msh: ${error.message || String(error)}\n`,
|
|
220
|
+
);
|
|
221
|
+
} catch {
|
|
222
|
+
}
|
|
223
|
+
process.exit(1);
|
|
371
224
|
});
|
|
372
225
|
}
|
|
373
226
|
|
|
227
|
+
function isWindowsServiceInstalled() {
|
|
228
|
+
try {
|
|
229
|
+
const out = execFileSync("sc", ["query", SERVICE_NAME], { stdio: "pipe" }).toString();
|
|
230
|
+
return out.includes("SERVICE_NAME");
|
|
231
|
+
} catch {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function autoInstallServiceIfNeeded() {
|
|
237
|
+
if (process.platform === "linux") {
|
|
238
|
+
const serviceFile = `/etc/systemd/system/${SERVICE_NAME}.service`;
|
|
239
|
+
if (!fs.existsSync(serviceFile)) {
|
|
240
|
+
log("Service not found, attempting auto-install...");
|
|
241
|
+
installLinuxService();
|
|
242
|
+
}
|
|
243
|
+
} else if (process.platform === "win32") {
|
|
244
|
+
if (!isWindowsServiceInstalled()) {
|
|
245
|
+
log("Service not found, attempting auto-install...");
|
|
246
|
+
installWindowsService();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
374
251
|
function main() {
|
|
375
252
|
if (hasArg("--help") || hasArg("-h")) {
|
|
376
253
|
printHelp();
|
|
@@ -382,16 +259,7 @@ function main() {
|
|
|
382
259
|
process.exit(0);
|
|
383
260
|
}
|
|
384
261
|
|
|
385
|
-
|
|
386
|
-
uninstallService();
|
|
387
|
-
process.exit(0);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
if (hasArg("--service-status")) {
|
|
391
|
-
printServiceStatus();
|
|
392
|
-
process.exit(0);
|
|
393
|
-
}
|
|
394
|
-
|
|
262
|
+
autoInstallServiceIfNeeded();
|
|
395
263
|
startMainProcess();
|
|
396
264
|
}
|
|
397
265
|
|