More Hacks for the User Environment in BSD

In this article, the third and last of a series, you’ll learn how to customize a BSD environment for other users; maintain your chosen environment on multiple machines; and more. It is excerpted from chapter one of the book BSD Hacks, written by Dru Lavigne (O’Reilly, 2005; ISBN: 0596006799), Copyright © 2005 O’Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O’Reilly Media.

Hack 9: Customize User Configurations

Now that you know how to set up a useful environment for yourself, it’s time to share the wealth.

It’s very easy for a system administrator to ensure that each newly created user starts out with the same configuration files. For example, every user can receive the same customized prompt, shell variables, or hotkeys.

Whenever you create a new user, several default (and hidden, or dot, files) are copied into the new user’s home directory. In FreeBSD, the source of these files is /usr/share/skel/. Any customizations you make to these files will be seen by all subsequently created users. Do note that you’ll have to manually copy over any modified files to existing users.

It’s useful to understand these files, as they apply to every user you create. Depending upon your needs, you’ll probably end up removing some of the defaults, customizing others, and even adding a few of your own.

Default Files

Let’s take a quick tour of the default files:

  % ls -l /usr/share/skel
  total 24
  drwxr-xr-x  2 root wheel 512 Jul 28 16:09 ./
  drwxr-xr-x 27 root wheel 512 Jul 28 16:06 ../
  -rw-r–r–  1 root wheel 921 Jul 28 16:09 dot.cshrc
  -rw-r–r–  1 root wheel 248 Jul 28 16:09 dot.login
  -rw-r–r–  1 root wheel 158 Jul 28 16:09 dot.login_conf
  -rw——-  1 root wheel 371 Jul 28 16:09 dot.mail_aliases
  -rw-r–r–  1 root wheel 331 Jul 28 16:09 dot.mailrc
  -rw-r–r–  1 root wheel 797 Jul 28 16:09 dot.profile
  -rw——-  1 root wheel 276 Jul 28 16:09 dot.rhosts
  -rw-r–r–  1 root wheel 975 Jul 28 16:09 dot.shrc

Note that each starts with the word dot . However, when the files are copied into a user’s home directory, the dot s turn into literal dots ( . ). Also, the files in this directory are owned by root , but when a new user is created, the cop ied over files will change ownership as they are placed in that user’s home directory.

dot.cshrc. Let’s examine each default file, starting with dot.cshrc. (“Useful tcsh Shell Configuration File Options” [Hack #2] introduced several .cshrc

hacks.) If you’d like new users to receive your customizations, simply replace /usr/share/skel/dot.cshrc with your hacked version of .cshrc. Don’t forget to rename the file as you copy it:

# cp /root/.cshrc /usr/share/skel/dot. cshrc

Here, I overwrote the default dot.cshrc by copying over the superuser’s customized version of .cshrc. Although you could edit /usr/share/skel/dot.cshrc directly, you may find it more convenient to have a customized copy stored elsewhere.

All isn’t lost if you already have existing users whom you’d like to receive this file. First, find out what users already exist and have home directories. This is a quick way to do so:

  # ls /usr/home
  dru     test

Since this system has only two existing users, it’s an easy matter to copy over my customized .cshrc. I’m also a lazy typist, so I use ~ instead of typing out /usr/home . Also note that I have to remember to manually change ownership:

  # cp /root/.cshrc ~dru/
  # chown dru ~dru/.cshrc
  # cp /root/.cshrc ~test/
chown test ~test/.cshrc

If your system already contains many users, you’ll probably prefer to write a script. Here is an example:

  #!/usr/bin/perl -w
# copydotfiles.p l
  #    – copy default files to user directories
  #    – change ownership of those files
  # You may wish to change these constants for your system:
use constant HOMEDIR => ‘/usr/home’;
  use constant SKELDIR => ‘/usr/share/skel’;
  use constant PREFIX => ‘dot’;
  use strict;
use File::Copy;
  use File::Spec::Functions;
die "Usage: $0 <files> <to> <copy>n" unless @ARGV;
for my $user ( get_users() )
      for my $dotfile (@ARGV)
my $source = catfile( SKELDIR(), PREFIX() . $dotfile );
        my $dest = catfile( $user->{homedir}, $dotfile );
if (-e $dest)
warn "Skipping existing dotfile $dest…n";
copy( $source,      $dest )
            or die "Cannot copy $source to $dest: $!n";
        chown( $user->{uid}, $dest );
sub get_users
or die "Cannot open home directory: $!n";
my @users;
while (my $directory = readdir( DIRHANDLE ))
         next if $directory =~ /^./;
         my $path = File::Spec->catdir( HOMEDIR(), $directory );
         my $uid = getpwnam( $directory );
next unless -d $path;
next unless $uid;
push @users, { homedir => $path, uid => $uid };
return @users;

This script first examines all of the users with home directories, returning a list of those directories and the user IDs. It loops through that list, copying each dot file you provided on the command line to that user’s home direc tory and changing the ownership to the user.

If you run it as:

  # .cshrc

all users will receive a new .cshrc file, unless one already exists.

dot.login. The next file, dot.login, is used only by the csh and tcsh shells. If your users don’t plan on using these shells, you can safely remove this file from /usr/share/skel. If your users do use those shells, consider whether there are any commands you would like to run when users log in. Note that this file is read after .cshrc.

By default, the only uncommented line in this file is:

  % grep -v ‘#’ /usr/share/skel/dot.login
[ -x /usr/games/fortune ] && /usr/games/fortune freebsd-tips

Here, I used the reverse filter switch -v to the grep search utility to look for all the lines that do not begin with the # comment symbol.

The resulting line tells the shell to run the fortune program. If you chose to install the games distribution when you installed FreeBSD, your fortune appears just before the MOTD whenever you login. Have you ever noticed that you don’t receive a fortune when you use su ? That’s because .login is only read when you log in, and the default invocation of su does not actually log you in.

Instead, it opens what is known as a nonlogin shell. You also get one of those every time you open an xterm . Basically, the only time you get a real login shell is when you type in your username and password at a login prompt.

Herein lies the difference between .cshrc and .login. Place what you would like to happen only when you log in into .login, and place what you would like to happen whenever you use the csh shell, even if it isn’t a login shell, into .cshrc. If you don’t see the need for a difference, you don’t need /usr/share/skel/ dot.login.

dot.login_conf. Reading the default contents of dot.login_conf will give you an idea of its purpose and where to go for additional information:

  % more /usr/share/skel/dot.login_conf 
  # $FreeBSD: src/share/skel/dot.login_conf,v 1.3 2001/06/10 17:08:53 ache Exp $
  # see login.conf(5)
  #        :charset=iso-8859-1: 
  #        :lang=de_DE.ISO8859-1:

Note that this file is commented by default, but shows the syntax a user can use to create a customized  .login.conf. Usually such settings are set in the glo bally administrated /etc/login.conf file, and individual users can override only some of those settings. If your users don’t have a need or the know-how to configure those settings, you can safely remove this file from /usr/share/skel.

dot.mail_aliases and dot.mailrc. The next two files work hand in hand and customize the behavior of man mail . Since it is quite rare to find users who still rely on the original mail program, you can safely remove those files.

dot.profile. The dot.profile file is read by the Bourne, bash , and Korn shells. It is the only file read when a user logs into a Bourne shell, the first file read when a user logs into the Korn shell, and is optional for bash users.

If your users don’t use the Bourne or Korn shells, there’s not much sense populating their home directories with this file. Depending upon your slant, you may wish to keep this file in order to place path statements and environment variables for use with Bourne shell scripts. However, most users tend to place those directly into the script itself to allow for portability.

If your users wish to use the bash shell, which isn’t installed by default, keep in mind that .profile allows a user to override the settings found in the global /etc/profile file. You may find it easier to make your edits to the global file and then remove  /usr/share/skel/dot.profile. More sophisticated users can always create their own ~/.profile. However, most bash users tend to make their modifications to ~/.bash_profile.

dot.rhosts. Did you happen to notice in the earlier long listing that this file has different permissions from most of the other files? If you read man rhosts , you’ll see that this file is ignored if it is writable by any user other than the owner of the file.

So, when is this file used? It’s used when a user types one of the r* commands: rsh , rcp , or rlogin . I won’t show you how to set up this file or use those commands, as they were designed for use back in the days when networks were considered trusted. They’ve pretty well been replaced by ssh and scp , which provide a much safer way to log into remote systems and to transfer files. For this reason, I always remove /usr/share/skel/dot.rhosts from my systems.

dot.shrc. The last default file is dot.shrc. As you may have guessed, it is the rc file for sh , the Bourne shell. Again, if your users don’t log into that shell, they won’t miss this file.

Missing (but Useful) Dot Files

Now that we’ve had the opportunity to look at the default files, it’s time to consider any useful missing files.

dot.logout. We’ve already seen that ~/.login is read when a user logs into the csh or tcsh shells. Not surprisingly, ~/.logout is read when a user logs out of their login shell. This is an excellent place to put commands you would like to execute as a user logs out. It could be something as simple as:

  # more dot.logout
  # this line clears your screen when you logout
  # add your own commands or scripts, one line at a time,
  # which you would like to execute
  # whenever you logout and leave your terminal

This dot.logout will clear the user’s terminal, making it much neater for the next person who logs in. Notice that I commented this file, so the user is aware of its use. When creating your own dot files, use lots of comments. If you intend for your users to customize their own dot files, use comments that explain the syntax they can use when they do their modifications.

dot.logout can run any command or script that suits a user’s needs. Here are some ideas to get your imagination rolling:

  • A script that backs up the user’s home directory
  • A script that shows how much time the user spent online
  • A script that displays other statistics, such as available disk space

dot.xinitrc. I also find it very useful to create a custom dot.xinitrc. By default, users receive the extremely lightweight twm window manager. Since I usually install KDE, this line ensures that each user will receive that window man ager instead:

  # more dot.xinitrc
  exec startkde

You can also specify which programs you would like to launch when a user types startx and their ~/.xinitrc file kicks in. For example, this is a popular line to add:

  # more dot.xinitrc
  exec xterm &
  exec startkde

This starts an xterm in the background. Notice the & at the end of its line—this is to ensure that once xterm loads, it doesn’t interfere with any other programs that are still loading. When you’re creating your own dot.xinitrc, you can start any program you like. However, start your window manager last. Start your other programs, one line at a time, putting an & at the end of each line. The only line that does not have an & will be the very last line, the one that loads your window manager.

Since I prefer to start my browser instead of an xterm , here is my customized dot.xinitrc:

  #to start another program when you "startx", type:
  #exec path_to_program &
  #before these lines 
  exec /usr/X11R6/bin/mozilla &
  exec startkde

There are dozens of possibilities for customized dot files. Take stock of your own systems, and ask yourself: “What programs do my users use?” For example, if your users use bash , vim , screen , procmail , or fetchmail , why not start them off with a customized configuration file that contains comments on how to add their own customizations and URLs of where to go for fur ther ideas? A little homework and creativity on your part can help your users get the most out of the utilities they use on a daily basis.

Editing /usr/src/share/skel/Makefile

Let’s end this hack by examining where the default dot files in /usr/share/skel came from in the first place. You’ll find the answer here:

  % ls /usr/src/share/skel
  ./         dot.login         dot.profile
  ../        dot.login_conf    dot.rhosts 
  Makefile   dot.mail_aliases  dot.shrc 
  dot.cshrc  dot.mailrc

That Makefile controls the installation of those files:

  # more /usr/src/share/skel/Makefile
  #        @(#)Makefile     8.1 (Berkeley) 6/8/93
  # $FreeBSD: src/share/skel/Makefile,v 1.8 2002/07/29 09:40:13 ru Exp $
FILES1= dot.cshrc dot.login dot.login_conf dot.mailrc dot.profile dot.shrc
  FILES2=        dot.mail_aliases dot.rhosts
  MODE1=        0644
  MODE2=        0600
NOOBJ=        noobj
all clean cleandir depend lint tags:
         ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${MODE1} ${FILES1}   
         ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${MODE2} ${FILES2}
.include <>

Even if you’ve never read a Makefile before, you’ll find it’s not too hard to figure out what’s going on if you already know which results to expect. In this Makefile, FILES=1 is simply a list of files to install. Take a look at MODE1 ; it tells the chmod command what permissions to set on those files.

Similarly, FILES=2 is another list of files. Those two files had different per missions, which were defined by MODE2 .

Move down to the install section. Don’t worry so much about the syntax; rather, notice the pattern. The first set of files are installed and their mode is applied. Then the second set of files are installed with their mode.

It’s an easy matter to customize this file to reflect the dot files you’d like to see installed. In this example, I only want to install my custom versions of dot.cshrc, dot.login, and dot.xinitrc. Since they all require the first mode, I’ll remove any references to the second set of files:

  # cd /usr/src/share/skel
  # cp Makefile Makefile.orig
vi Makefile
#        @(#)Makefile      8.1 (Berkeley) 6/8/93
  # my customized dot files to be installed into /usr/share/skel

  FILES1= dot.cshrc dot.login dot.xinitrc 
  MODE1=       0644
NOOBJ=       noobj
all clean cleandir depend lint tags: 
         ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${MODE1} ${FILES1}
.include <>

Now let’s try a test run. I’ll replace the default dot files found in /usr/src/share/skel with my customized versions. I’ll then remove the contents of /usr/ share/skel and see what happens when I run my customized Makefile:

  # cd /usr/src/share/skel
  # rm dot.*
  # cp ~/mystuff/dot.* .
  # rm /usr/share/skel/*
  # ls /usr/share/skel
  # make install
  install -o root -g wheel -m 0644 dot.cshrc dot.login dot.xinitrc
# ls /usr/share/skel
dot.cshrc     dot.login   dot.xinitr

I find it very handy to keep a copy of my customized Makefile and dot files in a separate directory, in this case ~/mystuff. This ensures they are backed up. It’s easy for me to grab those files whenever I want to customize a partic ular system.

{mospagebreak title=Hack 10: Maintain Your Environment on Multiple Systems}

It’s especially important to use a separate location if you use cvsup to keep your system up-to-date. Otherwise, your next update will notice your modified src and happily replace those missing original source files. But don’t worry; it won’t touch your new

Of course, sometimes this is a very useful trick in itself. If you ever mess up a file located somewhere within /usr/src , a quick cvsup will put everything back the way it was. See “Automate Updates” [Hack #80] for details on automating cvsup .

The Other BSDs

The preceding discussion is based on FreeBSD, but it also applies to NetBSD and OpenBSD systems, save for a few tiny differences outlined here.

NetBSD. NetBSD administrators will find the skeleton home directory in /etc/skel. Specify a different location by passing the -k option to useradd .

OpenBSD. OpenBSD systems store the skeleton home directory in /etc/skel. Specify a different skeleton directory location by passing the -dotdir option to adduser .

See Also

  • man adduser 
  • The manpages returned by apropos user


The sign of a true Unix guru is the ability to perform a task quickly when confronted with an unfamiliar shell, keyboard, terminal, window manager, or operating system.

A large part of using Unix systems effectively involves configuring a comfortable environment using familiar tools available from the Unix shell prompt. It’s much easier to perform a task quickly when all of the shortcuts your fingers have learned work on the first try.

Even something as simple as setting up your prompt the way you like it can steal significant time from your productivity if you need to do it on several hosts. If you’re going to spend significant time in a Unix shell, it’s worth getting organized. A bit of onetime effort will reward you later, every time you sit down at the keyboard.

Enter unison

unison is a tool for maintaining synchronized copies of directories. I’ve used it to maintain a central repository of all of my dot files, shell scripts, signatures file, SpamAssassin configuration—basically any file I’d like to have available, regardless of which host I happen to be logged into.

You can install unison from the NetBSD pkgsrc collection:

  # cd /usr/pkgsrc/net/unison
  # make install clean

FreeBSD and OpenBSD ports also include net/unison.

Even better, this utility is available for most Unix and Windows platforms. See the main unison web site for details.

Using unison

Whenever I configure a new Unix host or get a shell on another system, I install unison . Then, I create a directory to receive the files I’ve stored in the /usr/work/sync directory at I call the local directory ~/sync.

To synchronize those two directories:

  % unison ~/sync ssh:// work/sync
  p = /home/david/.unison; bn = .unison  
  Contacting server…
  p = /home/david/sync; bn = sync’s password:

After ssh prompts for a password or pass phrase, the unison exchange begins. On a first-time synchronization, unison will ask only one question: whether you wish to copy the remote directory to the local host.

  Looking for changes
  Warning: No archive files were found for these roots. This can happen
  either because this is the first time you have synchronized these roots,
  or because you have upgraded Unison to a new version with a different
  archive format.

Update detection may take a while on this run if the replicas are large.

unison will assume that the last synchronized state of both replicas was com pletely empty. This means that any files that are different will be reported as conflicts, and any files that exist only on one replica will be judged as new and propagated to the other replica. If the two replicas are identical, then unison will report no changes:

  Press return to continue .
  Waiting for changes from server
  Reconciling changes
        <—- dir        / [f]
Proceed with propagating updates? [] y 
  Propagating updates
UNISON started propagating changes at 11:44:39 on 02 Feb 2004
  [BGN] Copying 
  from // 
  to /home/david/sync
  [END] Copying
  UNISON finished propagating changes at 11:44:41 on 02 Feb 2004
  Saving synchronizer state
  Synchronization complete

I now have a populated ~/sync directory on the new system, organized into subdirectories. Each subdirectory contains the files I find useful to carry around with my various accounts on multiple Unix machines.

Notice also that although my preferred shell is tcsh , I maintain a .cshrc and .profile for use on systems where tcsh is not available.

Automating the Process

I’ve automated the process with a simple shell script called sy in my bin directory. sy runs the unison command to synchronize the ~/sync directory.

  unison ~/sync ssh://username@host. sync

Creating Portable Files

Making good use of the sync directory requires some discipline. It’s one thing to be able to copy files easily; it’s another thing to be able to use them without modification on several hosts.

To take advantage of this hack, when you copy the dot files to your home directory and notice that something doesn’t work exactly the way you like it to, make sure you don’t simply change it for the local host.

Instead, update the dot files so that they use conditional if statements, shell backticks (e.g., `hostname` ), or environment variables, to make them behave correctly on the new hosts without breaking them on the systems where you already use them. Then, copy the dot file back into your ~/sync directory and run the sy script. unison will prompt for a password or passphrase for the ssh connection, then ask you to verify that you want to update your files back to the main server.

The first few times you do this, you may introduce breakage when the new dot file is used on another host. With a bit of practice you’ll learn how to avoid that. The most important trick is to test. Open a shell to the host and update the dot file, and then open a second shell to the host without closing the first one. If you broke anything that affects your ability to log in, you can fix it with the first shell and test again.

There’s no need to resynchronize every other host you use for each file you change. I generally wait until I’m logged onto a given host and need a newer script, or need to make some additional changes to the local copy of the dot file. Then I synchronize, make the changes in the sync directory, test them locally, and resync them back to the main host.

Using this approach means that I don’t have to reinvent the wheel every time I want to perform a procedure I’ve done before. Any process useful enough to be done a couple of times becomes a script in my toolkit, and is conveniently available anywhere I have a shell. With unison , I don’t have to keep track of which files were modified on which end of the connection since my last update.

Keep in mind that using a tool like unison can provide a mechanism for someone to attempt to feed updates into your central file repository. When you log into a host and run the update, be conscious of whether unison asks for approval to send back changes. If you don’t remember making those changes, you might be helping an attacker feed a Trojan horse into your .login, which could end up giving the attacker access to every system you use that script on. unison will ask for confirmation for every file change. Presumably, your central host is secure, but you need to be partic ularly conscious when permitting file uploads.

See Also

  • The unison home page ( unison/)

{mospagebreak title=Hack 11: Use an Interactive Shell}

Save and share an entire login session.

How many times have you either struggled with or tried to troubleshoot another user through a thorny problem? Didn’t you wish you had another set of eyes behind you so you could simply type your command set, point at the troublesome output, and say, “That’s the problem.” Well, if you can’t bring another user to your output, you can still share that real-time output using an interactive shell.

Recording All Shell Input and Output

There are actually several ways to share what is happening on your screen. Let’s start by recording all of your input and output to a file. Then we’ll see how we can also allow another user to view that output from another terminal.

Your BSD system comes with the script command which, not surprisingly, allows you to script your session. This command is extremely simple to use. Simply type script :

  % script
Script started, output file is typescript

By default, script will create an output file named typescript in your current directory. If you prefer, you can specify a more descriptive name for your script file:

  % script configure.firewall.nov.11.2003
  Script started, output file is configure.firewall.nov.11.2003

Regardless of how you invoke the command, a new shell will be created. This means that you will see the MOTD and possibly a fortune, and your .cshrc will be reread.

You can now carry on as usual and all input and output will be written to your script file. When you are finished, simply press Ctrl-d. You will see this message:

  Script done, output file is configure.firewall.nov.11.2003

If you’ve ended a script and decide later to append some more work to a previous session, remember the -a (append) switch:

  % script -a configure.firewall.nov.11.2003

This will append your current scripting session to the named file.

I find script extremely useful, especially when I’m learning how to config ure something for the first time. I can easily create a written record of which commands I used, which commands were successful, and which commands caused which error messages. It also comes in handy when I need to send an error message to a mailing list or a program’s maintainer. I can simply copy or attach my script file into an email.

Cleaning Up script Files

The script utility is a very quick and dirty way to record a session, and it does have its limitations. One of its biggest is that it records everything, including escape characters. For example, here is the first line from one of my script files:

  [1mdru@~ [m: cd /s [K/ysr/ [K [K [K [K [Kusr/ports/security/sn o rt

It’s a bit hard to tell, but this is what script was recording:

  cd /usr/ports/security/snort

This isn’t really script ’s fault; it’s ugly for several reasons. One, my customized prompt contains control characters. Those display as [1m and [m around my username. Second, I had problems typing that day. Instead of /usr , I typed /s and had to backspace a character. Then I typed /ysr and had to backspace three characters. Finally, I used tab completion. You can see that I tried to tab at sn but received a beep; I then tried to tab at sno and had my input completed to snort .

Granted, if I had first used the file utility on my script file, I would have received a warning about this behavior:

  % file configure.firewall.nov.11.2003  
  configure.firewall.nov.11.2003: ASCII English text, with CRLF, CR, LF line
  terminators, with escape sequences

All is not lost, though. This command will get rid of most of the garbage characters:

  % more configure.firewall.nov.11.2003 |
    col -b > configure.firewall.nov.11.2003.clean

col is an interesting little utility. It silently filters out what it doesn’t understand. Here’s an example where this actually works to our advantage. col doesn’t understand control characters and escape sequences, which is exactly what we wish to get rid of. Including 
-b also asks col to remove backspaces.

The result is much more readable:

  1mdlavigne6@~m: cd /usr/ports/security/snort
  % file configure.firewall.nov.11.2003.clean 
  configure.firewall.nov.11.2003.clean: ASCII English text

I’ve found that using an editor during a script session also produces very messy output into my script file. The preceding col -b command will clean up most of the mess, but I still won’t have a very good idea of exactly what I typed while I was in that editor. For this reason, I use the echo command to send little comments to myself:

  % echo # once you open up /etc/rc.conf
% echo # change this line: linux_enable="NO"
  % echo # to this: linux_enable="YES"
  % echo # and add this line: sshd_enable="YES"

If you really want to get fancy, map one key to “start echo” and another to “end echo” as in “Use Terminal and X Bindings” [Hack #4].

Recording an Interactive Shell Session

Let’s look at an alternate way of recording a session. This time I’ll use the -i (or interactive) switch of my shell:

  % csh -i | & tee test_session.nov.12.2003

tcsh is linked to csh in FreeBSD. It doesn’t matter which one I type; I’ll still end up with the tcsh shell.

In that command, I used -i to start an interactive tcsh shell. I then piped ( | ) both stdout and stderr ( & ) to the tee command. If you’ve ever looked at physical pipe plumbing, you’ll recognize the job of a “tee” in a pipe: whatever is flowing will start going in both directions when it hits the “tee.” In my case, all stdout and stderr generated by my shell will flow to both my monitor and to the test_session.nov.12.2003 file. When I’m finished recording my session, I can type Ctrl-c, Ctrl-d, or exit to quit.

Like the previous script command, an interactive csh shell will present me with a new shell. However, this method does not record escape characters, meaning I won’t need to use the col -b command to clean up the resulting file.

But if I try to use vi during my session, the shell will refuse to open the editor and will instead present me with this interesting error message:

  ex/vi: Vi’s standard input and output must be a terminal.

If I try to use ee , it will open, but none of the commands will work. pico works nicely but still throws garbage into the session file. So, if I need to use an editor during my session, I’ll still echo some comments to myself so I can remember what I did while I was in there.

Appending works almost exactly like it does for script , again with the -a (append) switch:

  % csh -i | & tee -a test_session.nov.12.2003

Letting Other People Watch Your Live Shell Sessions

Regardless of which method you choose to record a session, another user can watch your session as it occurs. In order for this to work, that user must:

  • Be logged into the same system
  • Know the name and location of your script file

For example, I’ve created a test account on my system and configured sshd . I’ll now see if I can ssh into my system as the user test and watch the results of dru ’s test_session.nov.12.2003.

  % ssh -l test

Once I successfully log in, my customized prompt indicates I’m the test user. I can now use the tail command to watch what is happening in dru ’s session:

  % tail -f ~dru/test_session.nov.12.2003

My prompt will appear to change to indicate I am the user dru . However, I’m not. I’m simply viewing dru ’s session. In fact, I can see everything that the user dru is seeing on her terminal. This includes all of her input, output, and any error messages she is receiving.

While tail is running, I won’t be able to use my prompt. If I try typing any thing, nothing will happen. I also can’t interact with the user or change what is happening on her terminal. However, I do have a bird’s eye view of what that user is experiencing on her terminal. When I’m ready to return to my own prompt, which will also end my view of the session, I simply need to press Ctrl-c.

See Also

  1. man script
  2. man file
  3. man col
  4. man tee
  5. man tail

{mospagebreak title=Hack 12: Use Multiple Screens on One Terminal}

Who says you can’t run multiple sessions from one terminal?

Running a graphical environment is great. You can have numerous applications and utilities running, and you can interact with all of them at the same time. Many people who have grown up with a GUI environment look down upon those poor souls who continue to work in a terminal console environment. “After all,” they say, “you can only do one thing at a time and don’t get the same information and control that you have in a desktop environment.”

It’s true; they do say those things. (I am curious to know who they are, however.)

It’s also true that the utility of a graphical environment diminishes when you need to administer machines remotely. Do you really want to squander network bandwidth just to maintain a GUI session?

Here are some more questions to ask yourself regarding remote administration:

  1. Are you worried about making your services vulnerable just so you can administer them across the Internet?
  2. Do you want a secure connection?
  3. Do you want to run multiple terminal sessions from a single login?
  4. Do you want to be able to password protect your session to prevent unauthorized access?
  5. Do you want multiple windows with labels and of different sizes?
  6. Do you want to copy and paste between the windows?
  7. Are you prepared to lose a connection to your remote machine in the middle of a critical operation?
  8. Would you like to be able keep the session active even after you’ve lost it or you’ve logged off the remote server?
  9. Do you want to take over a session that you launched from another machine?
  10. Would you like to keep a hardcopy log of your sessions?

You are indeed a poor soul if you’ve reconciled yourself to the standard ssh login without any hope of resolving these questions. But all is not lost—the solution is screen .

What Is screen?

screen is a terminal screen window manager. That means you can use a console and run multiple terminals at the same time. The fancy term for this ability is multiplexing.

Getting and installing screen is straightforward using the ports facility:

  # cd /usr/ports/misc/screen
  # make install clean

I’m working with Version 4.00.01 (FAU) 18-Sep-03.

Getting Started

screen has many options, settings, and commands. Although we’ll attempt to address the major features, the definitive reference is, of course, the manpage.

There are three methods of command-line invocation:

screen [ –options ] [ cmd [ args ] ]

For invoking screen for the first time and running specific options and commands

screen -r [[pid.]tty[.host]]

For attaching to and detaching from running sessions

screen -r sessionowner/[[pid.]tty[.host]]

For attaching to and detaching from existing sessions being run by other users

Multitasking with screen

The best way to understand screen ’s power is to give you an example of how you can take advantage of it.

Suppose you are sitting at workstation alpha . You want to access your machine, bravo , to download and compile the latest PostgreSQL source code. Log into host bravo as user charlie using SSH:

  % ssh -l charlie bravo

Invoke screen . If you give it a session name, with the -s flag, you can address this session by name. This will pay off shortly.

  % screen -s A

Go ahead and download the source code now:

  % ftp

Using windows with screen. So far, this has no advantage over a normal SSH login. Yet suppose you need to send some email while you’re downloading. Instead of putting the download into the background, create another screen window with the key sequence C-a c. This symbolizes that the Ctrl key is pressed with the lowercase letter a and then, after releasing them, you press a second key, in this case c.

At this point the console will go blank. You’ll be presented with a second window. Use your favorite email client to compose your message.

Switching between windows. You’ll probably want to switch between the download and mailer windows. Cycle forward in the window list with C-a n . Cycle backward with C-a p , although you’ll likely see no difference with two windows.

Splitting windows. Being the efficient person that you are, you’d like to com pile the source code as soon as it has downloaded. Even though you haven’t completed your email, go back to the original window and extract the tarball:

  % tar -xzpvf postgresql-7.4.tar.gz

Wise administrators read the INSTALL file to make sure all the correct options are invoked. It’d be very handy to be able to read the instructions as you compose the configure command in the same console. screen comes to the rescue here, too: split the window horizontally, running configure in the top half and reading the documentation in the bottom half.

Type C-a S to split the screen, where the S is uppercase. You should see a wide horizontal bar in the middle of the screen. The top window will show whatever existed when you split the window. You’ll also see the window’s ID on the left side of the middle bar, along with the name of the shell.

The bottom window doesn’t yet have a shell running. Set the focus to the other window with C-a Tab . Create a new window with C-a c , as usual. Notice that the window has the ID of 2 (shown in the bottom lefthand corner); that’s because the email window that you created after starting the download has the ID of 1.

Better window switching. To list all windows associated with this session, use the command C-a " .

If cycling through windows is onerous, you can also switch between windows by ID. For example, C-a ‘ 1 will go to window 1.

Be prepared for a little confusion because the screen remains split and now shows the window of your choice in the currently focused window. You can quite easily show the same window in both the top and bottom halves.

Enter window 0 with C-a ‘ 0 , and extract the tarball into its own directory. Enter window 2 with C-a ‘ 2 , and navigate to the uppermost directory of the source code to read the INSTALL file.

Naming windows. ID numbers identify windows pretty well, but I prefer to use names of my own choosing. Change a window’s name with the command C-a A . For example, C-a A email , C-a A source , and C-a A doc seem like a big improvement for the currently active windows.

Now, listing the active windows with C-a " will show the following:

0    source
  1    email
  2    doc

At this point, you have one screen session with three windows. Your terminal is split such that it shows two windows at the same time.

Attaching and Deattaching

Suppose you are called away from the workstation in the middle of a sensitive operation (that is, you haven’t yet sent your email). Type C-a x to protect your session. Depending on your configuration, you will either input a password for the screen or use the default account password.

Now suppose you don’t return to your workstation. What do you do? You can ssh into bravo from a new location and attach to your existing screen session with screen -dr A . Remember, A was the name of the screen session.

After finishing and sending your email, kill off that screen. Type the command C-a k in the email window.

With that business finished, scroll back through the INSTALL text file to find interesting configuration switches. You could retype them, but screen has a perfectly capable copy mode. Type C-a ESC .

Use the cursor keys to navigate to the portions of the document you want to copy. Hit the space bar to mark the beginning of the text to copy. Scroll around to the end of the text with the cursor keys. The current selection will display in reverse video. When you’re satisfied, hit the space bar to copy the current selection into the buffer.

Switch to the source window and use C-a ] to paste the copied text.

You don’t need the doc window anymore, so switch into it and either exit the shell or use the key sequence C-a k to kill it. You could also merge the split screens together with the key sequence C-a X .

Once you’ve started compiling, you can close the terminal but leave the session active by detaching it; just type C-a d . One of the nice features about detaching the screen is that it is done automatically if you lose connection with the server, so you won’t lose your session. You can reattach to the session later from the same location or from another workstation altogether.

Additional Features

These are only the basics of what screen can do. Here’s a quick listing of other features you might enjoy:

  • Since the key bindings are not cast in stone, you change them as you see fit in the .screenrc resource file.
  • It’s possible to authorize other users access to your screen session via an access control list.
  • More than one user can access the same screen session.
  • You can create any number of windows in a given screen session.
  • It’s possible to hardcopy all activity in a screen session to a buffer and even a file.
  • An extensive system of copy and paste features exist within the screen session.

You can control all of these features with the .screenrc resource file. See man screen for details.

See Also

  • man screen
  •   The GNU Screen home page (
[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye