#!/bin/bash # mds - Media Downloader Services manager # Usage: mds [command] [service(s)...] # # Commands: # status - Show status of services (default) # start - Start service(s) # stop - Stop service(s) # restart - Restart service(s) # logs - Show recent logs for a service # # Services: # all - All services # scheduler - media-downloader (scheduler) # api - media-downloader-api # frontend - media-downloader-frontend # xvfb - xvfb-media-downloader # proxy - unified-proxy (Docker) # cache - media-cache-builder # enrich - media-celebrity-enrichment # embeddings - media-embedding-generator # dbcleanup - media-downloader-db-cleanup # backup - cloud-backup-sync # backupui - backup-central (web UI) # # Examples: # mds # status of all services # mds status # same # mds restart api # restart just the API # mds restart api frontend # restart API and frontend # mds restart all # restart all services # mds stop scheduler # stop the scheduler # mds logs scheduler # show scheduler logs set -euo pipefail # Color codes RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' BOLD='\033[1m' DIM='\033[2m' NC='\033[0m' # No Color # Service name mapping declare -A SERVICE_MAP=( [scheduler]="media-downloader" [api]="media-downloader-api" [frontend]="media-downloader-frontend" [xvfb]="xvfb-media-downloader" [cache]="media-cache-builder" [enrich]="media-celebrity-enrichment" [embeddings]="media-embedding-generator" [dbcleanup]="media-downloader-db-cleanup" [backup]="cloud-backup-sync" [backupui]="backup-central" ) ALL_ALIASES=(scheduler api frontend xvfb proxy cache enrich embeddings dbcleanup backup backupui) resolve_service() { local alias="$1" if [[ "$alias" == "proxy" ]]; then echo "proxy" elif [[ -n "${SERVICE_MAP[$alias]+x}" ]]; then echo "${SERVICE_MAP[$alias]}" else # Try as a literal service name for key in "${!SERVICE_MAP[@]}"; do if [[ "${SERVICE_MAP[$key]}" == "$alias" ]]; then echo "$alias" return fi done echo "" fi } get_alias() { local service="$1" for key in "${!SERVICE_MAP[@]}"; do if [[ "${SERVICE_MAP[$key]}" == "$service" ]]; then echo "$key" return fi done echo "$service" } print_status_line() { local alias="$1" local service="$2" if [[ "$alias" == "proxy" ]]; then # Docker container local state state=$(docker inspect -f '{{.State.Status}}' unified-proxy 2>/dev/null || echo "not found") local uptime uptime=$(docker inspect -f '{{.State.StartedAt}}' unified-proxy 2>/dev/null || echo "") local color="$RED" local symbol="●" if [[ "$state" == "running" ]]; then color="$GREEN" fi printf " ${color}${symbol}${NC} %-12s %-30s %s\n" "$alias" "unified-proxy (docker)" "$state" return fi local active_state sub_state active_state=$(systemctl show -p ActiveState --value "$service" 2>/dev/null || echo "unknown") sub_state=$(systemctl show -p SubState --value "$service" 2>/dev/null || echo "unknown") local color="$RED" local symbol="●" case "$active_state" in active) color="$GREEN" ;; inactive) if [[ "$sub_state" == "failed" ]]; then color="$RED" else color="$DIM" fi ;; deactivating) color="$YELLOW" ;; activating) color="$BLUE" ;; failed) color="$RED" ;; esac # Get memory and uptime local memory="" local pid="" if [[ "$active_state" == "active" ]]; then memory=$(systemctl show -p MemoryCurrent --value "$service" 2>/dev/null || echo "") pid=$(systemctl show -p MainPID --value "$service" 2>/dev/null || echo "") if [[ -n "$memory" && "$memory" != "[not set]" && "$memory" != "infinity" ]]; then # Convert bytes to human readable local mem_mb=$((memory / 1024 / 1024)) if [[ $mem_mb -gt 1024 ]]; then local mem_gb=$((mem_mb / 1024)) local mem_frac=$(( (mem_mb % 1024) * 10 / 1024 )) memory="${mem_gb}.${mem_frac}G" else memory="${mem_mb}M" fi else memory="" fi fi local details if [[ "$active_state" == "inactive" && "$sub_state" == "dead" ]]; then details="stopped" elif [[ "$active_state" == "failed" || "$sub_state" == "failed" ]]; then details="failed" elif [[ "$active_state" == "active" && "$sub_state" == "running" ]]; then details="running" else details="$active_state ($sub_state)" fi if [[ -n "$memory" ]]; then details="$details ${DIM}mem: ${memory}${NC}" fi if [[ -n "$pid" && "$pid" != "0" ]]; then details="$details ${DIM}pid: ${pid}${NC}" fi printf " ${color}${symbol}${NC} %-12s %-30s %b\n" "$alias" "$service" "$details" } do_status() { local services=("$@") if [[ ${#services[@]} -eq 0 ]]; then services=("${ALL_ALIASES[@]}") fi echo -e "\n${BOLD}Media Downloader Services${NC}\n" for alias in "${services[@]}"; do local service service=$(resolve_service "$alias") if [[ -z "$service" ]]; then echo -e " ${RED}?${NC} ${alias} (unknown service)" continue fi print_status_line "$alias" "$service" done echo "" } do_action() { local action="$1" shift local services=("$@") if [[ ${#services[@]} -eq 0 ]]; then echo -e "${RED}Error: specify service(s) or 'all'${NC}" echo "Usage: mds $action [service(s)...]" exit 1 fi # Expand 'all' if [[ "${services[0]}" == "all" ]]; then services=("${ALL_ALIASES[@]}") fi for alias in "${services[@]}"; do local service service=$(resolve_service "$alias") if [[ -z "$service" ]]; then echo -e " ${RED}✗${NC} ${alias}: unknown service" continue fi if [[ "$alias" == "proxy" ]]; then case "$action" in start) echo -e " ${CYAN}▶${NC} Starting unified-proxy..." docker start unified-proxy 2>/dev/null && echo -e " ${GREEN}✓${NC} unified-proxy started" || echo -e " ${RED}✗${NC} Failed to start unified-proxy" ;; stop) echo -e " ${YELLOW}■${NC} Stopping unified-proxy..." docker stop unified-proxy 2>/dev/null && echo -e " ${GREEN}✓${NC} unified-proxy stopped" || echo -e " ${RED}✗${NC} Failed to stop unified-proxy" ;; restart) echo -e " ${CYAN}↻${NC} Restarting unified-proxy..." docker restart unified-proxy 2>/dev/null && echo -e " ${GREEN}✓${NC} unified-proxy restarted" || echo -e " ${RED}✗${NC} Failed to restart unified-proxy" ;; esac continue fi case "$action" in start) echo -e " ${CYAN}▶${NC} Starting ${alias} (${service})..." sudo systemctl start "$service" && echo -e " ${GREEN}✓${NC} ${alias} started" || echo -e " ${RED}✗${NC} Failed to start ${alias}" ;; stop) echo -e " ${YELLOW}■${NC} Stopping ${alias} (${service})..." sudo systemctl stop "$service" && echo -e " ${GREEN}✓${NC} ${alias} stopped" || echo -e " ${RED}✗${NC} Failed to stop ${alias}" ;; restart) echo -e " ${CYAN}↻${NC} Restarting ${alias} (${service})..." sudo systemctl restart "$service" && echo -e " ${GREEN}✓${NC} ${alias} restarted" || echo -e " ${RED}✗${NC} Failed to restart ${alias}" ;; esac done } do_logs() { local alias="${1:-scheduler}" local service service=$(resolve_service "$alias") if [[ -z "$service" ]]; then echo -e "${RED}Unknown service: ${alias}${NC}" exit 1 fi if [[ "$alias" == "proxy" ]]; then docker logs --tail 50 unified-proxy return fi sudo journalctl -u "$service" --no-pager -n 50 } # Main command="${1:-status}" shift 2>/dev/null || true case "$command" in status|st|s) do_status "$@" ;; start) do_action start "$@" ;; stop) do_action stop "$@" ;; restart|rs|r) do_action restart "$@" ;; logs|log|l) do_logs "$@" ;; help|--help|-h) head -27 "$0" | tail -25 ;; *) echo -e "${RED}Unknown command: ${command}${NC}" echo "Commands: status, start, stop, restart, logs" exit 1 ;; esac