@@ -7,22 +7,17 @@ const execAsync = promisify(exec);
77
88const isDocker = process . env . DOCKER === "true" ;
99
10- // Helper function to get host information when in Docker
1110export async function getHostInfo ( ) : Promise < { hostname : string ; ip : string ; uptime : string } > {
1211 if ( isDocker ) {
1312 try {
14- // Read hostname from host's /etc/hostname
1513 const hostname = await fs . readFile ( "/host/etc/hostname" , "utf-8" ) ;
1614
17- // Read IP from host's network interfaces
1815 let ipOutput = "" ;
1916 try {
20- // Try to get IP from hostname -I first
2117 const { stdout } = await execAsync ( "hostname -I | awk '{print $1}'" ) ;
2218 ipOutput = stdout ;
2319 console . log ( "Docker mode: Got IP from hostname -I:" , ipOutput ) ;
2420 } catch ( error ) {
25- // Fallback: try to read from /proc/net/fib_trie
2621 try {
2722 const fibInfo = await fs . readFile ( "/host/proc/net/fib_trie" , "utf-8" ) ;
2823 const lines = fibInfo . split ( "\n" ) ;
@@ -38,7 +33,6 @@ export async function getHostInfo(): Promise<{ hostname: string; ip: string; upt
3833 }
3934 }
4035
41- // Read uptime from host's /proc/uptime
4236 const uptimeContent = await fs . readFile ( "/host/proc/uptime" , "utf-8" ) ;
4337 const uptimeSeconds = parseFloat ( uptimeContent . split ( " " ) [ 0 ] ) ;
4438 const uptime = formatUptime ( uptimeSeconds ) ;
@@ -50,7 +44,6 @@ export async function getHostInfo(): Promise<{ hostname: string; ip: string; upt
5044 } ;
5145 } catch ( error ) {
5246 console . error ( "Error reading host info:" , error ) ;
53- // Fallback to container info
5447 const { stdout : hostname } = await execAsync ( "hostname" ) ;
5548 const { stdout : ip } = await execAsync ( "hostname -I | awk '{print $1}'" ) ;
5649 const { stdout : uptime } = await execAsync ( "uptime" ) ;
@@ -61,7 +54,6 @@ export async function getHostInfo(): Promise<{ hostname: string; ip: string; upt
6154 } ;
6255 }
6356 } else {
64- // Not in Docker, run commands normally
6557 const { stdout : hostname } = await execAsync ( "hostname" ) ;
6658 const { stdout : ip } = await execAsync ( "hostname -I | awk '{print $1}'" ) ;
6759 const { stdout : uptime } = await execAsync ( "uptime" ) ;
@@ -73,7 +65,6 @@ export async function getHostInfo(): Promise<{ hostname: string; ip: string; upt
7365 }
7466}
7567
76- // Helper function to format uptime
7768export function formatUptime ( seconds : number ) : string {
7869 const days = Math . floor ( seconds / 86400 ) ;
7970 const hours = Math . floor ( ( seconds % 86400 ) / 3600 ) ;
@@ -88,20 +79,16 @@ export function formatUptime(seconds: number): string {
8879 }
8980}
9081
91- // Helper function to parse uptime command output and make it clearer
9282export function parseUptimeOutput ( uptimeOutput : string ) : string {
93- // Remove extra whitespace
9483 const cleanOutput = uptimeOutput . trim ( ) ;
9584
96- // Extract the time part (e.g., "5:54" from "up 5:54")
9785 const match = cleanOutput . match ( / u p \s + ( [ ^ , ] + ) / ) ;
9886 if ( ! match ) {
9987 return "Unknown" ;
10088 }
10189
10290 const timePart = match [ 1 ] . trim ( ) ;
10391
104- // If it's in format "X:YY" (hours:minutes)
10592 const timeMatch = timePart . match ( / ^ ( \d + ) : ( \d + ) $ / ) ;
10693 if ( timeMatch ) {
10794 const hours = parseInt ( timeMatch [ 1 ] ) ;
@@ -122,11 +109,9 @@ export function parseUptimeOutput(uptimeOutput: string): string {
122109 }
123110 }
124111
125- // If it's already in a readable format, return as is
126112 return timePart ;
127113}
128114
129- // Helper function to get system path for Docker
130115export function getSystemPath ( originalPath : string ) : string {
131116 if ( isDocker ) {
132117 switch ( originalPath ) {
@@ -141,13 +126,10 @@ export function getSystemPath(originalPath: string): string {
141126 return originalPath ;
142127}
143128
144- // Docker-specific crontab reading
145129export async function readCronFilesDocker ( ) : Promise < string > {
146130 try {
147131 const crontabDir = "/host/cron/crontabs" ;
148- console . log ( "Docker mode: Reading crontab from" , crontabDir ) ;
149132 const files = await fs . readdir ( crontabDir ) ;
150- console . log ( "Found crontab files:" , files ) ;
151133
152134 let allCronContent = "" ;
153135
@@ -157,24 +139,9 @@ export async function readCronFilesDocker(): Promise<string> {
157139 try {
158140 const filePath = path . join ( crontabDir , file ) ;
159141
160- // Try to read with sudo or change permissions temporarily
161- let content = "" ;
162- try {
163- content = await fs . readFile ( filePath , "utf-8" ) ;
164- } catch ( permError ) {
165- // If permission denied, try to change permissions temporarily
166- try {
167- await execAsync ( `chmod 644 ${ filePath } ` ) ;
168- content = await fs . readFile ( filePath , "utf-8" ) ;
169- // Restore original permissions
170- await execAsync ( `chmod 600 ${ filePath } ` ) ;
171- } catch ( chmodError ) {
172- console . error ( `Could not read crontab for user ${ file } :` , chmodError ) ;
173- continue ;
174- }
175- }
142+ // Read the crontab file directly
143+ const content = await fs . readFile ( filePath , "utf-8" ) ;
176144
177- // Add user identifier comment
178145 allCronContent += `# User: ${ file } \n` ;
179146 allCronContent += content ;
180147 allCronContent += "\n\n" ;
@@ -184,7 +151,6 @@ export async function readCronFilesDocker(): Promise<string> {
184151 }
185152 }
186153
187- // Also read system crontab
188154 try {
189155 const systemCrontab = await fs . readFile ( "/host/crontab" , "utf-8" ) ;
190156 allCronContent += "# System Crontab\n" ;
@@ -197,7 +163,6 @@ export async function readCronFilesDocker(): Promise<string> {
197163 return allCronContent . trim ( ) ;
198164 } catch ( error ) {
199165 console . error ( "Error reading host crontab files:" , error ) ;
200- // Fallback to container's crontab command
201166 try {
202167 const { stdout } = await execAsync ( 'crontab -l 2>/dev/null || echo ""' ) ;
203168 return stdout ;
@@ -208,55 +173,43 @@ export async function readCronFilesDocker(): Promise<string> {
208173 }
209174}
210175
211- // Docker-specific crontab writing
212176export async function writeCronFilesDocker ( content : string ) : Promise < boolean > {
213177 try {
214- // Parse the content to separate different users
215178 const lines = content . split ( "\n" ) ;
216179 const userCrontabs : { [ key : string ] : string [ ] } = { } ;
217180 let currentUser = "" ;
218181 let currentContent : string [ ] = [ ] ;
219182
220183 for ( const line of lines ) {
221184 if ( line . startsWith ( "# User: " ) ) {
222- // Save previous user's content
223185 if ( currentUser && currentContent . length > 0 ) {
224186 userCrontabs [ currentUser ] = [ ...currentContent ] ;
225187 }
226- // Start new user
227188 currentUser = line . substring ( 8 ) . trim ( ) ;
228189 currentContent = [ ] ;
229190 } else if ( line . startsWith ( "# System Crontab" ) ) {
230- // Save previous user's content
231191 if ( currentUser && currentContent . length > 0 ) {
232192 userCrontabs [ currentUser ] = [ ...currentContent ] ;
233193 }
234- // Handle system crontab separately
235194 currentUser = "system" ;
236195 currentContent = [ ] ;
237196 } else if ( currentUser && line . trim ( ) && ! line . startsWith ( "#" ) ) {
238- // This is a cron job line
239197 currentContent . push ( line ) ;
240198 }
241199 }
242200
243- // Save last user's content
244201 if ( currentUser && currentContent . length > 0 ) {
245202 userCrontabs [ currentUser ] = [ ...currentContent ] ;
246203 }
247204
248- // Write each user's crontab
249205 for ( const [ username , cronJobs ] of Object . entries ( userCrontabs ) ) {
250206 if ( username === "system" ) {
251- // Write to system crontab
252207 const systemContent = cronJobs . join ( "\n" ) + "\n" ;
253208 await fs . writeFile ( "/host/crontab" , systemContent ) ;
254209 } else {
255- // Write to user crontab
256210 const userCrontabPath = `/host/cron/crontabs/${ username } ` ;
257211 const userContent = cronJobs . join ( "\n" ) + "\n" ;
258212 await fs . writeFile ( userCrontabPath , userContent ) ;
259- // Set proper permissions
260213 await execAsync ( `chmod 600 ${ userCrontabPath } ` ) ;
261214 await execAsync ( `chown ${ username } :crontab ${ userCrontabPath } ` ) ;
262215 }
@@ -269,7 +222,6 @@ export async function writeCronFilesDocker(content: string): Promise<boolean> {
269222 }
270223}
271224
272- // Docker-specific memory info
273225export async function getMemoryInfoDocker ( ) {
274226 try {
275227 const meminfo = await fs . readFile ( "/host/proc/meminfo" , "utf-8" ) ;
@@ -314,14 +266,12 @@ export async function getMemoryInfoDocker() {
314266 } ;
315267 } catch ( error ) {
316268 console . error ( "Error reading host memory info:" , error ) ;
317- throw error ; // Let the main function handle fallback
269+ throw error ;
318270 }
319271}
320272
321- // Docker-specific CPU info
322273export async function getCPUInfoDocker ( ) {
323274 try {
324- // Read CPU info from host's /proc/cpuinfo
325275 const cpuinfo = await fs . readFile ( "/host/proc/cpuinfo" , "utf-8" ) ;
326276 const lines = cpuinfo . split ( "\n" ) ;
327277
@@ -333,25 +283,21 @@ export async function getCPUInfoDocker() {
333283 }
334284 }
335285
336- // Count CPU cores from cpuinfo
337286 const cores = lines . filter ( line => line . startsWith ( "processor" ) ) . length ;
338287
339288 return { model, cores } ;
340289 } catch ( error ) {
341290 console . error ( "Error reading host CPU info:" , error ) ;
342- throw error ; // Let the main function handle fallback
291+ throw error ;
343292 }
344293}
345294
346- // Docker-specific GPU info
347295export async function getGPUInfoDocker ( ) {
348296 console . log ( "getGPUInfo called" ) ;
349297 try {
350- // Try to get GPU info from host's PCI information
351298 let gpuInfo = "Unknown GPU" ;
352299
353300 try {
354- // Try to read from host's sysfs first
355301 const { stdout } = await execAsync ( "find /host/sys/devices -name 'card*' -type d | head -1" ) ;
356302 if ( stdout . trim ( ) ) {
357303 const cardPath = stdout . trim ( ) ;
@@ -361,7 +307,6 @@ export async function getGPUInfoDocker() {
361307 }
362308 } catch ( sysfsError ) {
363309 console . log ( "Could not read GPU info from host sysfs:" , sysfsError ) ;
364- // Fallback: try to read from /proc/bus/pci/devices
365310 try {
366311 const pciInfo = await fs . readFile ( "/host/proc/bus/pci/devices" , "utf-8" ) ;
367312 const lines = pciInfo . split ( "\n" ) ;
@@ -399,7 +344,6 @@ export async function getGPUInfoDocker() {
399344 }
400345}
401346
402- // Docker-specific network info
403347export async function getNetworkInfoDocker ( ) {
404348 console . log ( "getNetworkInfo called" ) ;
405349 try {
@@ -413,7 +357,6 @@ export async function getNetworkInfoDocker() {
413357 pingOutput = stdout ;
414358 } catch ( pingError ) {
415359 console . log ( "Ping command failed, trying curl instead" ) ;
416- // Try using curl instead of ping
417360 try {
418361 const startTime = Date . now ( ) ;
419362 const { stdout } = await execAsync (
@@ -442,7 +385,6 @@ export async function getNetworkInfoDocker() {
442385 } ;
443386 }
444387
445- // If we used curl, latency is already calculated
446388 if ( latency === 0 ) {
447389 const lines = pingOutput . split ( "\n" ) ;
448390 const timeLine = lines . find ( ( line ) => line . includes ( "time=" ) ) ;
0 commit comments