From 8431ef91a813477744055ee693a5adf2586da5ae Mon Sep 17 00:00:00 2001
From: Philipp Kunz <code@philkunz.com>
Date: Tue, 25 Mar 2025 09:20:55 +0000
Subject: [PATCH] fix(cli): Refactor logs command to use child_process spawn
 for real-time log tailing

---
 changelog.md             |  7 +++++++
 ts/00_commitinfo_data.ts |  2 +-
 ts/cli.ts                | 20 ++++++++++++++++++--
 ts/daemon.ts             | 15 +++++++++++++++
 4 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/changelog.md b/changelog.md
index 28dcf9f..448d17a 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,12 @@
 # Changelog
 
+## 2025-03-25 - 1.8.2 - fix(cli)
+Refactor logs command to use child_process spawn for real-time log tailing
+
+- Replaced execSync call with spawn to properly follow logs
+- Forward SIGINT to the spawned process for graceful termination
+- Await the child process exit to ensure clean shutdown of the CLI log command
+
 ## 2025-03-25 - 1.8.1 - fix(systemd)
 Update ExecStart in systemd service template to use /opt/nupst/bin/nupst for daemon startup
 
diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts
index f419379..56c8b2c 100644
--- a/ts/00_commitinfo_data.ts
+++ b/ts/00_commitinfo_data.ts
@@ -3,6 +3,6 @@
  */
 export const commitinfo = {
   name: '@serve.zone/nupst',
-  version: '1.8.1',
+  version: '1.8.2',
   description: 'Node.js UPS Shutdown Tool for SNMP-enabled UPS devices'
 }
diff --git a/ts/cli.ts b/ts/cli.ts
index fd17e10..6da118e 100644
--- a/ts/cli.ts
+++ b/ts/cli.ts
@@ -131,8 +131,24 @@ export class NupstCli {
    */
   private async logs(): Promise<void> {
     try {
-      const logs = execSync('journalctl -u nupst.service -n 50 -f').toString();
-      console.log(logs);
+      // Use exec with spawn to properly follow logs in real-time
+      const { spawn } = await import('child_process');
+      console.log('Tailing nupst service logs (Ctrl+C to exit)...\n');
+      
+      const journalctl = spawn('journalctl', ['-u', 'nupst.service', '-n', '50', '-f'], {
+        stdio: ['ignore', 'inherit', 'inherit']
+      });
+      
+      // Forward signals to child process
+      process.on('SIGINT', () => {
+        journalctl.kill('SIGINT');
+        process.exit(0);
+      });
+      
+      // Wait for process to exit
+      await new Promise<void>((resolve) => {
+        journalctl.on('exit', () => resolve());
+      });
     } catch (error) {
       console.error('Failed to retrieve logs:', error);
       process.exit(1);
diff --git a/ts/daemon.ts b/ts/daemon.ts
index 13ddfee..a29c51f 100644
--- a/ts/daemon.ts
+++ b/ts/daemon.ts
@@ -193,11 +193,15 @@ export class NupstDaemon {
     console.log('Starting UPS monitoring...');
     
     let lastStatus: 'online' | 'onBattery' | 'unknown' = 'unknown';
+    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 {
         const status = await this.snmp.getUpsStatus(this.config.snmp);
+        const currentTime = Date.now();
+        const shouldLogStatus = (currentTime - lastLogTime) >= LOG_INTERVAL;
         
         // Log status changes
         if (status.powerStatus !== lastStatus) {
@@ -205,6 +209,17 @@ export class NupstDaemon {
           console.log(`│ Power status changed: ${lastStatus} → ${status.powerStatus}`);
           console.log('└──────────────────────────────────────────┘');
           lastStatus = status.powerStatus;
+          lastLogTime = currentTime; // Reset log timer when status changes
+        }
+        // Log status periodically (at least every 5 minutes)
+        else if (shouldLogStatus) {
+          const timestamp = new Date().toISOString();
+          console.log('┌──────────────────────────────────────────┐');
+          console.log(`│ [${timestamp}] Periodic Status Update`);
+          console.log(`│ Power Status: ${status.powerStatus}`);
+          console.log(`│ Battery: ${status.batteryCapacity}% | Runtime: ${status.batteryRuntime} min`);
+          console.log('└──────────────────────────────────────────┘');
+          lastLogTime = currentTime;
         }
         
         // Handle battery power status