So what does this script do:
- Query the user for the NFS server IP
- List all NFS shares this server exposes (using nmap for this)
- Ask for the default mount path. Default is set to /mnt/
- Ask for each share that is found, if this share should be mounted and to which folder it should be mounted
- Create an init.d file to automatically mount these shares at boot
#!/system/bin/sh #Default Values nfs nfs_options="rw,nosuid,nodev,nolock,rsize=32768,wsize=32768,intr,noatime" mount_path="/mnt/" wait_network="5" file_initd="/etc/init.d/97NFS" # Paths and busybox commands awk_cmd="busybox awk" stat_cmd="busybox stat" printf_cmd="busybox printf" nmap_bin="/sbin/nmap" nmap_data="/sdcard/Download/nmap-5.61TEST4/share/nmap/" nmap_dns="--dns-servers 8.8.8.8" $printf_cmd "Please enter your nfs server IP: \c" read nfs_server nfs_available=($($nmap_bin --script=nfs-showmount.nse $nfs_server $nmap_dns --datadir $nmap_data | grep -e "| " -e "|_ " | $awk_cmd '{print $2;}')) # List all found nfs shares let i=0 $printf_cmd "The server $nfs_server exposes following shares:\n" while (( ${#nfs_available[@]} > i )); do $printf_cmd "$i) ${nfs_available[i++]}\n" done $printf_cmd "####################\n\n" # Query user for the default base mount path $printf_cmd "Please enter your base path for mounting the shares.\n" $printf_cmd "If you are unsure leave the default value given.\n" $printf_cmd "Note that the path has to end with /!\n" $printf_cmd "Base path for mounting the nfs shares [$mount_path]: \c" read mount_path_new [ -n "$mount_path_new" ] && mount_path=$mount_path_new $printf_cmd "####################\n\n" #Collect all shares and corresponding folders in arrays let i=0 while (( ${#nfs_available[@]} > i )); do $printf_cmd "Do you want to mount the share "${nfs_available[i++]}"?\n" select yn in "Yes" "No"; do case $yn in Yes ) $printf_cmd "Please enter the name of the local folder to mount this share: \c"; read local_folder; if [ -d "$mount_path$local_folder" ]; then folder_type=$($stat_cmd -f $mount_path$local_folder | grep -e "Type" | $awk_cmd '{print $6;}') $printf_cmd "The path $mount_path$local_folder already exists\n" $printf_cmd "Folder type of $mount_path$local_folder is: $folder_type\n" $printf_cmd "Do you really want to use this folder?\n" select yn in "Yes" "No"; do case $yn in Yes ) to_mount+=("busybox mount -o $nfs_options $nfs_server:${nfs_available[i++]} $mount_path$local_folder\n"); break;; No ) $printf_cmd "Please enter a new name of the local folder to mount this share: \c"; read local_folder; to_create+=("mkdir $mount_path$local_folder\n"); to_mount+=("busybox mount -o $nfs_options $nfs_server:${nfs_available[i++]} $mount_path$local_folder\n"); break;; esac done else to_create+=("mkdir $mount_path$local_folder\n"); to_mount+=("busybox mount -o $nfs_options $nfs_server:${nfs_available[i++]} $mount_path$local_folder\n"); fi break;; No ) break;; esac done done let i=0 while (( ${#to_create[@]} > i )); do $printf_cmd "$i) ${to_create[i++]}\n" done let i=0 while (( ${#to_mount[@]} > i )); do $printf_cmd "$i) ${to_mount[i++]}\n" done # Create the init.d file if [ -f "$file_initd" ] then rm "$file_initd" touch "$file_initd" else touch "$file_initd" fi ( $printf_cmd "#!/system/bin/sh\n" $printf_cmd "\n" $printf_cmd "# Make sure networking is up before mounting\n" $printf_cmd "busybox sleep $wait_network\n" $printf_cmd "\n" $printf_cmd "# Switch rootfs to read / write\n" $printf_cmd "# Be careful after this. Misplaced commands may\n" $printf_cmd "# brick your system\n" $printf_cmd "busybox mount -o rw,remount /\n" $printf_cmd "\n" $printf_cmd "# Create Mount Points\n" ) >> "$file_initd" let i=0 while (( ${#to_create[@]} > i )); do $printf_cmd "${to_create[i++]}" >> "$file_initd" done let i=0 $printf_cmd '\n' >> "$file_initd" $printf_cmd '# Mount nfs shares\n' >> "$file_initd" while (( ${#to_mount[@]} > i )); do $printf_cmd "${to_mount[i++]}" >> "$file_initd" done $printf_cmd '\n# Switch rootfs to read only\n' >> "$file_initd" $printf_cmd 'busybox mount -o ro,remount /\n' >> "$file_initd" # Make init.d file executeable and make sure it is root owned chmod 0755 $file_initd # Execute the new init.d "$file_initd"
The nmap /bin files and /share files have to be installed somewhere with permission to execute and the first few lines of the shell script modified to reflect this.
Please note that this script is not really intended to be setup by the end-user. It is harder to setup this script and nmap than to manually edit a init.d file.
If ROM Devs are interested, they could provide it preconfigured alongside with their ROMs and then it would be an easy way for the end-user to configure his NFS shares, e.g. by providing a shortcut from the launcher
If there is interest, i could extend it to provide the same functionality for SMB shares as well, otherwise I leave it as an excerise to dust of my shell skills.
Side note on KitKat:
Kit Kat seems to use some kind of "emulated" folders like
- /mnt/shell/emulated/
- /sdcard/
- /storage/
and others depending on the ROM. These folder are likely to be causing empty mounts.
In multi-user environment the path /data/media/0/ seems to be a safe bet.
Comment