Skip to content

Run logs

RunWisp saves the stdout and stderr of every run to a file on disk. You can watch a running task’s output live, scroll through old runs, download a log, or search every run of a task. The database keeps the run details (exit code, duration, start time); the output itself stays in the log files.

<data dir>/logs/<task-name>/<YYYYMMDD>_<HHMMSS>_<run-id>.log

The data directory is set with --data (default .runwisp); see global options. Each run gets its own file, named after the run’s time (in UTC) and its run ID, so files sort by time. Characters other than letters, digits, _, and - in the task name become _.

stdout and stderr are written to the same file, in the order they arrived. Next to each .log there is a hidden .<name>.log.meta file with the indexes that make scrolling fast. RunWisp manages it; don’t delete it while the run is still going.

One runaway script shouldn’t fill the disk, so each run’s log has a size limit:

[tasks.bulky-job]
cron = "0 4 * * *"
run = "/usr/local/bin/bulky.sh"
log_max_size = "50mb"
log_on_full = "drop_old"

log_max_size is the limit. log_on_full decides what happens when a run reaches it: keep the newest output (drop_old, the default), keep the first output (drop_new), or stop the run as log_overflow (kill). In every case RunWisp writes a line into the log where it cut, so you can see that output is missing.

For limits across all tasks (total log size and free disk space), see [storage]. When free space runs low during a run, log_on_full decides what happens there too.

Old runs and their logs are deleted by a cleanup that runs every hour. Set a count, an age, or both:

[tasks.metrics]
cron = "* * * * *"
run = "/usr/local/bin/metrics.sh"
keep_runs = 500
keep_for = "7d"

keep_runs keeps the newest N runs; keep_for deletes runs older than the age. With both, whichever deletes more wins. Each task uses its own settings, or the ones in [defaults].

Only finished runs are deleted; a run that is still going is never touched. Because the cleanup runs on a timer, you may briefly see a few more runs than keep_runs. The database row and the log files are deleted together.

The Web UI and the TUI show a running task’s output as it’s printed. When you open a run, they first show what’s already on disk, then switch to live, so you never miss the first lines. A finished run opens at the end of its log; scroll up to load earlier lines.

From a shell, runwisp logs -f does the same, and keeps following new runs:

Terminal window
runwisp logs -f backup
runwisp logs -f 'web*'

See runwisp logs for the flags.

Many tools redraw a line in place, like a download bar that rewrites itself with \r, or docker pull redrawing a stack of bars. RunWisp handles these so the log stays readable:

  • On disk, a redraw is saved as its final frame: build: 100%, not every percentage it passed through.
  • Live, the Web UI and TUI animate the bar in place. A partial line (like echo -n output) shows up right away.
  • Afterwards, you can look at earlier frames of a redraw. In the Web UI, click the marked line. In the TUI, move between marked lines with [ and ] and press enter. The frames are sampled a few times per second, so very fast changes may not all be kept.

RunWisp doesn’t give the task a terminal (no PTY). Many tools notice that and print plain lines instead of a progress bar, which is fine. A redraw on stdout can’t move lines on stderr, and the other way round.

Click the download button in the run header.

If the log was cut by drop_old during the run, the download includes both the earlier part that’s still on disk and the current part, as one file.

Search looks through the log files of a task’s runs, newest run first. There’s no index to build or wait for; a bigger search just takes longer, so results come in pages.

On the task page, type into Search output across runs…. The buttons next to it turn on case sensitivity and regular expressions. Click a result to jump to that line in the log.

A bad query (an empty q, a broken regular expression) is rejected with a 400 before any searching starts.

If the daemon dies while a run is writing (power loss, kill -9), the log is not truncated: everything that reached the disk stays, and the viewer handles a half-written last line. On the next start the run is marked crashed (see After a crash) and its log is left as it was. The last lines are often the best clue to what went wrong.