From c492e213376ebd8070a333092876dbd223763b9d Mon Sep 17 00:00:00 2001 From: Puechberty Arthur Date: Wed, 24 Jun 2026 00:15:34 +0200 Subject: [PATCH] fix many error in .install.sh script --- airootfs/root/.install.sh | 350 ++++++++++++++++++++++---------------- 1 file changed, 203 insertions(+), 147 deletions(-) diff --git a/airootfs/root/.install.sh b/airootfs/root/.install.sh index e6d31dc..c144b3b 100755 --- a/airootfs/root/.install.sh +++ b/airootfs/root/.install.sh @@ -2,61 +2,68 @@ set -euo pipefail # ========================================== -# UI SYSTEM (Robust Bash Nameref) +# UI SYSTEM # ========================================== declare -A GRID_DATA GRID_NUM_PAGES=0 grid_menu() { - # Crée un alias local vers le tableau passé en argument (nom en string) - local -n _items=$1 - local max_cols=$3 max_rows=$4 - local data_page=0 item_number=0 max_cols_data line + local -n items=$1 + local page=$2 + local max_cols=$3 + local max_rows=$4 + local data_page=0 + local item_number=0 + local max_cols_data + local line GRID_DATA=() GRID_NUM_PAGES=0 - local total_items=${#_items[@]} - while (( item_number < total_items )); do + while (( item_number < ${#items[@]} )); do max_cols_data=1 for (( line=0; line= total_items )); then break; fi + if (( item_number >= ${#items[@]} )); then break; fi local key="P${data_page}L${line}" - [[ ! -v GRID_DATA[$key] ]] && GRID_DATA[$key]="" + if [[ ! -v GRID_DATA[$key] ]]; then GRID_DATA[$key]=""; fi local index=$(( item_number + max_rows - line )) - (( index >= total_items )) && index=$(( total_items - 1 )) - if (( index < 0 )); then index=$(( total_items + index )); (( index < 0 )) && index=0; fi + if (( index >= ${#items[@]} )); then index=$(( ${#items[@]} - 1 )) + elif (( index < 0 )); then index=$(( ${#items[@]} + index )) + (( index < 0 )) && index=0 + fi - local index_str item_num_plus1 item_num_str spaces_needed spaces add - printf -v index_str "%d" "$index" - item_num_plus1=$(( item_number + 1 )) - printf -v item_num_str "%d" "$item_num_plus1" - spaces_needed=$(( ${#index_str} - ${#item_num_str} )) - (( spaces_needed < 0 )) && spaces_needed=0 - printf -v spaces "%*s" "$spaces_needed" "" - - local item="${_items[$item_number]}" - add="${spaces}${item_num_plus1}) ${item}" + local index_str; printf -v index_str "%d" "$index" + local item_num_plus1=$(( item_number + 1 )) + local item_num_str; printf -v item_num_str "%d" "$item_num_plus1" + local spaces_needed=$(( ${#index_str} - ${#item_num_str} )) + if (( spaces_needed < 0 )); then spaces_needed=0; fi + local spaces; printf -v spaces "%*s" "$spaces_needed" "" + local item="${items[$item_number]}" + local add="${spaces}${item_num_plus1}) ${item}" local current_line="${GRID_DATA[$key]}" - if (( ${#current_line} + ${#add} > max_cols )); then (( data_page++ )); break; fi - + if (( ${#current_line} + ${#add} > max_cols )); then + data_page=$(( data_page + 1 )) # CORRECTION ICI + break + fi GRID_DATA[$key]="${current_line}${add}" - max_cols_data=$(( max_cols_data > ( ${#item} + 2 ) ? max_cols_data : ( ${#item} + 2 ) )) - (( item_number++ )) + local len_item_plus2=$(( ${#item} + 2 )) + max_cols_data=$(( max_cols_data > len_item_plus2 ? max_cols_data : len_item_plus2 )) + item_number=$(( item_number + 1 )) # CORRECTION ICI done for (( line=0; line= total_items )); then idx=$(( total_items - 1 )); fi - - local item="${_items[$idx]}" + if (( idx < 0 )); then idx=$(( ${#items[@]} + idx )) + (( idx < 0 )) && idx=0 + elif (( idx >= ${#items[@]} )); then idx=$(( ${#items[@]} - 1 )) + fi + local item="${items[$idx]}" local pad=$(( max_cols_data - ${#item} )) - (( pad < 0 )) && pad=0 + if (( pad < 0 )); then pad=0; fi local spaces_pad; printf -v spaces_pad "%*s" "$pad" "" GRID_DATA[$key]="${GRID_DATA[$key]}${spaces_pad}" done @@ -65,44 +72,22 @@ grid_menu() { } print_grid_menu() { - local page=$1 found=0 key - for key in "${!GRID_DATA[@]}"; do [[ $key == P${page}L* ]] && found=1 && break; done - (( found == 0 )) && echo "Page $(( page + 1 )) does not exist." && return + local page=$1 + local found=0 + local key + for key in "${!GRID_DATA[@]}"; do + if [[ $key == P${page}L* ]]; then found=1; break; fi + done + if (( found == 0 )); then echo "Page $(( page + 1 )) does not exist."; return; fi - echo -e "\n--- Page $(( page + 1 )) of $GRID_NUM_PAGES ---\n" + echo "" + echo "Page $(( page + 1 )) of $GRID_NUM_PAGES" + echo "" for key in $(printf "%s\n" "${!GRID_DATA[@]}" | grep "^P${page}L" | sort -t 'L' -k2 -n); do echo "${GRID_DATA[$key]}" done } -grid_choose() { - local arr_name=$1 cols=${2:-80} rows=${3:-15} page=0 - - grid_menu "$arr_name" "$page" "$cols" "$rows" - - # Crée un alias local pour lire la taille et l'élément choisi - local -n _items=$arr_name - - while true; do - clear - print_grid_menu "$page" - echo -e "\n[n]ext | [p]rev | [q]uit" - read -rp "Choice: " choice - if [[ "$choice" == "q" ]]; then return 1; fi - if [[ "$choice" == "n" && $page -lt $((GRID_NUM_PAGES - 1)) ]]; then ((page++)); continue; fi - if [[ "$choice" == "p" && $page -gt 0 ]]; then ((page--)); continue; fi - - if [[ "$choice" =~ ^[0-9]+$ ]]; then - local idx=$((choice - 1)) - if (( idx >= 0 && idx < ${#_items[@]} )); then - echo "${_items[$idx]}" - return 0 - fi - fi - sleep 0.5 - done -} - ask_confirm() { read -rp "$1 (y/n): " ans; [[ "$ans" =~ ^[yY]$ ]]; } # ========================================== @@ -118,15 +103,15 @@ cleanup_install_disk() { [[ -b "$dev" ]] || continue swapoff "$dev" 2>/dev/null || true while read -r target; do [[ -n "$target" ]] && umount "$target" 2>/dev/null; done < <(findmnt -rn -S "$dev" -o TARGET 2>/dev/null) - done < <(lsblk -rnpo PATH "$disk") + done < <(lsblk -rnpo PATH "$disk" 2>/dev/null) while read -r dev type; do [[ "$type" == "disk" || "$type" == "part" || "$type" == "crypt" ]] || continue while read -r vg; do [[ -n "$vg" ]] && vgchange -an "$vg" 2>/dev/null; done < <(pvs --noheadings -o vg_name "$dev" 2>/dev/null | awk '{$1=$1; print}' | sort -u) - done < <(lsblk -rnpo PATH,TYPE "$disk") - while read -r dev type; do [[ "$type" == "crypt" ]] && cryptsetup close "$dev" 2>/dev/null; done < <(lsblk -rnpo PATH,TYPE "$disk") + done < <(lsblk -rnpo PATH,TYPE "$disk" 2>/dev/null) + while read -r dev type; do [[ "$type" == "crypt" ]] && cryptsetup close "$dev" 2>/dev/null; done < <(lsblk -rnpo PATH,TYPE "$disk" 2>/dev/null) blockdev --flushbufs "$disk" 2>/dev/null || true partprobe "$disk" 2>/dev/null || true - udevadm settle || true + udevadm settle 2>/dev/null || true } install_base_system() { @@ -152,13 +137,34 @@ install_base_system() { run_configurator() { command -v jq >/dev/null || pacman -Sy --noconfirm jq - # 1. Keyboard (PAS de 'local' devant le tableau !) - kb_keys=("us" "fr" "de" "uk" "es" "it" "pt-latin1" "br-abnt2" "dvorak" "colemak" "ru" "jp106") - kb_choice=$(grid_choose kb_keys 80 10) || exit 1 - keyboard="$kb_choice" + # --- 1. KEYBOARD --- + KB_LAYOUT=("us" "fr" "de" "uk" "es" "it" "pt-latin1" "br-abnt2" "dvorak" "colemak" "ru" "jp106") + PAGE=1 + COLS=80 + ROWS=15 + + grid_menu KB_LAYOUT "$PAGE" "$COLS" "$ROWS" + + while true; do + clear + print_grid_menu $(( PAGE - 1 )) + echo -e "\n[n] Next | [p] Prev | [q] Quit" + read -rp "Entrée (n/p ou nombre) : " input + + if [[ "$input" == "q" ]]; then exit 1; fi + if [[ "$input" =~ ^[0-9]+$ ]]; then + PAGE="$input" + break + elif [[ "$input" == "n" ]]; then + if (( PAGE < GRID_NUM_PAGES )); then PAGE=$(( PAGE + 1 )); fi # CORRECTION ICI + elif [[ "$input" == "p" ]]; then + if (( PAGE > 1 )); then PAGE=$(( PAGE - 1 )); fi # CORRECTION ICI + fi + done + keyboard="${KB_LAYOUT[$((PAGE - 1))]}" [[ $(tty 2>/dev/null) == "/dev/tty"* ]] && loadkeys "$keyboard" 2>/dev/null || true - # 2. User + # --- 2. USER --- while true; do clear; read -rp "Username: " username [[ "$username" =~ ^[a-z_][a-z0-9_-]*[$]?$ ]] && break @@ -172,102 +178,152 @@ run_configurator() { clear; read -rp "Hostname [archlinux]: " hostname [[ -z "$hostname" ]] && hostname="archlinux" - # 3. Timezone (PAS de 'local' devant le tableau !) + # --- 3. TIMEZONE --- clear; echo "Loading timezones..." - mapfile -t timezones < <(timedatectl list-timezones) - timezone=$(grid_choose timezones 100 20) || exit 1 + mapfile -t TIMEZONES < <(timedatectl list-timezones) + PAGE=1 + COLS=100 + ROWS=20 - # 4. Disk (PAS de 'local' devant les tableaux !) + grid_menu TIMEZONES "$PAGE" "$COLS" "$ROWS" + + while true; do + clear + print_grid_menu $(( PAGE - 1 )) + echo -e "\n[n] Next | [p] Prev | [q] Quit" + read -rp "Entrée (n/p ou nombre) : " input + + if [[ "$input" == "q" ]]; then exit 1; fi + if [[ "$input" =~ ^[0-9]+$ ]]; then + PAGE="$input" + break + elif [[ "$input" == "n" ]]; then + if (( PAGE < GRID_NUM_PAGES )); then PAGE=$(( PAGE + 1 )); fi + elif [[ "$input" == "p" ]]; then + if (( PAGE > 1 )); then PAGE=$(( PAGE - 1 )); fi + fi + done + timezone="${TIMEZONES[$((PAGE - 1))]}" + + # --- 4. DISK --- clear local boot_source exclude_disk boot_source=$(findmnt -no SOURCE /run/archiso/bootmnt 2>/dev/null || true) - local device_b=$(readlink -f "$boot_source" 2>/dev/null || echo "") + local device_b + device_b=$(readlink -f "$boot_source" 2>/dev/null || echo "") while [[ -n "$device_b" ]]; do - local parent_b=$(lsblk -dno PKNAME "$device_b" 2>/dev/null | tail -n1) + local parent_b + parent_b=$(lsblk -dno PKNAME "$device_b" 2>/dev/null | tail -n1) [[ -z "$parent_b" ]] && break; device_b="/dev/$parent_b" done [[ $(lsblk -dno TYPE "$device_b" 2>/dev/null) == "disk" ]] && exclude_disk="$device_b" - disk_options_array=() + DISKS=() mapfile -t available_disks < <(lsblk -dpno NAME,TYPE | awk '$2=="disk"{print $1}' | grep -E '/dev/(sd|hd|vd|nvme|mmcblk|xv)' | { [[ -n "${exclude_disk:-}" ]] && grep -Fvx "$exclude_disk" || cat; }) for dev in "${available_disks[@]}"; do - local size=$(lsblk -dno SIZE "$dev") model=$(lsblk -dno MODEL "$dev" | sed 's/ *$//') - disk_options_array+=("$dev ($size) - $model") + local size; size=$(lsblk -dno SIZE "$dev" 2>/dev/null) || true + local model; model=$(lsblk -dno MODEL "$dev" 2>/dev/null | sed 's/ *$//') || true + DISKS+=("$dev ($size) - $model") done - selected_disk_display=$(grid_choose disk_options_array 100 10) || exit 1 - disk=$(echo "$selected_disk_display" | awk '{print $1}') - # 5. Encryption + PAGE=1 + COLS=100 + ROWS=10 + + grid_menu DISKS "$PAGE" "$COLS" "$ROWS" + + while true; do + clear + print_grid_menu $(( PAGE - 1 )) + echo -e "\n[n] Next | [p] Prev | [q] Quit" + read -rp "Entrée (n/p ou nombre) : " input + + if [[ "$input" == "q" ]]; then exit 1; fi + if [[ "$input" =~ ^[0-9]+$ ]]; then + PAGE="$input" + break + elif [[ "$input" == "n" ]]; then + if (( PAGE < GRID_NUM_PAGES )); then PAGE=$(( PAGE + 1 )); fi + elif [[ "$input" == "p" ]]; then + if (( PAGE > 1 )); then PAGE=$(( PAGE - 1 )); fi + fi + done + disk=$(echo "${DISKS[$((PAGE - 1))]}" | awk '{print $1}') + + # --- 5. ENCRYPTION --- clear; local encrypt_installation="false" ask_confirm "Encrypt disk?" && encrypt_installation="true" # --- JSON GENERATION --- - local pw_esc=$(echo -n "$password" | jq -Rsa) - local hash_esc=$(echo -n "$password_hash" | jq -Rsa) - local user_esc=$(echo -n "$username" | jq -Rsa) - local enc_line=""; [[ "$encrypt_installation" == "true" ]] && enc_line="\"encryption_password\": $pw_esc," + jq -n \ + --arg pw "$password" \ + --arg hash "$password_hash" \ + --arg user "$username" \ + '{ + root_enc_password: $hash, + users: [{ enc_password: $hash, groups: [], sudo: true, username: $user }] + } + (if $pw != "" then { encryption_password: $pw } else {} end)' > user_credentials.json - cat <<_EOF_ >user_credentials.json -{ - $enc_line -"root_enc_password": $hash_esc, -"users": [{ "enc_password": $hash_esc, "groups": [], "sudo": true, "username": $user_esc }] -} -_EOF_ - - local disk_size=$(lsblk -bdno SIZE "$disk") mib=$((1024*1024)) gib=$((mib*1024)) - local disk_size_in_mib=$((disk_size / mib * mib)) boot_size=$((2 * gib)) main_start=$((boot_size + mib)) + local disk_size; disk_size=$(lsblk -bdno SIZE "$disk" 2>/dev/null) || true + local mib=$((1024*1024)) + local gib=$((mib*1024)) + local disk_size_in_mib=$((disk_size / mib * mib)) + local boot_size=$((2 * gib)) + local main_start=$((boot_size + mib)) local main_size=$((disk_size_in_mib - main_start - mib)) - - local disk_enc="" - [[ "$encrypt_installation" == "true" ]] && disk_enc=$(cat <<_EOF_ -, -"disk_encryption": { -"encryption_type": "luks", -"lvm_volumes": [], -"iter_time": 2000, -"partitions": [ "8c2c2b92-1070-455d-b76a-56263bab24aa" ], -"encryption_password": $pw_esc -} -_EOF_ -) - cat <<_EOF_ >user_configuration.json -{ -"archinstall-language": "English", -"audio_config": { "audio": "pipewire" }, -"bootloader": "systemd-boot", -"disk_config": { -"btrfs_options": { "snapshot_config": { "type": "Snapper" } }, -"config_type": "default_layout", -"device_modifications": [{ -"device": "$disk", -"partitions": [ -{ "btrfs": [], "dev_path": null, "flags": ["boot", "esp"], "fs_type": "fat32", "mount_options": [], "mountpoint": "/boot", "obj_id": "ea21d3f2-82bb-49cc-ab5d-6f81ae94e18d", "size": { "sector_size": { "unit": "B", "value": 512 }, "unit": "B", "value": $boot_size }, "start": { "sector_size": { "unit": "B", "value": 512 }, "unit": "B", "value": $mib }, "status": "create", "type": "primary" }, -{ "btrfs": [ {"mountpoint": "/", "name": "@"}, {"mountpoint": "/home", "name": "@home"}, {"mountpoint": "/var/log", "name": "@log"}, {"mountpoint": "/var/cache/pacman/pkg", "name": "@pkg"} ], "dev_path": null, "flags": [], "fs_type": "btrfs", "mount_options": ["compress=zstd"], "mountpoint": null, "obj_id": "8c2c2b92-1070-455d-b76a-56263bab24aa", "size": { "sector_size": { "unit": "B", "value": 512 }, "unit": "B", "value": $main_size }, "start": { "sector_size": { "unit": "B", "value": 512 }, "unit": "B", "value": $main_start }, "status": "create", "type": "primary" } -], -"wipe": true -}]$disk_enc -}, -"hostname": "$hostname", -"kernels": ["linux"], -"network_config": { "type": "iso" }, -"ntp": true, -"parallel_downloads": 8, -"swap": true, -"timezone": "$timezone", -"locale_config": { "kb_layout": "$keyboard", "sys_enc": "UTF-8", "sys_lang": "en_US.UTF-8" }, -"mirror_config": { -"custom_servers": [ -{"url": "https://geo.mirror.pkgbuild.com/\$repo/os/\$arch"}, -{"url": "https://mirror.rackspace.com/archlinux/\$repo/os/\$arch"} -] -}, -"packages": ["base-devel", "git", "snapper"], -"profile_config": { "gfx_driver": null, "greeter": null, "profile": {} }, -"version": "3.0.9" -} -_EOF_ + jq -n \ + --arg disk "$disk" \ + --arg hostname "$hostname" \ + --arg timezone "$timezone" \ + --arg keyboard "$keyboard" \ + --argjson boot_size "$boot_size" \ + --argjson mib "$mib" \ + --argjson main_size "$main_size" \ + --argjson main_start "$main_start" \ + --argjson encrypt "$encrypt_installation" \ + --arg enc_pw "$password" \ + '{ + "archinstall-language": "English", + "audio_config": { "audio": "pipewire" }, + "bootloader": "systemd-boot", + "disk_config": { + "btrfs_options": { "snapshot_config": { "type": "Snapper" } }, + "config_type": "default_layout", + "device_modifications": [{ + "device": $disk, + "partitions": [ + { "btrfs": [], "dev_path": null, "flags": ["boot", "esp"], "fs_type": "fat32", "mount_options": [], "mountpoint": "/boot", "obj_id": "ea21d3f2-82bb-49cc-ab5d-6f81ae94e18d", "size": { "sector_size": { "unit": "B", "value": 512 }, "unit": "B", "value": $boot_size }, "start": { "sector_size": { "unit": "B", "value": 512 }, "unit": "B", "value": $mib }, "status": "create", "type": "primary" }, + { "btrfs": [ {"mountpoint": "/", "name": "@"}, {"mountpoint": "/home", "name": "@home"}, {"mountpoint": "/var/log", "name": "@log"}, {"mountpoint": "/var/cache/pacman/pkg", "name": "@pkg"} ], "dev_path": null, "flags": [], "fs_type": "btrfs", "mount_options": ["compress=zstd"], "mountpoint": null, "obj_id": "8c2c2b92-1070-455d-b76a-56263bab24aa", "size": { "sector_size": { "unit": "B", "value": 512 }, "unit": "B", "value": $main_size }, "start": { "sector_size": { "unit": "B", "value": 512 }, "unit": "B", "value": $main_start }, "status": "create", "type": "primary" } + ], + "wipe": true + }], + (if $encrypt == "true" then { + "disk_encryption": { + "encryption_type": "luks", "lvm_volumes": [], "iter_time": 2000, + "partitions": [ "8c2c2b92-1070-455d-b76a-56263bab24aa" ], + "encryption_password": $enc_pw + } + } else {} end) + }, + "hostname": $hostname, + "kernels": ["linux"], + "network_config": { "type": "iso" }, + "ntp": true, + "parallel_downloads": 8, + "swap": true, + "timezone": $timezone, + "locale_config": { "kb_layout": $keyboard, "sys_enc": "UTF-8", "sys_lang": "en_US.UTF-8" }, + "mirror_config": { + "custom_servers": [ + {"url": "https://geo.mirror.pkgbuild.com/$repo/os/$arch"}, + {"url": "https://mirror.rackspace.com/archlinux/$repo/os/$arch"} + ] + }, + "packages": ["base-devel", "git", "snapper"], + "profile_config": { "gfx_driver": null, "greeter": null, "profile": {} }, + "version": "3.0.9" + }' > user_configuration.json } # ==========================================