From dd5890e015cedd81d95f7f5f183bc284ec498c03 Mon Sep 17 00:00:00 2001 From: lionel <.> Date: Thu, 15 May 2025 19:09:48 +0200 Subject: [PATCH] first commit --- Makefile | 49 +++++++++ README.md | 106 +++++++++++++++++++ smbmount | 287 ++++++++++++++++++++++++++++++++++++++++++++++++++ smbmount.bash | 36 +++++++ 4 files changed, 478 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100755 smbmount create mode 100644 smbmount.bash diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6e92f55 --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +# Makefile hybride avec support de PREFIX et fallback utilisateur + +SCRIPT = smbmount +COMPLETION = smbmount.bash + +PREFIX ?= /usr/local +BINDIR = $(PREFIX)/bin +COMPDIR = /etc/bash_completion.d # Bash completion n’est pas sous PREFIX + +# Répertoires utilisateur +USR_BINDIR = $(HOME)/.local/bin +USR_COMPDIR = $(HOME)/.bash_completion.d + +.PHONY: all install install-sys install-user uninstall + +all: + @echo "Utilisez 'make install' pour installer $(SCRIPT) avec fallback utilisateur si nécessaire." + +install: + @echo "Tentative d'installation dans $(BINDIR)..." + @if [ -w "$(BINDIR)" ] && [ -w "$(COMPDIR)" ]; then \ + $(MAKE) install-sys BINDIR=$(BINDIR) COMPDIR=$(COMPDIR); \ + else \ + echo "Pas d'accès en écriture à $(BINDIR) ou $(COMPDIR), installation utilisateur..."; \ + $(MAKE) install-user; \ + fi + +install-sys: + @echo "Installation dans $(BINDIR) et $(COMPDIR)..." + install -d $(BINDIR) $(COMPDIR) + install -m 0755 $(SCRIPT) $(BINDIR)/$(SCRIPT) + install -m 0644 $(COMPLETION) $(COMPDIR)/$(SCRIPT) + +install-user: + @echo "Installation utilisateur dans $(USR_BINDIR) et $(USR_COMPDIR)..." + install -d $(USR_BINDIR) $(USR_COMPDIR) + install -m 0755 $(SCRIPT) $(USR_BINDIR)/$(SCRIPT) + install -m 0644 $(COMPLETION) $(USR_COMPDIR)/$(SCRIPT) + @echo "Ajoutez à votre ~/.bashrc si nécessaire :" + @echo ' export PATH="$$HOME/.local/bin:$$PATH"' + @echo ' [ -f "$$HOME/.bash_completion.d/$(SCRIPT)" ] && source "$$HOME/.bash_completion.d/$(SCRIPT)"' + +uninstall: + @echo "Suppression de $(SCRIPT) côté système et utilisateur..." + rm -f $(BINDIR)/$(SCRIPT) 2>/dev/null || true + rm -f $(COMPDIR)/$(SCRIPT) 2>/dev/null || true + rm -f $(USR_BINDIR)/$(SCRIPT) 2>/dev/null || true + rm -f $(USR_COMPDIR)/$(SCRIPT) 2>/dev/null || true + diff --git a/README.md b/README.md new file mode 100644 index 0000000..bfba2ff --- /dev/null +++ b/README.md @@ -0,0 +1,106 @@ +# smbmount + +`smbmount` est un script Bash pour monter facilement des partages SMB, avec complétion dynamique basée sur la découverte réseau via Avahi ou smbtree. + +--- + +## Fonctionnalités + +* Montage de partages SMB via plusieurs méthodes : + + * Découverte SMBTREE (`-s`) + * Découverte Avahi + `smbclient` (`-a` ou `-A `) + * Montage direct via adresse IP (`-i `) +* Mode démontage (`-u`) +* Gestion des mots de passe via `secret-tool` (GNOME Keyring) +* Complétion dynamique des serveurs SMB +* Installation flexible en mode système ou utilisateur + +--- + +## Prérequis et dépendances + +Pour Debian / Ubuntu, installe les paquets suivants : + +```bash +sudo apt-get update +sudo apt-get install -y avahi-utils smbclient cifs-utils secret-tool bash-completion +``` + +* `avahi-utils` : outil `avahi-browse` pour découvrir les services SMB sur le réseau. +* `smbclient` : client SMB/CIFS en ligne de commande, utilisé pour lister les partages. +* `cifs-utils` : fournit la commande `mount.cifs` pour monter les partages SMB. +* `secret-tool` : interface avec le trousseau GNOME pour stocker et récupérer les mots de passe. +* `bash-completion` : améliore la complétion Bash, nécessaire pour la complétion dynamique. + +--- + +## Installation + +Le `Makefile` gère à la fois l’installation système avec la personnalisation du préfixe **et** le fallback utilisateur : + +```bash +make install [PREFIX=/chemin/personnalisé] +``` + +* **Sans préciser `PREFIX`**, `/usr/local` est utilisé par défaut : + + * Script → `/usr/local/bin/` + * Complétion → `/etc/bash_completion.d/` + +* **Avec `PREFIX`**, l’installation se fait sous : + + * Script → `${PREFIX}/bin/` + * Complétion → `/etc/bash_completion.d/` + +* Si vous n’avez pas les droits d’écriture dans `${PREFIX}/bin` **et** `/etc/bash_completion.d`, l’installation bascule automatiquement en **mode utilisateur** : + + * Script → `~/.local/bin/` + * Complétion → `~/.bash_completion.d/` + +--- + +En installation utilisateur, n’oubliez pas d’ajouter dans votre `~/.bashrc` : + +```bash +export PATH="$HOME/.local/bin:$PATH" +[ -f "$HOME/.bash_completion.d/smbmount" ] && source "$HOME/.bash_completion.d/smbmount" +``` + +Puis rechargez votre shell : + +```bash +source ~/.bashrc +``` + +--- + +## Désinstallation + +Pour supprimer l’installation (mode système ou utilisateur), lance : + +```bash +make uninstall +``` + +--- + +## Utilisation + +```bash +smbmount -s # Découverte et montage avec smbtree +smbmount -a # Découverte et montage avec Avahi + smbclient +smbmount -A nom_serveur # Montage direct avec nom serveur Avahi +smbmount -i adresse_ip # Montage direct via IP +smbmount -u # Démontage interactif des partages montés +``` + +--- + +## Aide + +```bash +smbmount +``` + +Affiche l’aide rapide avec les options disponibles. diff --git a/smbmount b/smbmount new file mode 100755 index 0000000..d91b29c --- /dev/null +++ b/smbmount @@ -0,0 +1,287 @@ +#!/bin/bash + +#if [ "$EUID" -ne 0 ] +#then +# echo "Please run as root" +# exit 1 +#fi + +usage() +{ + cat < /dev/null | grep '\\\\' | sed -e 's/\t\t\\\\\(.*\)/\1/' -e 's/\\\(.*\)//' -e 's/^\s*//' -e '/^$/d' | uniq) + + if [ -z "$listServers" ]; then + echo "No server found" + exit 0 + fi + + echo "List of Server : " + while IFS= read -r line; do + ((i=i+1)) + echo " $i $line" + done <<< "$listServers" + + read -p "Your Choose : " choix + + server=$(sed -n ${choix}p <<< "$listServers") + + mountDir=${server} + + mapfile -t partage < <(smbtree -N 2> /dev/null | grep '\\\\'"$server"'\\' | grep -v 'IPC\$' | sed -e 's/\t\t\\\\'"$server"'\\\(.*\)/\1/' -e 's/\t\(.*\)//' -e 's/ //g') +} + +_avahiMode() +{ + + browse=$(avahi-browse -tpr _smb._tcp) + while IFS= read -r line; do + if [[ $(cut -d';' -f1 <<< "$line") = "=" ]]; then + listServers="${listServers}$(cut -d';' -f7 <<< "$line")"$'\n' + fi + done <<< "$browse" + + if [ -z "$listServers" ]; then + echo "No server found" + exit 0 + fi + + # Delete empty line, space and duplicate line + listServers=$(sed -e 's/\t\(.*\)//' -e 's/ //g' <<< "$listServers" | uniq) + + listServers=$(sort <<<"$listServers") + +} + +_chooseAvahi() +{ + i=1 + echo "List of Server : " + while IFS= read -r line; do + echo " $i $line" + ((i=i+1)) + done <<< "$listServers" + + read -p "Your Choose : " choix + + server=$(sed -n ${choix}p <<< "$listServers") + + mountDir=$(sed 's/.LOCAL//g' <<<"${server^^}") + + server="${server}" + + echo "$server" + + mapfile -t partage < <(smbclient -L $server -U " "%" " 2> /dev/null | grep "Disk" | sed -e 's/ //g' -e 's/\t\(.*\)Disk.*/\1/') + +} + +_findAvahi() +{ + + while IFS= read -r line; do + if [ "$name" == "$line" ] + then + find="yes" + break + fi + done <<< "$listServers" + + if [ "$find" != "yes" ] + then + echo "Server not found" + exit 1 + fi + + server="$name" + + mountDir=$(sed 's/.LOCAL//g' <<<"${server^^}") + + server="${server}" + + echo "$server" + + mapfile -t partage < <(smbclient -L $server -U " "%" " 2> /dev/null | grep "Disk" | sed -e 's/ //g' -e 's/\t\(.*\)Disk.*/\1/') + +} + +ipMode() +{ + + server=$ip + + echo "$server" + + lastOctet=$(rev <<< "$ip" | cut -d'.' -f 1 | rev) + + mountDir=$(avahi-resolve -4a $server | sed "s/$server\\t\(.*\).local/\1/; {q100}") + + if [ $? -ne 100 ] || [ -z "$mountDir" ]; then + mountDir=${lastOctet} + fi + + mountDir=${mountDir^^} + + echo "$mountDir" + + smbclient -L $server -U " "%" " 1> /dev/null 2>&1 + + if [ $? -ne 0 ]; then + echo "No found Server with IP : $ip" + exit 1 + fi + + mapfile -t partage < <(smbclient -L $server -U " "%" " 2> /dev/null | grep "Disk" | sed -e 's/ //g' -e 's/\t\(.*\)Disk/\1/') + + + +} + +_mount() +{ + + if [ ! -d /media/$mountDir ] + then + + mkdir /media/$mountDir + fi + + toMount=() + + for i in ${!partage[@]} + do + + if [ ! -d /media/$mountDir/${partage[$i]} ] + then + toMount=( "${partage[$i]}" "${toMount[@]}" ) + else + echo "${partage[$i]} Alredy mount" + fi + done + + if [ ${#toMount[@]} -ne 0 ]; then + + _secret-tool + + for partage in "${toMount[@]}" + do + echo "mount $partage" + mkdir /media/$mountDir/$partage + #version: /usr/bin/mount -t cifs //$server/$partage /media/$mountDir/$partage -o uid=$(id -ru),gid=$(id -rg),file_mode=0664,dir_mode=0775,vers=2.0,user=$user,pass=$password + #no show: /usr/bin/mount -t cifs //$server/$partage /media/$mountDir/$partage -o uid=$(id -ru),gid=$(id -rg),file_mode=0664,dir_mode=0775,user=$user,pass=$password + /usr/bin/mount -t cifs //$server/$partage /media/$mountDir/$partage -o uid=$(id -ru),gid=$(id -rg),file_mode=0664,dir_mode=0775,user=$user,pass=$password,x-gvfs-show + + done + + password="" + + fi + + + +} + +unmountMode() +{ + + listDir=$(find /media -mindepth 1 -maxdepth 1 -type d -printf "%f\n") + + echo "List of dir in /media : " + while IFS= read -r line; do + ((i=i+1)) + echo " $i $line" + done <<< "$listDir" + + read -p "Unmount Dir : " choix + + mountDir=$(sed -n ${choix}p <<< "$listDir") + + echo "$mountDir" + + read -p "You sure ? " -n 1 -r + echo + if [[ $REPLY =~ ^[YyOo]$ ]] + then + mapfile -t partage < <(find /media/$mountDir -mindepth 1 -maxdepth 1 -type d -printf "%f\n") + for i in ${!partage[@]} + do + if mountpoint -q /media/$mountDir/${partage[$i]} ;then + umount /media/$mountDir/${partage[$i]} + echo "umount ${partage[$i]}" + fi + if [ -d /media/$mountDir/${partage[$i]} ];then + rmdir /media/$mountDir/${partage[$i]} + fi + done + rmdir /media/$mountDir + else + echo "Cancel" + fi + + +} + +_secret-tool() +{ + user=lionel +# secret-tool clear api smbmount server $server user $user + password=$(secret-tool lookup api smbmount server $server user $user) + if [ -z "$password" ];then + echo -e "Password for $user@//$server: \c" + read -s password + echo "" + secret-tool store --label=$user@$server api smbmount server $server user $user <<< $password + fi + +} + +if [ -z "$1" ] +then + usage + exit 1 +fi + +while getopts "saA:ui:" OPTION; do + case $OPTION in + s) + smbMode + _mount + ;; + a) + _avahiMode + _chooseAvahi + _mount + ;; + A) + _avahiMode + name=${OPTARG} + _findAvahi + _mount + ;; + u) + unmountMode + ;; + i) + ip=${OPTARG} + ipMode + _mount + ;; + *) + usage + exit 1 + ;; + esac +done + + diff --git a/smbmount.bash b/smbmount.bash new file mode 100644 index 0000000..c59b956 --- /dev/null +++ b/smbmount.bash @@ -0,0 +1,36 @@ +#/usr/bin/env bash +#complete -W "now tomorrow never" ./dothis.sh +#complete -A directory ./dothis.sh + +_smbmount() +{ + listServers="" + + browse=$(avahi-browse -tpr _smb._tcp) + while IFS= read -r line; do + if [[ $(cut -d';' -f1 <<< "$line") = "=" ]]; then + listServers="${listServers}$(cut -d';' -f7 <<< "$line")"$'\n' + fi + done <<< "$browse" + + # Delete empty line, space and duplicate line + listServers=$(sed -e 's/\t\(.*\)//' -e 's/ //g' <<< "$listServers" | uniq) + + listServers=$(sort <<<"$listServers") + + OPTIONS="-s -a -A -u -i" + + # Si on est en train d'écrire le 2ème mot (1er argument) + if [ "$prev" == "-A" ]; then + + COMPREPLY=( $(compgen -W "$listServers" -- "$cur" ) ) +# else +# +# +# COMPREPLY=( $(compgen -W '$OPTIONS' -- "$cur" ) ) + fi + + +} + +complete -F _smbmount smbmount