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'

Monday, November 19, 2007

How to Look Up a Process

You can look up a process in many ways. Often, you have the name of a daemon, command, or a program, and you want to know its process ID. For example, you may want to find the process ID of firefox.

  • pgrep

    $ pgrep firefox
    4559


    You do not need to specify the complete name.

    $ pgrep fox
    4559


    Because of the partial matching, it is prudent to have pgrep report both the process ID and the matching name:

    $ pgrep -l fox
    4559 firefox-bin


  • ps
    $ ps aux |grep fox 
    peter 4559 4.0 8.7 211680 84668 ? Sl 08:58 6:20 /usr/lib/iceweasel/firefox-bin -a firefox
    root 10611 0.0 0.0 2848 696 pts/0 R+ 11:36 0:00 grep fox


    Alternatively,
    $ ps -ef |grep fox
    peter 4559 1 4 08:58 ? 00:06:26 /usr/lib/iceweasel/firefox-bin -a firefox
    root 10645 8518 0 11:38 pts/0 00:00:00 grep fox


    The second output line for each of the 2 commands refers to the grep itself, and should be ignored.


The pgrep and the ps approaches can be adjusted to look up a process using other criteria besides the name.

For example, to look up all processes being executed by an user ID (0 = root):


  • $ pgrep -lu 0
    pgrep -lu 0
    1 init
    2 migration/0
    3 ksoftirqd/0
    4 events/0
    5 khelper
    6 kthread
    9 kblockd/0
    ....


  • $ ps -ef |grep root 
    root 1 0 0 08:56 ? 00:00:01 init [2]
    root 2 1 0 08:56 ? 00:00:00 [migration/0]
    root 3 1 0 08:56 ? 00:00:00 [ksoftirqd/0]
    root 4 1 0 08:56 ? 00:00:00 [events/0]
    root 5 1 0 08:56 ? 00:00:00 [khelper]
    root 6 1 0 08:56 ? 00:00:00 [kthread]
    root 9 6 0 08:56 ? 00:00:00 [kblockd/0]
    ...

    The grep command will match root along anywhere on the output line. This is sufficient for most casual command line lookup of processes. Of course, you can write to your heart's content a pattern-matching awk/perl script to only output lines that have root in the user name field.


For details, please read the pgrep and ps man pages.

Tuesday, November 13, 2007

How to Scroll the Command Window

How many times have you been annoyed by the command output spanning over the length of the window? If the window is in the X-Window environment, then you could use the scroll bars to scroll back. What if this is your console window, and it does not have scroll bars?

Sure, if only you had remembered, you could have piped the command to the less command. For example,
ps -ef |less


It turns out that you can scroll the bash command window.

To scroll up, hit Shift-Up.

To scroll down, hit Shift-Down.

Simple? Yes. And Effective !!

Saturday, November 10, 2007

Get into the right groups

In Linux, belonging to the right group gives you permission to use restricted-access resources.

When you create a new user, by default,

$ useradd -m george
$ passwd george
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

Of course, you could have done the above using the wizard-styled adduser command.

Now, see what default groups george is in:

$ groups george
george : george

Poor george: he is a loner: being a group of oneself.

george may one day try to use some peripheral devices like the CDROM drive, USB drive, or floppy drive, and discovers that he simply cannot.

What do you do?

First, make sure that for pre-configured drives like the CDROM and floppy drives, the user option is specified. The default option is nouser which restricts access to root only.

cat /etc/fstab
...
/dev/hdb        /media/cdrom0   udf,iso9660 user,noauto     0       0
/dev/fd0        /media/floppy0  auto        rw,user,noauto  0       0
...

If the drive is configured correctly, then determine if george is in the right groups. The easiest way is to reference some user whom you know can access the target devices.

$ groups peter
peter : peter dialout cdrom floppy audio video plugdev netdev powerdev

Most group names are self-explanatory. For USB thumb drives, make sure that george is in plugdev.

To add george to the right groups:

usermod -aG  cdroom,floppy,plugdev  george

usermod -aG appends the new groups to george's existing groups.

$ groups george
george : george cdrom floppy plugdev

Remember this: if you are not in the right group, you don't get invited to the right parties ....

Click here for an updated post about group membership.