#!/bin/bash # T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ # Copyright © 2020 Simon Lindner (https://github.com/szaimen) # shellcheck disable=2034,2059 true SCRIPT_NAME="SMB Mount" # shellcheck source=lib.sh . <(curl -sL https://raw.githubusercontent.com/nextcloud/vm/master/lib.sh) # Check for errors + debug code and abort if something isn't right # 1 = ON # 0 = OFF DEBUG=0 debug_mode # Check if root root_check # Variables MAX_COUNT=16 SMBSHARES="/mnt/smbshares" SMBSHARES_SED=${SMBSHARES//\//\\/} SMB_CREDENTIALS="/root/.smbcredentials" # Install whiptail if not existing install_if_not whiptail # Check MAX_COUNT if ! [ $MAX_COUNT -gt 0 ] then msg_box "The MAX_COUNT variable has to be a positive integer, greater than 0. Please change it accordingly. Recommended is MAX_COUNT=16, because not all menus work reliably with a higher count." exit fi # Inform the user msg_box "This script automates mounting SMB-shares locally in your system and adds them automatically as external storage to your Nextcloud." if ! yesno_box_yes "Do you want to proceed with this script?" then exit 1 fi # Needed for DFS-shares to work install_if_not keyutils # Install cifs-utils install_if_not cifs-utils # Make sure, that name resolution works install_if_not winbind if [ "$(grep "^hosts:" /etc/nsswitch.conf | grep wins)" == "" ] then sed -i '/^hosts/ s/$/ wins/' /etc/nsswitch.conf fi # Functions add_mount() { local SUBTITLE="Add a SMB-mount" # Check if mounting slots are available count=1 while [ $count -le $MAX_COUNT ] do if grep -q "$SMBSHARES/$count " /etc/fstab then count=$((count+1)) else break fi done if [ $count -gt $MAX_COUNT ] then msg_box "All $MAX_COUNT slots are occupied. No mounting slots available. Please delete one of the SMB-mounts. If you really want to mount more, you can simply download the smb-mount script directly and edit the variable 'MAX_COUNT' to a higher value than $MAX_COUNT by running: 'curl -sLO https://raw.githubusercontent.com/nextcloud/vm/master/apps/smbmount.sh /var/scripts' 'sudo nano /var/scripts/smbmount.sh' # Edit MAX_COUNT=$MAX_COUNT to your likings and save the file 'sudo bash /var/scripts/smbmount.sh' # Execute the script." "$SUBTITLE" return fi # Enter SMB-server and Share-name while : do SERVER_SHARE_NAME=$(input_box "Please enter the server and Share-name like this:\n//Server/Share\nor\n//IP-address/Share" "$SUBTITLE") if ! yesno_box_yes "Is this correct? $SERVER_SHARE_NAME" "$SUBTITLE" then msg_box "It seems like your weren't satisfied by the PATH you entered. Please try again." "$SUBTITLE" else SERVER_SHARE_NAME=${SERVER_SHARE_NAME// /\\040} break fi done # Enter the SMB-user while : do SMB_USER=$(input_box "Please enter the username of the SMB-user" "$SUBTITLE") if ! yesno_box_yes "Is this correct? $SMB_USER" "$SUBTITLE" then msg_box "It seems like your weren't satisfied by the SMB-user you entered. Please try again." "$SUBTITLE" else break fi done # Enter the password of the SMB-user while : do SMB_PASSWORD=$(input_box "Please enter the password of the SMB-user $SMB_USER." "$SUBTITLE") if ! yesno_box_yes "Is this correct? $SMB_PASSWORD" "$SUBTITLE" then msg_box "It seems like your weren't satisfied by the password for the SMB-user you entered. Please try again." "$SUBTITLE" else break fi done # Write everything to /etc/fstab, mount and connect external storage count=1 while [ $count -le $MAX_COUNT ] do # Check which mounting slot is available if ! grep -q "$SMBSHARES/$count " /etc/fstab then # Write to /etc/fstab and mount echo "$SERVER_SHARE_NAME $SMBSHARES/$count cifs credentials=$SMB_CREDENTIALS/SMB$count,uid=www-data,gid=www-data,file_mode=0770,dir_mode=0770,nounix,noserverino,cache=none 0 0" >> /etc/fstab mkdir -p $SMB_CREDENTIALS touch $SMB_CREDENTIALS/SMB$count chown -R root:root $SMB_CREDENTIALS chmod -R 600 $SMB_CREDENTIALS echo "username=$SMB_USER" > $SMB_CREDENTIALS/SMB$count echo "password=$SMB_PASSWORD" >> $SMB_CREDENTIALS/SMB$count unset SMB_USER && unset SMB_PASSWORD mkdir -p "$SMBSHARES/$count" mount "$SMBSHARES/$count" # Check if mounting was successful if ! mountpoint -q $SMBSHARES/$count then # If not remove this line from fstab msg_box "It seems like the mount wasn't successful. It will get deleted now. Please try again. As a hint: - you might fix the connection problem by enabling SMB3 on your SMB-server. - You could also try to use the IP-address of the SMB-server instead of the Server-name, if not already done. - Please also make sure, that 'ping IP-address' of your SMB-Server from your Nextcloud-instance works." "$SUBTITLE" sed -i "/$SMBSHARES_SED\/$count /d" /etc/fstab if [ -f $SMB_CREDENTIALS/SMB$count ] then check_command rm $SMB_CREDENTIALS/SMB$count fi break else # Check if Nextcloud is existing if [ -f $NCPATH/occ ] then # Install and enable files_external if ! is_app_enabled files_external then install_and_enable_app files_external fi # Create and mount external storage to the admin group MOUNT_ID=$(occ_command files_external:create "SMB$count" local null::null -c datadir="$SMBSHARES/$count" ) MOUNT_ID=${MOUNT_ID//[!0-9]/} occ_command files_external:applicable --add-group=admin "$MOUNT_ID" -q occ_command files_external:option "$MOUNT_ID" filesystem_check_changes 1 # Inform the user that mounting was successful msg_box "Your mount was successful, congratulations! It's now accessible in your root directory under $SMBSHARES/$count. You are now using the Nextcloud external storage app to access files there. The Share has been mounted to the Nextcloud admin-group. You can now access 'https://yourdomain-or-ipaddress/settings/admin/externalstorages' to rename 'SMB$count' to whatever you like or e.g. enable sharing." "$SUBTITLE" break else # Inform the user that mounting was successful msg_box "Your mount was successful, congratulations!\nIt's now accessible in your root directory under $SMBSHARES/$count." "$SUBTITLE" break fi fi fi count=$((count+1)) done return } mount_shares() { local SUBTITLE="Mount SMB-shares" # Check if any SMB-share is created if ! grep -q "$SMBSHARES" /etc/fstab then msg_box "It seems like you have not created any SMB-share." "$SUBTITLE" return fi count=1 while [ $count -le $MAX_COUNT ] do if grep -q "$SMBSHARES/$count " /etc/fstab then if mountpoint -q $SMBSHARES/$count then count=$((count+1)) else break fi else count=$((count+1)) fi done if [ $count -gt $MAX_COUNT ] then msg_box "No existing SMB-mount-entry is unmounted. So nothing to mount." "$SUBTITLE" return fi args=(whiptail --title "$TITLE - $SUBTITLE" --checklist "This option let you mount SMB-shares to connect to network-shares from the host-computer or other machines in the local network.\nChoose which one you want to mount.\n$CHECKLIST_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4) count=1 # Find out which SMB-shares are available while [ $count -le $MAX_COUNT ] do if ! mountpoint -q $SMBSHARES/$count && grep -q "$SMBSHARES/$count " /etc/fstab then args+=("$SMBSHARES/$count " "$(grep "$SMBSHARES/$count " /etc/fstab | awk '{print $1}')" OFF) fi count=$((count+1)) done # Let the user choose which SMB-shares he wants to mount selected_options=$("${args[@]}" 3>&1 1>&2 2>&3) count=1 # Mount selected SMB-shares while [ $count -le $MAX_COUNT ] do if [[ $selected_options == *"$SMBSHARES/$count "* ]] then mount "$SMBSHARES/$count" if ! mountpoint -q $SMBSHARES/$count then msg_box "It seems like the mount of $SMBSHARES/$count wasn't successful. Please try again." "$SUBTITLE" else msg_box "Your mount was successful, congratulations!\n It is accessible in your root directory in $SMBSHARES/$count\nYou can use the Nextcloud external storage app to access files there." "$SUBTITLE" fi fi count=$((count+1)) done return } show_all_mounts() { local SUBTITLE="Show all SMB-mounts" # If no entry created, nothing to show if ! grep -q "$SMBSHARES" /etc/fstab then msg_box "You haven't created any SMB-mount. So nothing to show." "$SUBTITLE" return fi # Find out which SMB-shares are available args=(whiptail --title "$TITLE - $SUBTITLE" --checklist "This option let you show detailed information about your SMB-shares.\nChoose which one you want to see.\n$CHECKLIST_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4) count=1 while [ $count -le $MAX_COUNT ] do if grep -q "$SMBSHARES/$count " /etc/fstab then args+=("$SMBSHARES/$count " "$(grep "$SMBSHARES/$count " /etc/fstab | awk '{print $1}')" OFF) fi count=$((count+1)) done # Let the user choose which details he wants to see selected_options=$("${args[@]}" 3>&1 1>&2 2>&3) # Show selected Shares count=1 while [ $count -le $MAX_COUNT ] do if [[ $selected_options == *"$SMBSHARES/$count "* ]] then if [ -f $SMB_CREDENTIALS/SMB$count ] then msg_box "$(grep "$SMBSHARES/$count " /etc/fstab)\n$(cat $SMB_CREDENTIALS/SMB$count)" "$SUBTITLE" else msg_box "$(grep "$SMBSHARES/$count " /etc/fstab)" "$SUBTITLE" fi fi count=$((count+1)) done return } change_mount() { local SUBTITLE="Change a SMB-mount" # If no entry created, nothing to show if ! grep -q "$SMBSHARES" /etc/fstab then msg_box "You haven't created any SMB-mount. So nothing to change." "$SUBTITLE" return fi # Find out which SMB-shares are available args=(whiptail --title "$TITLE - $SUBTITLE" --menu "This option let you change the password, the username and/or the network-share of one of your SMB-mounts.\nChoose which one you want to show." "$WT_HEIGHT" "$WT_WIDTH" 4) count=1 while [ $count -le $MAX_COUNT ] do if grep -q "$SMBSHARES/$count " /etc/fstab then args+=("$SMBSHARES/$count " "$(grep "$SMBSHARES/$count " /etc/fstab | awk '{print $1}')" ) fi count=$((count+1)) done # Let the user choose which mount he wants to change selected_option=$("${args[@]}" 3>&1 1>&2 2>&3) if [[ "$selected_option" == "" ]] then return fi # Get count back from selected_option count=${selected_option//[!0-9]/} # Test if SMB-share is still mounted and unmount if yes if mountpoint -q "$SMBSHARES/$count" then umount "$SMBSHARES/$count" was_mounted=yes if mountpoint -q "$SMBSHARES/$count" then msg_box "It seems like the unmount of $SMBSHARES/$count wasn't successful while trying to change the mount. Please try again." "$SUBTITLE" return fi fi # Store fstab entry for later in a variable fstab_entry=$(grep "$SMBSHARES/$count " /etc/fstab) # Get old password and username if ! [ -f "$SMB_CREDENTIALS/SMB$count" ] then SERVER_SHARE_NAME=$(echo "$fstab_entry" | awk '{print $1}') SMB_USER=${fstab_entry##*username=} SMB_USER=${SMB_USER%%,*} SMB_PASSWORD=${fstab_entry##*password=} SMB_PASSWORD=${SMB_PASSWORD%%,*} else old_credentials=$(cat "$SMB_CREDENTIALS/SMB$count") SMB_USER=$(echo "$old_credentials" | grep username=) SMB_USER=${SMB_USER##*username=} SMB_PASSWORD=$(echo "$old_credentials" | grep password=) SMB_PASSWORD=${SMB_PASSWORD##*password=} fi # Let the user choose which entries he wants to change choice=$(whiptail --title "$TITLE - $SUBTITLE" --checklist "$fstab_entry\n$old_credentials\nChoose which option you want to change.\n$CHECKLIST_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4 \ "Password" "(change the password of the SMB-user)" OFF \ "Username" "(change the username of the SMB-user)" OFF \ "Share" "(change the SMB-share to use the same mount directory)" OFF 3>&1 1>&2 2>&3) case "$choice" in *"Share"*) clear # Enter SMB-server and Share-name while : do SERVER_SHARE_NAME=$(input_box "Please enter the server and Share-name like this:\n//Server/Share\nor\n//IP-address/Share" "$SUBTITLE") if ! yesno_box_yes "Is this correct? $SERVER_SHARE_NAME" "$SUBTITLE" then msg_box "It seems like your weren't satisfied by the PATH you entered. Please try again." "$SUBTITLE" else SERVER_SHARE_NAME=${SERVER_SHARE_NAME// /\\040} break fi done ;;& *"Username"*) clear # Enter the SMB-user while : do SMB_USER=$(input_box "Please enter the username of the SMB-user" "$SUBTITLE") if ! yesno_box_yes "Is this correct? $SMB_USER" "$SUBTITLE" then msg_box "It seems like your weren't satisfied by the SMB-user you entered. Please try again." "$SUBTITLE" else break fi done ;;& *"Password"*) clear # Enter the password of the SMB-user while : do SMB_PASSWORD=$(input_box "Please enter the password of the SMB-user $SMB_USER." "$SUBTITLE") if ! yesno_box_yes "Is this correct? $SMB_PASSWORD" "$SUBTITLE" then msg_box "It seems like your weren't satisfied by the password for the SMB-user you entered. Please try again." "$SUBTITLE" else break fi done ;;& "") return ;;& *) ;; esac # Remove that line from fstab selected_option_sed=${selected_option//\//\\/} sed -i "/$selected_option_sed/d" /etc/fstab unset old_credentials # Backup old credentials file if [ -f "$SMB_CREDENTIALS/SMB$count" ] then mv "$SMB_CREDENTIALS/SMB$count" "$SMB_CREDENTIALS/SMB$count.old" fi # Write changed line to /etc/fstab and mount echo "$SERVER_SHARE_NAME $SMBSHARES/$count cifs credentials=$SMB_CREDENTIALS/SMB$count,uid=www-data,gid=www-data,file_mode=0770,dir_mode=0770,nounix,noserverino,cache=none 0 0" >> /etc/fstab mkdir -p $SMB_CREDENTIALS touch "$SMB_CREDENTIALS/SMB$count" chown -R root:root $SMB_CREDENTIALS chmod -R 600 $SMB_CREDENTIALS echo "username=$SMB_USER" > "$SMB_CREDENTIALS/SMB$count" echo "password=$SMB_PASSWORD" >> "$SMB_CREDENTIALS/SMB$count" unset SMB_USER && unset SMB_PASSWORD mount "$SMBSHARES/$count" # Check if mounting was successful if ! mountpoint -q "$SMBSHARES/$count" then # If not remove this line from fstab msg_box "It seems like the mount of the changed configuration wasn't successful. It will get deleted now. The old config will get restored now. Please try again to change the mount." "$SUBTITLE" sed -i "/$selected_option_sed/d" /etc/fstab echo "$fstab_entry" >> /etc/fstab unset fstab_entry if [ -f "$SMB_CREDENTIALS/SMB$count.old" ] then rm "$SMB_CREDENTIALS/SMB$count" mv "$SMB_CREDENTIALS/SMB$count.old" "$SMB_CREDENTIALS/SMB$count" fi if [[ $was_mounted == yes ]] then unset was_mounted mount "$SMBSHARES/$count" if ! mountpoint -q "$SMBSHARES/$count" then msg_box "Your old configuration couldn't get mounted but is restored to /etc/fstab." "$SUBTITLE" fi fi else # Remove the backup file if [ -f "$SMB_CREDENTIALS/SMB$count.old" ] then check_command rm "$SMB_CREDENTIALS/SMB$count.old" fi # Inform the user that mounting was successful msg_box "Your change of the mount was successful, congratulations!" "$SUBTITLE" fi } unmount_shares() { local SUBTITLE="Unmount SMB-shares" # Check if any SMB-shares are available for unmounting count=1 while [ $count -le $MAX_COUNT ] do if ! mountpoint -q $SMBSHARES/$count then count=$((count+1)) else break fi done if [ $count -gt $MAX_COUNT ] then msg_box "You haven't mounted any SMB-mount. So nothing to unmount" "$SUBTITLE" return fi # Find out which SMB-shares are available args=(whiptail --title "$TITLE - $SUBTITLE" --checklist "This option let you unmount SMB-shares to disconnect network-shares from the host-computer or other machines in the local network.\nChoose what you want to do.\n$CHECKLIST_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4) count=1 while [ $count -le $MAX_COUNT ] do if mountpoint -q $SMBSHARES/$count then args+=("$SMBSHARES/$count " "$(grep "$SMBSHARES/$count " /etc/fstab | awk '{print $1}')" OFF) fi count=$((count+1)) done # Let the user select which SMB-shares he wants to unmount selected_options=$("${args[@]}" 3>&1 1>&2 2>&3) count=1 while [ $count -le $MAX_COUNT ] do if [[ $selected_options == *"$SMBSHARES/$count "* ]] then umount "$SMBSHARES/$count" if mountpoint -q $SMBSHARES/$count then msg_box "It seems like the unmount of $SMBSHARES/$count wasn't successful. Please try again." "$SUBTITLE" else msg_box "Your unmount of $SMBSHARES/$count was successful!" "$SUBTITLE" fi fi count=$((count+1)) done return } delete_mounts() { local SUBTITLE="Delete SMB-mounts" # Check if any SMB-share is available if ! grep -q "$SMBSHARES" /etc/fstab then msg_box "You haven't created any SMB-mount, nothing to delete." "$SUBTITLE" return fi # Check which SMB-shares are available args=(whiptail --title "$TITLE - $SUBTITLE" --checklist "This option let you delete SMB-shares to disconnect and remove network-shares from the Nextcloud VM.\nChoose what you want to do.\n$CHECKLIST_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4) count=1 while [ $count -le $MAX_COUNT ] do if grep -q "$SMBSHARES/$count " /etc/fstab then args+=("$SMBSHARES/$count " "$(grep "$SMBSHARES/$count " /etc/fstab | awk '{print $1}')" OFF) fi count=$((count+1)) done # Let the user choose which SMB-shares he wants to delete selected_options=$("${args[@]}" 3>&1 1>&2 2>&3) # Delete the selected SMB-shares count=1 while [ $count -le $MAX_COUNT ] do if [[ $selected_options == *"$SMBSHARES/$count "* ]] then if mountpoint -q $SMBSHARES/$count then umount "$SMBSHARES/$count" if mountpoint -q $SMBSHARES/$count then msg_box "It seems like the unmount of $SMBSHARES/$count wasn't successful during the deletion. Please try again." "$SUBTITLE" else sed -i "/$SMBSHARES_SED\/$count /d" /etc/fstab if [ -f $SMB_CREDENTIALS/SMB$count ] then check_command rm $SMB_CREDENTIALS/SMB$count fi msg_box "Your deletion of $SMBSHARES/$count was successful!" "$SUBTITLE" fi else sed -i "/$SMBSHARES_SED\/$count /d" /etc/fstab if [ -f $SMB_CREDENTIALS/SMB$count ] then check_command rm $SMB_CREDENTIALS/SMB$count fi msg_box "Your deletion of $SMBSHARES/$count was successful!" "$SUBTITLE" fi fi count=$((count+1)) done return } # Loop main menu until exited while : do # Main menu choice=$(whiptail --title "$TITLE" --menu "This script let you manage SMB-shares to access files from the host-computer or other machines in the local network.\nChoose what you want to do." "$WT_HEIGHT" "$WT_WIDTH" 4 \ "Add a SMB-mount" "(and mount/connect it)" \ "Mount SMB-shares" "(connect SMB-shares)" \ "Show all SMB-mounts" "(show detailed information about the SMB-mounts)" \ "Change a SMB-mount" "(change password, username &/or share of a mount)" \ "Unmount SMB-shares" "(disconnect SMB-shares)" \ "Delete SMB-mounts" "(and unmount/disconnect them)" \ "Exit SMB-share" "(exit this script)" 3>&1 1>&2 2>&3) case "$choice" in "Add a SMB-mount") add_mount ;; "Mount SMB-shares") mount_shares ;; "Show all SMB-mounts") show_all_mounts ;; "Change a SMB-mount") change_mount ;; "Unmount SMB-shares") unmount_shares ;; "Delete SMB-mounts") delete_mounts ;; "Exit SMB-share") break ;; "") break ;; *) ;; esac done exit