Wednesday, November 17, 2010

Setting a useful command prompt in Unix

I just came across a unix system at my workplace that had a static prompt set. Basically, the prompt was just the shell executable's name and version, more like 

bash-3.2 $

Well, this kind of prompt has many drawbacks, some of them i'd list here - 
1. You never know (just like that) where you are in the file system. When you are dealing with multi-directory situations, you might want to stop typing pwd to figure out ur current location.

2. You never know by what user you are logged in (again, just by looking at the prompt). You'd have to run a whoami to figure that out.

3. More importantly, if you are dealing with multiple systems, this one's the most killer.  You never know to what system you are logged in right now. you'd have to issue a hostname command.

Well, there might be, and for sure there are many other, consequences of having such a cryptic command prompt.  And therefore, my favourite, to have a command prompt, that displays at least these three things, always, dynamically...

Something like, 

raghav@deskubuntu:/homes/raghav/rails $ 

wherein, I am always aware of the three things mentioned earlier. This is very very useful when you are dealing with multiple systems and you have multiple users who are configured to run different types of processes.  For example, an oracle user who is supposed to be owner of oracle processes, and an informatica user which is supposed to own everything linked to informatica, and then a connect direct user which owns the CD processes, which receives files coming in from some other system.

With this kind of system, and your own user id to log in to the system, you'd better be careful which processes you are looking at / launching and by what user.  Its really very very important.

When and if you are dealing with a multiple system scenario, like dev / test / acceptance / production, you'd be better advised to use something like this only.

the magic command to do that is by setting appropriate flags and text in a environment variable called PS1.

Just set PS1 to your .profile or .bashrc (depending on your environment) file and you are set .

The example prompt that I mentioned can be achieved by saying - 

export PS1="\\u@\\h:\\w \\$ "

There are many more possibilities that go with special meanings for PS1 variable. Read some of them here - 

    * \$ : if the effective UID is 0, a #, otherwise a $
    * \[ : begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt
    * \\ : a backslash
    * \] : end a sequence of non-printing characters
    * \a : an ASCII bell character (07)
    * \@ : the current time in 12-hour am/pm format
    * \A : the current time in 24-hour HH:MM format
    * \d : the date in "Weekday Month Date" format (e.g., "Tue May 26")
    * \D{format} : the format is passed to strftime(3) and the result is inserted into the prompt string; an empty format results in a locale-specific time representation. The braces are required
    * \e : an ASCII escape character (033)
    * \H : the hostname
    * \h : the hostname up to the first '.'
    * \j : the number of jobs currently managed by the shell
    * \l : the basename of the shell’s terminal device name
    * \n : newline
    * \nnn : the character corresponding to the octal number nnn
    * \r : carriage return
    * \T : the current time in 12-hour HH:MM:SS format
    * \t : the current time in 24-hour HH:MM:SS format
    * \u : the username of the current user
    * \s : the name of the shell, the basename of $0 (the portion following the final slash)
    * \V : the release of bash, version + patch level (e.g., 2.00.0)
    * \v : the version of bash (e.g., 2.00)
    * \W : the basename of the current working directory
    * \w : the current working directory

Monday, November 15, 2010

scripts and hash bang ( #! )

More often than not, people have to tell the unix shell / perl scripts or other programs where lies their interpretor, e.g. write their command line calls as 

perl SomeScript.pl

or 

ruby ARubyProgram.rb

or 

sh SomeShellScript.sh

this is because the system may not be aware of the location of the the executable interpreter of the exact type that needs to be used for the corresponding script.  Well, for this purpose, windows has the file extension association concept, but we are dealing with Unix like systems not windows, so that option is not really available to us (besides, there are ill effects of that convention too, but lets not go in that discussion).

So, to tell a unix program where to find its interpreter, besides launching the script along with it on command line, there is another way, and rather beautiful at that.

Just put the exact path of your interpreter executable at the very first line of your script preceded by these two magic characters, a hash and an exclamation (#!) also called as hash-bang or shebang.  Now, once your script is marked as executable (see chmod), you are good to go, no need of putting explicit calls to the interpreter to run your code.

Basically, your code should now look like this - 

#!/usr/local/bin/perl5
print "testing hashbang with raghav"

Save this short script as aa.pl (assuming that your system has perl 5 interpreter installed in the location I used). Make the script executable (chmod) and you can just launch the script, like ./aa.pl  instead of earlier example perl aa.pl

A word of caution though, these magic characters have to be absolutely the first and second character of the file, no exceptions to that. Else, the system cant make out the special meaning of this and the purpose is lost.

Pretty neat.. hunh...