Back to skills
extension
Category: OtherNo API key required

构建心跳监控

This skill should be used when running long-running build or compile tasks (mobile app packaging, native cross-compilation, large Gradle/CMake/Flutter builds, CI jobs) that may silently hang, get killed by the sandbox, or disappear when a session idles, and need observable progress plus a reliable way to detect RUNNING, STUCK, SUCCESS, or FAILED states. It provides a reusable heartbeat writer and a log-based monitor reader so builds never vanish without a trace.

personAuthor: user_62138798hubcommunity

Build Heartbeat Monitor

Overview

Wrap any long-running build command so its progress stays observable and its final state is unambiguous. A background heartbeat appends a [HEARTBEAT] marker to a log file every N seconds (refreshing the file's mtime) and prints elapsed time to the terminal; on exit it writes a terminal marker (BUILD_EXIT=0 or [FAILED]). A separate monitor reader inspects the log and reports RUNNING / STUCK / SUCCESS / FAILED / NOLOG. This eliminates the "build silently died and nobody noticed for hours" failure mode common in sandboxed or idle-session environments.

When To Use

Trigger this skill when:

  • A build step is expected to take minutes to hours (Flutter/iOS/Android packaging, NDK cross-compile, FreeRDP/OpenSSL cross-build, large gradle/cmake/xcodebuild runs).
  • The environment has killed background tasks before (session idle reclaim, sandbox resource limits that kill flutter/dart/gradle without an exit code).
  • A previous attempt produced no log, an empty log, or a build that hung with no signal.
  • When designing a one-click build script and wanting built-in observability + a monitor that a scheduled automation or a human can poll.

Do NOT use this for quick commands (< 30s) — the overhead is unnecessary.

How To Use

1. One-shot wrapper (recommended)

Source the library and wrap the build command in a single call:

source "$(dirname "$0")/heartbeat.sh"   # or the skill's scripts/ path
LOG=build_run.log
run_with_heartbeat "$LOG" 60 flutter build hap --release
# exit code 0 = success (BUILD_EXIT=0 written); non-zero = failed ([FAILED] written)

run_with_heartbeat <logfile> <interval_sec> <cmd...> truncates the log (via : >, NOT rm), starts the heartbeat, tees the build output to the log, stops the heartbeat, and writes the terminal marker.

2. Manual start/stop (embed in an existing script)

source heartbeat.sh
start_heartbeat build_run.log 60      # launches bg loop + registers EXIT/INT/TERM trap
<your long command> 2>&1 | tee -a build_run.log
stop_heartbeat                        # trap also cleans up on script exit

3. Monitor / poll status

bash monitor_build.sh build_run.log --stuck-minutes 3
# outputs one line: NOLOG | SUCCESS | FAILED | RUNNING | STUCK, with exit codes 3/0/1/0/2

For live observation, run tail -f build_run.log in another window, or wire monitor_build.sh into a scheduled automation that alerts on STUCK (exit 2).

4. Integration into a one-click build script

Combine with environment setup (NODE_HOME, SDK paths, signing) as shown in references/pattern.md §四. The heartbeat is orthogonal to deployment: it only makes the build observable; device install/verify is a separate stage.

Critical Constraints (sandbox-safe)

These come from repeated failures and MUST be preserved:

  • Truncate logs with : > file, never rm. A safe-delete shim intercepts rm and rename-over-existing, which would abort the command chain and make the log vanish.
  • Append markers with >>, never overwrite.
  • Track the heartbeat subprocess by PID and make stop idempotent (kill -0 before kill).
  • Register an EXIT/INT/TERM trap so the terminal marker is always written, even on Ctrl-C or unexpected exit.
  • Use tee -a so build output reaches both terminal and log without disturbing the heartbeat's mtime refresh.

Resources

scripts/heartbeat.sh

Bash function library. Provides run_with_heartbeat, start_heartbeat, stop_heartbeat. Source it, then call run_with_heartbeat <log> <interval> <cmd...>. Implements the log protocol and all sandbox-safe constraints above.

scripts/monitor_build.sh

Standalone status reader. monitor_build.sh <logfile> [--stuck-minutes N] [--quiet]. Prints one status line and uses exit codes: 0=SUCCESS/RUNNING, 1=FAILED, 2=STUCK, 3=NOLOG.

references/pattern.md

Full rationale: why builds silently die, the log protocol table, the sandbox-safe implementation constraints, copy-paste integration templates, and a cross-project adaptation checklist (interval / STUCK threshold / CI wiring).