menios icon indicating copy to clipboard operation
menios copied to clipboard

Implement uptime command - display system uptime and load averages

Open pbalduino opened this issue 3 months ago • 1 comments

Overview

Implement the uptime command to display system status information. This is a standard POSIX utility that shows how long the system has been running, current time, logged-in users, and system load averages.

Reference: https://man7.org/linux/man-pages/man1/uptime.1.html

Purpose

Display a one-line summary of system status:

  • Current system time
  • System uptime (how long since boot)
  • Number of logged-in users
  • System load averages (1, 5, and 15 minutes)

Requirements

Core Functionality

  • [ ] Display current time
  • [ ] Display system uptime (days, hours, minutes)
  • [ ] Display number of active users
  • [ ] Display load averages (1, 5, 15 minute intervals)
  • [ ] Single-line output format

Essential Options

Must Have:

  • [ ] Default format: HH:MM:SS up DD days, HH:MM, N users, load average: X.XX, X.XX, X.XX
  • [ ] -p, --pretty - Show uptime in human-readable format
  • [ ] -s, --since - Show system boot time (YYYY-MM-DD HH:MM:SS)

Nice to Have:

  • [ ] --help - Display usage information
  • [ ] --version - Display version information

Implementation Approach

Phase 1: Basic Uptime Display

Goal: Show system uptime without load averages or user count

// uptime.c - minimal version
#include <stdio.h>
#include <time.h>
#include <sys/sysinfo.h>

int main(int argc, char *argv[]) {
    struct sysinfo info;
    
    if (sysinfo(&info) < 0) {
        perror("sysinfo");
        return 1;
    }
    
    // Current time
    time_t now = time(NULL);
    struct tm *tm = localtime(&now);
    printf("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec);
    
    // Uptime
    long uptime_secs = info.uptime;
    int days = uptime_secs / 86400;
    int hours = (uptime_secs % 86400) / 3600;
    int minutes = (uptime_secs % 3600) / 60;
    
    if (days > 0) {
        printf("up %d day%s, %2d:%02d, ", 
               days, days > 1 ? "s" : "", hours, minutes);
    } else {
        printf("up %2d:%02d, ", hours, minutes);
    }
    
    // Placeholder for users (implement later)
    printf("0 users, ");
    
    // Placeholder for load (implement later)
    printf("load average: 0.00, 0.00, 0.00\n");
    
    return 0;
}

Phase 2: Add Load Averages

Implement system load tracking:

// Load averages represent average # of runnable/waiting processes
struct sysinfo {
    unsigned long loads[3];  // 1, 5, 15 minute load averages
    // ... scaled by 65536
};

// Display
printf("load average: %.2f, %.2f, %.2f\n",
       info.loads[0] / 65536.0,
       info.loads[1] / 65536.0,
       info.loads[2] / 65536.0);

Phase 3: Add User Count

Count logged-in users (via utmp/wtmp or session tracking):

int count_users(void) {
    // Option 1: Parse /var/run/utmp (if available)
    // Option 2: Count active login sessions
    // Option 3: Track via kernel session info
    return 0;  // Placeholder
}

Phase 4: Pretty Format

Add -p option for human-readable output:

// Example: "up 2 days, 3 hours, 45 minutes"
void print_pretty_uptime(long uptime_secs) {
    int days = uptime_secs / 86400;
    int hours = (uptime_secs % 86400) / 3600;
    int minutes = (uptime_secs % 3600) / 60;
    
    printf("up ");
    if (days > 0) printf("%d day%s, ", days, days > 1 ? "s" : "");
    if (hours > 0) printf("%d hour%s, ", hours, hours > 1 ? "s" : "");
    printf("%d minute%s\n", minutes, minutes != 1 ? "s" : "");
}

Dependencies

Required (Check Availability)

  • Time syscalls - time(), localtime() (likely available via #193, #240)
  • System boot time - Kernel must track boot timestamp
  • sysinfo syscall - Or equivalent mechanism to get uptime
  • Load average tracking - Kernel must calculate 1/5/15 minute averages

Optional (For Full Features)

  • utmp/wtmp - For user count (if session tracking exists)
  • Session management - Alternative to utmp for counting users

Check These Issues:

  • #193 - Minimal libc (provides time functions?)
  • #240 - time() syscall
  • #239 - Kernel time syscalls

Kernel Support Needed

System Uptime:

  • Kernel must track boot_time or uptime_seconds
  • Expose via sysinfo() syscall or /proc/uptime

Load Averages:

  • Track exponential moving average of runnable processes
  • Calculate over 1, 5, and 15 minute windows
  • Standard Unix algorithm (see Linux kernel kernel/sched/loadavg.c)

Load Average Calculation:

// Simplified algorithm (runs periodically, e.g., every 5 seconds)
void update_load_averages(void) {
    unsigned long active = nr_running + nr_uninterruptible;
    
    // Exponential moving average with decay constants
    load_avg_1  = (load_avg_1  * exp_1)  + active * (1 - exp_1);
    load_avg_5  = (load_avg_5  * exp_5)  + active * (1 - exp_5);
    load_avg_15 = (load_avg_15 * exp_15) + active * (1 - exp_15);
}

Testing Strategy

Basic Tests

# Test 1: Basic uptime display
uptime
# Expected: HH:MM:SS up X min, 0 users, load average: 0.00, 0.00, 0.00

# Test 2: Pretty format
uptime -p
# Expected: up X minutes

# Test 3: Since (boot time)
uptime -s
# Expected: YYYY-MM-DD HH:MM:SS

# Test 4: After running for hours
# (Run after system has been up for a while)
uptime
# Expected: Shows correct days/hours/minutes

Edge Cases

  • System just booted (0 minutes uptime)
  • System up for multiple days
  • System up for exactly 24 hours
  • Leap seconds / time changes

Implementation Phases

Phase 1: Minimal MVP (1-2 days)

  • Display current time
  • Display uptime (requires kernel boot_time)
  • Hardcode users=0, load=0.00
  • Basic format only

Phase 2: Load Averages (2-3 days)

  • Implement kernel load tracking
  • sysinfo() syscall to expose loads
  • Display real load averages

Phase 3: User Count (1-2 days)

  • Count active sessions/logins
  • Display real user count

Phase 4: Options (1 day)

  • Add -p (pretty)
  • Add -s (since)
  • Add --help

Integration

Build System

# app/uptime/Makefile
$(BUILD_DIR)/uptime: app/uptime/uptime.c
	$(CC) $(CFLAGS) -o $@ $<

Disk Image

Package in /bin/uptime alongside other utilities:

  • cat, echo, env, true, false, touch, realpath, stat, head

Documentation

Update README.md:

### System Utilities
- **uptime** — Display system uptime and load averages

Acceptance Criteria

  • [ ] uptime command available in /bin
  • [ ] Displays current time correctly
  • [ ] Displays system uptime correctly
  • [ ] Displays load averages (or 0.00 if not implemented)
  • [ ] Displays user count (or 0 if not tracked)
  • [ ] -p pretty format works
  • [ ] -s since format works
  • [ ] Error handling for missing kernel support
  • [ ] Documentation updated

Timeline

Estimated: 1-2 weeks (depending on kernel support required)

Phase Duration Description
Phase 1 2-3 days Basic uptime display (MVP)
Phase 2 2-3 days Kernel load average tracking
Phase 3 1-2 days User count integration
Phase 4 1 day Pretty/since options
Documentation 1 day README, help text

Priority

Medium - Useful system monitoring tool, commonly expected in Unix-like systems

Not critical for core functionality, but useful for:

  • System administration
  • Performance monitoring
  • Debugging (understanding system load)
  • Expected by users familiar with Unix/Linux

Related Issues

  • #183 - /bin utilities (cat, echo, env, etc.) - Similar userland tools
  • #240 - time() syscall - Required for current time
  • #239 - Kernel time syscalls - May provide uptime support
  • #370 - stat command - Recent userland utility
  • #374 - head command - Recent userland utility
  • #326 - Centralized timekeeper abstraction - May provide boot_time

Notes

Why Implement This?

  1. Common Unix Utility - Expected in most Unix-like systems
  2. System Monitoring - Quick way to check system status
  3. Performance Insight - Load averages show system health
  4. Administrative Tool - Useful for system management
  5. Quick Win - Basic version is straightforward

Scope Decisions

Include in MVP:

  • Current time display
  • System uptime (days/hours/minutes)
  • Basic output format
  • Pretty format (-p)
  • Since format (-s)

Defer to Future:

  • Accurate load averages (requires kernel work)
  • User count (requires session tracking)
  • Advanced options (--raw, etc.)

Implementation Notes

Kernel Support Required:

  • Track system boot time (boot_timestamp)
  • Expose via sysinfo() syscall or /proc/uptime
  • Load average calculation (optional, can show 0.00)

Load Average Considerations:

  • Standard Unix uses exponential moving average
  • Decay constants: ~0.92 (1 min), ~0.98 (5 min), ~0.99 (15 min)
  • Updated periodically (every 5 seconds typically)
  • Not adjusted for CPU count

User Count Alternatives:

  1. Parse /var/run/utmp (if exists)
  2. Count active TTY sessions
  3. Track login/logout in kernel
  4. Start with 0 if tracking not available

Labels: enhancement, build Priority: Medium Complexity: Medium (requires kernel support for full implementation)

pbalduino avatar Oct 28 '25 15:10 pbalduino