Saturday, March 6, 2010

UNIX tips: Productivity tips

Introduction

The language of the UNIX® command line is notoriously versatile: With a panorama of small tools and utilities and a shell to combine and execute them, you can specify many precise and complex tasks.

But when used in an office setting, these same tools can become a
powerful ally toward increasing your productivity. Many techniques unique
to UNIX can be applied to the issue of workplace efficiency.

This article gives several suggestions and techniques for
bolstering office productivity at the command-line level: how to
review your current system habits, how to time your work, secrets for
manipulating dates, a quick and simple method of sending yourself a
reminder, and a way to automate repetitive interactions.

Review
your daily habits

The first step toward increasing your office productivity using the
UNIX command line is to take a close look at your current day-to-day
habits. The tools and applications you regularly use and the files you
access and modify can give you an idea of what routines are taking up
a lot of your time -- and what you might be avoiding.

Review the
tools you use

You'll want to see what tools and applications you're using
regularly. You can easily ascertain your daily work habits on the
system with the shell's history built-in,
which outputs an enumerated listing of the input lines you've sent to
the shell in the current and past sessions. See Listing 1 for a typical example.


Listing 1. Sample output of the
shell history built-in



$ history
1 who
2 ls
3 cd /usr/local/proj
4 ls
5 cd websphere
6 ls
7 ls -l
$

The actual history is usually kept in a file so that it can be
kept through future sessions; for example, the Korn shell keeps
its command history hidden in the .sh_history file in the user's home
directory, and the Bash shell uses .bash_history. These files are
usually overwritten when they reach a certain length, but many shells
have variables to set the maximum length of the history; the Korn and
Bash shells have the HISTSIZE and HISTFILESIZE variables,
which you can set in your shell startup file.

It can be useful to run history through
sort to get a list of the most popular
commands. Then, use awk to strip out the
command name minus options and arguments, and pass the sorted list to

uniq to give an enumerated list. Finally,
call sort again to resort the list in
reverse order (highest first) by the first column, which is the
enumeration itself. Listing 2 shows an example
of this in action.


Listing 2. Listing the
commands in the shell history by popularity


$ history|awk '{print $2}'|awk 'BEGIN {FS="|"} {print $1}'|sort|uniq -c|sort -r

4 ls
2 cd
1 who
$


If your history file is large, you can run periodic checks by
piping to tail first -- for example, to check
the last 1,000 commands, try:


$ history|tail -1000|awk '{print $2}'|awk 'BEGIN {FS="|"} {print $1}'|sort|uniq -c|sort -r

Review the files you access
or modify

Use the same principle to review the files that you've modified or
accessed. To do this, use the find utility
to locate and review all files you've accessed or changed during a
certain time period -- today, yesterday, or at any date or segment of
time in the past.

You generally can't find out who last accessed or modified a
file, because this information isn't easily available under UNIX, but you
can review your personal files by limiting the search to only files
contained in your home directory tree. You can also limit the search
to only files in the directory of a particular project that you're
monitoring or otherwise working on.

The find utility has several flags that
aid in locating files by time, as listed in Table
1
. Directories aren't regular files but are accessed every
time you list them or make them the current working directory, so exclude
them in the search using a negation and the -type flag.


Table 1. Selected flags of the

find utility

FlagDescription
-daystartThis flag starts at the beginning of the day.
-atimeThe time the file was last accessed -- in number of days.
-ctimeThe time the file's status last changed -- in number of days.
-mtimeThe time the file was last modified -- in number of days.
-aminThe time the file was last accessed -- in number of minutes. (It is not available
on all implementations.)
-cminThe time the file's status last changed -- in number of minutes. (It is not
available on all implementations.)
-mminThe time the file was last modified -- in number of minutes. (It is not available
on all implementations.)
-typeThis flag describes the type of file, such as d for
directories.
-userXFiles belonging to user X.
-groupXFiles belonging to group X.
-newerXFiles that are newer than file X.

Here's how to list all the files in your home directory tree that
were modified exactly one hour ago:



$ find ~ -mmin 60 \! -type d

Giving a negative value for a flag means to match that number or
sooner
. For example, here's how to list all the files in your home
directory tree that were modified exactly one hour ago or any time
since:


$ find ~ -mmin -60 \! -type d

Not all implementations of find support
the min flags. If yours doesn't, you can
make a workaround by using touch to create
a dummy file whose timestamp is older than what you're looking for,
and then search for files newer than it with the -newer flag:



$ date
Mon Oct 23 09:42:42 EDT 2006
$ touch -t 10230842 temp
$ ls -l temp
-rw-r--r-- 1 joe joe 0 Oct 23 08:42 temp
$ find ~ -newer temp \! -type d

The special -daystart flag, when used in
conjunction with any of the day options, measures days from the
beginning of the current day instead of from 24 hours previous to when
the command is executed. Try listing all of your files, existing
anywhere on the system, that have been accessed any time from the
beginning of the day today up until right now:


$ find / -user `whoami` -daystart -atime -1 \! -type d

Similarly, you can list all the files in your home directory tree
that were modified at any time today:



$ find ~ -daystart -mtime -1 \! -type d

Give different values for the various time flags to change the
search times. You can also combine flags. For instance, you can list
all the files in your home directory tree that were both
accessed and modified between now and seven days ago:


$ find ~ -daystart -atime -7 -mtime -7 \! -type d

You can also find files based on a specific date or a range of
time, measured in either days or minutes. The general way to do this
is to use touch to make a dummy file or
files, as described earlier.

When you want to find files that match a certain range, make two
dummy files whose timestamps delineate the range. Then, use the -newer flag with the older file, and use "\! -newer" on the second file.

For example, to find all the files in the /usr/share directory
tree that were accessed in August, 2006, try the following:



$ touch -d "Aug 1 2006" file.start
$ touch -d "Sep 1 2006" file.end
$ find /usr/share -daystart -newer file.start \! -daystart -newer file.end

Finally, it's sometimes helpful when listing the contents of a
directory to view the files sorted by their time of last modification.
Some versions of the ls tool have the -c option, which sorts by the time of file
modification, showing the most recently modified files first. In
conjunction with the -l (long-listing)
and -t (sort by modification time) options,
you can peruse a directory listing by the most recently modified files
first; the long listing shows the file modification time
instead of the default creation time:



$ ls -ltc /usr/local/proj/websphere | less

Time your work

Another useful means of increasing office productivity using UNIX is
to time commands that you regularly execute. Then, you can evaluate
the results and determine whether you're spending too much time
waiting for a particular process to finish.

Time command
execution

Is the system slowing you down? How long are you waiting at
the shell, doing nothing, while a particular command is being
executed? How long does it take you to run through your usual morning
routine?

You can get concrete answers to these questions when you use the
date, sleep, and
echo commands to time your work.

To do this, type a long input line that first contains a date statement to output the time and date in the
desired format (usually hours and minutes suffice). Then, run the
command input line -- this can be several lines strung
together with shell directives -- and finally, get the date again on
the same input line. If the commands you're testing produce a lot of
output, redirect it so that you can read both start and stop dates.
Calculate the difference between the two dates:



$ date; system-backup > /dev/null; system-diag > /dev/null;\
> netstat > /dev/null; df > /dev/null; date

Test your typing
speed

You can use these same principles to test your typing speed:


$ date;cat|wc -w;date

This command works best if you give a long typing sample that lasts at
least a minute, but ideally three minutes or more. Take the
difference in minutes between the two dates and divide by the number
of words you typed (which is output by the middle command) to get the
average number of words per minute you type.

You can automate this by setting variables for the start and stop
dates and for the command that outputs the number of words.
But to do this right, you must be careful to avoid a common
error in calculation when subtracting times. A GNU extension to the

date command, the %s format option, avoids such errors -- it
outputs the number of seconds since the UNIX epoch, which is
defined as midnight UTC on January 1, 1970. Then, you can calculate the
time based on seconds alone.

Assign a variable, SPEED, as the output of an echo command to set up the right equation to pipe
to a calculator tool, such as bc. Then,
output a new echo statement that
outputs a message with the speed:



$ START=`date +%s`;WORDS=`cat|wc -w`; STOP=`date +%s; SPEED=\
> `echo "$WORDS / ( ( $STOP - $START ) / 60 )"|bc`;echo \
> "You have a typing speed of $SPEED words per minute."

You can put this in a script and then change the permissions to
make it executable by all users, so that others on the system can use
it, too, as in Listing 3.


Listing 3. Example of running
the typespeed script


$ typespeedThe quick brown fox jumped over the lazy dog. The quick brown dog--
...
--jumped over the lazy fox.^D

You have a typing speed of 82.33333333 words per minute.
$


Know your dates

The date tool can do much more than just
print the current system date. You can use it to get the day of the
week on which a given date falls and to get dates relative to the
current date.

Get the day of a
date

Another GNU extension to the date
command, the -d option, comes in handy when
you don't have a desk calendar nearby -- and what UNIX person bothers
with one? With this powerful option, you can quickly find out what day
of the week a particular date falls on by giving the date as a quoted
argument:



$ date -d "nov 22"
Wed Nov 22 00:00:00 EST 2006
$

In this example, you see that November 22 of this year is on a
Wednesday.

So, when it's suggested that the big meeting be held on November 22,
you'll know right away that it falls on a Wednesday -- which is the
day you're out in the field office.

Get relative
dates

The -d option can also tell you what
the date will be relative to the current
date -- either a number of days or weeks from now, or before now
(ago). Do this by quoting this relative offset as an argument to the
-d option.

Suppose, for example, that you need to know the date two weeks hence. If
you're at a shell prompt, you can get the answer immediately:



$ date -d '2 weeks'

There are other important ways to use this command. With the next
directive, you can get the day of the week for a coming day:


$ date -d 'next monday'

With the ago directive, you can get dates in the past:


$ date -d '30 days ago'

And you can use negative numbers to get dates in reverse:



$ date -d 'dec 14 -2 weeks'

This technique is useful to give yourself a reminder based on a
coming date, perhaps in a script or shell startup file, like so:


DAY=`date -d '2 weeks' +"%b %d"`
if test "`echo $DAY`" = "Aug 16"; then echo 'Product launch is now two weeks away!'; fi


Give yourself
reminders

Use the tools at your disposal to leave reminders for yourself on
the system -- they take up less space than notes on paper, and you'll
see them from anywhere you happen to be logged in.

Know when it's time to
leave

When you're working on the system, it's easy to get distracted.
The leave tool, common on the IBM AIX®
operating system and Berkeley Software Distribution (BSD) systems
(see Resources) can help.

Give leave the time when you have
to leave, using a 24-hour format: HHMM. It runs in the background, and five minutes before that
given time, it outputs on your terminal a reminder for you to leave.
It does this again one minute before the given time if you're still
logged in, and then at the time itself -- and from then on, it keeps
sending reminders every minute until you log out (or kill
the leave process). See Listing 4 for an example. When you log out, the

leave process is killed.


Listing 4. Example of running
the leave command


$ leave
When do you have to leave? 1830
Alarm set for Fri Aug 4 18:30. (pid 1735)
$ date +"Time now: %l:%M%p"

Time now: 6:20PM
$
<system bell rings>
You have to leave in 5 minutes.
$ date +"Time now: %l:%M%p"
Time now: 6:25PM
$
<system bell rings>
Just one more minute!
$ date +"Time now: %l:%M%p"
Time now: 6:29PM
$
Time to leave!
$ date +"Time now: %l:%M%p"
Time now: 6:30PM
$
<system bell rings>

Time to leave!
$ date +"Time now: %l:%M%p"
Time now: 6:31PM
$ kill 1735
$ sleep 120; date +"Time now: %l:%M%p"
Time now: 6:33PM
$

You can give relative times. If you want to leave a certain
amount of time from now, precede the time argument with a +. So, to be reminded to leave in two hours,
type the following:


$ leave +0200

To give a time amount in minutes, make the hours field 0.
For example, if you know you have only 10 more minutes before you
absolutely have to go, type:



$ leave +0010

You can also specify the time to leave as an argument, which makes
leave a useful command to put in
scripts -- particularly in shell startup files. For instance, if you're
normally scheduled to work until 5 p.m., but on Fridays you have to
be out of the building at 4 p.m., you can set a weekly reminder in your
shell startup file:


if test "`date +%a`" = "Fri"; then leave 1600; fi

You can put a plain leave
statement, with no arguments, in a startup script. Every time you
start a login shell, you can enter a time to be reminded when to
leave; if you press the Enter key, giving no
value, then leave exits without
setting a reminder.

Send yourself an e-mail
reminder

You can also send yourself a reminder using a text message. Sometimes it's
useful to make a reminder that you'll see either later in
your current login session or the next time you log in.

At one time, the old elm mail agent came
bundled with a tool that enabled you to send memorandums using e-mail; it
was basically a script that prompted for the sender, the subject, and the body
text. This is easily replicated by the time-honored method of
sending mail to yourself with the command-line mailx tool. (On some UNIX systems, mail is used instead of mailx.)

Give as an argument your e-mail address (or your username on the
local system, if that's where you read mail); then, you can type the
reminder on the Subject line when prompted, if it's short enough, as
in Listing 5. If the reminder won't fit on the
Subject line, type it in the body of the message. A ^D on a line by
itself exits mailx and sends the mail.


Listing 5. Example of sending
yourself a reminder with the mailx

command


$ mailx joe
Subject: Call VP on Monday^D
Cc:
Null message body; hope that's ok
$


Automate your repetitive
interactions

The Expect language (an extension of Tcl/Tk, but other variations
are also available) is used to write scripts that run sessions with
interactive programs, as if the script were a user interacting
directly with the program.

Expect scripts can save you a great deal of time, particularly when you
find yourself engaging in repetitive tasks. Expect can interact with
multiple programs including shells and text-based Web browsers, start
remote sessions, and run over the network.

For example, if you frequently connect to a system
on your local intranet to run particular program -- the test-servers command, for instance -- you can
automate it with an Expect script named servmaint, whose contents appear in Listing 6.


Listing 6. Sample Expect
script to automate remote system program execution



#!/usr/bin/expect -f
spawn telnet webserv4
expect "login:"
send "joe\r"
expect "Password:"
send "secret\r"
expect "webserv4>$"
send "test-servers\r"
expect "webserv4>$"
send "bye\r"
expect eof

Now, instead of going through the entire process of having to run
telnet to connect to the remote system, log
in with your username and password, run the command(s) on that system,
and then log out. You just run the servmaint script as given in Listing 6; everything else is done for
you. Of course, if you give a password or other proprietary
information in such a script, there is a security consideration; at
minimum, you should change the file's permissions so that you're
the only user (besides the superuser) who can read it.

Any repetitive task involving system interaction can be programmed
in Expect -- it's capable of branching, conditionals, and all other
features of a high-level language so that the response and direction
of the interaction with the program(s) can be completely
automated.


Conclusion

In an office setting, UNIX systems can handle many of the tasks
that are normally handled by standalone computers running other operating
systems -- and with their rich supply of command-line tools, they're
capable of productivity boosters that can't be found anywhere
else.

This article introduced several techniques and concepts to increase
your office productivity using UNIX command-line tools and
applications. You should be able to apply these ideas to your own
office situations and, with a little command-line ingenuity, come up
with even more ways to save time and be more productive.

0 Comment :