Tuesday, December 18, 2007

Part 1: How to work with Access Control Lists from the Command Line

The basic Linux permission model lets you specify permissions for the file's owner and group, and all others. This article assumes that you are familiar with the basic permissions, and know how to set them. The Access Control List (ACL) feature extends the model to allow much finer control: you can specify permissions for each individual user and group defined in your system.

Consider this scenario: your server supports multiple office departments: Sales, Marketing, and Helpdesk. Each department has a manager, and one or more staff members.

You define a group for each department that comprises of its manager and staff members: sales-g, marketing-g, and helpdesk-g. Then, you also define a managers only group: managers-g.

It is normal that some departments need to share files among each other, but not with all departments. For instance, Sales needs to share a file with Marketing, but not with HelpDesk. To set that up using only the basic permissions, you can define yet more groups: sales-marketing-g, sales-marketing-managers-g, etc.

Alternatively, you can use ACL to assign permissions to individual group and user.

Before you can use ACL, you must explicitly turn it on for the partitions you want to have the ACL feature available.

As root, edit /etc/fstab. Find the partition that you want ACL enabled, and add the mount option acl.
/dev/mapper/star-home /home ext3  defaults,acl 0 2


Next, assuming that your partition is already mounted, then either reboot the system, or better yet, remount dynamically:
mount -o remount,acl /home


Next, you need to make sure that you have 2 ACL utilities installed: getfacl, and setfacl.

On a Debian system, install the utilities like this:
$ apt-get install acl


Note: eiciel is a GUI-based utility that can both get and set ACLs. It adds a new Access Control List tab to the Properties view in Nautilus. You can also run eiciel on its own, and edit the ACL of any file or directory.

Now, you are ready to tackle ACL.

Let's start simple: you have a file /home/peter/targets.txt that you want to share between sales-g, marketing-g, and an user named george.
$ cd /home/peter;ls -l
total 64
-rw-r--r-- 1 peter peter 60097 2007-12-08 10:55 targets.txt


Use setfacl -m to set Access Control List for the file.
$ setfacl -m group:sales-g:rw-   targets.txt


The group:sales-g:rw- parameter specifies Read and Write permissions (rw) for the group: sales-g.

To enable the Read/Write permissions for the Marketing department, and george the user:
$ setfacl -m group:marketing-g:rw-,user:george:rw- targets.txt
$ ls -l
total 68
-rw-rw-r--+ 1 peter peter 60097 2007-12-08 10:55 targets.txt


Note that ls -l does not display the actual ACL of a file. It only tells you that ACL is defined for that file: a plus character (+) is displayed to the right of the permissions.

To examine the actual ACL, run getfacl.

$ getfacl targets.txt
# file: targets.txt
# owner: peter
# group: peter
user::rw-
user:george:rw-
group::r--
group:sales-g:rw-
group:marketing-g:rw-
mask::rw-
other::r--


Part 2 of this article describes how to define ACL for a directory. As you would expect, you can specify the read/write/execute permissions for any group or user on a directory. In addition, you can specify the DEFAULT permissions for any FILE created under this directory.

Saturday, December 8, 2007

How to Change Mount Options at Runtime

File systems need to be mounted on Linux before you can access the data on them. You can specify mount options such as whether the file system is Read Only or Read/Write, and whether to support Access Control List, etc.

To see what file systems are currently mounted, where, and with what options, issue the mount command without arguments:
$ mount
...
/dev/hda5 on /home type ext3 (rw,acl)
...


Recently, I wanted to tell the file system not to track the last access time (atime) of files under /home. I did not have any good use for the last access time. So, I opted to disable its tracking to reduce disk activity and save a few watts. This is accomplished through adding the mount option noatime.

To change the mount option for /home:

  1. Edit /etc/fstab as root.
  2. Add the option noatime to the line that corresponds to /home:
    /dev/hda5 /home ext3    defaults,acl,noatime   0  2

  3. To make the change effective, you can either reboot (to which you sneer) or you can remount /home.

To remount a file system, say /home, with new mount options at run-time, issue a command like this:
$ mount -o  remount,noatime   /home

There you have it. You can now feel good about saving a few watts, and be the hero in saving the environment.

Saturday, December 1, 2007

How To Mount USB flash drive from Command Line

Mounting a USB flash drive in GNOME (or another Linux desktop environment) is as easy as plug and play. Yet, occasionally, you need to mount one on a server which does not run X, then you must know how to do it on the command line.

  1. Become root.

    $ sudo -s


  2. Plug in USB drive to a USB port.

  3. Identify the correct partition name corresponding to the USB drive.

    For my Debian system, it is sda, and partition 1.
    $ dmesg |grep -i 'SCSI device'
    ...
    SCSI device sda: 3903488 512-byte hdwr sectors (1999 MB)

    Alternatively,
     $ grep  SCSI /var/log/messages
    ...
    Dec 1 11:52:26 tiger kernel: SCSI device sda: 3903488 512-byte hdwr sectors (1999 MB)

  4. Mount the partition to an existing mount point (directory).

    $ mkdir -p /mnt/myusb
    $ mount -t vfat -o rw,users /dev/sda1 /mnt/myusb

    users give non-root users the ability to unmount the drive.

    You can verify the drive is indeed mounted as follows:
     $ mount

    You should see a line in the output that looks like:

    /dev/sda1 on /mnt/myusb type vfat (rw,noexec,nosuid,nodev)


To retrieve the USB drive:

  1. You must unmount the partition before physically unplugging the USB device.


    $ umount /mnt/myusb

    You can run the mount command again (with no argument) to verify that the volume is indeed mounted.

  2. Unplug USB drive.

Monday, November 26, 2007

Use of --parents flag in mkdir and cp

Occasionally, you want to create a directory structure several levels deep.
For example, /home/peter/status/2007/november.

Your first attempt may be something like this:
$ mkdir /home/peter/status/2007/november
mkdir: cannot create directory `/home/peter/status/2007/november':
No such file or directory


The problem is that the intermediate directories (status and 2007) do not exist.

The following will work, but it is quite clumsy.
$ cd /home/peter; mkdir status
$ cd status; mkdir 2007
$ cd 2007; mkdir november


A much shorter way is simply:
$ mkdir --parents /home/peter/status/2007/november


With the --parents option, mkdir will actually create the intermediate parent directories if needed.

-p is the short equivalent of --parent for the mkdir command.

When the time comes to create the december directory, you can issue this:
$ mkdir -p /home/peter/status/2007/december


Although you have specified the -p (--parents) option, and the parent
directory structure already exists, it will quietly create the december
directory below it. This is just what we expect.


To check your results, do a ls -R (recursively list the directory)
$ cd /home/peter; ls -R status
status:
2007

status/2007:
december november

status/2007/december:

status/2007/november:


Let's create a file in /home/peter/status/2007/november.
 $ touch /home/peter/status/2007/november/nov12.txt

The above will create an empty file named nov12.txt.

Next, we will copy the nov12.txt file like this:
$ cd /home/peter
$ cp --parents status/2007/november/nov12.txt /home/peter/tmp


The --parents flag will cause the full path to be copied to tmp ("status/2007/november/nov12.txt")

$ cd /home/peter/tmp/
$ ls -R status
status:
2007

status/2007:
november

status/2007/november:
nov12.txt


How is cp --parents different from cp -r (recursive copy)?

$ cd /home/peter
$ cp -r status /home/peter/tmp


The recursive copy will have copied everything under status (including the contents of the december directory).

ls -R /home/peter/tmp/status
/home/peter/tmp/status:
2007

/home/peter/tmp/status/2007:
december november

/home/peter/tmp/status/2007/december:

/home/peter/tmp/status/2007/november:
nov12.txt

Tuesday, November 20, 2007

sudo hacks: making cd and redirection work

Suppose you want to run a command that requires root privileges. Conventional wisdom says don't login as root. Instead, login as a non-root user, and then sudo.
$ sudo 'cd /root/restricted'
Password:
sudo: cd /root/restricted: command not found
$

cd Not Found ?? That is RIGHT !

cd is a shell built-in command. It cannot be run in a child process. The child process simply cannot change the working directory of its parent shell process.

Redirection also does not work with sudo for the same reason (redirection being a shell "thing")
$ sudo 'ls /root/restricted >/root/out.txt'
sudo: ls /root/restricted >/root/out.txt: command not found
$


The workaround in both cases is to execute the command in a subshell.

$ sudo sh -c 'cd /root/restricted'

$ sudo sh -c 'ls /root/restricted >/root/out.txt'