I noticed my OpenClaw gateway log files were growing unbounded. The service runs via launchd, and while the app has built-in log rotation, the stdout/stderr capture in the launchd plist was bypassing it entirely.
The Problem
When a macOS service uses StandardOutPath and StandardErrorPath in its launchd plist, those files just append forever. My logs had grown to 38MB with no mechanism to clean them up:
|
|
OpenClaw’s internal logger writes date-based rotating logs to /tmp/openclaw/, but launchd’s stdout capture writes directly to the configured files, bypassing that rotation logic.
The Hidden Trap: When log rotation tools like newsyslog create new log files, they default to root:root ownership. If your launchd service runs as your user (not root), it suddenly can’t write to its own log files after rotation. The daemon fails to start with “Permission denied” errors, and you’re left wondering why your service won’t start.
The Solution: newsyslog
macOS includes newsyslog, a utility for managing log file rotation. It’s already running on your system, checking logs periodically via launchd. You just need to tell it about your custom log files.
Configuration
Create a config file for your service logs:
|
|
Important: Notice the clawd:staff owner:group fields. Without these, newsyslog creates the new log files as root:root after rotation. When your launchd service tries to write to a root-owned file, it gets “Permission denied” and the daemon fails to start.
Field breakdown:
clawd:staff— Owner and group for the log files (critical!)644— File permissions (owner read/write, others read-only)0— Number of archived files to keep (zero = just truncate)10000— Size threshold in KB (~10MB)*— Rotate at any time (not just specific hours)B— Treat as binary (no special encoding)
What Happens Without Owner Specified
If you omit the owner:group fields, you’ll see this after newsyslog runs:
|
|
Then your service fails to start with errors like:
Could not open log file /Users/clawd/.openclaw/logs/gateway.log: Permission denied
Service exited with abnormal code: 1
The clawd:staff fields ensure the rotated files remain owned by your user, not root.
Reload and Verify
Tell newsyslog to reload its configuration:
|
|
Check that the config loaded correctly:
|
|
Force an immediate rotation to test:
|
|
Note: The
-Rflag with a requestor name is optional. Plainnewsyslog -v -f /path/to/configworks fine for testing.
Why Not Cron?
I considered a simple cron job:
|
|
That would work, but newsyslog is the native macOS tool for this. It’s already running, already has permission handling figured out, and rotates based on file size rather than just time. If your log suddenly explodes to 500MB, newsyslog catches it on the next check cycle (every 30 minutes). Cron would wait until 3 AM.
Result
After setup, my 38MB error log was truncated to zero bytes:
|
|
No manual intervention needed going forward. When either file crosses 10MB, newsyslog truncates it automatically.
