xray-manager 1.0.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/LICENSE +21 -0
- package/README.md +798 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +113 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +49 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +295 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/interactive.d.ts +83 -0
- package/dist/commands/interactive.d.ts.map +1 -0
- package/dist/commands/interactive.js +362 -0
- package/dist/commands/interactive.js.map +1 -0
- package/dist/commands/logs.d.ts +43 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +257 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/service.d.ts +43 -0
- package/dist/commands/service.d.ts.map +1 -0
- package/dist/commands/service.js +177 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/commands/user.d.ts +43 -0
- package/dist/commands/user.d.ts.map +1 -0
- package/dist/commands/user.js +212 -0
- package/dist/commands/user.js.map +1 -0
- package/dist/constants/exit-codes.d.ts +49 -0
- package/dist/constants/exit-codes.d.ts.map +1 -0
- package/dist/constants/exit-codes.js +100 -0
- package/dist/constants/exit-codes.js.map +1 -0
- package/dist/constants/paths.d.ts +57 -0
- package/dist/constants/paths.d.ts.map +1 -0
- package/dist/constants/paths.js +72 -0
- package/dist/constants/paths.js.map +1 -0
- package/dist/constants/timeouts.d.ts +84 -0
- package/dist/constants/timeouts.d.ts.map +1 -0
- package/dist/constants/timeouts.js +111 -0
- package/dist/constants/timeouts.js.map +1 -0
- package/dist/services/config-manager.d.ts +66 -0
- package/dist/services/config-manager.d.ts.map +1 -0
- package/dist/services/config-manager.js +206 -0
- package/dist/services/config-manager.js.map +1 -0
- package/dist/services/log-manager.d.ts +113 -0
- package/dist/services/log-manager.d.ts.map +1 -0
- package/dist/services/log-manager.js +288 -0
- package/dist/services/log-manager.js.map +1 -0
- package/dist/services/systemd-manager.d.ts +197 -0
- package/dist/services/systemd-manager.d.ts.map +1 -0
- package/dist/services/systemd-manager.js +458 -0
- package/dist/services/systemd-manager.js.map +1 -0
- package/dist/services/user-manager.d.ts +63 -0
- package/dist/services/user-manager.d.ts.map +1 -0
- package/dist/services/user-manager.js +219 -0
- package/dist/services/user-manager.js.map +1 -0
- package/dist/types/config.d.ts +256 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +7 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/service.d.ts +96 -0
- package/dist/types/service.d.ts.map +1 -0
- package/dist/types/service.js +7 -0
- package/dist/types/service.js.map +1 -0
- package/dist/types/user.d.ts +114 -0
- package/dist/types/user.d.ts.map +1 -0
- package/dist/types/user.js +7 -0
- package/dist/types/user.js.map +1 -0
- package/dist/utils/clipboard.d.ts +21 -0
- package/dist/utils/clipboard.d.ts.map +1 -0
- package/dist/utils/clipboard.js +45 -0
- package/dist/utils/clipboard.js.map +1 -0
- package/dist/utils/format.d.ts +93 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +242 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/logger.d.ts +113 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +260 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/preflight.d.ts +57 -0
- package/dist/utils/preflight.d.ts.map +1 -0
- package/dist/utils/preflight.js +215 -0
- package/dist/utils/preflight.js.map +1 -0
- package/dist/utils/validator.d.ts +102 -0
- package/dist/utils/validator.d.ts.map +1 -0
- package/dist/utils/validator.js +238 -0
- package/dist/utils/validator.js.map +1 -0
- package/dist/utils/which.d.ts +13 -0
- package/dist/utils/which.d.ts.map +1 -0
- package/dist/utils/which.js +28 -0
- package/dist/utils/which.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SystemdManager - Service Management via systemctl
|
|
3
|
+
*
|
|
4
|
+
* Provides safe interface to systemd service management with:
|
|
5
|
+
* - Command injection prevention
|
|
6
|
+
* - Action and service name validation
|
|
7
|
+
* - Graceful shutdown with configurable timeout
|
|
8
|
+
* - Detailed status parsing
|
|
9
|
+
*
|
|
10
|
+
* @module services/systemd-manager
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Service status information
|
|
14
|
+
*/
|
|
15
|
+
export interface ServiceStatus {
|
|
16
|
+
/** Service name */
|
|
17
|
+
serviceName: string;
|
|
18
|
+
/** Whether service is active */
|
|
19
|
+
active: boolean;
|
|
20
|
+
/** Active state (active, inactive, failed, etc.) */
|
|
21
|
+
activeState: string;
|
|
22
|
+
/** Sub state (running, dead, failed, etc.) */
|
|
23
|
+
subState: string;
|
|
24
|
+
/** Whether service is loaded */
|
|
25
|
+
loaded: boolean;
|
|
26
|
+
/** Whether service is healthy */
|
|
27
|
+
healthy: boolean;
|
|
28
|
+
/** Main process PID (null if not running) */
|
|
29
|
+
pid: number | null;
|
|
30
|
+
/** Memory usage (formatted string) */
|
|
31
|
+
memory?: string;
|
|
32
|
+
/** Number of restarts */
|
|
33
|
+
restarts?: number;
|
|
34
|
+
/** Uptime (formatted string) */
|
|
35
|
+
uptime?: string;
|
|
36
|
+
/** Start timestamp */
|
|
37
|
+
startTime?: Date;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Service operation result
|
|
41
|
+
*/
|
|
42
|
+
export interface ServiceOperationResult {
|
|
43
|
+
/** Whether operation succeeded */
|
|
44
|
+
success: boolean;
|
|
45
|
+
/** Operation type */
|
|
46
|
+
operation: string;
|
|
47
|
+
/** Service name */
|
|
48
|
+
serviceName: string;
|
|
49
|
+
/** Exit code */
|
|
50
|
+
exitCode: number;
|
|
51
|
+
/** Duration in milliseconds */
|
|
52
|
+
duration: number;
|
|
53
|
+
/** Downtime in milliseconds (for restart) */
|
|
54
|
+
downtime?: number;
|
|
55
|
+
/** Standard output */
|
|
56
|
+
stdout?: string;
|
|
57
|
+
/** Standard error */
|
|
58
|
+
stderr?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Systemctl execution options
|
|
62
|
+
*/
|
|
63
|
+
export interface SystemctlOptions {
|
|
64
|
+
/** Timeout in milliseconds */
|
|
65
|
+
timeout?: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Restart options
|
|
69
|
+
*/
|
|
70
|
+
export interface RestartOptions {
|
|
71
|
+
/** Graceful shutdown timeout in milliseconds */
|
|
72
|
+
gracefulTimeout?: number;
|
|
73
|
+
/** Whether to wait for active connections to complete */
|
|
74
|
+
waitForConnections?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* SystemdManager - Safe systemctl wrapper
|
|
78
|
+
*/
|
|
79
|
+
export declare class SystemdManager {
|
|
80
|
+
private serviceName;
|
|
81
|
+
/** Valid systemctl actions (whitelist) */
|
|
82
|
+
private static readonly VALID_ACTIONS;
|
|
83
|
+
/**
|
|
84
|
+
* Create a new SystemdManager
|
|
85
|
+
*
|
|
86
|
+
* @param serviceName - Service name to manage
|
|
87
|
+
* @throws Error if service name is invalid
|
|
88
|
+
*/
|
|
89
|
+
constructor(serviceName: string);
|
|
90
|
+
/**
|
|
91
|
+
* Validate service name
|
|
92
|
+
*
|
|
93
|
+
* @param name - Service name to validate
|
|
94
|
+
* @throws Error if service name is invalid
|
|
95
|
+
*/
|
|
96
|
+
private validateServiceName;
|
|
97
|
+
/**
|
|
98
|
+
* Validate systemctl action
|
|
99
|
+
*
|
|
100
|
+
* @param action - Action to validate
|
|
101
|
+
* @throws Error if action is invalid
|
|
102
|
+
*/
|
|
103
|
+
validateAction(action: string): void;
|
|
104
|
+
/**
|
|
105
|
+
* Execute systemctl command
|
|
106
|
+
*
|
|
107
|
+
* @param action - Systemctl action to execute
|
|
108
|
+
* @param options - Execution options
|
|
109
|
+
* @returns Command output
|
|
110
|
+
*/
|
|
111
|
+
executeSystemctl(action: string, options?: SystemctlOptions): Promise<string>;
|
|
112
|
+
/**
|
|
113
|
+
* Parse systemd error messages and provide suggestions
|
|
114
|
+
*
|
|
115
|
+
* @param errorOutput - Error output from systemctl
|
|
116
|
+
* @param action - Action that was attempted
|
|
117
|
+
* @returns User-friendly error message with suggestions
|
|
118
|
+
*/
|
|
119
|
+
private parseSystemdError;
|
|
120
|
+
/**
|
|
121
|
+
* Parse systemctl show output
|
|
122
|
+
*
|
|
123
|
+
* @param output - Raw output from systemctl show
|
|
124
|
+
* @returns Parsed service status
|
|
125
|
+
*/
|
|
126
|
+
parseSystemdShow(output: string): ServiceStatus;
|
|
127
|
+
/**
|
|
128
|
+
* Format bytes to human-readable string
|
|
129
|
+
*
|
|
130
|
+
* @param bytes - Number of bytes
|
|
131
|
+
* @returns Formatted string (e.g., "45.2 MB")
|
|
132
|
+
*/
|
|
133
|
+
private formatBytes;
|
|
134
|
+
/**
|
|
135
|
+
* Format uptime in milliseconds to human-readable string
|
|
136
|
+
*
|
|
137
|
+
* @param ms - Uptime in milliseconds
|
|
138
|
+
* @returns Formatted string (e.g., "2小时15分钟")
|
|
139
|
+
*/
|
|
140
|
+
private formatUptime;
|
|
141
|
+
/**
|
|
142
|
+
* Get service status
|
|
143
|
+
*
|
|
144
|
+
* @returns Service status information
|
|
145
|
+
*/
|
|
146
|
+
getStatus(): Promise<ServiceStatus>;
|
|
147
|
+
/**
|
|
148
|
+
* Start service
|
|
149
|
+
*
|
|
150
|
+
* @returns Operation result
|
|
151
|
+
*/
|
|
152
|
+
start(): Promise<ServiceOperationResult>;
|
|
153
|
+
/**
|
|
154
|
+
* Stop service
|
|
155
|
+
*
|
|
156
|
+
* @returns Operation result
|
|
157
|
+
*/
|
|
158
|
+
stop(): Promise<ServiceOperationResult>;
|
|
159
|
+
/**
|
|
160
|
+
* Restart service with graceful shutdown
|
|
161
|
+
*
|
|
162
|
+
* @param options - Restart options
|
|
163
|
+
* @returns Operation result
|
|
164
|
+
*/
|
|
165
|
+
restart(options?: RestartOptions): Promise<ServiceOperationResult>;
|
|
166
|
+
/**
|
|
167
|
+
* Wait for service to be ready after start/restart
|
|
168
|
+
*
|
|
169
|
+
* @param maxWait - Maximum time to wait in milliseconds
|
|
170
|
+
*/
|
|
171
|
+
private waitForServiceReady;
|
|
172
|
+
/**
|
|
173
|
+
* Check if running as root
|
|
174
|
+
*
|
|
175
|
+
* @returns True if running as root
|
|
176
|
+
*/
|
|
177
|
+
isRoot(): boolean;
|
|
178
|
+
/**
|
|
179
|
+
* Check if sudo is available
|
|
180
|
+
*
|
|
181
|
+
* @returns True if sudo is available
|
|
182
|
+
*/
|
|
183
|
+
canUseSudo(): Promise<boolean>;
|
|
184
|
+
/**
|
|
185
|
+
* Get permission warning message
|
|
186
|
+
*
|
|
187
|
+
* @returns Warning message if not running with sufficient permissions
|
|
188
|
+
*/
|
|
189
|
+
getPermissionWarning(): string | undefined;
|
|
190
|
+
/**
|
|
191
|
+
* Estimate downtime for restart operation
|
|
192
|
+
*
|
|
193
|
+
* @returns Estimated downtime in milliseconds
|
|
194
|
+
*/
|
|
195
|
+
estimateDowntime(): number;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=systemd-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemd-manager.d.ts","sourceRoot":"","sources":["../../src/services/systemd-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SystemdManager - Service Management via systemctl
|
|
4
|
+
*
|
|
5
|
+
* Provides safe interface to systemd service management with:
|
|
6
|
+
* - Command injection prevention
|
|
7
|
+
* - Action and service name validation
|
|
8
|
+
* - Graceful shutdown with configurable timeout
|
|
9
|
+
* - Detailed status parsing
|
|
10
|
+
*
|
|
11
|
+
* @module services/systemd-manager
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.SystemdManager = void 0;
|
|
15
|
+
const child_process_1 = require("child_process");
|
|
16
|
+
const timeouts_1 = require("../constants/timeouts");
|
|
17
|
+
/**
|
|
18
|
+
* SystemdManager - Safe systemctl wrapper
|
|
19
|
+
*/
|
|
20
|
+
class SystemdManager {
|
|
21
|
+
/**
|
|
22
|
+
* Create a new SystemdManager
|
|
23
|
+
*
|
|
24
|
+
* @param serviceName - Service name to manage
|
|
25
|
+
* @throws Error if service name is invalid
|
|
26
|
+
*/
|
|
27
|
+
constructor(serviceName) {
|
|
28
|
+
this.validateServiceName(serviceName);
|
|
29
|
+
this.serviceName = serviceName;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Validate service name
|
|
33
|
+
*
|
|
34
|
+
* @param name - Service name to validate
|
|
35
|
+
* @throws Error if service name is invalid
|
|
36
|
+
*/
|
|
37
|
+
validateServiceName(name) {
|
|
38
|
+
// Prevent empty names
|
|
39
|
+
if (!name || name.trim().length === 0) {
|
|
40
|
+
throw new Error('Service name cannot be empty');
|
|
41
|
+
}
|
|
42
|
+
// Prevent path traversal attempts
|
|
43
|
+
if (name.includes('/') || name.includes('\\') || name.includes('..')) {
|
|
44
|
+
throw new Error(`Invalid service name: ${name} (path traversal detected)`);
|
|
45
|
+
}
|
|
46
|
+
// Prevent command injection attempts
|
|
47
|
+
const dangerousChars = /[;&|`$()]/;
|
|
48
|
+
if (dangerousChars.test(name)) {
|
|
49
|
+
throw new Error(`Invalid service name: ${name} (potentially dangerous characters detected)`);
|
|
50
|
+
}
|
|
51
|
+
// Only allow alphanumeric, dash, underscore
|
|
52
|
+
const validPattern = /^[a-zA-Z0-9_-]+$/;
|
|
53
|
+
if (!validPattern.test(name)) {
|
|
54
|
+
throw new Error(`Invalid service name: ${name} (only alphanumeric, dash, and underscore allowed)`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Validate systemctl action
|
|
59
|
+
*
|
|
60
|
+
* @param action - Action to validate
|
|
61
|
+
* @throws Error if action is invalid
|
|
62
|
+
*/
|
|
63
|
+
validateAction(action) {
|
|
64
|
+
if (!SystemdManager.VALID_ACTIONS.includes(action)) {
|
|
65
|
+
throw new Error(`Invalid systemctl action: ${action} (must be one of: ${SystemdManager.VALID_ACTIONS.join(', ')})`);
|
|
66
|
+
}
|
|
67
|
+
// Extra paranoia: check for command injection attempts
|
|
68
|
+
const dangerousChars = /[;&|`$()]/;
|
|
69
|
+
if (dangerousChars.test(action)) {
|
|
70
|
+
throw new Error(`Invalid systemctl action: ${action} (potentially dangerous characters detected)`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Execute systemctl command
|
|
75
|
+
*
|
|
76
|
+
* @param action - Systemctl action to execute
|
|
77
|
+
* @param options - Execution options
|
|
78
|
+
* @returns Command output
|
|
79
|
+
*/
|
|
80
|
+
async executeSystemctl(action, options) {
|
|
81
|
+
// Validate action to prevent command injection
|
|
82
|
+
this.validateAction(action);
|
|
83
|
+
const timeout = options?.timeout || timeouts_1.TIMEOUTS.SYSTEMCTL_DEFAULT;
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
// Use spawn (not exec) to prevent shell injection
|
|
86
|
+
const child = (0, child_process_1.spawn)('systemctl', [action, this.serviceName], {
|
|
87
|
+
timeout,
|
|
88
|
+
});
|
|
89
|
+
let stdout = '';
|
|
90
|
+
let stderr = '';
|
|
91
|
+
child.stdout?.on('data', (data) => {
|
|
92
|
+
stdout += data.toString();
|
|
93
|
+
});
|
|
94
|
+
child.stderr?.on('data', (data) => {
|
|
95
|
+
stderr += data.toString();
|
|
96
|
+
});
|
|
97
|
+
child.on('close', (code) => {
|
|
98
|
+
if (code === 0) {
|
|
99
|
+
resolve(stdout);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const errorMessage = this.parseSystemdError(stderr || stdout, action);
|
|
103
|
+
reject(new Error(errorMessage));
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
child.on('error', (error) => {
|
|
107
|
+
reject(new Error(`Failed to execute systemctl: ${error.message}`));
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Parse systemd error messages and provide suggestions
|
|
113
|
+
*
|
|
114
|
+
* @param errorOutput - Error output from systemctl
|
|
115
|
+
* @param action - Action that was attempted
|
|
116
|
+
* @returns User-friendly error message with suggestions
|
|
117
|
+
*/
|
|
118
|
+
parseSystemdError(errorOutput, action) {
|
|
119
|
+
const lowerError = errorOutput.toLowerCase();
|
|
120
|
+
// Service not found
|
|
121
|
+
if (lowerError.includes('not found') ||
|
|
122
|
+
lowerError.includes('does not exist') ||
|
|
123
|
+
lowerError.includes('could not be found')) {
|
|
124
|
+
return `服务 '${this.serviceName}' 不存在。请确认服务名称是否正确。`;
|
|
125
|
+
}
|
|
126
|
+
// Permission denied
|
|
127
|
+
if (lowerError.includes('permission denied') ||
|
|
128
|
+
lowerError.includes('access denied') ||
|
|
129
|
+
lowerError.includes('authentication required')) {
|
|
130
|
+
return `权限不足: 无法执行 ${action} 操作。请使用 sudo 或以 root 用户运行。`;
|
|
131
|
+
}
|
|
132
|
+
// Timeout
|
|
133
|
+
if (lowerError.includes('timeout') || lowerError.includes('timed out')) {
|
|
134
|
+
return `操作超时: ${action} 操作未能在规定时间内完成。`;
|
|
135
|
+
}
|
|
136
|
+
// Already running/stopped
|
|
137
|
+
if (action === 'start' &&
|
|
138
|
+
(lowerError.includes('already running') || lowerError.includes('already active'))) {
|
|
139
|
+
return `服务 '${this.serviceName}' 已经在运行中。`;
|
|
140
|
+
}
|
|
141
|
+
if (action === 'stop' &&
|
|
142
|
+
(lowerError.includes('already stopped') || lowerError.includes('inactive'))) {
|
|
143
|
+
return `服务 '${this.serviceName}' 已经停止。`;
|
|
144
|
+
}
|
|
145
|
+
// Generic error with original output
|
|
146
|
+
return `执行 systemctl ${action} 失败: ${errorOutput}`;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Parse systemctl show output
|
|
150
|
+
*
|
|
151
|
+
* @param output - Raw output from systemctl show
|
|
152
|
+
* @returns Parsed service status
|
|
153
|
+
*/
|
|
154
|
+
parseSystemdShow(output) {
|
|
155
|
+
const lines = output.split('\n');
|
|
156
|
+
const props = {};
|
|
157
|
+
// Parse key=value pairs
|
|
158
|
+
for (const line of lines) {
|
|
159
|
+
const trimmed = line.trim();
|
|
160
|
+
if (!trimmed || !trimmed.includes('=')) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const [key, ...valueParts] = trimmed.split('=');
|
|
164
|
+
const value = valueParts.join('='); // Handle values with '=' in them
|
|
165
|
+
props[key] = value;
|
|
166
|
+
}
|
|
167
|
+
// Validate we have at least basic properties
|
|
168
|
+
if (!props.ActiveState && !props.SubState) {
|
|
169
|
+
throw new Error('Invalid systemctl show output: missing required fields (parse error)');
|
|
170
|
+
}
|
|
171
|
+
// Parse active state
|
|
172
|
+
const activeState = props.ActiveState || 'unknown';
|
|
173
|
+
const subState = props.SubState || 'unknown';
|
|
174
|
+
const active = activeState === 'active';
|
|
175
|
+
// Parse loaded state
|
|
176
|
+
const loaded = props.LoadState === 'loaded';
|
|
177
|
+
// Parse PID
|
|
178
|
+
const pidStr = props.MainPID || '0';
|
|
179
|
+
const pid = parseInt(pidStr, 10);
|
|
180
|
+
const pidValue = pid > 0 ? pid : null;
|
|
181
|
+
// Parse memory usage
|
|
182
|
+
const memoryBytes = parseInt(props.MemoryCurrent || '0', 10);
|
|
183
|
+
const memory = this.formatBytes(memoryBytes);
|
|
184
|
+
// Parse restart count
|
|
185
|
+
const restarts = parseInt(props.NRestarts || '0', 10);
|
|
186
|
+
// Parse start time and calculate uptime
|
|
187
|
+
const startTimestamp = props.ExecMainStartTimestamp;
|
|
188
|
+
let uptime;
|
|
189
|
+
let startTime;
|
|
190
|
+
if (startTimestamp && startTimestamp.trim() !== '') {
|
|
191
|
+
try {
|
|
192
|
+
startTime = new Date(startTimestamp);
|
|
193
|
+
const now = Date.now();
|
|
194
|
+
const startMs = startTime.getTime();
|
|
195
|
+
const uptimeMs = now - startMs;
|
|
196
|
+
uptime = this.formatUptime(uptimeMs);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Ignore parse errors
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Determine health
|
|
203
|
+
const healthy = active && subState === 'running';
|
|
204
|
+
return {
|
|
205
|
+
serviceName: this.serviceName,
|
|
206
|
+
active,
|
|
207
|
+
activeState,
|
|
208
|
+
subState,
|
|
209
|
+
loaded,
|
|
210
|
+
healthy,
|
|
211
|
+
pid: pidValue,
|
|
212
|
+
memory,
|
|
213
|
+
restarts,
|
|
214
|
+
uptime,
|
|
215
|
+
startTime,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Format bytes to human-readable string
|
|
220
|
+
*
|
|
221
|
+
* @param bytes - Number of bytes
|
|
222
|
+
* @returns Formatted string (e.g., "45.2 MB")
|
|
223
|
+
*/
|
|
224
|
+
formatBytes(bytes) {
|
|
225
|
+
if (bytes === 0)
|
|
226
|
+
return '0 B';
|
|
227
|
+
const units = ['B', 'KB', 'MB', 'GB'];
|
|
228
|
+
const k = 1024;
|
|
229
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
230
|
+
const value = bytes / Math.pow(k, i);
|
|
231
|
+
return `${value.toFixed(1)} ${units[i]}`;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Format uptime in milliseconds to human-readable string
|
|
235
|
+
*
|
|
236
|
+
* @param ms - Uptime in milliseconds
|
|
237
|
+
* @returns Formatted string (e.g., "2小时15分钟")
|
|
238
|
+
*/
|
|
239
|
+
formatUptime(ms) {
|
|
240
|
+
const seconds = Math.floor(ms / 1000);
|
|
241
|
+
const minutes = Math.floor(seconds / 60);
|
|
242
|
+
const hours = Math.floor(minutes / 60);
|
|
243
|
+
const days = Math.floor(hours / 24);
|
|
244
|
+
if (days > 0) {
|
|
245
|
+
return `${days}天${hours % 24}小时`;
|
|
246
|
+
}
|
|
247
|
+
else if (hours > 0) {
|
|
248
|
+
return `${hours}小时${minutes % 60}分钟`;
|
|
249
|
+
}
|
|
250
|
+
else if (minutes > 0) {
|
|
251
|
+
return `${minutes}分钟`;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
return `${seconds}秒`;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Get service status
|
|
259
|
+
*
|
|
260
|
+
* @returns Service status information
|
|
261
|
+
*/
|
|
262
|
+
async getStatus() {
|
|
263
|
+
const output = await this.executeSystemctl('show');
|
|
264
|
+
return this.parseSystemdShow(output);
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Start service
|
|
268
|
+
*
|
|
269
|
+
* @returns Operation result
|
|
270
|
+
*/
|
|
271
|
+
async start() {
|
|
272
|
+
const startTime = Date.now();
|
|
273
|
+
try {
|
|
274
|
+
const stdout = await this.executeSystemctl('start', {
|
|
275
|
+
timeout: timeouts_1.TIMEOUTS.SERVICE_START,
|
|
276
|
+
});
|
|
277
|
+
const duration = Date.now() - startTime;
|
|
278
|
+
return {
|
|
279
|
+
success: true,
|
|
280
|
+
operation: 'start',
|
|
281
|
+
serviceName: this.serviceName,
|
|
282
|
+
exitCode: 0,
|
|
283
|
+
duration,
|
|
284
|
+
stdout,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
const duration = Date.now() - startTime;
|
|
289
|
+
return {
|
|
290
|
+
success: false,
|
|
291
|
+
operation: 'start',
|
|
292
|
+
serviceName: this.serviceName,
|
|
293
|
+
exitCode: 1,
|
|
294
|
+
duration,
|
|
295
|
+
stderr: error.message,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Stop service
|
|
301
|
+
*
|
|
302
|
+
* @returns Operation result
|
|
303
|
+
*/
|
|
304
|
+
async stop() {
|
|
305
|
+
const startTime = Date.now();
|
|
306
|
+
try {
|
|
307
|
+
const stdout = await this.executeSystemctl('stop', {
|
|
308
|
+
timeout: timeouts_1.TIMEOUTS.SERVICE_STOP,
|
|
309
|
+
});
|
|
310
|
+
const duration = Date.now() - startTime;
|
|
311
|
+
return {
|
|
312
|
+
success: true,
|
|
313
|
+
operation: 'stop',
|
|
314
|
+
serviceName: this.serviceName,
|
|
315
|
+
exitCode: 0,
|
|
316
|
+
duration,
|
|
317
|
+
stdout,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
const duration = Date.now() - startTime;
|
|
322
|
+
return {
|
|
323
|
+
success: false,
|
|
324
|
+
operation: 'stop',
|
|
325
|
+
serviceName: this.serviceName,
|
|
326
|
+
exitCode: 1,
|
|
327
|
+
duration,
|
|
328
|
+
stderr: error.message,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Restart service with graceful shutdown
|
|
334
|
+
*
|
|
335
|
+
* @param options - Restart options
|
|
336
|
+
* @returns Operation result
|
|
337
|
+
*/
|
|
338
|
+
async restart(options) {
|
|
339
|
+
const gracefulTimeout = options?.gracefulTimeout || 10000; // Default 10s (FR-016)
|
|
340
|
+
const restartStartTime = Date.now();
|
|
341
|
+
try {
|
|
342
|
+
// Measure service downtime
|
|
343
|
+
const downtimeStart = Date.now();
|
|
344
|
+
// Use systemctl restart which handles graceful shutdown internally
|
|
345
|
+
const stdout = await this.executeSystemctl('restart', {
|
|
346
|
+
timeout: timeouts_1.TIMEOUTS.SERVICE_RESTART,
|
|
347
|
+
});
|
|
348
|
+
// Wait a moment for service to fully start
|
|
349
|
+
await this.waitForServiceReady(gracefulTimeout);
|
|
350
|
+
const downtimeEnd = Date.now();
|
|
351
|
+
const downtime = downtimeEnd - downtimeStart;
|
|
352
|
+
const duration = Date.now() - restartStartTime;
|
|
353
|
+
return {
|
|
354
|
+
success: true,
|
|
355
|
+
operation: 'restart',
|
|
356
|
+
serviceName: this.serviceName,
|
|
357
|
+
exitCode: 0,
|
|
358
|
+
duration,
|
|
359
|
+
downtime,
|
|
360
|
+
stdout,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
const duration = Date.now() - restartStartTime;
|
|
365
|
+
return {
|
|
366
|
+
success: false,
|
|
367
|
+
operation: 'restart',
|
|
368
|
+
serviceName: this.serviceName,
|
|
369
|
+
exitCode: 1,
|
|
370
|
+
duration,
|
|
371
|
+
stderr: error.message,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Wait for service to be ready after start/restart
|
|
377
|
+
*
|
|
378
|
+
* @param maxWait - Maximum time to wait in milliseconds
|
|
379
|
+
*/
|
|
380
|
+
async waitForServiceReady(maxWait) {
|
|
381
|
+
const startTime = Date.now();
|
|
382
|
+
const pollInterval = 100; // Check every 100ms
|
|
383
|
+
while (Date.now() - startTime < maxWait) {
|
|
384
|
+
try {
|
|
385
|
+
const status = await this.getStatus();
|
|
386
|
+
if (status.active && status.subState === 'running') {
|
|
387
|
+
return; // Service is ready
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
catch {
|
|
391
|
+
// Ignore errors during polling
|
|
392
|
+
}
|
|
393
|
+
// Wait before next poll
|
|
394
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
395
|
+
}
|
|
396
|
+
// If we get here, service didn't become ready in time
|
|
397
|
+
// But don't throw - let caller determine if this is critical
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Check if running as root
|
|
401
|
+
*
|
|
402
|
+
* @returns True if running as root
|
|
403
|
+
*/
|
|
404
|
+
isRoot() {
|
|
405
|
+
return !!(process.getuid && process.getuid() === 0);
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Check if sudo is available
|
|
409
|
+
*
|
|
410
|
+
* @returns True if sudo is available
|
|
411
|
+
*/
|
|
412
|
+
async canUseSudo() {
|
|
413
|
+
return new Promise((resolve) => {
|
|
414
|
+
const child = (0, child_process_1.spawn)('which', ['sudo']);
|
|
415
|
+
child.on('close', (code) => {
|
|
416
|
+
resolve(code === 0);
|
|
417
|
+
});
|
|
418
|
+
child.on('error', () => {
|
|
419
|
+
resolve(false);
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Get permission warning message
|
|
425
|
+
*
|
|
426
|
+
* @returns Warning message if not running with sufficient permissions
|
|
427
|
+
*/
|
|
428
|
+
getPermissionWarning() {
|
|
429
|
+
if (this.isRoot()) {
|
|
430
|
+
return undefined;
|
|
431
|
+
}
|
|
432
|
+
return '当前用户不是 root - 某些操作可能需要 sudo 权限';
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Estimate downtime for restart operation
|
|
436
|
+
*
|
|
437
|
+
* @returns Estimated downtime in milliseconds
|
|
438
|
+
*/
|
|
439
|
+
estimateDowntime() {
|
|
440
|
+
// Estimate based on typical graceful shutdown time
|
|
441
|
+
// Conservative estimate: 5 seconds
|
|
442
|
+
return 5000;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
exports.SystemdManager = SystemdManager;
|
|
446
|
+
/** Valid systemctl actions (whitelist) */
|
|
447
|
+
SystemdManager.VALID_ACTIONS = [
|
|
448
|
+
'start',
|
|
449
|
+
'stop',
|
|
450
|
+
'restart',
|
|
451
|
+
'status',
|
|
452
|
+
'enable',
|
|
453
|
+
'disable',
|
|
454
|
+
'is-active',
|
|
455
|
+
'is-enabled',
|
|
456
|
+
'show',
|
|
457
|
+
];
|
|
458
|
+
//# sourceMappingURL=systemd-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemd-manager.js","sourceRoot":"","sources":["../../src/services/systemd-manager.ts"],"names":[],"mappings":"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"}
|