bs9 1.4.0 → 1.4.1
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/package.json +1 -1
- package/src/commands/status.ts +105 -19
package/package.json
CHANGED
package/src/commands/status.ts
CHANGED
|
@@ -27,6 +27,7 @@ interface ServiceStatus {
|
|
|
27
27
|
memory?: string;
|
|
28
28
|
uptime?: string;
|
|
29
29
|
tasks?: string;
|
|
30
|
+
pid?: string;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
export async function statusCommand(options: StatusOptions): Promise<void> {
|
|
@@ -93,20 +94,46 @@ async function getLinuxServices(): Promise<ServiceStatus[]> {
|
|
|
93
94
|
description,
|
|
94
95
|
};
|
|
95
96
|
|
|
96
|
-
// Get additional metrics
|
|
97
|
+
// Get additional metrics with better error handling
|
|
97
98
|
try {
|
|
98
|
-
|
|
99
|
+
// Get comprehensive service information
|
|
100
|
+
const showOutput = execSync(`systemctl --user show ${name}`, { encoding: "utf-8" });
|
|
101
|
+
|
|
102
|
+
// Extract CPU usage
|
|
99
103
|
const cpuMatch = showOutput.match(/CPUUsageNSec=(\d+)/);
|
|
104
|
+
if (cpuMatch) {
|
|
105
|
+
status.cpu = formatCPU(Number(cpuMatch[1]));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Extract memory usage
|
|
100
109
|
const memMatch = showOutput.match(/MemoryCurrent=(\d+)/);
|
|
110
|
+
if (memMatch) {
|
|
111
|
+
const memoryBytes = Number(memMatch[1]);
|
|
112
|
+
status.memory = formatMemory(memoryBytes);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Extract startup time and calculate uptime
|
|
101
116
|
const timeMatch = showOutput.match(/ActiveEnterTimestamp=(.+)/);
|
|
117
|
+
if (timeMatch) {
|
|
118
|
+
status.uptime = formatUptime(timeMatch[1]);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Extract task count
|
|
102
122
|
const tasksMatch = showOutput.match(/TasksCurrent=(\d+)/);
|
|
123
|
+
if (tasksMatch) {
|
|
124
|
+
status.tasks = tasksMatch[1];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Get process ID for additional info
|
|
128
|
+
const pidMatch = showOutput.match(/MainPID=(\d+)/);
|
|
129
|
+
if (pidMatch && pidMatch[1] !== "0") {
|
|
130
|
+
// We could get more detailed process info here if needed
|
|
131
|
+
status.pid = pidMatch[1];
|
|
132
|
+
}
|
|
103
133
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (tasksMatch) status.tasks = tasksMatch[1];
|
|
108
|
-
} catch {
|
|
109
|
-
// Metrics might not be available
|
|
134
|
+
} catch (metricsError: any) {
|
|
135
|
+
// If metrics fail, at least we have basic status
|
|
136
|
+
console.warn(`⚠️ Could not get metrics for ${name}: ${metricsError?.message || metricsError}`);
|
|
110
137
|
}
|
|
111
138
|
|
|
112
139
|
services.push(status);
|
|
@@ -145,25 +172,84 @@ async function getWindowsServices(): Promise<ServiceStatus[]> {
|
|
|
145
172
|
}
|
|
146
173
|
|
|
147
174
|
function displayServices(services: ServiceStatus[]): void {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
175
|
+
if (services.length === 0) {
|
|
176
|
+
console.log("📋 No BS9 services found");
|
|
177
|
+
console.log("💡 Use 'bs9 start <file>' to create a service");
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Header with better formatting
|
|
182
|
+
console.log(`${"SERVICE".padEnd(18)} ${"STATUS".padEnd(15)} ${"CPU".padEnd(10)} ${"MEMORY".padEnd(12)} ${"UPTIME".padEnd(12)} ${"TASKS".padEnd(8)} DESCRIPTION`);
|
|
183
|
+
console.log("─".repeat(100));
|
|
151
184
|
|
|
152
|
-
|
|
153
|
-
|
|
185
|
+
// Sort services by status (running first, then by name)
|
|
186
|
+
const sortedServices = services.sort((a, b) => {
|
|
187
|
+
const aRunning = a.active === "active" && a.sub === "running";
|
|
188
|
+
const bRunning = b.active === "active" && b.sub === "running";
|
|
189
|
+
if (aRunning !== bRunning) return bRunning ? 1 : -1;
|
|
190
|
+
return a.name.localeCompare(b.name);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
for (const svc of sortedServices) {
|
|
194
|
+
// Better status formatting with colors/indicators
|
|
195
|
+
let statusIndicator = "";
|
|
196
|
+
let status = `${svc.active}/${svc.sub}`;
|
|
197
|
+
|
|
198
|
+
if (svc.active === "active" && svc.sub === "running") {
|
|
199
|
+
statusIndicator = "✅";
|
|
200
|
+
status = "running";
|
|
201
|
+
} else if (svc.active === "activating" && svc.sub.includes("auto-restart")) {
|
|
202
|
+
statusIndicator = "🔄";
|
|
203
|
+
status = "restarting";
|
|
204
|
+
} else if (svc.active === "failed" || svc.sub === "failed") {
|
|
205
|
+
statusIndicator = "❌";
|
|
206
|
+
status = "failed";
|
|
207
|
+
} else if (svc.active === "inactive") {
|
|
208
|
+
statusIndicator = "⏸️";
|
|
209
|
+
status = "stopped";
|
|
210
|
+
} else {
|
|
211
|
+
statusIndicator = "⚠️";
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const displayStatus = `${statusIndicator} ${status}`;
|
|
215
|
+
|
|
154
216
|
console.log(
|
|
155
|
-
`${svc.name.padEnd(
|
|
217
|
+
`${svc.name.padEnd(18)} ${displayStatus.padEnd(15)} ${(svc.cpu || "-").padEnd(10)} ${(svc.memory || "-").padEnd(12)} ${(svc.uptime || "-").padEnd(12)} ${(svc.tasks || "-").padEnd(8)} ${svc.description}`
|
|
156
218
|
);
|
|
157
219
|
}
|
|
158
220
|
|
|
159
|
-
|
|
221
|
+
// Enhanced summary
|
|
222
|
+
console.log("\n📊 Service Summary:");
|
|
160
223
|
const totalServices = services.length;
|
|
161
|
-
const runningServices = services.filter(s => s.active === "active").length;
|
|
224
|
+
const runningServices = services.filter(s => s.active === "active" && s.sub === "running").length;
|
|
225
|
+
const failedServices = services.filter(s => s.active === "failed" || s.sub === "failed").length;
|
|
226
|
+
const restartingServices = services.filter(s => s.active === "activating" && s.sub.includes("auto-restart")).length;
|
|
162
227
|
const totalMemory = services.reduce((sum, s) => sum + (s.memory ? parseMemory(s.memory) : 0), 0);
|
|
163
228
|
|
|
164
|
-
console.log(`
|
|
165
|
-
console.log(`
|
|
166
|
-
console.log(`
|
|
229
|
+
console.log(` 📈 Status: ${runningServices} running, ${failedServices} failed, ${restartingServices} restarting`);
|
|
230
|
+
console.log(` 📦 Total: ${runningServices}/${totalServices} services running`);
|
|
231
|
+
console.log(` 💾 Memory: ${formatMemory(totalMemory)}`);
|
|
232
|
+
console.log(` 🕒 Last updated: ${new Date().toLocaleString()}`);
|
|
233
|
+
|
|
234
|
+
// Show failed services details
|
|
235
|
+
if (failedServices > 0) {
|
|
236
|
+
console.log("\n❌ Failed Services:");
|
|
237
|
+
const failed = services.filter(s => s.active === "failed" || s.sub === "failed");
|
|
238
|
+
for (const svc of failed) {
|
|
239
|
+
console.log(` • ${svc.name}: ${svc.active}/${svc.sub}`);
|
|
240
|
+
console.log(` 💡 Try: bs9 logs ${svc.name} --tail 20`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Show restarting services details
|
|
245
|
+
if (restartingServices > 0) {
|
|
246
|
+
console.log("\n🔄 Restarting Services:");
|
|
247
|
+
const restarting = services.filter(s => s.active === "activating" && s.sub.includes("auto-restart"));
|
|
248
|
+
for (const svc of restarting) {
|
|
249
|
+
console.log(` • ${svc.name}: ${svc.active}/${svc.sub}`);
|
|
250
|
+
console.log(` 💡 Try: bs9 logs ${svc.name} --tail 20`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
167
253
|
}
|
|
168
254
|
|
|
169
255
|
function formatCPU(nsec: number): string {
|