Created
June 4, 2025 09:57
-
-
Save olibartfast/89d0b49dac26b33dcb984c16d47e0d46 to your computer and use it in GitHub Desktop.
How mount a shared folder from your NAS on your Linux Server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # NAS Share Mounter - Mount CIFS/SMB shares with enhanced features | |
| # Prerequisites: sudo apt-get install cifs-utils | |
| set -euo pipefail # Exit on error, undefined variables, pipe failures | |
| # ======= CONFIGURATION ======= | |
| SCRIPT_NAME=$(basename "$0") | |
| CONFIG_FILE="$HOME/.nas_mounter.conf" | |
| LOG_FILE="/tmp/nas_mounter_$(date +%Y%m%d).log" | |
| # Default shares (edit as needed) | |
| declare -a SHARES=("Folder1" "Folder2" "FolderN") | |
| # Color codes for output | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| NC='\033[0m' # No Color | |
| # ======= FUNCTIONS ======= | |
| # Logging function | |
| log() { | |
| echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE" | |
| } | |
| # Colored output functions | |
| error() { | |
| echo -e "${RED}[ERROR]${NC} $*" >&2 | |
| log "ERROR: $*" | |
| } | |
| success() { | |
| echo -e "${GREEN}[SUCCESS]${NC} $*" | |
| log "SUCCESS: $*" | |
| } | |
| warning() { | |
| echo -e "${YELLOW}[WARNING]${NC} $*" | |
| log "WARNING: $*" | |
| } | |
| # Check prerequisites | |
| check_prerequisites() { | |
| if ! command -v mount.cifs &> /dev/null; then | |
| error "cifs-utils not installed" | |
| echo "Please install with: sudo apt-get install cifs-utils" | |
| exit 1 | |
| fi | |
| if ! sudo -n true 2>/dev/null; then | |
| warning "This script requires sudo privileges for mounting" | |
| fi | |
| } | |
| # Validate IP address | |
| validate_ip() { | |
| local ip=$1 | |
| if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then | |
| for octet in $(echo "$ip" | tr '.' ' '); do | |
| if (( octet > 255 )); then | |
| return 1 | |
| fi | |
| done | |
| return 0 | |
| fi | |
| return 1 | |
| } | |
| # Save configuration | |
| save_config() { | |
| cat > "$CONFIG_FILE" << EOF | |
| NAS_IP="$nas_ip" | |
| NAS_BASE="$nas_base" | |
| NAS_USER="$nas_user" | |
| MOUNT_BASE="$mount_base" | |
| EOF | |
| chmod 600 "$CONFIG_FILE" | |
| success "Configuration saved to $CONFIG_FILE" | |
| } | |
| # Load configuration | |
| load_config() { | |
| if [[ -f "$CONFIG_FILE" ]]; then | |
| # shellcheck source=/dev/null | |
| source "$CONFIG_FILE" | |
| return 0 | |
| fi | |
| return 1 | |
| } | |
| # Get user input with defaults | |
| get_input() { | |
| local prompt=$1 | |
| local default=$2 | |
| local var_name=$3 | |
| local is_password=${4:-false} | |
| if [[ -n "$default" ]]; then | |
| prompt="$prompt [$default]" | |
| fi | |
| prompt="$prompt: " | |
| if [[ "$is_password" == "true" ]]; then | |
| read -s -r -p "$prompt" value | |
| echo # New line after password | |
| else | |
| read -r -p "$prompt" value | |
| fi | |
| value="${value:-$default}" | |
| eval "$var_name='$value'" | |
| } | |
| # Collect configuration from user | |
| collect_config() { | |
| echo "=== NAS Mount Configuration ===" | |
| # Try to load existing config | |
| if load_config; then | |
| warning "Found existing configuration. Press Enter to keep current values." | |
| fi | |
| # Get inputs with validation | |
| while true; do | |
| get_input "Enter NAS server IP" "${NAS_IP:-}" "nas_ip" | |
| if validate_ip "$nas_ip"; then | |
| break | |
| else | |
| error "Invalid IP address format. Please try again." | |
| fi | |
| done | |
| get_input "Enter NAS share base path (leave blank for root)" "${NAS_BASE:-}" "nas_base" | |
| get_input "Enter your NAS username" "${NAS_USER:-}" "nas_user" | |
| get_input "Enter local mount base directory" "${MOUNT_BASE:-$HOME/nas_shares}" "mount_base" | |
| # Get password securely | |
| get_input "Enter your NAS password" "" "nas_pass" true | |
| # Mount options | |
| while true; do | |
| get_input "Enter 'r' for read-only or 'w' for read-write" "w" "mount_option" | |
| if [[ "$mount_option" =~ ^[rw]$ ]]; then | |
| break | |
| else | |
| error "Invalid option. Please enter 'r' or 'w'" | |
| fi | |
| done | |
| # Ask to save config | |
| get_input "Save configuration for future use? (y/n)" "y" "save_conf" | |
| if [[ "$save_conf" =~ ^[yY]$ ]]; then | |
| save_config | |
| fi | |
| } | |
| # Mount a share | |
| mount_share() { | |
| local share_name="$1" | |
| local nas_path | |
| # Construct NAS path | |
| if [[ -z "$nas_base" ]]; then | |
| nas_path="//$nas_ip/$share_name" | |
| else | |
| nas_path="//$nas_ip/$nas_base/$share_name" | |
| fi | |
| local mount_point="$mount_base/$share_name" | |
| # Check if already mounted | |
| if mountpoint -q "$mount_point" 2>/dev/null; then | |
| warning "$share_name is already mounted at $mount_point" | |
| return 0 | |
| fi | |
| # Create mount point | |
| if ! mkdir -p "$mount_point"; then | |
| error "Failed to create mount point: $mount_point" | |
| return 1 | |
| fi | |
| # Prepare mount options | |
| local mount_opts="username=$nas_user,password=$nas_pass,uid=$(id -u),gid=$(id -g)" | |
| mount_opts+=",forceuid,forcegid,dir_mode=0770,file_mode=0660,iocharset=utf8" | |
| if [[ "$mount_option" == "r" ]]; then | |
| mount_opts+=",ro" | |
| else | |
| mount_opts+=",rw" | |
| fi | |
| # Attempt to mount | |
| log "Attempting to mount $nas_path to $mount_point" | |
| if sudo mount -t cifs "$nas_path" "$mount_point" -o "$mount_opts" 2>/tmp/mount_error.log; then | |
| success "Mounted $share_name at $mount_point" | |
| return 0 | |
| else | |
| error "Failed to mount $share_name" | |
| if [[ -f /tmp/mount_error.log ]]; then | |
| cat /tmp/mount_error.log >&2 | |
| fi | |
| rmdir "$mount_point" 2>/dev/null | |
| return 1 | |
| fi | |
| } | |
| # Unmount a share | |
| unmount_share() { | |
| local share_name="$1" | |
| local mount_point="$mount_base/$share_name" | |
| if ! mountpoint -q "$mount_point" 2>/dev/null; then | |
| warning "$share_name is not mounted" | |
| return 0 | |
| fi | |
| log "Attempting to unmount $mount_point" | |
| if sudo umount "$mount_point"; then | |
| success "Unmounted $share_name" | |
| rmdir "$mount_point" 2>/dev/null | |
| return 0 | |
| else | |
| error "Failed to unmount $share_name" | |
| return 1 | |
| fi | |
| } | |
| # List mounted shares | |
| list_mounted() { | |
| echo "=== Currently Mounted Shares ===" | |
| local found=false | |
| for share in "${SHARES[@]}"; do | |
| local mount_point="$mount_base/$share" | |
| if mountpoint -q "$mount_point" 2>/dev/null; then | |
| echo -e "${GREEN}✓${NC} $share -> $mount_point" | |
| found=true | |
| fi | |
| done | |
| if [[ "$found" == "false" ]]; then | |
| echo "No shares currently mounted" | |
| fi | |
| } | |
| # Mount all shares | |
| mount_all() { | |
| echo "=== Mounting All Shares ===" | |
| local success_count=0 | |
| local fail_count=0 | |
| for share in "${SHARES[@]}"; do | |
| if mount_share "$share"; then | |
| ((success_count++)) | |
| else | |
| ((fail_count++)) | |
| fi | |
| done | |
| echo | |
| echo "Summary: $success_count succeeded, $fail_count failed" | |
| } | |
| # Unmount all shares | |
| unmount_all() { | |
| echo "=== Unmounting All Shares ===" | |
| local success_count=0 | |
| for share in "${SHARES[@]}"; do | |
| if unmount_share "$share"; then | |
| ((success_count++)) | |
| fi | |
| done | |
| echo | |
| success "Unmounted $success_count shares" | |
| } | |
| # Interactive menu | |
| show_menu() { | |
| while true; do | |
| echo | |
| echo "=== NAS Share Mounter ===" | |
| echo "1) Mount a specific share" | |
| echo "2) Mount all shares" | |
| echo "3) Unmount a specific share" | |
| echo "4) Unmount all shares" | |
| echo "5) List mounted shares" | |
| echo "6) Reconfigure settings" | |
| echo "7) Quit" | |
| echo | |
| read -r -p "Select an option [1-7]: " choice | |
| case $choice in | |
| 1) | |
| echo "Available shares:" | |
| select share in "${SHARES[@]}" "Back"; do | |
| if [[ "$share" == "Back" ]]; then | |
| break | |
| elif [[ -n "$share" ]]; then | |
| mount_share "$share" | |
| break | |
| fi | |
| done | |
| ;; | |
| 2) | |
| mount_all | |
| ;; | |
| 3) | |
| echo "Select share to unmount:" | |
| select share in "${SHARES[@]}" "Back"; do | |
| if [[ "$share" == "Back" ]]; then | |
| break | |
| elif [[ -n "$share" ]]; then | |
| unmount_share "$share" | |
| break | |
| fi | |
| done | |
| ;; | |
| 4) | |
| unmount_all | |
| ;; | |
| 5) | |
| list_mounted | |
| ;; | |
| 6) | |
| collect_config | |
| ;; | |
| 7) | |
| echo "Goodbye!" | |
| exit 0 | |
| ;; | |
| *) | |
| error "Invalid option. Please select 1-7" | |
| ;; | |
| esac | |
| done | |
| } | |
| # Cleanup function | |
| cleanup() { | |
| # Clear password from memory | |
| nas_pass="" | |
| log "Script execution completed" | |
| } | |
| # ======= MAIN EXECUTION ======= | |
| # Set trap for cleanup | |
| trap cleanup EXIT | |
| # Start logging | |
| log "Starting $SCRIPT_NAME" | |
| # Check prerequisites | |
| check_prerequisites | |
| # Collect configuration | |
| collect_config | |
| # Show interactive menu | |
| show_menu |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment