Using external file devices in Linux: Climbing the "mount" command
In my four years of using Linux, getting USB drives, memory cards, CD-ROMs, and Windows shares in a state where I could actually use them has been one of my most frustrating problems. Printing, by comparison, has been far easier. I was frustrated even that I had to use the "mount" command, not to mention all the issues with getting it to work the way I wanted it to. In my four years of using Linux, it has gotten a lot better about automatically detecting and mounting devices; in particular, I almost never have to mount hard drives or CD-ROMs manually any more. Other devices, however, remain problematic. You may never have to use the mount command in Linux. You may also win the lottery jackpot; I wouldn't bet on either. This article is intended to help new users save a lot of the time and trouble that I have gone through.
(Note: I am not a Linux expert. I have learned a lot, but I'm sure there is plenty I don't know. This article is based on my experience, not on a detailed technical knowledge of how Linux works behind the scenes. Also, I have been using Ubuntu almost exclusively for about two years now, and although most of this should apply to any distribution, there is a possibility that some things will be different.)
Syntax of the "mount" command
We're going to delve into the command line, which is probably enough to discourage some people. I certainly avoided it when I started using Linux, but sometimes there is no good way around it. The good news is that the mount command is not all that difficult in principle. In order for you to use files on a given device, you have to tell Linux three things. First, you have to tell it which device you want it to read—a hard drive, USB drive, etc. Second, you have to tell it the directory that you want to assign to the device. Unlike in Windows, each device does not get a separate drive letter, like C: or D:. Under Linux, the device just shows up in a directory somewhere in your file hierarchy. Third, you have to tell Linux what filesystem the device uses.
The syntax for the mount command, then, is this:
mount -t [type] [device] [directory]
You usually have to be root to run this command, or else preface it with "sudo."
The last parameter, directory, is the easiest part. You simply have to create a directory somewhere in your file system where the files will show up. For removable media such as CD-ROMs and floppy drives, many distributions will put these directories under /mnt or /media. For example, Ubuntu has a directory for the CD-ROM at /media/cdrom0 and for the floppy at /media/floppy0. This is a convenient place to put things so you can easily find devices that have been automatically mounted, but you can put the directory anywhere. For example, you may want to create a directory under your home directory, such as /home/[username]/cdrom. (I'm assuming that you're the only person using your computer; if several people use it, you wouldn't want to mount a drive under your home directory unless you had some reason to keep other people from seeing it.)
The first parameter, type, refers to the filesystem used by the device. There are different ways of storing files on a device, and Linux needs to know which one the device is using before it can read it. Although this sounds intimidating, it's usually pretty simple. The external devices that we're dealing with will use one of the following three filesystems:
- iso9660: cdrom drives
- smbfs: Windows share
- vfat: floppy disk, USB drive, memory card
There are many more types of filesystems, but most of them are used by Linux to store files on the hard drive (as in other cases, Linux gives you a lot of choices). There is a nice, in-depth discussion of filesystems on on Wikipedia if you want to know more—but you probably don't need to know any of that information for common uses. There is also an "autofs" option, which I gather is supposed to detect the filesystem for you automatically, but I've never gotten it to work (nor have I had much need for it).
The second parameter of the mount command, "device", is the one that has caused me the most trouble. Linux recognizes devices as files under the /dev directory. Most of them are assigned perfectly logical names. For example, if you have an IDE hard drive, it will probably be /dev/hda. A second hard drive would be /dev/hdb, and so on through the alphabet. If your hard drive is partitioned, as it probably is if you use Linux, each partition is a separate device. The first partition would be /dev/hda1, the second /dev/hda2, and so on.
That's relatively easy, because you usually only have one or two hard drives. The same also goes for floppy or CD-ROM drives. The first floppy drive is usually /dev/fd0. CD-ROM drives using IDE (as mine does) are just like hard drives, so if you have one hard drive at /dev/hda, your first CD-ROM will be /dev/hdb. (Since the CD-ROM is not partitioned, you don't have to worry about a number; it would not be /dev/hdb1, for example.)
Okay, but what if you plug in a USB drive? I've got four USB ports on my computer, plus a four-port USB hub plugged into one of them. USB devices are at /dev/sd*, but which one? You can actually test for the existence of a device by using the command
or whatever device you want to check. If there is a device at that address, your screen will quickly fill up with garbage; if not, you will get a notice that there is no such file or directory. Checking all possible devices this way would be tedious, however.
That's where I was stuck until a few months ago, when I learned a valuable tip. When you plug in a device, Linux knows that it is there and immediately assigns it to a file in the /dev directory. Even though it is not mounted, therefore, the system knows it's there — you just have to figure out where. The answer is in the /var/log/messages file, or in the "dmesg" command. I'm not sure what the difference between them is; both seem to work for me, and to have approximately the same information. You'll want to look at the end of the output, since, if you just plugged in your device, it will be the last thing in there. To do that, you can use the "tail" command:
dmesg | tail
This will only give you the last 10 lines of a file, by default. I often use the "less" command instead (same as above, but substitute "less" for "tail"). You can use capital G to jump to the end of the file, and then page backward by pressing "b" as often as you need to.
Let's take the example of a secure digital (SD) card, which I just plugged into my card reader. The last few lines from /var/log/messages are:
Mar 20 14:57:50 localhost kernel: [17202504.352000] SCSI device sdc: 1960449 512-byte hdwr sectors (1004 MB)
Mar 20 14:57:50 localhost kernel: [17202504.352000] sdc: Write Protect is off
Mar 20 14:57:50 localhost kernel: [17202504.352000] SCSI device sdc: 1960449 512-byte hdwr sectors (1004 MB)
Mar 20 14:57:50 localhost kernel: [17202504.356000] sdc: Write Protect is off
Mar 20 14:57:50 localhost kernel: [17202504.356000] sdc: sdc1
Mar 20 14:57:50 localhost kernel: [17202504.376000] printk: 144 messages suppressed.
You can see that the device I plugged in was a SCSI device, which tells me that the device name will begin "sd". I don't really need to know that, however, because a few lines later I get the exact device: sdc1. All devices are in the /dev directory, so the full path to my memory card is /dev/sdc1.
We also know that memory cards use a vfat filesystem (see above). I'm going to choose to mount the memory card at /media/sdcard. Finally, we have enough to use the mount command:
mount -t vfat /dev/sdc1 /media/sdcard
How can I be sure that the mount worked? One way is to look at the /etc/mtab file, which is a list of all currently-mounted filesystems. The information in this file is the same as that passed to the mount command, although, for some reason, in a different order: device, directory, type. If your device is mounted, you should see a line like the following, probably at the end:
/dev/sdc1 /media/sdcard vfat ro 0 0
(I have no idea what the numbers at the end mean, and I've never had a need to change them.) I usually navigate to the directory where the device was just mounted (using either the command line or a GUI tool like Nautilus) to make sure something is in there. However, this is not a good way to check if the device is mounted, unless you already know what is on the device. For one thing, if the device is empty, you'll get the same empty directory listing that you would if the mount command failed. Second, the directory that you are using to mount the filesystem is still a usable directory, even if the mount command failed. That's right, you can have two sets of data in the same directory: one from the device mounted at the directory's nearest parent (for example, your hard drive), and a second from the removable device that you are mounting! The good news is that there doesn't appear to be any danger of overwriting data by mounting a device onto a directory that is already being used (at least, I haven't had a problem with it). The bad news is that you could see files in a directory even when your device is not mounted. The best practice is always to mount devices to an empty directory (create one if you need to), and always check your mount command by looking in /etc/mtab if you have any doubts about whether it worked.
Happily, our device shows up in /etc/mtab, so everything's fine now, right? Maybe. At least, if we got the contents of the directory, we know we can read files from the disk; but can we write to it? We didn't specify that we were mounting the memory card so we could write to it, so it may have been mounted read-only. We can correct that by passing an option to the mount command. But before we do can mount our device with the correct options, we have to unmount the incorrectly mounted version. (There are ways to re-mount a device with different options, but we won't go into that here.)
The command to unmount is, thankfully, simple:
umount [directory | device]
That is, you can specify the directory or the device that you want to unmount, and you don't need to add in any arguments. Notice that it is "umount" (no "n" after the "u") instead of "unmount". The only catch with unmounting is that nothing can be accessing the device at the time. Therefore, if you have Konqueror or some other file manager open to the mounted directory, or if the current working directory in one of your command shells is the mounted directory, umount will fail. Sometimes a process will be using a file from a mounted device in the background and you won't know what it is. In that case, you can try passing the "-l" option to umount to do a "lazy" unmount. Of coure, with removable media such as a USB drive or memory card, you can always just pull it out — but I don't recommend it. Chances are good that if you do this, all the changes that you just made to the device will be lost. I've had this happen a number of times when I removed a device after umount failed—trust me, it is very frustating. Also, with CD-ROM drives, usually Linux will not let you eject the CD until it has been unmounted properly.
We've unmounted our device, so now let's remount it and specify that it will be "read-write." We do this by adding the "-o" argument to the end of the mount command (for "options"), and putting "rw" (for "read-write") after it:
mount -t vfat /dev/sdc1 /media/sdcard -o rw
We've done that step, but when I go to copy a file to it, I still get the error "Permission denied." Why? Well, I mounted the device read-write, but only for the owner; and since I mounted it as root, the owner of the directory is root. To explain this further, you need to understand Linux file permissions, which are beyond the scope of this article. I will simply say that the permissions that you assign to a directory are *irrelevant* to the permissions of the directory after it is mounted. It took me quite a while to figure out that the permissions are assigned *in the mount command*, and override whatever permissions you have set on the directory. You need to add an option to set the permissions you want. To allow full permission to everyone, you will add "umask=000" (those are zeroes, not the capital letter "o"s). Our command is now:
mount -t vfat /dev/sdc1 /media/sdcard -o rw,umask=000
Notice that we can add additional options by just separating them by a comma.
I have saved the problem of mounting Windows shares for a separate section. The protocol for sharing file information in Windows is called Samba, and the filesystem that you use for the mount command is smbfs. Actually, there is a separate mount command, "smbmount", just for Windows shares, but you don't use it. Instead, when you mount an smbfs filesystem, the mount command calls smbmount for you. For the most part, you never need to know the difference. The only time I have found it important is when I need to know the options for smbmount, which are not found on the man page for the mount command; instead, do "man smbmount".
Mounting a Windows share is pretty much like mounting any other device, with the obvious exception that the Windows computer is not connected directly to your computer, but instead you communicate with it over a network. Therefore, the "device" that you are mounting is not in the /dev directory. Instead, you will use (a) the name of the Windows computer, and (b) the directory that it is sharing. Use slashes as in the following example:
mount -t smbfs //WindowsPC/SharedFolder /MountDirectory
If you don't specify a share in exactly the format shown above, you may get an error that you have too few "\" characters in the share name. Don't let the fact that this error refers to a backslash deter you; what it actually wants is a regular Unix forward slash.
Another possible difference when using a Windows share is that you may have to log in to use it. To do this, we will simply use the options at the end of the mount command to specify a user name and password, as follows:
mount -t smbfs //Windowscomp/sharedfolder /mywindowsdir -o username=myuser,password=mypassword
There are lots of other options here, for example, passing "guest" instead of a username and password, and ways of passing the username and password more securely; but this should at least get you hooked up.
Finally, mounting a Samba share does not have the "umask" option. Instead, you can use the "fmask" and "dmask" options, which set permissions for files and directories, respectively. The trick is that this is exactly backward of how umask works: it sets the permissions that are turned on, not the permissions that are turned off. So, to allow all permissions on a share, do this:
mount -t smbfs //Windowscomp/sharedfolder /mywindowsdir -o username=myuser,password=mypassword,dmask=777,fmask=777
Dmask and fmask are available as options for other filesystems if you want to set permissions for directories and files separately, but they work like umask, so set them to 000 for full permission.
I will mention one other issue with Samba shares, because I ran into it recently and had a heck of a time finding the solution. Apparently, Samba is only set up to deal with files of up to 2GB, which is not usually a problem. Since I was trying to copy videos, however, it was an issue for me. The solution is to pass "lfs" as one of the options:
mount -t smbfs //Windowscomp/sharedfolder /mywindowsdir -o username=myuser,password=mypassword,lfs
This article has not tried to cover all aspects of the mount command. I have not dealt with filesystems on your local hard drive, mainly because most distributions mount them automatically. The principle is the same, but you have to choose the correct filesystem, and Linux can use almost all of them; you may also have a Windows partition that uses vfat or ntfs. I have not dealt with NFS shares, which is a common way of sharing files on a Unix network. Since you almost always have to set up NFS shares yourself, I figured that, if you are using them, you already know how to mount them. Again, the principle is the same, and the filesystem is nfs, but the device name takes a special form. You can find information about all of this in the man page for mount, along with many other options.
Finally, I have not dealt with getting Linux to mount your devices automatically when they are connected. To mount them automatically at boot time is actually pretty simple: you just need to add a line to /etc/fstab that matches the mount command parameters that you want to use, but in the format of the /etc/mtab file. The problem is that, for removable devices, mounting at boot time is rarely an option. There is a way to get Linux to detect when a USB device connects and to mount it automatically, but I haven't figured it out. Actually, my Ubuntu distribution (Edgy) is good enough to detect a USB drive or memory card, mount it, and open up Nautilus to the appropriate directory. Unfortunately, it mounts the device read-only, so I have to unmount it and remount it using the parameters that I want.
What I have given you, I hope, is a simple set of instructions for mounting devices that will deal with your most common problems. Unless you use a distribution that automatically mounts and unmounts devices for you, this is probably something that you will have to learn sooner or later.
If you need any help with any Free Software we're waiting to help in Nuxified forums.
Note: Many things in this article have been corrected or add to in the comments that follow.