openwrt-initd-service

star 0

Use when installing background services on OpenWrt with automatic startup on boot and process supervision. Use for agents, monitoring tools, or any long-running background processes that need persistent logging and respawn on crash.

deuxksy By deuxksy schedule Updated 3/25/2026

name: openwrt-initd-service description: Use when installing background services on OpenWrt with automatic startup on boot and process supervision. Use for agents, monitoring tools, or any long-running background processes that need persistent logging and respawn on crash.

OpenWrt Init.d Service Installation

Overview

Install background services on OpenWrt as init.d scripts with procd supervision. Services auto-start on boot, log to /var/log/, and respawn on failure.

When to Use

Need to run service on OpenWrt? This skill Is it background process? This skill Need auto-start on boot? This skill Need crash recovery? This skill

Use cases:

  • Monitoring agents (beszel-agent, telegraf, etc.)
  • Custom daemons
  • Network services
  • Data collectors

NOT for:

  • One-time scripts (use /etc/rc.local)
  • Interactive commands (run manually)
  • CGIs/FastCGI (use uhttpd configuration)

Core Pattern

OpenWrt init.d = /etc/init.d/ + START priority + start() function

#!/bin/sh /etc/rc.common

START=99              # Start late (network ready)
USE_PROCD=1          # Enable procd supervision

start_service() {
    procd_open_instance
    procd_set_param command "/usr/bin/service"
    procd_set_param respawn 3600 5 5
    procd_set_param stdout "/var/log/service.log"
    procd_set_param stderr "/var/log/service.log"
    procd_close_instance
}

Quick Reference

Task Command
Install script cat > /etc/init.d/service-name
Set executable chmod +x /etc/init.d/service-name
Enable autostart /etc/init.d/service-name enable
Start service /etc/init.d/service-name start
Check status /etc/init.d/service-name status
Stop service /etc/init.d/service-name stop

UCI Configuration (Optional)

For configurable services, use UCI:

# Create config
cat > /etc/config/service
config service 'main'
    option port '8080'
    option token 'abc123'

# In init.d script
local port=$(uci get service.main.port 2>/dev/null)

# Update config
uci set service.main.port='8080'
uci commit service

Log Management

# Create log directory with error checking
mkdir -p /var/log || {
    echo "Error: Cannot create log directory" >&2
    return 1
}

# Set restrictive permissions
umask 077
touch "$LOG_FILE"

# Verify logs
tail -n 50 /var/log/service.log

Direct Logging (When procd stdout/stderr Fails)

If procd log redirection doesn't work, use background process with redirection:

start() {
    mkdir -p /var/log /var/run || return 1

    # Stop existing
    stop

    # Start with logging
    "$PROG" \
        -l "$port" \
        -k "$ssh_key" \
        -t "$token" \
        -u "$hub_url" \
        >> "$LOG_FILE" 2>&1 &

    local pid=$!
    echo "$pid" > "$PID_FILE"
}

Common Pitfalls

Issue Solution
Service won't start Check shebang: #!/bin/sh /etc/rc.common
Enable doesn't persist Verify symlink: ls -la /etc/rc.d/service
No logs created Use direct redirection: >> "$LOG_FILE" 2>&1 &
Permissions too open Set umask: umask 077 before touch
Binary not found Copy to /usr/bin/ not /usr/local/bin
procd_status not found Use pgrep or PID file instead

Service Script Template

#!/bin/sh /etc/rc.common

START=99
STOP=10

PROG="/usr/bin/service"
LOG_FILE="/var/log/service.log"
PID_FILE="/var/run/service.pid"

start() {
    mkdir -p /var/log /var/run || return 1

    # Read UCI config (optional)
    local setting=$(uci get service.main.setting 2>/dev/null)

    # Validate required config
    [ -z "$setting" ] && echo "Error: setting not configured" && return 1

    stop

    umask 077
    touch "$LOG_FILE"

    "$PROG" \
        --config "$setting" \
        >> "$LOG_FILE" 2>&1 &

    local pid=$!
    echo "$pid" > "$PID_FILE"
    sleep 1

    if kill -0 "$pid" 2>/dev/null; then
        echo "Service started (PID: $pid)"
        return 0
    else
        echo "Failed to start service" >&2
        rm -f "$PID_FILE"
        return 1
    fi
}

stop() {
    if [ -f "$PID_FILE" ]; then
        kill $(cat "$PID_FILE") 2>/dev/null
        rm -f "$PID_FILE"
    fi
    pkill -9 -f "$PROG" 2>/dev/null
}

restart() {
    stop
    sleep 1
    start
}

status() {
    if [ -f "$PID_FILE" ]; then
        local pid=$(cat "$PID_FILE")
        if kill -0 "$pid" 2>/dev/null; then
            echo "[OK] service: running (PID: $pid)"
        else
            echo "[STOPPED] service: stopped (stale PID file)"
            rm -f "$PID_FILE"
        fi
    else
        local pid=$(pgrep -f "$PROG" | head -1)
        if [ -n "$pid" ]; then
            echo "[OK] service: running (PID: $pid)"
        else
            echo "[STOPPED] service: stopped"
        fi
    fi

    echo ""
    echo "=== Latest 50 log lines ==="
    if [ -f "$LOG_FILE" ]; then
        tail -n 50 "$LOG_FILE"
    else
        echo "Log file not found: $LOG_FILE"
    fi
}

Real-World Example

See: Beszel Agent installation on arv.bun-bull.ts.net

  • Binary: /usr/bin/beszel-agent
  • Config: /etc/config/beszel (UCI)
  • Init script: /etc/init.d/beszel-agent
  • Log: /var/log/beszel-agent.log
Install via CLI
npx skills add https://github.com/deuxksy/skill-openwrt-initd --skill openwrt-initd-service
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator