A command-line service manager for running and managing binary files on Linux and macOS.
- âś… Create and manage tasks/services
- âś… Start/stop services with graceful shutdown
- âś… Environment variable support
- âś… Automatic .env file loading
- âś… Custom working directories
- âś… Auto-restart configuration
- âś… Task status monitoring with detailed information
- âś… Cross-platform support (Linux & macOS)
- âś… Persistent task configuration
- âś… Process monitoring with PID tracking
- âś… Memory usage in list view (per-process MB)
- âś… Log management with rotation (>10MB)
- âś… Real-time log following (--follow flag)
- âś… Separate stdout/stderr log viewing
- âś… Enhanced process management with signal handling
- âś… Diagnostic tools for troubleshooting
- âś… Exit code tracking
- âś… Restart count monitoring
- âś… Persistent running-task state across hyperV restarts
- Clone the repository
- Build the project:
cargo build --release
- The binary will be available at
target/release/hyperV
# Basic task
hyperV new --name "my-service" --binary "/path/to/binary"
# Task with arguments
hyperV new --name "web-server" --binary "/usr/bin/python3" --args "server.py" "--port=8080"
# Task with environment variables
hyperV new --name "api-service" --binary "/path/to/api" --env "PORT=3000" --env "NODE_ENV=production"
# Task with working directory and auto-restart
hyperV new --name "worker" --binary "/path/to/worker" --workdir "/opt/app" --auto-restartIf a .env file exists in the specified working directory (--workdir), it will be automatically loaded. Environment variables passed via the --env flag will take precedence over the variables in the .env file.
Example .env file:
DB_HOST=localhost
DB_USER=myuser
DB_PASS=secret
Creating a task with a .env file:
hyperV new --name "my-app" \
--binary "/path/to/app" \
--workdir "/path/to/my-app-folder" \
--auto-restartIf /path/to/my-app-folder contains a .env file, the variables within it will be loaded when the my-app service is started.
hyperV listhyperV start my-service
# or by partial ID
hyperV start abff48b0hyperV stop my-service# Show specific task
hyperV status my-service
# Show all tasks
hyperV statushyperV remove my-service# Show last 50 lines of stdout (default)
hyperV logs my-service
# Show last 100 lines of stdout
hyperV logs my-service --lines 100
# Show stderr logs
hyperV logs my-service --log-type stderr
# Show both stdout and stderr
hyperV logs my-service --log-type both
# Follow logs in real-time (like tail -f)
hyperV logs my-service --follow
# Follow stderr logs in real-time
hyperV logs my-service --log-type stderr --follow# Analyze binary file and configuration for issues
hyperV diagnose my-serviceTasks with --auto-restart flag will automatically restart if they fail (up to 5 attempts):
hyperV new --name "critical-service" --binary "/path/to/service" --auto-restart- Logs are automatically rotated when they exceed 10MB
- Separate stdout and stderr log files
- Real-time log following capability
- Fast last-N reading for tail-like views (reads from end of file efficiently)
- Historical log preservation (.old files)
- Graceful shutdown with SIGTERM before SIGKILL
- Process group handling for shell scripts
- Proper cleanup of zombie processes
- Exit code tracking
The status command now shows:
- Last start time
- Restart count
- Last exit code
- Detailed process information
hyperV persists the set of running tasks to a small JSON file (running_tasks.json) under the configuration directory. On startup:
- It reads this file and checks each recorded PID to see if the process is still alive.
- Tasks whose PIDs are still running are marked as Running and their PID is restored.
- Stale entries (where the PID is no longer alive) are ignored.
This file is automatically updated when tasks start/stop and when the manager detects that a process has exited. You generally do not need to edit it manually.
Tasks are stored in JSON format at:
- macOS:
~/Library/Application Support/hyperV/tasks.json - Linux:
~/.config/hyperV/tasks.json
Logs are stored in:
- macOS:
~/Library/Application Support/hyperV/logs/<task-id>/ - Linux:
~/.config/hyperV/logs/<task-id>/
Runtime state (persisted running tasks) is stored in:
- macOS:
~/Library/Application Support/hyperV/running_tasks.json - Linux:
~/.config/hyperV/running_tasks.json
Each task contains:
id: Unique identifier (UUID)name: Human-readable namebinary: Path to executableargs: Command-line argumentsenv: Environment variablesworkdir: Working directory (optional)auto_restart: Auto-restart on failurestatus: Current status (Running/Stopped/Failed)pid: Process ID when runningcreated_at: Creation timestamplast_started: Last start timestamprestart_count: Number of automatic restartslast_exit_code: Exit code from last runstdout_log_path: Path to stdout log filestderr_log_path: Path to stderr log file
hyperV new --name "flask-app" \
--binary "/usr/bin/python3" \
--args "app.py" \
--env "FLASK_ENV=production" \
--env "PORT=5000" \
--workdir "/opt/webapp" \
--auto-restart
hyperV start flask-apphyperV new --name "node-api" \
--binary "/usr/bin/node" \
--args "index.js" \
--env "NODE_ENV=production" \
--env "PORT=3000" \
--auto-restart
hyperV start node-apihyperV new --name "my-daemon" \
--binary "/usr/local/bin/mydaemon" \
--args "--config" \
--args "/etc/mydaemon.conf" \
--auto-restart
hyperV start my-daemonA helper script is provided to launch SurrealDB using environment variables: tests/surreal.sh.
Create a task that runs the script via bash:
hyperV new --name "surrealdb" \
--binary "/bin/bash" \
--args "./tests/surreal.sh" \
--workdir "/path/to/this/repo" \
--env "SURREAL_HOST=0.0.0.0" \
--env "SURREAL_PORT=8000" \
--env "SURREAL_STORAGE_PATH=/tmp/surreal_data" \
--env "SURREAL_LOG_LEVEL=info" \
--env "SURREAL_USER=root" \
--env "SURREAL_PASSWORD=secret" \
--auto-restart
# Start the database
hyperV start surrealdb
# View logs
hyperV logs surrealdb --followThe script builds and executes the command:
SURREAL_CMD="surreal start --bind $SURREAL_HOST:$SURREAL_PORT rocksdb:$SURREAL_STORAGE_PATH --log $SURREAL_LOG_LEVEL --user $SURREAL_USER --password $SURREAL_PASSWORD"Ensure the surreal binary is available in your PATH. Adjust environment variables as needed.
You can also define and run SurrealDB purely from hyperv.yaml without a helper script. Example hyperv.yaml fragment:
services:
surrealdb:
binary: "/bin/bash"
args:
- "-lc"
- "surreal start --bind $SURREAL_HOST:$SURREAL_PORT rocksdb:$SURREAL_STORAGE_PATH --log $SURREAL_LOG_LEVEL --user $SURREAL_USER --password $SURREAL_PASSWORD"
env:
SURREAL_HOST: "0.0.0.0"
SURREAL_PORT: "8000"
SURREAL_STORAGE_PATH: "/tmp/surreal_data"
SURREAL_LOG_LEVEL: "info"
SURREAL_USER: "root"
SURREAL_PASSWORD: "secret"
auto_restart: trueThen apply and start it with:
# create/update tasks from hyperv.yaml and start them
hyperV up -f hyperv.yaml --start
# inspect
hyperV list
hyperV logs surrealdb --follow
# remove the services defined in hyperv.yaml
hyperV down -f hyperv.yamlNotes:
- We use /bin/bash -lc so that environment variables in the command are expanded by the shell.
- The env block in YAML sets those variables for the process; adjust as needed.
- Ensure the surreal binary is available in PATH for the user running hyperV.
- Alternatively, you can keep using the provided tests/surreal.sh wrapper if you prefer.
- Log file management and viewing
- Process monitoring with automatic restart
- Resource usage tracking
- Systemd/launchd integration
- Web UI for management
- Task dependencies
- Scheduling support
- Better error handling and recovery
MIT License