Monday, 30 June 2008

Customizing BASH command prompt

The prompt text can hold more information than just username and hostname, such as command numbers, time, date, shell version etc.
The text for the prompt is held in environment variable PS1 (Prompt String 1), and all that needs to be done is to change that variable.
Default prompt on most Linux systems consists of username, hostname and current working directory, something like this:
username@hostname:~$ 

The prompt is fully customizable and the PS1 variable can be changed to users needs. We can have either extra short prompt with just one symbol, or a very long one showing all sorts of information in all sorts of colors. Simple example would be prompt consisting of simple series of characters, for example a 'my prompt: ' character. So we assign a new value to PS1:
tvrtko@tvrtko-laptop:~$ PS1='my prompt: '
my prompt:
my prompt:

Prompt string can have a wide range of characters, escaped control sequence characters and color codes.
Here are bash escaped control sequence characters:

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

Now lets set a prompt displaying current time in 12-hour format, username, the command number and the '$' sign at the end:
my prompt: PS1='\T-\u-\# $ '
10:22:28-tvrtko-4 $
10:22:32-tvrtko-4 $ ls -a
...
10:22:38-tvrtko-5 $

How to add colors to a prompt?

This might look a little complicated at start but its really not a big deal. To add colors to the shell prompt use the following export command syntax:
'\e[x;ym $PS1 \e[0m'
Where:
* \e[ - Start color scheme
* x;y - Color pair to use (x - foreground;y - background)
* $PS1 - your shell prompt
* \e[0m - Stop color scheme

foreground colors:
* 30 black
* 31 red
* 32 green
* 33 brown
* 34 blue
* 35 purple
* 36 light
* 37 gray

background colors:
* 40 black
* 41 red
* 42 green
* 43 brown
* 44 blue
* 45 purple
* 46 light blue
* 47 white

Now lets set the new color prompt with light blue background displaying 24hr - time in black, username in brown and the '$' sign in black again:



Notice that the \e[0m end sequence brings back the default color. To set text after the prompt in brown foreground and black background we would end sequence with \e[33;40m.
To make prompt string effective every time bash starts put your PS1='...' line in .bashrc file.

Well, I hope this guide was clear to understand. Have fun.

Thursday, 19 June 2008

How to start a script at boot time

Making script start at the boot time is really not a big deal, it's done with ease with a few commands and actually no knowledge about system runlevels is required for simple tasks. But a little background info won't hurt.Runlevel is a state or mode in which system works, and each runlevel uses its own specific services/scripts. Usually there are 8 of them:

* 0 System Halt
* 1 Single user
* 2 Full multi-user mode (Default)
* 3-5 Same as 2
* 6 System Reboot

There is also runlevel called "s" which is used by the system when it changes runlevels.
Default runlevel for a Linux based system is 2 generally. Finding out in which runlevel system resides is done running 'runlevel' command as root
$ sudo runlevel
[sudo] password for tvrtko:
N 2

Number 2 means system is in runlevel 2 and the N character means 'None' - system was in that runlevel since boot.
For each runlevel there is a directory filled with needed scripts in /etc. On Debian/Ubuntu systems these directories are called: rc0.d, rc1.d, rc2.d, rc3.d, rc4.d, rc5.d and rc6.d, and if you open one of them you'll see all those scripts with weird names that are actually just links to real scripts that reside in /etc/init.d directory. Command update-rc.d makes those links, and I will explain its most basic usage.

Suppose I have a script named "myfirewall" filled with lots of commands needed to configure my network and protection, and I need to start it every time the system boots. This script must reside in /etc/init.d directory for this to work, and it must be executable.
$ chmod 755 /etc/init.d/myfirewall

All that it must be now is to run update-rc.d command like this:
$ sudo update-rc.d myfirewall defaults
password:
Adding system startup for /etc/init.d/myfirewall ...
/etc/rc0.d/K20myfirewall -> ../init.d/myfirewall
/etc/rc1.d/K20myfirewall -> ../init.d/myfirewall
/etc/rc6.d/K20myfirewall -> ../init.d/myfirewall
/etc/rc2.d/S20myfirewall -> ../init.d/myfirewall
/etc/rc3.d/S20myfirewall -> ../init.d/myfirewall
/etc/rc4.d/S20myfirewall -> ../init.d/myfirewall
/etc/rc5.d/S20myfirewall -> ../init.d/myfirewall

And that's it. The script will run for every runlevel now. Notice the script will run as root user. If you need to run some service as a less privileged user simply create a script in /etc/init.d with the line:
su [username_you_want_as_owner] -c /path/to/program

To remove script from startup sequence:
$ update-rc.d -f  myfirewall remove

This should be enough for a start.

Wednesday, 18 June 2008

Linux Command: alias

The alias command is used for creating shorter meaningful synonyms for longer, complex and sometimes meaningless shell commands.
Few years ago when I started being interested in all 'free' and 'open' things that Linux OS gives I also started being more an more frustrated typing some commands over and over again. Than I descovered aliases. Oh lucky me.
Most of advanced or even beginner Linux users already know this, but those that don't will find it quite handy in future.
Syntax goes like this:
alias [synonym]='[true shell command]'

Real examples might be:
alias lsa='ls -all -F'

Now if lsa is typed in a shell it will automatically run command ls -all -F. Saves so much typing.
Aliases are most efficient if they are defined at a shell startup time. To do that all that's needed is to put the line at the end of your bash profile file which is usually full of commands that run at shell startup and user mostly don't even know or think about it. Look for the file named '.bashrc', '.bash-profile' or simply '.profile' in your home directory.

Tuesday, 10 June 2008

Renaming multiple files with 'rename' command

The syntax for the rename command is:

rename [ -v ] [ -n ] [ -f ] perl_expression [ files ]

to rename for example multiple photo files with '.JPG' extension to '.jpg' extension:

rename -v ’s/\.JPG$/\.jpg/’ *.JPG

The perl substitution for regular expression syntax is: s/old/new/.
s means 'substitute'. Period character substitutes any character, but in this case it's not wanted and we need to escape it with '\'.

Tuesday, 3 June 2008

Downloading files from a cell-phone via Bluetooth

This is a guide for downloading files from a cell-phone to a linux pc from a terminal.
First thing to do is to activate a bluetooth adapter on both pc and a cellphone and make it visible and accessible. The necessery software must be installed too:
apt-get install obexftp bluetooth

First command is for scanning bluetooth enabled devices in range to get their address. Something like this:
tvrtko@tvrtko-laptop:~$ hcitool scan
Scanning ...
00:15:B9:9D:40:39 SGH-ZV10 t

Command for browsing appropriate channel for file transfers:
tvrtko@tvrtko-laptop:~$ sdptool browse 00:15:B9:9D:40:39
Browsing 00:15:B9:9D:40:39 ...
Service Name: QC Voice Gateway
Service RecHandle: 0x10000
Service Class ID List:
"Headset Audio Gateway" (0x1112)
"Generic Audio" (0x1203)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 3
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
Profile Descriptor List:
"Headset" (0x1108)
Version: 0x0100

Service Name: QC Voice Gateway
Service RecHandle: 0x10001
Service Class ID List:
"Handfree Audio Gateway" (0x111f)
"Generic Audio" (0x1203)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 4
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
Profile Descriptor List:
"Handsfree" (0x111e)
Version: 0x0101

Service Name: FTP
Service RecHandle: 0x10002
Service Class ID List:
"OBEX File Transfer" (0x1106)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 16
"OBEX" (0x0008)
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
Profile Descriptor List:
"OBEX File Transfer" (0x1106)
Version: 0x0100

Service Name: OPP
Service RecHandle: 0x10003
Service Class ID List:
"OBEX Object Push" (0x1105)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 17
"OBEX" (0x0008)
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
Profile Descriptor List:
"OBEX Object Push" (0x1105)
Version: 0x0100

Service Name: Serial Port
Service RecHandle: 0x10004
Service Class ID List:
"Serial Port" (0x1101)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 18
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
Profile Descriptor List:
"Serial Port" (0x1101)

Service Name: Dial-up Networking
Service RecHandle: 0x10005
Service Class ID List:
"Dialup Networking" (0x1103)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 8
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
Profile Descriptor List:
"Dialup Networking" (0x1103)
Version: 0x0100


Our channel of interest is 16. Bellow Service Class ID List: "OBEX File Transfer" lines.

To browse files on a cellphone use the command to gat folder listing (in my case it is in XML format):
tvrtko@tvrtko-laptop:~$ obexftp -b 00:15:B9:9D:40:39 -c / -l
Browsing 00:15:B9:9D:40:39 ...
Channel: 16
Connecting...done
Sending ""... done
Receiving "(null)"...\

(folder listing here)

Disconnecting...done

And now, to download your newly taken photo you need to type command similar to this:
tvrtko@tvrtko-laptop:~$ obexftp -b 00:15:B9:9D:40:39 -c /Pictures -g Photo-0062.jpg
Browsing 00:15:B9:9D:40:39 ...
Channel: 16
Connecting...done
....
....

For uploading files use this command:
obexftp -b 00:15:B9:9D:40:39 -c /Pictures -p Photo-0063.jpg

NOTICE: Use right addresses, folder and filename specific for your cellphone