You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

460 lines
14 KiB

#!/bin/bash
###############################################################################
# OpenClaw System Deployment & Management Script
#
# Features:
# - One-click deployment of OpenClaw with systemd services
# - Auto-healing configuration
# - Health monitoring
# - Rollback support via git
# - Telegram notifications
#
# Usage:
# ./deploy.sh install - Install and start all services
# ./deploy.sh start - Start all services
# ./deploy.sh stop - Stop all services
# ./deploy.sh restart - Restart all services
# ./deploy.sh status - Show service status
# ./deploy.sh logs - Show recent logs
# ./deploy.sh health - Run health check
# ./deploy.sh rollback - Rollback to previous git commit
# ./deploy.sh backup - Create backup of current state
# ./deploy.sh debug-stop - Stop ALL services (including monitor) for debugging
# ./deploy.sh debug-start - Start ALL services after debugging
# ./deploy.sh fix-service - Re-inject EnvironmentFile= after OpenClaw UI upgrade
###############################################################################
set -e
WORKSPACE="/root/.openclaw/workspace"
LOG_DIR="/root/.openclaw/workspace/logs/system"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
ensure_log_dir() {
mkdir -p "$LOG_DIR"
}
install_services() {
log_info "Installing OpenClaw systemd services..."
# Step 1: Enable linger for user-level systemd (CRITICAL for VPS/server deployments)
log_info "Enabling user linger for persistent user-level services..."
loginctl enable-linger $(whoami)
# Step 2: Export required environment variables
setup_user_env
if [ ! -d "$XDG_RUNTIME_DIR" ]; then
log_error "XDG_RUNTIME_DIR not found: $XDG_RUNTIME_DIR"
log_warning "Creating runtime directory..."
mkdir -p "$XDG_RUNTIME_DIR"
chmod 700 "$XDG_RUNTIME_DIR"
fi
# Step 3: Install user-level gateway services
log_info "Installing user-level gateway services..."
mkdir -p ~/.config/systemd/user/
cp "$WORKSPACE/systemd/openclaw-gateway-user.service" ~/.config/systemd/user/openclaw-gateway.service
cp "$WORKSPACE/systemd/agent-life.service" ~/.config/systemd/user/openclaw-gateway-life.service
systemctl --user daemon-reload
systemctl --user enable openclaw-gateway
systemctl --user enable openclaw-gateway-life
# Step 4: Install system-level agent monitor
log_info "Installing system-level agent monitor..."
cp "$WORKSPACE/systemd/openclaw-agent-monitor.service" /etc/systemd/system/
systemctl daemon-reload
systemctl enable openclaw-agent-monitor
# Step 5: Inject EnvironmentFile references
fix_service_files
# Step 6: Start services
log_info "Starting services..."
systemctl --user start openclaw-gateway
systemctl --user start openclaw-gateway-life
systemctl start openclaw-agent-monitor
sleep 3
log_success "OpenClaw services installed and started!"
log_info "Gateway: ws://localhost:18789"
log_info "Life Agent: openclaw-gateway-life.service"
log_info "User service logs: journalctl --user -u openclaw-gateway -f"
log_info "Life agent logs: journalctl --user -u openclaw-gateway-life -f"
log_info "Monitor logs: journalctl -u openclaw-agent-monitor -f"
}
setup_user_env() {
export XDG_RUNTIME_DIR=/run/user/$(id -u)
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
}
start_services() {
log_info "Starting OpenClaw services..."
setup_user_env
systemctl --user start openclaw-gateway
systemctl --user start openclaw-gateway-life
systemctl start openclaw-agent-monitor
log_success "All services started (gateway + life + monitor)"
}
stop_services() {
log_info "Stopping OpenClaw services..."
setup_user_env
systemctl --user stop openclaw-gateway
systemctl --user stop openclaw-gateway-life
systemctl stop openclaw-agent-monitor
log_success "All services stopped"
}
restart_services() {
log_info "Restarting OpenClaw services..."
setup_user_env
systemctl --user restart openclaw-gateway
systemctl --user restart openclaw-gateway-life
systemctl restart openclaw-agent-monitor
log_success "All services restarted (gateway + life + monitor)"
}
debug_stop() {
log_warning "=== DEBUG MODE: Stopping ALL services ==="
log_warning "Monitor will NOT auto-restart gateway while in debug mode."
log_warning "Run './deploy.sh debug-start' when done debugging."
setup_user_env
systemctl stop openclaw-agent-monitor 2>/dev/null || true
systemctl --user stop openclaw-gateway 2>/dev/null || true
systemctl --user stop openclaw-gateway-life 2>/dev/null || true
log_success "All services stopped. Safe to debug."
echo ""
log_info "Useful debug commands:"
log_info " openclaw gateway start # start gateway in foreground"
log_info " journalctl --user -u openclaw-gateway -n 100"
log_info " journalctl --user -u openclaw-gateway-life -n 100"
}
debug_start() {
log_info "=== Exiting DEBUG MODE: Restarting ALL services ==="
setup_user_env
systemctl --user start openclaw-gateway
systemctl --user start openclaw-gateway-life
systemctl start openclaw-agent-monitor
sleep 2
log_success "All services restored. Monitor is active again."
health_check
}
fix_service_files() {
log_info "Ensuring EnvironmentFile= is present in installed service files..."
setup_user_env
local gateway_svc="$HOME/.config/systemd/user/openclaw-gateway.service"
local life_svc="$HOME/.config/systemd/user/openclaw-gateway-life.service"
local gateway_env="$WORKSPACE/systemd/gateway.env"
local life_env="$WORKSPACE/systemd/life-gateway.env"
local changed=0
if [ -f "$gateway_svc" ]; then
if ! grep -q "EnvironmentFile=.*gateway.env" "$gateway_svc" 2>/dev/null; then
sed -i "/^\[Service\]/a EnvironmentFile=-${gateway_env}" "$gateway_svc"
log_info "Injected EnvironmentFile into openclaw-gateway.service"
changed=1
else
log_info "openclaw-gateway.service already has EnvironmentFile"
fi
fi
if [ -f "$life_svc" ]; then
if ! grep -q "EnvironmentFile=.*life-gateway.env" "$life_svc" 2>/dev/null; then
sed -i "/^\[Service\]/a EnvironmentFile=-${life_env}" "$life_svc"
log_info "Injected EnvironmentFile into openclaw-gateway-life.service"
changed=1
else
log_info "openclaw-gateway-life.service already has EnvironmentFile"
fi
fi
if [ $changed -eq 1 ]; then
systemctl --user daemon-reload
log_success "Service files updated. Run './deploy.sh restart' to apply."
else
log_success "All service files are up to date."
fi
}
show_status() {
setup_user_env
echo ""
log_info "=== OpenClaw Gateway (User Service) ==="
systemctl --user status openclaw-gateway --no-pager -l 2>&1 || true
echo ""
log_info "=== Life Agent (User Service) ==="
systemctl --user status openclaw-gateway-life --no-pager -l 2>&1 || true
echo ""
log_info "=== Agent Monitor (System Service) ==="
systemctl status openclaw-agent-monitor --no-pager -l 2>&1 || true
echo ""
log_info "=== Recent Gateway Logs ==="
journalctl --user -u openclaw-gateway --no-pager -n 10
echo ""
log_info "=== Recent Life Agent Logs ==="
journalctl --user -u openclaw-gateway-life --no-pager -n 10
echo ""
log_info "=== Recent Monitor Logs ==="
journalctl -u openclaw-agent-monitor --no-pager -n 10
}
show_logs() {
setup_user_env
log_info "Showing recent gateway logs (last 50 lines)..."
journalctl --user -u openclaw-gateway --no-pager -n 50
echo ""
log_info "Showing recent life agent logs (last 50 lines)..."
journalctl --user -u openclaw-gateway-life --no-pager -n 50
echo ""
log_info "Showing recent monitor logs (last 50 lines)..."
journalctl -u openclaw-agent-monitor --no-pager -n 50
}
rollback() {
log_warning "This will rollback the workspace to the previous git commit!"
read -p "Are you sure? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
cd "$WORKSPACE"
# Create backup before rollback
backup
# Show current commit
log_info "Current commit:"
git log -1 --oneline
# Rollback
git reset --hard HEAD~1
log_success "Rolled back to previous commit!"
log_info "Restarting services to apply changes..."
restart_services
else
log_info "Rollback cancelled."
fi
}
rollback_to() {
if [ -z "$1" ]; then
log_error "Please specify a commit hash or tag"
exit 1
fi
log_warning "This will rollback the workspace to commit: $1"
read -p "Are you sure? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
cd "$WORKSPACE"
backup
git reset --hard "$1"
log_success "Rolled back to commit: $1"
restart_services
else
log_info "Rollback cancelled."
fi
}
backup() {
local backup_dir="/root/.openclaw/backups"
mkdir -p "$backup_dir"
log_info "Creating backup..."
# Backup workspace
tar -czf "$backup_dir/workspace-$TIMESTAMP.tar.gz" \
--exclude='.git' \
--exclude='logs' \
-C /root/.openclaw workspace
# Backup config
cp /root/.openclaw/openclaw.json "$backup_dir/openclaw-config-$TIMESTAMP.json" 2>/dev/null || true
log_success "Backup created: $backup_dir/workspace-$TIMESTAMP.tar.gz"
}
health_check() {
log_info "Running health check..."
setup_user_env
local issues=0
if systemctl --user is-active --quiet openclaw-gateway 2>/dev/null; then
log_success "✓ Gateway is running"
else
log_error "✗ Gateway is not running"
((issues++))
fi
if systemctl --user is-active --quiet openclaw-gateway-life 2>/dev/null; then
log_success "✓ Life Agent is running"
else
log_error "✗ Life Agent is not running"
((issues++))
fi
if systemctl is-active --quiet openclaw-agent-monitor; then
log_success "✓ Agent Monitor is running"
else
log_error "✗ Agent Monitor is not running"
((issues++))
fi
# Check disk space
local disk_usage=$(df -h /root | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$disk_usage" -lt 80 ]; then
log_success "✓ Disk usage: ${disk_usage}%"
else
log_warning "⚠ Disk usage: ${disk_usage}%"
((issues++))
fi
# Check memory
local mem_usage=$(free | grep Mem | awk '{printf("%.0f", $3/$2 * 100.0)}')
if [ "$mem_usage" -lt 80 ]; then
log_success "✓ Memory usage: ${mem_usage}%"
else
log_warning "⚠ Memory usage: ${mem_usage}%"
((issues++))
fi
# Check XDG_RUNTIME_DIR
if [ -d "$XDG_RUNTIME_DIR" ]; then
log_success "✓ XDG_RUNTIME_DIR exists: $XDG_RUNTIME_DIR"
else
log_warning "⚠ XDG_RUNTIME_DIR not found"
((issues++))
fi
# Check linger status
if loginctl show-user $(whoami) -p Linger | grep -q "yes"; then
log_success "✓ User linger is enabled"
else
log_warning "⚠ User linger is NOT enabled (run: loginctl enable-linger)"
((issues++))
fi
echo ""
if [ $issues -eq 0 ]; then
log_success "All health checks passed!"
return 0
else
log_error "$issues health check(s) failed!"
return 1
fi
}
show_help() {
echo "OpenClaw System Management Script"
echo ""
echo "Usage: $0 <command>"
echo ""
echo "Commands:"
echo " install - Install and start all systemd services"
echo " start - Start all services (gateway + life + monitor)"
echo " stop - Stop all services"
echo " restart - Restart all services"
echo " status - Show service status"
echo " logs - Show recent logs"
echo " health - Run health check"
echo " backup - Create backup of current state"
echo " rollback - Rollback to previous git commit"
echo " rollback-to - Rollback to specific commit"
echo " debug-stop - Stop ALL services including monitor (safe for debugging)"
echo " debug-start - Restart all services after debugging"
echo " fix-service - Re-inject EnvironmentFile after OpenClaw UI upgrade"
echo " help - Show this help message"
echo ""
}
# Main
case "${1:-help}" in
install)
install_services
;;
start)
start_services
;;
stop)
stop_services
;;
restart)
restart_services
;;
status)
show_status
;;
logs)
show_logs
;;
health)
health_check
;;
backup)
backup
;;
rollback)
rollback
;;
rollback-to)
rollback_to "$2"
;;
debug-stop)
debug_stop
;;
debug-start)
debug_start
;;
fix-service)
fix_service_files
;;
help|--help|-h)
show_help
;;
*)
log_error "Unknown command: $1"
show_help
exit 1
;;
esac