From d00fbae6c322494fae447d2ed915b69fe3903a24 Mon Sep 17 00:00:00 2001 From: Frogg Date: Thu, 7 May 2026 23:40:22 +0200 Subject: [PATCH] =?UTF-8?q?-=20Ajout=20d=20un=20installer=20des=20fonction?= =?UTF-8?q?nalit=C3=A9=20pour=20uniformiser=20les=20linux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 777-welcome.sh | 6 +- TODO.md | 32 +--- config/config_cmd.sh | 23 ++- config/config_colors.sh | 2 +- config/config_conf.sh | 2 +- config/config_install.sh | 22 +++ func/common.sh | 10 ++ func/deb_sys.sh | 348 +++++++++++++++++++++++++++++++++++++++ func/mail.sh | 3 +- func/message.sh | 2 +- func/message_display.sh | 2 +- func/network.sh | 2 +- func/services_check.sh | 13 +- func/system_info.sh | 6 +- inc/alias.sh | 15 +- inc/infos.sh | 5 +- inc/mail_connect.sh | 4 +- inc/ps1.sh | 6 +- info/cmd | 1 + script/install.sh | 121 ++++++++++++++ 20 files changed, 566 insertions(+), 59 deletions(-) create mode 100644 config/config_install.sh create mode 100644 func/deb_sys.sh create mode 100644 script/install.sh diff --git a/777-welcome.sh b/777-welcome.sh index aa5a7c0..6f4014e 100755 --- a/777-welcome.sh +++ b/777-welcome.sh @@ -58,7 +58,5 @@ display_dashboard ################ if [[ $HAS_WELCOME_CONF_ERROR -eq 1 ]];then - msg_error "❎ TODO PROPOSER UNE INSTALL DE CE QUI MANQUE" - msg_error "faire une commande avec proposition, et l autre action pour mettre en place les propositions" - msg_error "basées sur les choses trouvées sur le systeme" -fi \ No newline at end of file + msg_error "Configurations manquantes, veuillez tapez ${COLOR_WHITE}deb-conf${COLOR_LIGHT_RED} pour plus d'informations" +fi diff --git a/TODO.md b/TODO.md index ebf7740..b428b3b 100644 --- a/TODO.md +++ b/TODO.md @@ -1,34 +1,17 @@ - # SCRIPT -- VERIF SI NOM DE L ENV DISPO -- faire un menu tool d install - - dont : - - confg mail - - conf ipv6 - - conf ip - - conf nom de machine - - menu qui propose des choix - - faire la connexion git sans faire pass a chaque fois en script - AJOUTER PLUS D ALIAS - AJOUTER PLUS DE CMD - AJOUTER PLUS DE PATH - - - - - ->> rename la machine -hostnamectl set-hostname gitea +# INFOS > /etc/hosts (changer le nom de la machine) -> > /etc/hostname (changer le nom de la machine) +> /etc/hostname (changer le nom de la machine) +> /etc/msmtprc (conf des mails) -# config de ADMIN_MAIL dans le ENV -ajouter ADMIN_MAIL dans /etc/environment -ADMIN_MAIL="admin@frogg.fr" -# LIB A DIRE D INSTALLER : -jq pour les json en bash -ncdu +- espace en trop PS1 + +# SCRIPT INSTALL +- faire la connexion git sans faire pass a chaque fois en script # GITEA - faire le redirect port 80 @@ -42,3 +25,4 @@ ncdu - config ndv - config gita + diff --git a/config/config_cmd.sh b/config/config_cmd.sh index 22e0bb6..e50d703 100644 --- a/config/config_cmd.sh +++ b/config/config_cmd.sh @@ -17,24 +17,37 @@ CMD_LIST_CONFIG_JSON=$(cat </dev/null } \ No newline at end of file diff --git a/func/deb_sys.sh b/func/deb_sys.sh new file mode 100644 index 0000000..4792d91 --- /dev/null +++ b/func/deb_sys.sh @@ -0,0 +1,348 @@ +check_deb_status() { + local type="$1" params="$2" + case "$type" in + "pkg") dpkg -s "$params" >/dev/null 2>&1 ;; + "sys") + func="check_deb_${type}_${params}" + if declare -F "$func" >/dev/null; then + "$func" + else + return 1 + fi + + #case "$params" in + # "apparmor")check_deb_sys_apparmor;; + # "ipv6") [[ $(sysctl -n net.ipv6.conf.all.disable_ipv6 2>/dev/null) -eq 1 ]] ;; + # "mail") grep -q "ADMIN_MAIL=" /etc/environment 2>/dev/null ;; + # "zabbix") dpkg -s zabbix-agent >/dev/null 2>&1 ;; + # "msmtp") [[ -f /etc/msmtprc ]] ;; + # *) return 1 ;; + #esac ;; + esac +} + +do_deb_install_action() { + local type="$1" params="$2" func + case "$type" in + "pkg") $SUDO apt-get install -y "$params" ;; + "sys") + func="do_deb_${type}_${params}" + if declare -F "$func" >/dev/null; then + "$func" + else + msg_error "la fonction do_deb_${type}_${params} n'est pas définie...(skip)" + fi + esac +} + +check_deb_sys_ipv6(){ + if [[ $(sysctl -n net.ipv6.conf.all.disable_ipv6 2>/dev/null) -eq 1 ]]; then + return 0 + else + return 1 + fi +} + +check_deb_sys_zabbix(){ + if dpkg -s zabbix-agent >/dev/null 2>&1; then + return 0 + else + return 1 + fi +} + +check_deb_sys_msmtp(){ + if [[ -f /etc/msmtprc ]]; then + return 1 + else + return 0 + fi +} + +check_deb_sys_mail(){ + if grep -q "ADMIN_MAIL=" /etc/environment 2>/dev/null; then + return 0 + else + return 1 + fi +} + +check_deb_sys_fail2ban() { + # Si le paquet n'est PAS installé, on ne propose pas la config + if ! dpkg -s fail2ban >/dev/null 2>&1; then + return 0 # Masquer (on attend l'étape 1) + fi + + # Si le paquet est là, on affiche la config tant que jail.local n'existe pas + if [[ ! -f /etc/fail2ban/jail.local ]]; then + return 1 # AFFICHER + else + return 0 # MASQUER (Déjà configuré) + fi +} + +check_deb_sys_apparmor(){ + if is_sys_lxc; then + ! systemctl is-enabled apparmor >/dev/null 2>&1 #Container + else + [[ $($SUDO cat /sys/module/apparmor/parameters/enabled 2>/dev/null) == "Y" ]] #VM + fi +} + +check_deb_sys_ufw() { + # 1. Si le paquet n'est pas là, on ne propose rien + if ! dpkg -s ufw >/dev/null 2>&1; then + return 0 + fi + + # 2. On vérifie l'état réel du firewall + # Si 'Status: active' est trouvé, on cache (0), sinon on affiche (1) + if $SUDO ufw status | grep -q "Status: active"; then + return 0 # Masquer + else + return 1 # AFFICHER + fi +} + +do_deb_sys_ufw() { + local ports_to_allow=() input_port="" current_ssh_port + + msg_info "Configuration interactive du Firewall UFW" + + # 1. On commence par les bases + $SUDO ufw default deny incoming + $SUDO ufw default allow outgoing + + # 2. Boucle de saisie des ports + while true; do + read -p "Entrez un port à ouvrir (ou 'f' pour terminer) : " input_port + + [[ "$input_port" == "f" ]] && break + + # Validation : est-ce un nombre ? + if [[ ! "$input_port" =~ ^[0-9]+$ ]]; then + msg_error "Veuillez entrer un numéro de port valide (chiffres uniquement)." + continue + fi + + # Gestion des DOUBLONS + if [[ " ${ports_to_allow[@]} " =~ " ${input_port} " ]]; then + msg_warning "Le port $input_port est déjà dans votre liste de saisie." + else + ports_to_allow+=("$input_port") + msg_success "Port $input_port ajouté à la file d'attente." + fi + done + + # 3. Sécurité SSH (vérification si le port 22 ou le port courant est là) + # On récupère le port SSH actuel pour éviter de se lock + current_ssh_port=$(ss -tlnp | grep sshd | awk '{print $4}' | awk -F':' '{print $NF}' | head -n1) + current_ssh_port=${current_ssh_port:-22} + + if [[ ! " ${ports_to_allow[@]} " =~ " ${current_ssh_port} " ]]; then + msg_warning "ATTENTION : Votre port SSH ($current_ssh_port) n'est pas dans la liste !" + read -p "Voulez-vous l'ajouter par sécurité ? (O/n) : " add_ssh + [[ "$add_ssh" != "n" ]] && ports_to_allow+=("$current_ssh_port") + fi + + # 4. Application des règles sans doublons dans UFW + msg_info "Application des règles..." + for port in "${ports_to_allow[@]}"; do + # On utilise /tcp par défaut pour être strict comme on l'a dit + $SUDO ufw allow "$port"/tcp >/dev/null + done + + # 5. Désactiver l'IPv6 dans UFW + msg_info "Desactivation de l IP v6..." + $SUDO sed -i 's/IPV6=yes/IPV6=no/' /etc/default/ufw + + # 6. Activation finale + if $SUDO ufw --force enable; then + msg_success "Firewall activé avec les ports : ${ports_to_allow[*]}" + fi +} + +do_deb_sys_fail2ban() { + msg_info "Configuration de Fail2Ban..." + # On crée la configuration personnalisée + $SUDO tee /etc/fail2ban/jail.local </dev/null) != "Y" ]]; then + if [ -f /etc/default/grub ]; then + $SUDO sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="apparmor=1 security=apparmor /' /etc/default/grub + $SUDO update-grub + msg_warning "Activation GRUB faite. Reboot nécessaire." + fi + else + msg_success "AppArmor est déjà actif dans le Kernel." + fi + fi +} + +do_deb_sys_zabbix(){ + read -rp "IP Zabbix : " ip; + $SUDO apt-get install -y zabbix-agent; + $SUDO sed -i "s/^Server=127.0.0.1/Server=$ip/" /etc/zabbix/zabbix_agentd.conf; + $SUDO systemctl restart zabbix-agent +} + +do_deb_sys_ipv6(){ + echo "net.ipv6.conf.all.disable_ipv6 = 1" | $SUDO tee -a /etc/sysctl.conf > /dev/null && $SUDO sysctl -p +} + +do_deb_sys_env_mail(){ + read -rp "Mail admin : " m; + echo "ADMIN_MAIL=\"$m\"" | $SUDO tee -a /etc/environment > /dev/null + # shellcheck disable=SC2034 + ADMIN_MAIL=$m +} + +do_deb_sys_static_ip() { + local interface + interface=$(ip -o link show | awk -F': ' '{print $2}' | grep -v 'lo' | head -n1) + + echo -e "${COLOR_WHITE}Configuration de l'interface : ${COLOR_CYAN}$interface${NONE}" + read -rp "Entrez l'IP (ex: 192.168.1.50) : " new_ip + read -rp "Entrez la Passerelle (Gateway) : " new_gw + read -rp "Entrez le DNS Primaire (ex: 1.1.1.1) : " dns1 + read -rp "Entrez le DNS Secondaire (ex: 8.8.8.8) : " dns2 + + # Validation minimale + if [[ -z "$new_ip" || -z "$new_gw" || -z "$dns1" ]]; then + msg_error "IP, Gateway ou DNS Primaire manquant. Annulation." + return 1 + fi + + # Si le DNS2 est vide, on peut mettre une valeur par défaut ou laisser vide + [[ -z "$dns2" ]] && dns2="8.8.4.4" + + # --- CAS 1 : NETPLAN (Ubuntu / Debian récentes) --- + if [ -d "/etc/netplan" ]; then + msg_info "Configuration via Netplan..." + $SUDO bash -c "cat < /etc/netplan/99-frogg-static.yaml +network: + version: 2 + renderer: networkd + ethernets: + $interface: + addresses: [$new_ip/24] + routes: [{to: default, via: $new_gw}] + nameservers: + addresses: [$dns1, $dns2] +EOF" + $SUDO netplan apply + + # --- CAS 2 : INTERFACES (Debian classique) --- + elif [ -f "/etc/network/interfaces" ]; then + msg_info "Configuration via /etc/network/interfaces..." + $SUDO bash -c "cat < /etc/network/interfaces.d/$interface +auto $interface +iface $interface inet static + address $new_ip + netmask 255.255.255.0 + gateway $new_gw + dns-nameservers $dns1 $dns2 +EOF" + $SUDO systemctl restart networking + else + msg_error "Aucun gestionnaire réseau trouvé." + return 1 + fi + + msg_success "$interface > IP [$new_ip] Gateway[$new_gw] DNS[$dns1, $dns2]" +} + +do_deb_sys_hostname() { + local old_h current_ip + old_h=$(hostname) + echo -e "${COLOR_WHITE}Nom actuel : ${COLOR_CYAN}$old_h${NONE}" + read -rp "Nouveau Hostname (FQDN recommandé, ex: machine.domaine.com) : " new_h + + if [[ -n "$new_h" ]]; then + # 1. On définit le hostname dans le système + $SUDO hostnamectl set-hostname "$new_h" + + # 2. On extrait le nom court + local short_h="${new_h%%.*}" + + # 3. Mise à jour de /etc/hosts + # STRATÉGIE : On identifie la ligne qui contient l'ancien hostname + # et on la remplace intégralement par "IP FQDN NOM_COURT" + + # On récupère l'IP associée à l'ancien hostname dans /etc/hosts + current_ip=$(grep -w "$old_h" /etc/hosts | awk '{print $1}' | head -n1) + + if [[ -n "$current_ip" ]]; then + msg_info "Mise à jour de la ligne pour l'IP $current_ip..." + # On remplace toute la ligne qui commence par cette IP + $SUDO sed -i "s/^$current_ip.*/$current_ip\t$new_h $short_h/" /etc/hosts + else + # Si on ne trouve pas l'IP, on ajoute une ligne propre sur la loopback locale + msg_warning "IP non trouvée dans /etc/hosts, ajout sur 127.0.1.1" + echo -e "127.0.1.1\t$new_h $short_h" | $SUDO tee -a /etc/hosts > /dev/null + fi + + msg_success "Hostname configuré : $new_h ($short_h)" + fi +} + + +do_deb_sys_msmtp() { + msg_info "Installation et configuration de MSMTP..." + + # Installation du paquet + $SUDO apt-get update -qq && $SUDO apt-get install -y msmtp msmtp-mta ca-certificates -qq + + # Saisie des informations + read -rp "Serveur SMTP (host) : " m_host + read -rp "Port (ex: 587 ou 465) : " m_port + read -rp "Email expéditeur (from) : " m_from + read -rp "Utilisateur (user/login) : " m_user + read -s -rp "Mot de passe : " m_pass + echo "" # Pour revenir à la ligne après le mot de passe masqué + + # Construction du fichier msmtprc + $SUDO bash -c "cat < /etc/msmtprc +# Configuration générée par Frogg Deploy +defaults +auth on +tls on +tls_trust_file /etc/ssl/certs/ca-certificates.crt +syslog LOG_MAIL +#logfile /var/log/msmtp.log + +account default +host $m_host +port $m_port +from $m_from +user $m_user +password $m_pass +EOF" + + # Sécurisation du fichier (Indispensable car contient un mot de passe) + $SUDO chmod 600 /etc/msmtprc + $SUDO chown root:root /etc/msmtprc + + msg_success "MSMTP configuré. Test d'envoi recommandé : echo 'Test' | mail -s 'Test sujet' ton@mail.com" +} \ No newline at end of file diff --git a/func/mail.sh b/func/mail.sh index 894eb2b..1d39510 100644 --- a/func/mail.sh +++ b/func/mail.sh @@ -40,7 +40,8 @@ send_login_mail() { fi if [[ -z "${ADMIN_MAIL}" ]]; then - msg_error "ADMIN_MAIL is not defined in /etc/environment" + msg_error "ADMIN_MAIL [${ADMIN_MAIL}] is not defined in /etc/environment" + # shellcheck disable=SC2034 HAS_WELCOME_CONF_ERROR=1 return 1 # ou exit 1 selon si c'est dans une fonction ou un script fi diff --git a/func/message.sh b/func/message.sh index 16965a8..065d622 100644 --- a/func/message.sh +++ b/func/message.sh @@ -13,7 +13,7 @@ msg_status_text() echo -e "${COLOR_LIGHT_RED}❎ ${msg}${NONE}" ;; info|inf) - echo -e "${COLOR_LIGHT_BLUE}ℹ️ ${msg}${NONE}" + echo -e "${COLOR_LIGHT_BLUE}🚀 ${msg}${NONE}" ;; *) echo -e "${msg}" diff --git a/func/message_display.sh b/func/message_display.sh index f70fea4..0211f1c 100644 --- a/func/message_display.sh +++ b/func/message_display.sh @@ -70,7 +70,7 @@ draw_bar() { local empty=$((size - filled)) # Affichage de la barre - printf "${NONE}[" + echo -ne "${NONE}[" echo -ne "${color}" for ((i=0; i/dev/null 2>&1; then + status=$(msg_status_text success "actif (conf sur l'hôte)") + display_line "AppArmor" "$status" + else + status=$(msg_status_text error "non disponible (conf sur l'hôte)") + display_line "AppArmor" "$status" + fi + return + fi + if [ ! -d /sys/kernel/security/apparmor ]; then status=$(msg_status_text error "non disponible") display_line "AppArmor" "$status" diff --git a/func/system_info.sh b/func/system_info.sh index f3ef605..e08fc2f 100644 --- a/func/system_info.sh +++ b/func/system_info.sh @@ -10,13 +10,11 @@ get_hardware_info() { disk_ko=$(df -k / | awk 'NR==2 {print $2}') disk_pretty=$(format_size "$disk_ko") - F_HARD="${COLOR_WHITE}C:$(nproc)Core M:${ram_pretty} D:${disk_pretty}" + F_HARD="Core=${COLOR_WHITE}$(nproc) ${COLOR_YELLOW}M=${COLOR_WHITE}${ram_pretty} ${COLOR_YELLOW}D=${COLOR_WHITE}${disk_pretty}" - F_CPU="${COLOR_WHITE}$(lscpu | grep 'Model name' | cut -d: -f2 | sed 's/^[ \t]*//; s/[ \t]*@.*//; s/ [0-9.]*GHz//i')" + F_CPU="${COLOR_WHITE}$(lscpu | grep 'Model name' | cut -d: -f2 | sed 's/^[ \t]*//; s/[ \t]*@.*//; s/ [0-9.]*GHz//i; s/(R)//g; s/(TM)//g; s/ CPU//g; s/ */ /g; s/[ \t]*$//')" } - - get_network_info() { F_IPS="${COLOR_WHITE}$(hostname -I)" } diff --git a/inc/alias.sh b/inc/alias.sh index 1559105..76f668e 100644 --- a/inc/alias.sh +++ b/inc/alias.sh @@ -5,7 +5,9 @@ alias cmd='bash /etc/profile.d/info/cmd' alias conf='bash /etc/profile.d/info/conf' alias colors='bash /etc/profile.d/info/colors' alias welcome='bash /etc/profile.d/777-welcome.sh' +alias deb-conf='bash /etc/profile.d/script/install.sh' #endregion + #region Shortcut BASICS alias cls='clear' alias ll='ls -lah' @@ -14,13 +16,15 @@ alias ..='cd ..' alias ...='cd ../..' alias home='welcome && cd ~' alias ffs='find / \( -path /proc -o -path /sys -o -path /dev -o -path /run \) -prune -o -type f -iname' -alias ff='sudo find / \( -path /proc -o -path /sys -o -path /dev -o -path /run \) -prune -o -type f -name' +alias ff='find / \( -path /proc -o -path /sys -o -path /dev -o -path /run \) -prune -o -type f -name' #endregion + #region Shortcut APT -alias update='sudo apt update && sudo apt upgrade -y' -alias install='sudo apt install' -alias remove='sudo apt remove' +alias update='apt update && sudo apt upgrade -y' +alias script='apt script' +alias remove='apt remove' #endregion + #region Shortcut DEBUG alias func='declare -F' alias grep='grep --color=auto' @@ -33,17 +37,18 @@ alias cpu='top -o %CPU' alias mem='top -o %MEM' alias hdd='ncdu' #endregion + #region Shortcut NETWORK alias myip='curl ifconfig.me' alias localip='ip a' #endregion + #region Shortcut APACHE alias wra='systemctl restart apache2' alias werr='tail -fn 100 /var/log/apache2/error.log' alias wlog='tail -fn 100 /var/log/apache2/access.log /var/log/apache2/error.log' #endregion - #region Shortcut GIT # LOAD GIT FUNCS if [[ -z "${WELCOME_SCRIPT_PATH}" ]]; then diff --git a/inc/infos.sh b/inc/infos.sh index dc6d6dd..c053627 100644 --- a/inc/infos.sh +++ b/inc/infos.sh @@ -8,7 +8,4 @@ fi # Infos echo "" -echo -e "${COLOR_YELLOW}Type ${COLOR_WHITE}cmd${COLOR_YELLOW}, ${COLOR_WHITE}conf${COLOR_YELLOW}, ${COLOR_WHITE}colors ${COLOR_YELLOW}or ${COLOR_WHITE}alias ${COLOR_YELLOW}for more information...${NONE}" -echo "" - - +echo -e "${COLOR_YELLOW}Type ${COLOR_WHITE}cmd${COLOR_YELLOW}, ${COLOR_WHITE}conf${COLOR_YELLOW}, ${COLOR_WHITE}colors${COLOR_YELLOW}, ${COLOR_WHITE}alias${COLOR_YELLOW} or ${COLOR_WHITE}deb-conf ${COLOR_YELLOW}for more information...${NONE}" diff --git a/inc/mail_connect.sh b/inc/mail_connect.sh index 4bbc903..2874155 100755 --- a/inc/mail_connect.sh +++ b/inc/mail_connect.sh @@ -2,8 +2,6 @@ if [[ -z "${WELCOME_SCRIPT_PATH}" ]]; then WELCOME_SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." &>/dev/null && pwd)" - USERIP=$("${SSH_CONNECTION%% *}") - FULLNAME=$(hostname).$(hostname --domain) fi #region INCLUDES @@ -13,4 +11,4 @@ fi . "${WELCOME_SCRIPT_PATH}/func/network.sh" #endregion -send_login_mail "$USERIP" "$USER" "$FULLNAME" \ No newline at end of file +send_login_mail "${SSH_CONNECTION%% *}" "$USER" "$(hostname)" \ No newline at end of file diff --git a/inc/ps1.sh b/inc/ps1.sh index cfc443a..04680fb 100644 --- a/inc/ps1.sh +++ b/inc/ps1.sh @@ -42,7 +42,7 @@ get_git_status() { if [[ "$behind" -gt 0 ]]; then # Raccord entre le segment précédent et le segment orange # On utilise la couleur de fond du précédent pour le texte du SEP - echo -ne "${current_color}$(color_secure "$COLOR_ORANGE_BG")${SEP}$(color_secure "$COLOR_WHITE") pull $behind 🆙" + echo -ne "${current_color}$(color_secure "$COLOR_ORANGE_BG")${SEP}$(color_secure "$COLOR_WHITE") pull $behind ✨"#🆙 # On met à jour les variables pour le SEP de fin # shellcheck disable=SC2086 @@ -91,9 +91,9 @@ set_ps1() { if [[ -n "$GIT_PART" ]]; then # On ne met pas d'espace avant ${GIT_PART} car le SEP s'en occupe - PS1="\n${P1}${P2} ${GIT_PART}" + PS1="${P1}${P2} ${GIT_PART}" else - PS1="\n${P1}${P2} ${NONE}$(color_secure "$COLOR_DARK_GRAY")${SEP}${NONE}" + PS1="${P1}${P2} ${NONE}$(color_secure "$COLOR_DARK_GRAY")${SEP}${NONE}" fi # Ligne 2 : Flèche de retour diff --git a/info/cmd b/info/cmd index b38b786..8ff078c 100644 --- a/info/cmd +++ b/info/cmd @@ -19,6 +19,7 @@ if ! command -v jq &> /dev/null; then fi #endregion + #region MAIN display_conditional_list "$CMD_LIST_CONFIG_JSON" #endregion diff --git a/script/install.sh b/script/install.sh new file mode 100644 index 0000000..25ffb76 --- /dev/null +++ b/script/install.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +if [[ -z "${WELCOME_SCRIPT_PATH}" ]]; then + WELCOME_SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." &>/dev/null && pwd)" +fi + +. "${WELCOME_SCRIPT_PATH}/config/config_colors.sh" +. "${WELCOME_SCRIPT_PATH}/config/config_install.sh" +. "${WELCOME_SCRIPT_PATH}/func/common.sh" +. "${WELCOME_SCRIPT_PATH}/func/message.sh" +. "${WELCOME_SCRIPT_PATH}/func/network.sh" +. "${WELCOME_SCRIPT_PATH}/func/deb_sys.sh" + +SUDO="" +[[ "$EUID" -ne 0 ]] && command -v sudo >/dev/null 2>&1 && SUDO="sudo" + +# Vérification JQ (une seule fois) +if ! command -v jq >/dev/null 2>&1; then + echo -e "${COLOR_YELLOW}⚡ JQ manquant... installation...${NONE}" + $SUDO apt-get update -qq && $SUDO apt-get install -y jq -qq +fi + +# ========================================== +# 2. DÉFINITION DES DONNÉES (JSON) +# ========================================== +# OPTIMISATION : On parse le JSON en tableaux Bash UNE SEULE FOIS +mapfile -t ALL_DEB_INSTALL_IDS < <(echo "$CONFIG_DEB_INSTALL_JSON" | jq -r '.[].id') +mapfile -t ALL_DEB_INSTALL_LABELS < <(echo "$CONFIG_DEB_INSTALL_JSON" | jq -r '.[].label') +mapfile -t ALL_DEB_INSTALL_TYPES < <(echo "$CONFIG_DEB_INSTALL_JSON" | jq -r '.[].type') +mapfile -t ALL_DEB_INSTALL_PARAMS < <(echo "$CONFIG_DEB_INSTALL_JSON" | jq -r '.[].params') + +# ========================================== +# 3. LOGIQUE INTERFACE +# ========================================== +do_deb_install_menu(){ + local cursor selected_ids visible_indices + + cursor=0 + selected_ids=() + + while true; do + # On filtre les indices visibles via Bash (très rapide) + visible_indices=() + for i in "${!ALL_DEB_INSTALL_IDS[@]}"; do + if ! check_deb_status "${ALL_DEB_INSTALL_TYPES[$i]}" "${ALL_DEB_INSTALL_PARAMS[$i]}"; then + visible_indices+=("$i") + fi + done + + # Sortie si vide + [[ ${#visible_indices[@]} -eq 0 ]] && echo -e "${COLOR_GREEN}Tout est OK !${NONE}" && exit 0 + + # Affichage + clear + echo -e "${COLOR_LIGHT_BLUE}====[ FROGG DEPLOY ]====${NONE}" + echo -e "Flèches: Naviguer | Espace: Sélectionner | Entrée: Lancer | ${COLOR_LIGHT_RED}q: Quitter ou Ctrl+C${NONE}\n" + + for i in "${!visible_indices[@]}"; do + idx=${visible_indices[$i]} + id=${ALL_DEB_INSTALL_IDS[$idx]} + + [[ $i -eq $cursor ]] && echo -ne "${COLOR_CYAN}> ${NONE}" || echo -ne " " + + is_selected=false + [[ " ${selected_ids[*]} " == *" $id "* ]] && is_selected=true + + [[ $is_selected == true ]] && echo -e "[X] ${ALL_DEB_INSTALL_LABELS[$idx]}" || echo -e "[ ] ${ALL_DEB_INSTALL_LABELS[$idx]}" + done + + # Lecture touche + IFS= read -rsn1 key + [[ $key == "q" ]] && exit 0 + if [[ $key == $'\x1b' ]]; then + read -rsn2 key + case $key in + '[A') ((cursor--)); [[ $cursor -lt 0 ]] && cursor=$((${#visible_indices[@]} - 1)) ;; + '[B') ((cursor++)); [[ $cursor -ge ${#visible_indices[@]} ]] && cursor=0 ;; + esac + elif [[ $key == "" ]]; then break + elif [[ $key == " " ]]; then + target_id=${ALL_DEB_INSTALL_IDS[${visible_indices[$cursor]}]} + if [[ " ${selected_ids[*]} " == *" $target_id "* ]]; then + selected_ids=("${selected_ids[@]//$target_id/}") # Décocher + else + selected_ids+=("$target_id") # Cocher + fi + fi + done + + # ========================================== + # 5. EXÉCUTION + # ========================================== + clear +# On compte le nombre d'éléments dans le tableau des IDs sélectionnés +nb_actions=${#selected_ids[@]} + +if [[ $nb_actions -eq 0 ]]; then + msg_warning "Aucune action sélectionnée. Sortie du script." + exit 0 +fi + +emsg_info "Lancement de $nb_actions tâche(s) sélectionnée(s)..." + for id in "${selected_ids[@]}"; do + [[ -z "$id" ]] && continue + # Trouver l'index original pour cet ID + for i in "${!ALL_DEB_INSTALL_IDS[@]}"; do + if [[ "${ALL_DEB_INSTALL_IDS[$i]}" == "$id" ]]; then + echo -e "${COLOR_YELLOW}--- ${ALL_DEB_INSTALL_LABELS[$i]} ---${NONE}" + do_deb_install_action "${ALL_DEB_INSTALL_TYPES[$i]}" "${ALL_DEB_INSTALL_PARAMS[$i]}" + fi + done + done + + msg_success "Terminé ! ✨" + + pause + + . "${WELCOME_SCRIPT_PATH}/777-welcome.sh" +} + +do_deb_install_menu \ No newline at end of file