style: configure deno fmt to use single quotes
All checks were successful
CI / Build All Platforms (Tag/Main only) (push) Has been skipped
CI / Type Check & Lint (push) Successful in 6s
CI / Build Test (Current Platform) (push) Successful in 6s

- Add singleQuote: true to deno.json fmt configuration
- Reformat all files with single quotes using deno fmt
This commit is contained in:
2025-10-19 13:14:18 +00:00
parent b935087d50
commit 071ded9c41
24 changed files with 1094 additions and 672 deletions

View File

@@ -1,8 +1,8 @@
import process from 'node:process';
import * as fs from "node:fs";
import * as path from "node:path";
import { exec, execFile } from "node:child_process";
import { promisify } from "node:util";
import * as fs from 'node:fs';
import * as path from 'node:path';
import { exec, execFile } from 'node:child_process';
import { promisify } from 'node:util';
import { NupstSnmp } from './snmp/manager.ts';
import type { ISnmpConfig } from './snmp/types.ts';
import { logger } from './logger.ts';
@@ -55,7 +55,7 @@ export interface INupstConfig {
groups: IGroupConfig[];
/** Check interval in milliseconds */
checkInterval: number;
// Legacy fields for backward compatibility
/** SNMP configuration settings (legacy) */
snmp?: ISnmpConfig;
@@ -109,14 +109,14 @@ export class NupstDaemon {
privProtocol: 'AES',
privKey: '',
// UPS model for OID selection
upsModel: 'cyberpower'
upsModel: 'cyberpower',
},
thresholds: {
battery: 60, // Shutdown when battery below 60%
runtime: 20, // Shutdown when runtime below 20 minutes
},
groups: []
}
groups: [],
},
],
groups: [],
checkInterval: 30000, // Check every 30 seconds
@@ -126,7 +126,7 @@ export class NupstDaemon {
private snmp: NupstSnmp;
private isRunning: boolean = false;
private upsStatus: Map<string, IUpsStatus> = new Map();
/**
* Create a new daemon instance with the given SNMP manager
*/
@@ -148,11 +148,11 @@ export class NupstDaemon {
this.logConfigError(errorMsg);
throw new Error(errorMsg);
}
// Read and parse config
const configData = fs.readFileSync(this.CONFIG_PATH, 'utf8');
const parsedConfig = JSON.parse(configData);
// Handle legacy configuration format
if (!parsedConfig.upsDevices && parsedConfig.snmp) {
// Convert legacy format to new format
@@ -163,28 +163,32 @@ export class NupstDaemon {
name: 'Default UPS',
snmp: parsedConfig.snmp,
thresholds: parsedConfig.thresholds,
groups: []
}
groups: [],
},
],
groups: [],
checkInterval: parsedConfig.checkInterval
checkInterval: parsedConfig.checkInterval,
};
logger.log('Legacy configuration format detected. Converting to multi-UPS format.');
// Save the new format
await this.saveConfig(this.config);
} else {
this.config = parsedConfig;
}
return this.config;
} catch (error) {
if (error instanceof Error && error.message && error.message.includes('No configuration found')) {
if (
error instanceof Error && error.message && error.message.includes('No configuration found')
) {
throw error; // Re-throw the no configuration error
}
this.logConfigError(`Error loading configuration: ${error instanceof Error ? error.message : String(error)}`);
this.logConfigError(
`Error loading configuration: ${error instanceof Error ? error.message : String(error)}`,
);
throw new Error('Failed to load configuration');
}
}
@@ -200,7 +204,7 @@ export class NupstDaemon {
}
fs.writeFileSync(this.CONFIG_PATH, JSON.stringify(config, null, 2));
this.config = config;
console.log('┌─ Configuration Saved ─────────────────────┐');
console.log(`│ Location: ${this.CONFIG_PATH}`);
console.log('└──────────────────────────────────────────┘');
@@ -215,7 +219,7 @@ export class NupstDaemon {
private logConfigError(message: string): void {
console.error('┌─ Configuration Error ─────────────────────┐');
console.error(`${message}`);
console.error('│ Please run \'nupst setup\' first to create a configuration.');
console.error("│ Please run 'nupst setup' first to create a configuration.");
console.error('└───────────────────────────────────────────┘');
}
@@ -225,7 +229,7 @@ export class NupstDaemon {
public getConfig(): INupstConfig {
return this.config;
}
/**
* Get the SNMP instance
*/
@@ -243,15 +247,15 @@ export class NupstDaemon {
}
logger.log('Starting NUPST daemon...');
try {
// Load configuration - this will throw an error if config doesn't exist
await this.loadConfig();
this.logConfigLoaded();
// Log version information
this.snmp.getNupst().logVersionInfo(false); // Don't check for updates immediately on startup
// Check for updates in the background
this.snmp.getNupst().checkForUpdates().then((updateAvailable: boolean) => {
if (updateAvailable) {
@@ -264,16 +268,18 @@ export class NupstDaemon {
logger.logBoxEnd();
}
}).catch(() => {}); // Ignore errors checking for updates
// Initialize UPS status tracking
this.initializeUpsStatus();
// Start UPS monitoring
this.isRunning = true;
await this.monitor();
} catch (error) {
this.isRunning = false;
logger.error(`Daemon failed to start: ${error instanceof Error ? error.message : String(error)}`);
logger.error(
`Daemon failed to start: ${error instanceof Error ? error.message : String(error)}`,
);
process.exit(1); // Exit with error
}
}
@@ -283,7 +289,7 @@ export class NupstDaemon {
*/
private initializeUpsStatus(): void {
this.upsStatus.clear();
if (this.config.upsDevices && this.config.upsDevices.length > 0) {
for (const ups of this.config.upsDevices) {
this.upsStatus.set(ups.id, {
@@ -293,10 +299,10 @@ export class NupstDaemon {
batteryCapacity: 100,
batteryRuntime: 999, // High value as default
lastStatusChange: Date.now(),
lastCheckTime: 0
lastCheckTime: 0,
});
}
logger.log(`Initialized status tracking for ${this.config.upsDevices.length} UPS devices`);
} else {
logger.error('No UPS devices found in configuration');
@@ -309,7 +315,7 @@ export class NupstDaemon {
private logConfigLoaded(): void {
const boxWidth = 50;
logger.logBoxTitle('Configuration Loaded', boxWidth);
if (this.config.upsDevices && this.config.upsDevices.length > 0) {
logger.logBoxLine(`UPS Devices: ${this.config.upsDevices.length}`);
for (const ups of this.config.upsDevices) {
@@ -318,7 +324,7 @@ export class NupstDaemon {
} else {
logger.logBoxLine('No UPS devices configured');
}
if (this.config.groups && this.config.groups.length > 0) {
logger.logBoxLine(`Groups: ${this.config.groups.length}`);
for (const group of this.config.groups) {
@@ -327,7 +333,7 @@ export class NupstDaemon {
} else {
logger.logBoxLine('No Groups configured');
}
logger.logBoxLine(`Check Interval: ${this.config.checkInterval / 1000} seconds`);
logger.logBoxEnd();
}
@@ -345,43 +351,45 @@ export class NupstDaemon {
*/
private async monitor(): Promise<void> {
logger.log('Starting UPS monitoring...');
if (!this.config.upsDevices || this.config.upsDevices.length === 0) {
logger.error('No UPS devices found in configuration. Monitoring stopped.');
this.isRunning = false;
return;
}
let lastLogTime = 0; // Track when we last logged status
const LOG_INTERVAL = 5 * 60 * 1000; // Log at least every 5 minutes (300000ms)
// Monitor continuously
while (this.isRunning) {
try {
// Check all UPS devices
await this.checkAllUpsDevices();
// Log periodic status update
const currentTime = Date.now();
if (currentTime - lastLogTime >= LOG_INTERVAL) {
this.logAllUpsStatus();
lastLogTime = currentTime;
}
// Check if shutdown is required based on group configurations
await this.evaluateGroupShutdownConditions();
// Wait before next check
await this.sleep(this.config.checkInterval);
} catch (error) {
logger.error(`Error during UPS monitoring: ${error instanceof Error ? error.message : String(error)}`);
logger.error(
`Error during UPS monitoring: ${error instanceof Error ? error.message : String(error)}`,
);
await this.sleep(this.config.checkInterval);
}
}
logger.log('UPS monitoring stopped');
}
/**
* Check status of all UPS devices
*/
@@ -398,14 +406,14 @@ export class NupstDaemon {
batteryCapacity: 100,
batteryRuntime: 999,
lastStatusChange: Date.now(),
lastCheckTime: 0
lastCheckTime: 0,
});
}
// Check UPS status
const status = await this.snmp.getUpsStatus(ups.snmp);
const currentTime = Date.now();
// Get the current status from the map
const currentStatus = this.upsStatus.get(ups.id);
@@ -417,7 +425,7 @@ export class NupstDaemon {
batteryCapacity: status.batteryCapacity,
batteryRuntime: status.batteryRuntime,
lastCheckTime: currentTime,
lastStatusChange: currentStatus?.lastStatusChange || currentTime
lastStatusChange: currentStatus?.lastStatusChange || currentTime,
};
// Check if power status changed
@@ -432,11 +440,15 @@ export class NupstDaemon {
// Update the status in the map
this.upsStatus.set(ups.id, updatedStatus);
} catch (error) {
logger.error(`Error checking UPS ${ups.name} (${ups.id}): ${error instanceof Error ? error.message : String(error)}`);
logger.error(
`Error checking UPS ${ups.name} (${ups.id}): ${
error instanceof Error ? error.message : String(error)
}`,
);
}
}
}
/**
* Log status of all UPS devices
*/
@@ -446,17 +458,19 @@ export class NupstDaemon {
logger.logBoxTitle('Periodic Status Update', boxWidth);
logger.logBoxLine(`Timestamp: ${timestamp}`);
logger.logBoxLine('');
for (const [id, status] of this.upsStatus.entries()) {
logger.logBoxLine(`UPS: ${status.name} (${id})`);
logger.logBoxLine(` Power Status: ${status.powerStatus}`);
logger.logBoxLine(` Battery: ${status.batteryCapacity}% | Runtime: ${status.batteryRuntime} min`);
logger.logBoxLine(
` Battery: ${status.batteryCapacity}% | Runtime: ${status.batteryRuntime} min`,
);
logger.logBoxLine('');
}
logger.logBoxEnd();
}
/**
* Evaluate if shutdown is required based on group configurations
*/
@@ -466,7 +480,7 @@ export class NupstDaemon {
for (const [id, status] of this.upsStatus.entries()) {
if (status.powerStatus === 'onBattery') {
// Find the UPS config
const ups = this.config.upsDevices.find(u => u.id === id);
const ups = this.config.upsDevices.find((u) => u.id === id);
if (ups) {
await this.evaluateUpsShutdownCondition(ups, status);
}
@@ -474,19 +488,19 @@ export class NupstDaemon {
}
return;
}
// Evaluate each group
for (const group of this.config.groups) {
// Find all UPS devices in this group
const upsDevicesInGroup = this.config.upsDevices.filter(ups =>
const upsDevicesInGroup = this.config.upsDevices.filter((ups) =>
ups.groups && ups.groups.includes(group.id)
);
if (upsDevicesInGroup.length === 0) {
// No UPS devices in this group
continue;
}
if (group.mode === 'redundant') {
// Redundant mode: only shutdown if ALL UPS devices in the group are in critical condition
await this.evaluateRedundantGroup(group, upsDevicesInGroup);
@@ -496,72 +510,90 @@ export class NupstDaemon {
}
}
}
/**
* Evaluate a redundant group for shutdown conditions
* In redundant mode, we only shut down if ALL UPS devices are in critical condition
*/
private async evaluateRedundantGroup(group: IGroupConfig, upsDevices: IUpsConfig[]): Promise<void> {
private async evaluateRedundantGroup(
group: IGroupConfig,
upsDevices: IUpsConfig[],
): Promise<void> {
// Count UPS devices on battery and in critical condition
let upsOnBattery = 0;
let upsInCriticalCondition = 0;
for (const ups of upsDevices) {
const status = this.upsStatus.get(ups.id);
if (!status) continue;
if (status.powerStatus === 'onBattery') {
upsOnBattery++;
// Check if this UPS is in critical condition
if (status.batteryCapacity < ups.thresholds.battery ||
status.batteryRuntime < ups.thresholds.runtime) {
if (
status.batteryCapacity < ups.thresholds.battery ||
status.batteryRuntime < ups.thresholds.runtime
) {
upsInCriticalCondition++;
}
}
}
// All UPS devices must be online for a redundant group to be considered healthy
const allUpsCount = upsDevices.length;
// If all UPS are on battery and in critical condition, shutdown
if (upsOnBattery === allUpsCount && upsInCriticalCondition === allUpsCount) {
logger.logBoxTitle(`Group Shutdown Required: ${group.name}`, 50);
logger.logBoxLine(`Mode: Redundant`);
logger.logBoxLine(`All ${allUpsCount} UPS devices in critical condition`);
logger.logBoxEnd();
await this.initiateShutdown(`All UPS devices in redundant group "${group.name}" in critical condition`);
await this.initiateShutdown(
`All UPS devices in redundant group "${group.name}" in critical condition`,
);
}
}
/**
* Evaluate a non-redundant group for shutdown conditions
* In non-redundant mode, we shut down if ANY UPS device is in critical condition
*/
private async evaluateNonRedundantGroup(group: IGroupConfig, upsDevices: IUpsConfig[]): Promise<void> {
private async evaluateNonRedundantGroup(
group: IGroupConfig,
upsDevices: IUpsConfig[],
): Promise<void> {
for (const ups of upsDevices) {
const status = this.upsStatus.get(ups.id);
if (!status) continue;
if (status.powerStatus === 'onBattery') {
// Check if this UPS is in critical condition
if (status.batteryCapacity < ups.thresholds.battery ||
status.batteryRuntime < ups.thresholds.runtime) {
if (
status.batteryCapacity < ups.thresholds.battery ||
status.batteryRuntime < ups.thresholds.runtime
) {
logger.logBoxTitle(`Group Shutdown Required: ${group.name}`, 50);
logger.logBoxLine(`Mode: Non-Redundant`);
logger.logBoxLine(`UPS ${ups.name} in critical condition`);
logger.logBoxLine(`Battery: ${status.batteryCapacity}% (threshold: ${ups.thresholds.battery}%)`);
logger.logBoxLine(`Runtime: ${status.batteryRuntime} min (threshold: ${ups.thresholds.runtime} min)`);
logger.logBoxLine(
`Battery: ${status.batteryCapacity}% (threshold: ${ups.thresholds.battery}%)`,
);
logger.logBoxLine(
`Runtime: ${status.batteryRuntime} min (threshold: ${ups.thresholds.runtime} min)`,
);
logger.logBoxEnd();
await this.initiateShutdown(`UPS "${ups.name}" in non-redundant group "${group.name}" in critical condition`);
await this.initiateShutdown(
`UPS "${ups.name}" in non-redundant group "${group.name}" in critical condition`,
);
return; // Exit after initiating shutdown
}
}
}
}
/**
* Evaluate an individual UPS for shutdown conditions
*/
@@ -570,38 +602,44 @@ export class NupstDaemon {
if (ups.groups && ups.groups.length > 0) {
return;
}
// Check threshold conditions
if (status.batteryCapacity < ups.thresholds.battery ||
status.batteryRuntime < ups.thresholds.runtime) {
if (
status.batteryCapacity < ups.thresholds.battery ||
status.batteryRuntime < ups.thresholds.runtime
) {
logger.logBoxTitle(`UPS Shutdown Required: ${ups.name}`, 50);
logger.logBoxLine(`Battery: ${status.batteryCapacity}% (threshold: ${ups.thresholds.battery}%)`);
logger.logBoxLine(`Runtime: ${status.batteryRuntime} min (threshold: ${ups.thresholds.runtime} min)`);
logger.logBoxLine(
`Battery: ${status.batteryCapacity}% (threshold: ${ups.thresholds.battery}%)`,
);
logger.logBoxLine(
`Runtime: ${status.batteryRuntime} min (threshold: ${ups.thresholds.runtime} min)`,
);
logger.logBoxEnd();
await this.initiateShutdown(`UPS "${ups.name}" battery or runtime below threshold`);
}
}
/**
* Initiate system shutdown with UPS monitoring during shutdown
* @param reason Reason for shutdown
*/
public async initiateShutdown(reason: string): Promise<void> {
logger.log(`Initiating system shutdown due to: ${reason}`);
// Set a longer delay for shutdown to allow VMs and services to close
const shutdownDelayMinutes = 5;
try {
// Find shutdown command in common system paths
const shutdownPaths = [
'/sbin/shutdown',
'/usr/sbin/shutdown',
'/bin/shutdown',
'/usr/bin/shutdown'
'/usr/bin/shutdown',
];
let shutdownCmd = '';
for (const path of shutdownPaths) {
try {
@@ -614,14 +652,16 @@ export class NupstDaemon {
// Continue checking other paths
}
}
if (shutdownCmd) {
// Execute shutdown command with delay to allow for VM graceful shutdown
logger.log(`Executing: ${shutdownCmd} -h +${shutdownDelayMinutes} "UPS battery critical..."`);
logger.log(
`Executing: ${shutdownCmd} -h +${shutdownDelayMinutes} "UPS battery critical..."`,
);
const { stdout } = await execFileAsync(shutdownCmd, [
'-h',
`+${shutdownDelayMinutes}`,
`UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes`
'-h',
`+${shutdownDelayMinutes}`,
`UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes`,
]);
logger.log(`Shutdown initiated: ${stdout}`);
logger.log(`Allowing ${shutdownDelayMinutes} minutes for VMs to shut down safely`);
@@ -629,29 +669,34 @@ export class NupstDaemon {
// Try using the PATH to find shutdown
try {
logger.log('Shutdown command not found in common paths, trying via PATH...');
const { stdout } = await execAsync(`shutdown -h +${shutdownDelayMinutes} "UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes"`, {
env: process.env // Pass the current environment
});
const { stdout } = await execAsync(
`shutdown -h +${shutdownDelayMinutes} "UPS battery critical, shutting down in ${shutdownDelayMinutes} minutes"`,
{
env: process.env, // Pass the current environment
},
);
logger.log(`Shutdown initiated: ${stdout}`);
} catch (e) {
throw new Error(`Shutdown command not found: ${e instanceof Error ? e.message : String(e)}`);
throw new Error(
`Shutdown command not found: ${e instanceof Error ? e.message : String(e)}`,
);
}
}
// Monitor UPS during shutdown and force immediate shutdown if battery gets too low
logger.log('Monitoring UPS during shutdown process...');
await this.monitorDuringShutdown();
} catch (error) {
logger.error(`Failed to initiate shutdown: ${error}`);
// Try alternative shutdown methods
const alternatives = [
{ cmd: 'poweroff', args: ['--force'] },
{ cmd: 'halt', args: ['-p'] },
{ cmd: 'systemctl', args: ['poweroff'] },
{ cmd: 'reboot', args: ['-p'] } // Some systems allow reboot -p for power off
{ cmd: 'reboot', args: ['-p'] }, // Some systems allow reboot -p for power off
];
for (const alt of alternatives) {
try {
// First check if command exists in common system paths
@@ -659,9 +704,9 @@ export class NupstDaemon {
`/sbin/${alt.cmd}`,
`/usr/sbin/${alt.cmd}`,
`/bin/${alt.cmd}`,
`/usr/bin/${alt.cmd}`
`/usr/bin/${alt.cmd}`,
];
let cmdPath = '';
for (const path of paths) {
if (fs.existsSync(path)) {
@@ -669,7 +714,7 @@ export class NupstDaemon {
break;
}
}
if (cmdPath) {
logger.log(`Trying alternative shutdown method: ${cmdPath} ${alt.args.join(' ')}`);
await execFileAsync(cmdPath, alt.args);
@@ -678,7 +723,7 @@ export class NupstDaemon {
// Try using PATH environment
logger.log(`Trying alternative via PATH: ${alt.cmd} ${alt.args.join(' ')}`);
await execAsync(`${alt.cmd} ${alt.args.join(' ')}`, {
env: process.env // Pass the current environment
env: process.env, // Pass the current environment
});
return; // Exit if successful
}
@@ -687,11 +732,11 @@ export class NupstDaemon {
// Continue to next method
}
}
logger.error('All shutdown methods failed');
}
}
/**
* Monitor UPS during system shutdown
* Force immediate shutdown if any UPS gets critically low
@@ -701,48 +746,62 @@ export class NupstDaemon {
const CHECK_INTERVAL = 30000; // Check every 30 seconds during shutdown
const MAX_MONITORING_TIME = 5 * 60 * 1000; // Max 5 minutes of monitoring
const startTime = Date.now();
logger.log(`Emergency shutdown threshold: ${EMERGENCY_RUNTIME_THRESHOLD} minutes remaining battery runtime`);
logger.log(
`Emergency shutdown threshold: ${EMERGENCY_RUNTIME_THRESHOLD} minutes remaining battery runtime`,
);
// Continue monitoring until max monitoring time is reached
while (Date.now() - startTime < MAX_MONITORING_TIME) {
try {
logger.log('Checking UPS status during shutdown...');
// Check all UPS devices
for (const ups of this.config.upsDevices) {
try {
const status = await this.snmp.getUpsStatus(ups.snmp);
logger.log(`UPS ${ups.name}: Battery ${status.batteryCapacity}%, Runtime: ${status.batteryRuntime} minutes`);
logger.log(
`UPS ${ups.name}: Battery ${status.batteryCapacity}%, Runtime: ${status.batteryRuntime} minutes`,
);
// If any UPS battery runtime gets critically low, force immediate shutdown
if (status.batteryRuntime < EMERGENCY_RUNTIME_THRESHOLD) {
logger.logBoxTitle('EMERGENCY SHUTDOWN', 50);
logger.logBoxLine(`UPS ${ups.name} runtime critically low: ${status.batteryRuntime} minutes`);
logger.logBoxLine(
`UPS ${ups.name} runtime critically low: ${status.batteryRuntime} minutes`,
);
logger.logBoxLine('Forcing immediate shutdown!');
logger.logBoxEnd();
// Force immediate shutdown
await this.forceImmediateShutdown();
return;
}
} catch (upsError) {
logger.error(`Error checking UPS ${ups.name} during shutdown: ${upsError instanceof Error ? upsError.message : String(upsError)}`);
logger.error(
`Error checking UPS ${ups.name} during shutdown: ${
upsError instanceof Error ? upsError.message : String(upsError)
}`,
);
}
}
// Wait before checking again
await this.sleep(CHECK_INTERVAL);
} catch (error) {
logger.error(`Error monitoring UPS during shutdown: ${error instanceof Error ? error.message : String(error)}`);
logger.error(
`Error monitoring UPS during shutdown: ${
error instanceof Error ? error.message : String(error)
}`,
);
await this.sleep(CHECK_INTERVAL);
}
}
logger.log('UPS monitoring during shutdown completed');
}
/**
* Force an immediate system shutdown
*/
@@ -753,9 +812,9 @@ export class NupstDaemon {
'/sbin/shutdown',
'/usr/sbin/shutdown',
'/bin/shutdown',
'/usr/bin/shutdown'
'/usr/bin/shutdown',
];
let shutdownCmd = '';
for (const path of shutdownPaths) {
if (fs.existsSync(path)) {
@@ -764,27 +823,34 @@ export class NupstDaemon {
break;
}
}
if (shutdownCmd) {
logger.log(`Executing emergency shutdown: ${shutdownCmd} -h now`);
await execFileAsync(shutdownCmd, ['-h', 'now', 'EMERGENCY: UPS battery critically low, shutting down NOW']);
await execFileAsync(shutdownCmd, [
'-h',
'now',
'EMERGENCY: UPS battery critically low, shutting down NOW',
]);
} else {
// Try using the PATH to find shutdown
logger.log('Shutdown command not found in common paths, trying via PATH...');
await execAsync('shutdown -h now "EMERGENCY: UPS battery critically low, shutting down NOW"', {
env: process.env // Pass the current environment
});
await execAsync(
'shutdown -h now "EMERGENCY: UPS battery critically low, shutting down NOW"',
{
env: process.env, // Pass the current environment
},
);
}
} catch (error) {
logger.error('Emergency shutdown failed, trying alternative methods...');
// Try alternative shutdown methods in sequence
const alternatives = [
{ cmd: 'poweroff', args: ['--force'] },
{ cmd: 'halt', args: ['-p'] },
{ cmd: 'systemctl', args: ['poweroff'] }
{ cmd: 'systemctl', args: ['poweroff'] },
];
for (const alt of alternatives) {
try {
// Check common paths
@@ -792,9 +858,9 @@ export class NupstDaemon {
`/sbin/${alt.cmd}`,
`/usr/sbin/${alt.cmd}`,
`/bin/${alt.cmd}`,
`/usr/bin/${alt.cmd}`
`/usr/bin/${alt.cmd}`,
];
let cmdPath = '';
for (const path of paths) {
if (fs.existsSync(path)) {
@@ -802,7 +868,7 @@ export class NupstDaemon {
break;
}
}
if (cmdPath) {
logger.log(`Emergency: using ${cmdPath} ${alt.args.join(' ')}`);
await execFileAsync(cmdPath, alt.args);
@@ -811,7 +877,7 @@ export class NupstDaemon {
// Try using PATH
logger.log(`Emergency: trying ${alt.cmd} via PATH`);
await execAsync(`${alt.cmd} ${alt.args.join(' ')}`, {
env: process.env
env: process.env,
});
return; // Exit if successful
}
@@ -819,7 +885,7 @@ export class NupstDaemon {
// Continue to next method
}
}
logger.error('All emergency shutdown methods failed');
}
}
@@ -828,6 +894,6 @@ export class NupstDaemon {
* Sleep for the specified milliseconds
*/
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
return new Promise((resolve) => setTimeout(resolve, ms));
}
}
}