secubox-openwrt/package/secubox/secubox-app-mmpm/files/usr/sbin/mmpmctl
CyberMind-FR 8c72679dea fix(mmpm): Update to MMPM v4.x CLI syntax for UI management
- Use `mmpm ui --start/--stop/--status` instead of `mmpm ui --port --host`
- MMPM v4 manages GUI via pm2, not direct execution
- Update status command to check pm2 status and get URL from mmpm
- Auto-install UI if not present when starting service

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 13:40:11 +01:00

329 lines
7.5 KiB
Bash

#!/bin/sh
# MMPM - MagicMirror Package Manager controller
# Manages MMPM inside MagicMirror2 LXC container
# Copyright (C) 2024-2026 CyberMind.fr
CONFIG="mmpm"
LXC_NAME="magicmirror2"
MMPM_REPO="https://github.com/Bee-Mar/mmpm.git"
usage() {
cat <<'EOF'
Usage: mmpmctl <command> [options]
Commands:
install Install MMPM in MagicMirror2 container
update Update MMPM to latest version
status Show MMPM status
logs Show MMPM logs (use -f to follow)
shell Open shell in container (MMPM context)
service-run Internal: run MMPM GUI under procd
service-stop Stop MMPM GUI
Module Management (via MMPM):
search <query> Search for modules
list List installed modules
install <module> Install a module
remove <module> Remove a module
upgrade [module] Upgrade module(s)
Examples:
mmpmctl install
mmpmctl search weather
mmpmctl install MMM-WeatherChart
mmpmctl list
MMPM Web GUI: http://<router-ip>:7891
EOF
}
log_info() { echo "[INFO] $*"; }
log_warn() { echo "[WARN] $*" >&2; }
log_error() { echo "[ERROR] $*" >&2; }
uci_get() { uci -q get ${CONFIG}.$1; }
uci_set() { uci set ${CONFIG}.$1="$2" && uci commit ${CONFIG}; }
load_config() {
port="$(uci_get main.port || echo 7891)"
address="$(uci_get main.address || echo 0.0.0.0)"
enabled="$(uci_get main.enabled || echo 0)"
}
# Check if MagicMirror2 LXC is running
check_mm2_running() {
if ! lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"; then
log_error "MagicMirror2 container not running"
log_error "Start it first: /etc/init.d/magicmirror2 start"
return 1
fi
return 0
}
# MMPM binary path inside container
MMPM_BIN="/usr/local/bin/mmpm"
# Node.js PATH inside container (for npm)
NODE_PATH="/opt/nodejs/node-v24.13.0/bin:/usr/local/bin:/usr/bin:/bin"
# Check if MMPM is installed in container
is_mmpm_installed() {
lxc-attach -n "$LXC_NAME" -- test -x "$MMPM_BIN"
}
# Run MMPM command with proper PATH (for npm access)
run_mmpm() {
lxc-attach -n "$LXC_NAME" -- sh -c "export PATH=$NODE_PATH:\$PATH && $MMPM_BIN $*"
}
# Install MMPM in container
cmd_install() {
check_mm2_running || return 1
if is_mmpm_installed; then
log_info "MMPM is already installed"
return 0
fi
log_info "Installing MMPM in MagicMirror2 container..."
# Install dependencies and MMPM via pip
lxc-attach -n "$LXC_NAME" -- sh -c '
# Update package lists
apt-get update 2>/dev/null || apk update 2>/dev/null || true
# Install Python and pip if not present
if ! command -v pip3 >/dev/null 2>&1; then
apt-get install -y python3 python3-pip python3-venv 2>/dev/null || \
apk add python3 py3-pip 2>/dev/null || true
fi
# Install MMPM via pip (--break-system-packages for Debian Trixie PEP 668)
pip3 install --upgrade --break-system-packages mmpm 2>/dev/null || \
pip3 install --upgrade mmpm 2>/dev/null || \
pip install --upgrade --break-system-packages mmpm 2>/dev/null || \
pip install --upgrade mmpm
# Initialize MMPM database
mmpm db --yes 2>/dev/null || true
' || {
log_error "Failed to install MMPM"
return 1
}
log_info "MMPM installed successfully"
log_info "Enable and start the GUI: /etc/init.d/mmpm enable && /etc/init.d/mmpm start"
}
# Update MMPM
cmd_update() {
check_mm2_running || return 1
if ! is_mmpm_installed; then
log_error "MMPM not installed. Run 'mmpmctl install' first"
return 1
fi
log_info "Updating MMPM..."
lxc-attach -n "$LXC_NAME" -- pip3 install --upgrade --break-system-packages mmpm 2>/dev/null || \
lxc-attach -n "$LXC_NAME" -- pip3 install --upgrade mmpm || {
log_error "Failed to update MMPM"
return 1
}
log_info "MMPM updated successfully"
}
# Show status
cmd_status() {
load_config
echo "=== MMPM Status ==="
echo ""
if ! lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"; then
echo "MagicMirror2 container: NOT RUNNING"
echo "MMPM: N/A (container not running)"
return
fi
echo "MagicMirror2 container: RUNNING"
if is_mmpm_installed; then
local version=$(run_mmpm version 2>/dev/null | head -1 || echo "unknown")
echo "MMPM installed: YES (v$version)"
else
echo "MMPM installed: NO"
echo ""
echo "Install with: mmpmctl install"
return
fi
echo ""
echo "=== GUI Status ==="
# Check if GUI is running via pm2
local ui_status=$(run_mmpm ui --status 2>/dev/null | grep "mmpm.ui" | grep -c "online" || echo "0")
if [ "$ui_status" != "0" ]; then
local gui_url=$(run_mmpm ui --url 2>/dev/null | grep -oE 'http://[^[:space:]]+' || echo "")
echo "GUI Status: RUNNING (pm2)"
echo "GUI URL: $gui_url"
else
echo "GUI Status: NOT RUNNING"
echo "Start with: /etc/init.d/mmpm start"
fi
}
# Show logs
cmd_logs() {
if [ "$1" = "-f" ]; then
logread -f -e mmpm
else
logread -e mmpm | tail -100
fi
}
# Start MMPM GUI (via pm2)
cmd_service_run() {
check_mm2_running || return 1
if ! is_mmpm_installed; then
log_error "MMPM not installed"
return 1
fi
log_info "Starting MMPM GUI..."
# Check if UI is installed, if not install it
local ui_status=$(run_mmpm ui --status 2>/dev/null | grep -c "mmpm.ui" || echo "0")
if [ "$ui_status" = "0" ]; then
log_info "Installing MMPM UI..."
run_mmpm ui install --yes 2>/dev/null || true
fi
# Start MMPM GUI via pm2
run_mmpm ui --start
}
# Stop MMPM GUI
cmd_service_stop() {
check_mm2_running || return 1
if ! is_mmpm_installed; then
return 0
fi
log_info "Stopping MMPM GUI..."
run_mmpm ui --stop 2>/dev/null || true
}
# Search modules
cmd_search() {
local query="$1"
check_mm2_running || return 1
if ! is_mmpm_installed; then
log_error "MMPM not installed"
return 1
fi
if [ -z "$query" ]; then
log_error "Search query required"
return 1
fi
run_mmpm search "$query"
}
# List installed modules
cmd_list() {
check_mm2_running || return 1
if ! is_mmpm_installed; then
log_error "MMPM not installed"
return 1
fi
run_mmpm list --installed
}
# Install module via MMPM
cmd_module_install() {
local module="$1"
check_mm2_running || return 1
if ! is_mmpm_installed; then
log_error "MMPM not installed"
return 1
fi
if [ -z "$module" ]; then
log_error "Module name required"
return 1
fi
log_info "Installing module: $module"
run_mmpm install "$module" --yes
}
# Remove module via MMPM
cmd_module_remove() {
local module="$1"
check_mm2_running || return 1
if ! is_mmpm_installed; then
log_error "MMPM not installed"
return 1
fi
if [ -z "$module" ]; then
log_error "Module name required"
return 1
fi
log_info "Removing module: $module"
run_mmpm remove "$module" --yes
}
# Upgrade modules
cmd_upgrade() {
local module="$1"
check_mm2_running || return 1
if ! is_mmpm_installed; then
log_error "MMPM not installed"
return 1
fi
if [ -n "$module" ]; then
log_info "Upgrading module: $module"
run_mmpm upgrade "$module" --yes
else
log_info "Upgrading all modules..."
run_mmpm upgrade --yes
fi
}
# Open shell in container
cmd_shell() {
check_mm2_running || return 1
lxc-attach -n "$LXC_NAME" -- /bin/sh
}
# Main entry point
case "${1:-}" in
install) shift; cmd_install "$@" ;;
update) shift; cmd_update "$@" ;;
status) shift; cmd_status "$@" ;;
logs) shift; cmd_logs "$@" ;;
shell) shift; cmd_shell "$@" ;;
service-run) shift; cmd_service_run "$@" ;;
service-stop) shift; cmd_service_stop "$@" ;;
search) shift; cmd_search "$@" ;;
list) shift; cmd_list "$@" ;;
install-module) shift; cmd_module_install "$@" ;;
remove) shift; cmd_module_remove "$@" ;;
upgrade) shift; cmd_upgrade "$@" ;;
help|--help|-h|'') usage ;;
*) echo "Unknown command: $1" >&2; usage >&2; exit 1 ;;
esac