Skip to content

Commit fac1008

Browse files
committed
break up system files, it was way too messy
1 parent 69358f9 commit fac1008

5 files changed

Lines changed: 7 additions & 82 deletions

File tree

app/_utils/system.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// Main system utilities - imports from modular files
21
export { getSystemInfo, type SystemInfo } from "./system/info";
32
export {
43
getCronJobs,

app/_utils/system/cron.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ async function readCronFiles(): Promise<string> {
2222
}
2323
}
2424

25-
// In Docker, use Docker-specific function
2625
return await readCronFilesDocker();
2726
}
2827

@@ -37,7 +36,6 @@ async function writeCronFiles(content: string): Promise<boolean> {
3736
}
3837
}
3938

40-
// In Docker, use Docker-specific function
4139
return await writeCronFilesDocker(content);
4240
}
4341

@@ -70,7 +68,6 @@ export async function getCronJobs(): Promise<CronJob[]> {
7068
}
7169

7270
if (trimmedLine.startsWith("#")) {
73-
// Skip user/system headers, but keep other comments
7471
if (!trimmedLine.startsWith("# User:") && !trimmedLine.startsWith("# System Crontab")) {
7572
currentComment = trimmedLine.substring(1).trim();
7673
}
@@ -82,7 +79,6 @@ export async function getCronJobs(): Promise<CronJob[]> {
8279
const schedule = parts.slice(0, 5).join(" ");
8380
const command = parts.slice(5).join(" ");
8481

85-
// Add user info to comment if available
8682
let fullComment = currentComment;
8783
if (currentUser && currentUser !== "system") {
8884
fullComment = fullComment ? `${currentComment} (User: ${currentUser})` : `User: ${currentUser}`;
@@ -116,9 +112,7 @@ export async function addCronJob(
116112
try {
117113
const cronContent = await readCronFiles();
118114

119-
// In Docker mode, we need to determine which user to add the job to
120115
if (isDocker) {
121-
// For now, add to the first user found, or create a default user entry
122116
const lines = cronContent.split("\n");
123117
let hasUserSection = false;
124118

@@ -130,22 +124,19 @@ export async function addCronJob(
130124
}
131125

132126
if (!hasUserSection) {
133-
// No user sections found, create a default one
134127
const newEntry = comment
135128
? `# User: root\n# ${comment}\n${schedule} ${command}`
136129
: `# User: root\n${schedule} ${command}`;
137130
const newCron = cronContent + "\n" + newEntry;
138131
await writeCronFiles(newCron);
139132
} else {
140-
// Add to existing content
141133
const newEntry = comment
142134
? `# ${comment}\n${schedule} ${command}`
143135
: `${schedule} ${command}`;
144136
const newCron = cronContent + "\n" + newEntry;
145137
await writeCronFiles(newCron);
146138
}
147139
} else {
148-
// Non-Docker mode, use original logic
149140
const newEntry = comment
150141
? `# ${comment}\n${schedule} ${command}`
151142
: `${schedule} ${command}`;

app/_utils/system/docker.ts

Lines changed: 4 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,17 @@ const execAsync = promisify(exec);
77

88
const isDocker = process.env.DOCKER === "true";
99

10-
// Helper function to get host information when in Docker
1110
export 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
7768
export 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
9282
export 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(/up\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
130115
export 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
145129
export 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
212176
export 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
273225
export 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
322273
export 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
347295
export 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
403347
export 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

Comments
 (0)