Wednesday, February 26, 2014

Connecting to an SMB share...

How to connect to an SMB share...

with spaces in its name...

from Mac OS X using the Terminal or a bash script

This is something I needed to do in order to back up some Windows systems with rsnapshot, a python script that uses rsync. Getting it to back up Windows systems over the network requires that the Windows computers share the directory or directories that need to be backed up, and the Mac OS X box mounts the shares for the backup to run. There may be other ways, but this works well for us at the moment. The only issue has been working out how to mount Windows shares with spaces in their names from a bash script, so the backup could be scheduled to run automatic and unattended.

It took a while to figure out. Googling didn't really help much - there were plenty of suggestions but nothing actually worked. These ranged from quoting the space with backslashes, replacing the quote with its octal representation (\040), using double-quotes. In the end, many people suggest that renaming the share to get rid of the space is the way to go.

In the past this is what I'd done: altered the name of the Windows share to remove the spaces, but in the back of my mind I knew it should be possible. Finally I got around to working it out properly...

The following are known to work in Mac OS X 10.9 with shares from Windows 7, XP and Vista. There are two steps to mount the share.

Create the mount point

This is pretty straightforward. If this is done in the bash shell the spaces can be quoted with a backslash, or the entire name can be double-quoted. The mount point can be created anywhere in the file system, but if it's in /Volumes the mounted volume will be available in the Finder.

mkdir /Volumes/Share\ Point

or

mkdir /Volumes/"Share Point"

Mount the share

This is done at the bash prompt or in a script using the mount command. You must specify the username and password, the address of the server, the name of the share and the mount point.

The path to the mount point is fairly simple. In typical bash fashion it can be specified with double quotes or the space could be preceded with a backslash - either will work. The real trick is getting the path to the SMB share exactly right. My first (failed) attempts were to use double quotes as follows:

> mount -t smbfs "//username:password@ip_number/Share Point" "/Volumes/Share Point"
mount_smbfs: URL parsing failed, please correct the URL and try again: Invalid argument

which clearly did not work. Next try was escaping the space with a backslash:

> mount -t smbfs //username:password@ip_number/Share\ Point "/Volumes/Share Point"
mount_smbfs: URL parsing failed, please correct the URL and try again: Invalid argument

which also failed. Similarly, using the octal representation of the space:

> mount -t smbfs //username:password@ip_number/Share\040Point "/Volumes/Share Point"
mount_smbfs: mount error: /Volumes/Bruker Backup: Unknown error: -1073741412

this gave an exciting new error message, but still failed :(

Finally, I was successful when I replaced the space with %20 its URL-encoded representation:

mount -t smbfs //username:password@ip_number/Share%20Point /Volumes/Share\ Point/

Phew! The share will now be available in /Volumes, and also visible in the Finder. When you're finished with it and it's no longer needed, it can be unmounted in the Terminal with

umount /Volumes/Share\ Point

or by Ejecting it in the Finder.

Getting it to work in a bash script

I use a function within a bash script to do the mounting of smb shares. I pass in the username and password, the server name and the share name and the function does the heavy lifting. If the share name to be mounted has spaces in its name, the spaces must be replaced with %20 in the function call. Within the function the share name is used with the %20 in the call to mount, and the %20 is replaced with a space and the share name is double-quoted when used to create the mount point, specify the mount point in the mount call, and to unmount the share when it's no longer needed. A proof of concept script would look something like:

#!/usr/bin/env bash

IP="192.168.0.1"
USERNAME="username"
PASSWD="password"
SHARE_NAME="Share%20Point"

# bash can replace the %20 with a space...
MOUNT_POINT="/Volumes/${SHARE_NAME//\%20/\ }"

mkdir "${MOUNT_POINT}"

mount -t smbfs "//${USERNAME}:${PASSWD}@${IP}/${SHARE_NAME}" "${MOUNT_POINT}"

# do something useful with the share at this point

umount "${MOUNT_POINT}"

2 comments:

  1. Worked great without the password variable but as soon as I pass my secure password in it errors out. I am wondering if my password uses characters that bash sees as reserved.

    ERROR MESSAGE
    mount_smbfs: URL parsing failed, please correct the URL and try again: Invalid argument

    ReplyDelete
  2. Thanks for the tip regarding the space - %20 work great!

    ReplyDelete