#!/bin/bash # ============================================================================= # Universal Samba Share Manager - FSA (Fucking Samba Ass) # ============================================================================= # Works on: Debian, Ubuntu, Arch Linux, RHEL/CentOS, Fedora # Auto-detects distribution and installs Samba if needed # ============================================================================= # Zkontrolujte, zda je skript spuštěn jako root if [ "$EUID" -ne 0 ]; then echo "Tento skript je nutné spustit s právy roota (sudo)." exit 1 fi # --- Detekce distribuce a správce balíčků --- detect_distro() { if [ -f /etc/os-release ]; then . /etc/os-release DISTRO_ID="$ID" DISTRO_NAME="$NAME" elif [ -f /etc/arch-release ]; then DISTRO_ID="arch" DISTRO_NAME="Arch Linux" elif [ -f /etc/debian_version ]; then DISTRO_ID="debian" DISTRO_NAME="Debian" else DISTRO_ID="unknown" DISTRO_NAME="Unknown Linux" fi echo "Detected distribution: $DISTRO_NAME" } # --- Instalace Samby pokud není nainstalovaná --- install_samba() { echo "Kontroluji instalaci Samby..." # Zkontroluj jestli už není Samba nainstalovaná if command -v smbd &> /dev/null; then echo "✅ Samba je již nainstalována." return 0 fi echo "⚠️ Samba není nainstalována. Instaluji..." case "$DISTRO_ID" in arch|manjaro) pacman -Sy --noconfirm samba ;; ubuntu|debian|linuxmint|pop) apt-get update apt-get install -y samba samba-common-bin ;; fedora) dnf install -y samba samba-common ;; rhel|centos|rocky|almalinux) yum install -y samba samba-common ;; opensuse*|sles) zypper install -y samba ;; *) echo "❌ CHYBA: Nepodařilo se detekovat distribuci pro automatickou instalaci." echo "Prosím nainstalujte Sambu manuálně a spusťte skript znovu." exit 1 ;; esac if [ $? -eq 0 ]; then echo "✅ Samba byla úspěšně nainstalována." else echo "❌ Instalace Samby selhala!" exit 1 fi } # --- Auto-detekce uživatele a síťových rozhraní --- DETECTED_USER="${SUDO_USER:-$(whoami)}" DETECTED_INTERFACES=$(ip -o link show | awk -F': ' '{print $2}' | grep -v '^lo$' | tr '\n' ' ') # --- Nastavení sdílení --- declare -A SHARES=( ["${DETECTED_USER}-home"]="/home/${DETECTED_USER}|Domovska slozka uzivatele ${DETECTED_USER}|home" ["server-root"]="/|Celý server (root filesystem)|root" ) CONFIG_FILE="/etc/samba/smb.conf" BACKUP_FILE="/etc/samba/smb.conf.bak.$(date +%F_%T)" # Spusť detekci distribuce a instalaci Samby detect_distro install_samba # Funkce pro kontrolu existence smb.conf check_config_exists() { if [ ! -f "$CONFIG_FILE" ]; then echo "Chyba: Konfigurační soubor $CONFIG_FILE neexistuje!" echo "Pokud je Samba nově nainstalovaná, vytvořte ho z šablony příkazem:" echo "sudo cp /etc/samba/smb.conf.default /etc/samba/smb.conf" exit 1 fi } # VYLEPŠENÁ FUNKCE: Najde všechny diskové oddíly a správně očistí jejich názvy discover_mounts() { echo "Hledám všechny existující diskové oddíly..." for key in "${!SHARES[@]}"; do if [[ $key == disk-* ]]; then unset SHARES[$key] fi done while read -r name label uuid mountpoint; do # Odstranění stromových znaků (└─, ├─) z názvu zařízení name=$(echo "$name" | sed 's/^[├└]─//g' | sed 's/ //g') local identifier="${label:-$name}" local clean_identifier clean_identifier=$(echo "$identifier" | sed 's/[^a-zA-Z0-9_-]//g') # Záložní varianta pro prázdné popisky (např. se speciálními znaky) if [ -z "$clean_identifier" ]; then clean_identifier="$name" fi local share_name="disk-$clean_identifier" local share_path="" local status_info="" if [ -n "$mountpoint" ]; then share_path="$mountpoint" local disk_info=$(df -h "$mountpoint" 2>/dev/null | tail -1 | awk '{print "("$2" celkem, "$4" volné)"}') status_info="✅ Připojeno na $mountpoint $disk_info" else share_path="/mnt/$clean_identifier" status_info="❌ Nepřipojeno (navrhovaná cesta: $share_path)" fi if [ -n "$clean_identifier" ]; then SHARES["$share_name"]="$share_path|Oddíl $identifier|disk" fi done < <(lsblk -no NAME,LABEL,UUID,MOUNTPOINT -e7,1) } # Funkce pro vytvoření dfree skriptu pro konkrétní disk create_dfree_script() { local mount_point="$1" local script_name="samba-dfree-$(basename "$mount_point").sh" local script_path="/usr/local/bin/$script_name" cat > "$script_path" << EOT #!/bin/bash # Auto-generated dfree script for $mount_point MOUNT_PATH="$mount_point" if [ -d "\$MOUNT_PATH" ]; then df -k --output=size,avail "\$MOUNT_PATH" | tail -n 1 else echo "0 0" fi EOT chmod +x "$script_path" echo "$script_path" } # Funkce pro vytvoření kompletní smb.conf s [global] sekcí create_complete_smb_config() { echo "Vytvářím kompletní SMB konfiguraci..." local HOSTNAME=$(hostname | tr '[:lower:]' '[:upper:]') cat > "$CONFIG_FILE" <> "$CONFIG_FILE" [$share_name] path = $share_path writable = yes guest ok = yes hosts allow = 127.0.0.1 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12 100.64.0.0/10 comment = $comment EOT ;; "root") cat <> "$CONFIG_FILE" [$share_name] path = $share_path writable = yes guest ok = no valid users = $DETECTED_USER admin users = $DETECTED_USER force user = root force group = root hosts allow = 127.0.0.1 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12 100.64.0.0/10 comment = $comment EOT ;; "disk") local dfree_script=$(create_dfree_script "$share_path") local PRIMARY_GROUP=$(id -gn "$DETECTED_USER") cat <> "$CONFIG_FILE" [$share_name] path = $share_path force user = $DETECTED_USER writable = yes guest ok = no valid users = $DETECTED_USER force group = $PRIMARY_GROUP create mask = 0664 directory mask = 0775 dfree command = $dfree_script hosts allow = 127.0.0.1 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12 100.64.0.0/10 comment = $comment EOT echo "Vytvořen dfree skript: $dfree_script" ;; *) cat <> "$CONFIG_FILE" [$share_name] path = $share_path writable = yes guest ok = yes hosts allow = 127.0.0.1 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12 100.64.0.0/10 comment = $comment EOT ;; esac if [ $? -eq 0 ]; then echo "Nové sdílení '$share_name' bylo přidáno."; else echo "Chyba při přidávání sdílení."; return 1; fi } # Funkce pro smazání sdílení delete_share() { local share_name="$1" if [ -z "$share_name" ]; then echo "Použití: sudo $0 delete "; exit 1; fi check_config_exists if ! grep -Fq "[$share_name]" "$CONFIG_FILE"; then echo "Chyba: Sdílení [$share_name] nebylo nalezeno."; exit 1; fi echo "Vytvářím zálohu..."; cp "$CONFIG_FILE" "$BACKUP_FILE"; echo "Mažu sdílení '[$share_name]'..." awk -v section="[$share_name]" 'BEGIN{p=1} /^\[/{p=($0!=section)} p' "$CONFIG_FILE" > "${CONFIG_FILE}.tmp" && mv "${CONFIG_FILE}.tmp" "$CONFIG_FILE" local dfree_script="/usr/local/bin/samba-dfree-${share_name#disk-}.sh" if [ -f "$dfree_script" ]; then echo "Mažu dfree skript: $dfree_script"; rm -f "$dfree_script"; fi echo "Sdílení '$share_name' bylo smazáno." } # Funkce pro zobrazení existujících sdílení list_shares() { check_config_exists echo "Existující sdílení v $CONFIG_FILE:"; echo "==================================" grep -E "^\[.*\]" "$CONFIG_FILE" | grep -v "\[global\]" } # Funkce pro vytvoření všech staticky definovaných sdílení create_all() { echo "Vytvářím všechna staticky definovaná sdílení..." create_share "${DETECTED_USER}-home" create_share "server-root" } # Funkce pro automatické vytvoření sdílení pro všechny disky auto_discover_and_create() { echo "=== AUTOMATICKÉ VYTVÁŘENÍ SDÍLENÍ PRO PŘIPOJENÉ DISKY ===" for share_name in "${!SHARES[@]}"; do IFS='|' read -r path comment share_type <<< "${SHARES[$share_name]}" if [ "$share_type" = "disk" ]; then if mountpoint -q "$path" 2>/dev/null; then echo "--- Vytvářím sdílení pro připojený disk: $share_name ---" create_share "$share_name" fi fi done } # Funkce pro přidání [global] sekce do existující konfigurace add_global_section() { echo "=== PŘIDÁVÁNÍ [GLOBAL] SEKCE ===" if grep -q "^\[global\]" "$CONFIG_FILE"; then echo "Sekce [global] již existuje."; return; fi echo "Vytvářím zálohu..."; cp "$CONFIG_FILE" "$BACKUP_FILE"; echo "Přidávám [global] na začátek..." local HOSTNAME=$(hostname | tr '[:lower:]' '[:upper:]') local GLOBAL_CONFIG=$(cat < "${CONFIG_FILE}.tmp" && mv "${CONFIG_FILE}.tmp" "$CONFIG_FILE" echo "Sekce [global] byla přidána." } # Funkce pro inicializaci kompletní konfigurace init_config() { echo "=== INICIALIZACE NOVÉ SMB KONFIGURACE ===" if [ -f "$CONFIG_FILE" ]; then echo "Zálohuji stávající konfiguraci..."; mv "$CONFIG_FILE" "${CONFIG_FILE}.backup-$(date +%F_%T)"; fi create_complete_smb_config create_share "${DETECTED_USER}-home" read -p "Přidat automaticky všechny nalezené PŘIPOJENÉ disky? (Y/n): " -n 1 -r; echo if [[ ! $REPLY =~ ^[Nn]$ ]]; then auto_discover_and_create fi echo "Inicializace dokončena!" } # Funkce pro testování a restart test_and_restart() { echo ""; echo "Kontroluji syntaxi..."; if ! testparm -s > /dev/null 2>&1; then echo "CHYBA: Konfigurace Samby je neplatná! Změny nebyly aplikovány."; testparm -s; exit 1 fi echo "Restartuji služby SMB a NMB..." # Detekuj správné názvy služeb pro různé distribuce local SMB_SERVICE="" local NMB_SERVICE="" if systemctl list-unit-files | grep -q "^smbd.service"; then SMB_SERVICE="smbd.service" NMB_SERVICE="nmbd.service" elif systemctl list-unit-files | grep -q "^smb.service"; then SMB_SERVICE="smb.service" NMB_SERVICE="nmb.service" elif systemctl list-unit-files | grep -q "^samba.service"; then SMB_SERVICE="samba.service" NMB_SERVICE="" fi if [ -z "$SMB_SERVICE" ]; then echo "CHYBA: Nepodařilo se najít Samba službu!" exit 1 fi # Aktivuj a restartuj služby systemctl enable "$SMB_SERVICE" 2>/dev/null if [ -n "$NMB_SERVICE" ]; then systemctl enable "$NMB_SERVICE" 2>/dev/null if systemctl restart "$SMB_SERVICE" "$NMB_SERVICE"; then echo "Služby SMB úspěšně restartovány." else echo "CHYBA: Restart služeb selhal. Zkontrolujte logy pomocí 'journalctl -u $SMB_SERVICE'." exit 1 fi else if systemctl restart "$SMB_SERVICE"; then echo "Služby SMB úspěšně restartovány." else echo "CHYBA: Restart služeb selhal. Zkontrolujte logy pomocí 'journalctl -u $SMB_SERVICE'." exit 1 fi fi echo "Hotovo! ✅" } # NOVÁ FUNKCE: Přidá záznam do /etc/fstab add_to_fstab() { local device_name="$1"; local mount_path="$2" local device_info; device_info=$(lsblk -no UUID,FSTYPE "/dev/$device_name"); local uuid; uuid=$(echo "$device_info" | awk '{print $1}'); local fstype; fstype=$(echo "$device_info" | awk '{print $2}') if [ -z "$uuid" ] || [ -z "$fstype" ]; then echo "Chyba: Nepodařilo se zjistit UUID."; return 1; fi echo " - UUID: $uuid"; echo " - Typ: $fstype" if grep -q "$uuid" /etc/fstab; then echo "Varování: Záznam pro UUID již existuje."; return 0; fi local fstab_line="UUID=$uuid $mount_path $fstype defaults,nofail 0 2" echo "Přidávám do /etc/fstab:"; echo " $fstab_line" echo "" >> /etc/fstab; echo "# Přidáno skriptem spravuj_sdileni.sh dne $(date)" >> /etc/fstab; echo "$fstab_line" >> /etc/fstab if [ $? -eq 0 ]; then echo "✅ Záznam úspěšně přidán."; else echo "Chyba: Zápis do /etc/fstab selhal."; return 1; fi } # NOVÁ FUNKCE: Interaktivně připojí a nasdílí disk interactive_mount_and_create() { local mode="$1" echo "=== INTERAKTIVNÍ PŘIPOJENÍ A SDÍLENÍ DISKU ===" local unmounted_partitions=() while read -r name label uuid mountpoint; do if [ -z "$mountpoint" ]; then name=$(echo "$name" | sed 's/^[├└]─//g' | sed 's/ //g') local identifier="${label:-$name}" unmounted_partitions+=("$name|$identifier") fi done < <(lsblk -no NAME,LABEL,UUID,MOUNTPOINT -e7,1) if [ ${#unmounted_partitions[@]} -eq 0 ]; then echo "Nenalezeny žádné nepřipojené diskové oddíly."; exit 0; fi echo "Který oddíl chcete připojit a sdílet?" local i=1 for info in "${unmounted_partitions[@]}"; do IFS='|' read -r name identifier <<< "$info"; echo " $i) $name (Popisek: $identifier)"; i=$((i+1)); done echo " 0) Zrušit" local choice read -p "Zadejte číslo: " choice if ! [[ "$choice" =~ ^[0-9]+$ ]] || [ "$choice" -lt 0 ] || [ "$choice" -gt ${#unmounted_partitions[@]} ]; then echo "Chyba: Neplatná volba."; exit 1; fi if [ "$choice" -eq 0 ]; then echo "Operace zrušena."; exit 0; fi IFS='|' read -r selected_device selected_identifier <<< "${unmounted_partitions[$((choice-1))]}" local clean_identifier; clean_identifier=$(echo "$selected_identifier" | sed 's/[^a-zA-Z0-9_-]//g') if [ -z "$clean_identifier" ]; then clean_identifier="$selected_device" fi local default_mount_path="/mnt/$clean_identifier" read -p "Zadejte cestu pro připojení [navrženo: $default_mount_path]: " mount_path mount_path="${mount_path:-$default_mount_path}" if [ ! -d "$mount_path" ]; then echo "Vytvářím adresář $mount_path..."; if ! mkdir -p "$mount_path"; then echo "Chyba: Nelze vytvořit adresář."; exit 1; fi; fi echo "Připojuji /dev/$selected_device na $mount_path..." if ! mount "/dev/$selected_device" "$mount_path"; then echo "CHYBA: Nepodařilo se připojit disk! (mount /dev/$selected_device)"; exit 1; fi echo "✅ Disk úspěšně připojen." if [ "$mode" == "always" ]; then echo ""; add_to_fstab "$selected_device" "$mount_path" else echo "INFO: Disk je připojen pouze dočasně." fi local share_name="disk-$clean_identifier" echo ""; echo "Nyní vytvářím Samba sdílení s názvem '$share_name'..." SHARES["$share_name"]="$mount_path|Oddíl $selected_identifier|disk" create_share "$share_name" } # --- Hlavní logika skriptu (Router) --- COMMAND="$1" ARGUMENT1="$2" ARGUMENT2="$3" # Před spuštěním hlavního příkazu vždy aktualizujeme seznam disků discover_mounts # Zpracování parametru --mode=always, který může být na druhé nebo třetí pozici MODE="" if [ "$ARGUMENT1" == "--mode=always" ] || [ "$ARGUMENT2" == "--mode=always" ]; then MODE="always" fi # Hlavní argument je ten, který není --mode=always MAIN_ARG="$ARGUMENT1" if [ "$ARGUMENT1" == "--mode=always" ]; then MAIN_ARG="$ARGUMENT2" fi case "$COMMAND" in mount-share) interactive_mount_and_create "$MODE" test_and_restart ;; create) create_share "$MAIN_ARG" test_and_restart ;; delete) delete_share "$MAIN_ARG" test_and_restart ;; list) list_shares ;; create-all) create_all test_and_restart ;; auto-disks) auto_discover_and_create test_and_restart ;; discover) echo "" echo "Dostupná sdílení pro 'create':" for name in "${!SHARES[@]}"; do IFS='|' read -r path comment type <<< "${SHARES[$name]}" echo " - $name (cesta: $path)" done ;; init) init_config test_and_restart ;; add-global) add_global_section test_and_restart ;; *) echo "SMB Share Manager pro Arch Linux" echo "=================================" echo "Použití: sudo $0 {příkaz} [argument]" echo "" echo "Hlavní příkazy:" echo " mount-share [--mode=always] - Interaktivně připojí a nasdílí nepřipojený disk." echo " init - Smaže starou a vytvoří novou, čistou konfiguraci." echo " add-global - Přidá [global] sekci do existující konfigurace." echo "" echo "Správa sdílení:" echo " discover - Najde a zobrazí všechny dostupné disky." echo " auto-disks - Vytvoří sdílení pro všechny AKTUÁLNĚ PŘIPOJENÉ disky." echo " create - Vytvoří sdílení." echo " create-all - Vytvoří statická sdílení (home, root)." echo " delete - Smaže existující sdílení." echo " list - Vypíše nakonfigurovaná sdílení." exit 1 ;; esac