#!/usr/bin/env bash # # Unified installer: backvicibox + Custom (CSS/logos) # - Ejecuta TODO desde un solo script interactivo # - Se puede lanzar desde cualquier ruta: usa su propio directorio como base # set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" LOG_FILE="${SCRIPT_DIR}/unified_installer.log" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' info() { echo -e "${GREEN}[INFO]${NC} $1" | tee -a "$LOG_FILE"; } warn() { echo -e "${YELLOW}[WARN]${NC} $1" | tee -a "$LOG_FILE"; } error() { echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE" >&2; } need_root() { if [[ "${EUID}" -ne 0 ]]; then error "Ejecuta como root: sudo $0" exit 1 fi } have_cmd() { command -v "$1" >/dev/null 2>&1; } copy_tree() { local src="$1" local dst="$2" mkdir -p "$dst" if have_cmd rsync; then rsync -a --delete "$src"/ "$dst"/ else cp -a "$src"/. "$dst"/ fi } prompt_yn() { local prompt="$1" local default="${2:-Y}" # Y/N local ans="" while true; do if [[ "$default" == "Y" ]]; then read -r -p "${prompt} [Y/n]: " ans || true ans="${ans:-Y}" else read -r -p "${prompt} [y/N]: " ans || true ans="${ans:-N}" fi case "$ans" in Y|y) return 0 ;; N|n) return 1 ;; *) echo "Responde Y o N." ;; esac done } prompt_text() { local prompt="$1" local default="${2:-}" local ans="" if [[ -n "$default" ]]; then read -r -p "${prompt} [${default}]: " ans || true ans="${ans:-$default}" else read -r -p "${prompt}: " ans || true fi printf '%s' "$ans" } print_menu() { cat <<'EOF' Selecciona qué quieres ejecutar (multi-selección permitida: ej. 1,3,4): 1) Stage assets (copiar Custom/backvicibox -> /home/backvicibox y Custom/installer custom -> HTDOCS/agc/css/installer) 2) Instalar backvicibox (ejecuta /home/backvicibox/install-vicibox.sh) 3) Custom: instalar CSS/logos (HTDOCS/agc/css/installer/install_custom_css.sh install) 4) Custom: status (HTDOCS/agc/css/installer/install_custom_css.sh status) 5) Custom: uninstall (HTDOCS/agc/css/installer/install_custom_css.sh uninstall) 6) Crear admin sapian (ejecuta /home/backvicibox/create-admin-sapian.sh) 7) Salir EOF } parse_multiselect() { # input: "1, 3 4" -> prints unique numbers one per line local raw="$1" raw="${raw//,/ }" # shellcheck disable=SC2206 local parts=($raw) for p in "${parts[@]}"; do [[ "$p" =~ ^[0-9]+$ ]] || continue echo "$p" done | awk '!seen[$0]++' } require_paths() { local back_src="${SCRIPT_DIR}/backvicibox" local inst_custom_src="${SCRIPT_DIR}/installer custom" [[ -d "$back_src" ]] || { error "No existe: ${back_src}"; exit 1; } [[ -d "$inst_custom_src" ]] || { error "No existe: ${inst_custom_src}"; exit 1; } } do_stage() { local htdocs="$1" local back_src="${SCRIPT_DIR}/backvicibox" local inst_custom_src="${SCRIPT_DIR}/installer custom" local back_dst="/home/backvicibox" local inst_dst="${htdocs}/agc/css/installer" info "Staging assets..." info " Origen backvicibox: ${back_src}" info " Destino backvicibox: ${back_dst}" info " Origen installer custom: ${inst_custom_src}" info " Destino installer: ${inst_dst}" copy_tree "$back_src" "$back_dst" copy_tree "$inst_custom_src" "$inst_dst" chmod +x "${back_dst}/"*.sh 2>/dev/null || true chmod +x "${inst_dst}/install_custom_css.sh" 2>/dev/null || true info "Stage completado." } do_backvicibox_install() { local back_dst="/home/backvicibox" local script="${back_dst}/install-vicibox.sh" [[ -x "$script" ]] || { error "No ejecutable/no existe: ${script}. Ejecuta primero 'Stage assets'."; exit 1; } info "Ejecutando backvicibox: ${script}" ( cd "$back_dst" && "$script" ) } do_custom() { local htdocs="$1" local action="$2" # install|uninstall|status local inst_dst="${htdocs}/agc/css/installer" local script="${inst_dst}/install_custom_css.sh" [[ -x "$script" ]] || { error "No ejecutable/no existe: ${script}. Ejecuta primero 'Stage assets'."; exit 1; } info "Ejecutando Custom: HTDOCS=${htdocs} ${script} ${action}" HTDOCS="$htdocs" "$script" "$action" } do_create_admin() { local back_dst="/home/backvicibox" local script="${back_dst}/create-admin-sapian.sh" [[ -x "$script" ]] || { error "No ejecutable/no existe: ${script}. Ejecuta primero 'Stage assets'."; exit 1; } info "Creando admin sapian: ${script}" ( cd "$back_dst" && "$script" ) } main() { need_root require_paths info "==========================================" info "Unified Installer (backvicibox + Custom)" info "Base: ${SCRIPT_DIR}" info "Log: ${LOG_FILE}" info "==========================================" local htdocs htdocs="$(prompt_text "Ruta HTDOCS (donde están vicidial/agc/VERM)" "/srv/www/htdocs")" if [[ ! -d "$htdocs" ]]; then error "HTDOCS no existe: ${htdocs}" exit 1 fi while true; do print_menu local sel sel="$(prompt_text "Opción(es)" "1,2,3")" local any=0 while read -r opt; do any=1 case "$opt" in 1) do_stage "$htdocs" ;; 2) do_backvicibox_install ;; 3) do_custom "$htdocs" install ;; 4) do_custom "$htdocs" status ;; 5) if prompt_yn "Confirmas desinstalar Custom (restaurará backups si existen)?" "N"; then do_custom "$htdocs" uninstall else info "Uninstall cancelado." fi ;; 6) do_create_admin ;; 7) info "Saliendo."; return 0 ;; *) warn "Opción inválida: $opt" ;; esac done < <(parse_multiselect "$sel") if [[ "$any" -eq 0 ]]; then warn "No entendí la selección: '$sel'" fi echo "" if ! prompt_yn "Quieres ejecutar otra acción?" "Y"; then info "Listo." return 0 fi done } main "$@"