From long deserted beaches & clear blue green waters, to lush green coconut trees, Konkan has it all. The Konkan region lies on the west cost of the Maharashtra state of India, along the Aribean sea.
Although not as famous amongst tourists as “Goa”, the konkan region is full of places to explore, from historic temples, to picturesque beaches, to dense jungles and not to mention the rich history of the “Maratha Empire” still echoing from the numerous mountains, hills, valleys, & gorges of the Sahyandries.
I was fortunate enough to visit the “Sindhudurga” district in Jan ‘09, during my vacation, and got some nice pictures of this fascinating land. Within a short span of 2-3 days, we were able to explore a lot of interesting places and learn a lot of fascinating history of this district. The beautiful beaches at Vengurla & Kunkeshwar, to the historic temples at Mangaon, Arawli, Akeri & Aachara, the ever so beautiful “Hiranyakeshi” river. Also the best of Sahayandries at “Amboli Ghat” , “Saat Kawale (Seven crows) point”. The awe-inspiring sea fort at Malwan. Not to mention the various small and large villages along the way and some mouth water “Malwani” cuisine.
Feel free to enjoy these memories of mine, and if possible visit the place your self.
Tags: konkan, Sindhudurga
In a typical web application, it is often necessary to work with multiple Timezones on the Client side. On the server side you may wish to store the data in one single “Timezone” preferably “GMT”, but it hardly makes sense to display and accept dates in GMT, as this places the onus on the user to translate time in his local timezone, to GMT before entering the time information, and vice-verse for interpreting any dates shown in the Web application.
What is required is for the web application to show and display date and times in the User’s timezone, and do all the necessary conversions while transmitting the date/time information between the User and the Back end. wicket framework makes this extremely simple to implement.
Wicket provides built in support to detect the Client’s Timezone and also provides necessary IO components as well as display components that transparently convert date/time data between the Server’s Timezone and the Client’s Timezone. What’s more you can also provide the Client an option to explicitly specify a Timezone and the said wicket components will use this user supplied Timezone instead of the User’s default Timezone.
Here I briefly describe how you can achieve seamless conversion of date/time wicket components between server and client Timezones.
We start with the Application class. In order for wicket to determine the Client’s Timezone, it needs to do a small redirect to an internal page that gathers information about the Client’s browser, that amongst other things includes the Client’s Timezone. Note For this to work , the browser must be Javascript enabled, but even if the user’s browser has disabled Javascript you can easily fallback to the Server’s Timezone in such a case.
For the internal page to gather browser information, we need to add some code in the Application.init() method.
import org.apache.wicket.Application;
public class MyApplication extends Application {
@Override
public void init() {
getRequestCycleSettings().setGaterExtendedBroserInfo(true);
}
}
The highlighted code is where the magic happens. Well not exactly. All the “setGatherExtendedBrowserInfo(true)” call does, is instructs Wicket to temporarily redirect an incoming request to an internal Wicket page, that will gather the extended browser info.
Of course this will not happen for any wicket Page, but has to be specifically coded in the Page class.
Even after setting the proper setting in the Application class, our work is not done. We need to tell wicket when to collect the browser’s information.
Typically to acchive a consistent look for your application, you would use markup inheritance, by having all your wicket Pages inherit from a BasePage.
So considering this, the code we need is best placed in the BasePage of your application. This way the redirect for gathering extended browser info. happens regardless of the URL used to enter the application. It can be via the Home Page or a Bookmarked page, as
long as all your wicket pages extend from your “BasePage” , you can be sure that wicket will discover
the client’s Timezone (provided javascript is enabled).
public class BasePage extends WebPage {
// we will use this to show the client what timezone are we using for this session.
private Timezone timezone ;
public BasePage() {
//trigger the redirect to an intermediate page which will obtain the timezone info for us.
getSession.getClientInfo();
add(new Label("timezone",new PropertyModel(BasePage.this,"timezone.displayName"));
// add date/time components from wicket-datetime project.
}
public Timezone getTimezone() {
if(timezone == null) {
timezone =
((WebClientInfo)getSession().getClientInfo()).getProperties().getTimezone();
}
// fallback to server's timezone if we can't determine the client's timezone.
if(timezone == null) {
timezone = Timezone.getDefault();
}
return timezone;
}
}
And the corresponding BasePage.html file
<!-- somewhere in a convenient location --> <span>America/NewYork</span>
In the constructor of ‘BasePage’ class, we trigger the redirect to the intermediate page, for obtaining the client browser’s properties, using the ‘getSession().getClinetInfo()’ call.
It is very important to have this call, otherwise wicket will not determine the client browser’s properties, one of which is the client m/c’s timezone.
Adding the timezone information in a wicket label is not strictly necessary, but it serves a purpose, without this the user will be unsure whether the date/time shown is in his local timezone or the server timezone. Of course as an alternative you can explictly display the timezone in each date/time textfiled/label.
Now for some wicket magic, after the client’s Timezone has been determined, we can now use any input/label components from the wicket-datetime project, and safely rely on them to do the automatic Timezone conversions between server and client.
e.g.
The DateTextField is an INPUT component which will translate the user inputted date/time values, from the client timezone to the server’s timezone.
The DateLabel is a display LABEL that will display a date/time value from the server, after converting it into the client’s timezone.
Thus using wicket you can greatly simplify working with client timezones, by coding only a few lines in about 2 Java files.
One thing to stress, is that wicket’s ability to correctly determine the clinet’s timezone depends on 2 things, one is the requirement that ‘javascript’ be turned on, in the client browser and secondly on the timezone offset provided by the javascript API. So it may not always work in every situation. But from my experience it works correctly most of the time.
In my next post I’ll examine how to convert the ‘timezone’ label in our example, in to a drop down select box, that will give the user an option to select the timezone he wants to see the date/time contents in.
Here are some Java system properties that can be used while starting a new JVM.
These options either provide some kind of performance benefits under certain conditions, or are used
to override default values, when using default values is not suitable or not a good option.
-Duser.timezone=XYZ
Used to set the Default Timezone of the JVM. This can be used, when you are not sure of the platform’s default Timezone, and want to be sure that the JVM always uses a certain timezone.
e.g. -Duser.timezone=GMT
-Djava.awt.headless=true
Used to run AWT in a headless (i.e. no X server) environment. Even if you are running an application server, if you need to use the AWT API to generate dynamic images, then you either need access to a Graphics Environment or you need to set this system property. This is relevant only in a *NIX environment.
-Djava.net.preferIPv4Stack=true
This property can be set to speed up certain parts of the Networking API, if you don’t intend to deploy the JVM in an IPV6 environment. Unless you are deploying your JVM in a IPV6 network it is a good idea to set this system property.
-Dsun.lang.ClassLoader.allowArraySyntax=true
This option is relevant only in Java 1.6 (Java 6) and above. If you get strange Arrays related errors while running code compiled with JDK 5 and below, you can try and set this property to solve this problem.
javax.net.ssl.keyStore=location
Used to override the default keystore location, from $HOME/.keystore
javax.net.ssl.trustStore=location
Used to override the default root CA file from $JAVA_HOME/jre/lib/security/cacerts
javax.net.ssl.keyStoreType
Used to change the default keystore type from JKS. You can use a different format to store your keys, provided you have a proper security provider installed.
javax.net.ssl.keyStorePassword
Used to provide a password for the keystore if different from the default “changeit”. And by the way it is a good idea to take that advise and change the default password.
javax.net.ssl.trustStoreType
Used to change the default truststore type from JKS. You can use a different format to store your keys, provided you have a proper security provider installed.
javax.net.ssl.trustStorePassword
Used to provide a password for the truststore if different from the default “changeit”. And by the way it is a good idea to take that advise and change the default password.
I often use these options to override the default locations of keystore and truststore files. Sometimes it is necessary that you need to import certain SSL certificates in your truststore file especially the self signed ones or when importing a CA Root Certificate that is not in the truststore.
If you use the default values, then it means you will have to change a file in the JDK installation, which is not a good idea. By overriding the default locations, you are free to place your truststore outside of the JDK, probably also bundle it as part of your installation. Same goes true for your keystore too.
-Dcom.sun.management.jmxremote
Used to enable local JMX agent for the target JVM. Once a JMX agent has been enabled for your JVM, you can use JMX applications such as JConsole etc for monitoring and managing your JVM. NoteSince Java 6 you no longer need this option if all you need is a local agent. Java 6 can automatically connect to any locally running (running on the same machine) JVM.
-Dcom.sun.management.jmxremote.port=portNum
-Dcom.sun.management.jmxremote.password.file=pwFilePath
-Dcom.sun.management.jmxremote.authenticate=false
com.sun.management.jmxremote.ssl=false
com.sun.management.jmxremote.ssl.need.client.auth=true
The default port for the JXM Remote agent is 1099. You can use the first option to override it. Jboss, starts up the Naming service on port 1099, so this option comes in handy when you want to enable remote jmx agent for a jboss server. The following options are for authentication and enabling SSL for the communications port. To be able to use SSL , you need to setup a Private Key and a Certificate and provide that information, using the security related JVM options as described above.
-Dsun.rmi.dgc.server.gcInterval=3600000
-Dsun.rmi.dgc.client.gcInterval=3600000
This increase the garbage collection interval for JVMs that start up an RMI communications. Ideal candidates for these settings are application servers.
-Duser.name=XYZ
This may not be useful to all, but it sets the default username of the JVM. One place where I find this useful is, when using maven2 + openssh for repository and site uploads. Usually I have different user a/cs on different subversion repositories, so I use this to set the username to my a/c name on the corresponding subversion repository for (svn+ssh) or site upload scp locations.
Please add any more options you can think of, in the comments section.
Tags: java
This is my first attempt to write a review of any kind, so please excuse any rookie mistakes. The entire review is written in EMACS…just kidding. The review was written in Vim 7.0
and screen shots were captured using ksnapshot and edited using krita. Normally putting up screen shots of Vim is a ridiculous idea, but many of the new features have visual components (like pop-ups etc), so screen shots seem appropriate here.
If you have to ask what is Vim, then this review is not for you, as I am not going to explain what Vim is, rather this is an attempt to give a brief description of new features of Vim 7.0. So without further a do, let's dive in to Vim 7.0.
New Features at a glance
Scripts extend the functionality of Vim in many ways. Vim Official Site is the place where to get them, but until rel 7.0 there was no way of auto upgrading scripts to their latest version. That's where the getscript plugin comes in handy. From within vim do ':GLVS' and the script will download the latest version of the plugins already installed in your '$HOME/.vim' directory. The script is not completely fool-proof and it requires some amount of preparation before it can get to work , but it is certainly step in the right direction.
Vim releases prior to 7.0 did support spell checking through external programs, but was clumsy and slow. Vim 7.0 has built in spell checking. It works out of box for English, all that is required is to issue an command
':setlocal spell spelllang=en_us'.
Al though of little use to programmers, this will come in handy for documentation (You do document your code don't you).
Attached are a few screen shots to demonstrate Vim spell checking in action.
Spell checking in text mode

Spell checking in gui mode

Sadly spell check did not work correctly while editing this document (how ironic). It would highlight mistakes only between link tags <A> and ignore the rest of the document. I had to rename the file with .txt extension to get spell check working. Also another annoyance is that if you are using a mouse to correct mistakes, you need to first left click on the misspelled word to move the cursor to that word, and then right click to activate the spelling menu, I would expect that right-clicking on a misspelled word should automatically move the cursor to it. Another option I couldn't find in the GUI pop-up for spelling suggestions was the "change/ignore all". I am sure the textmode working is much better.
Perhaps the most touted feature of all, initially called as intellisense, but renamed to omni complete due to trademark issues. This is a sort of smart complete primarily for programming/scripting languages.
The following languages are supported out of box, and the feature is extensible so adding support for other languages is trivial.
The help pages on omni complete have detailed instructions on using this new feature. The key sequence to trigger omni complete is ^X^O (Control-X followed by Control-O).
There are already plenty of plugins available at www.vim.org for other languages. VJDE plugin adds IDE like functionality to Vim for editing Java/C/C++ code as well as add omni completion support for Java. cppomnicomplete adds omni complete support for C++. For XML it is possible to convert XML DTDs in to VIM XML data file, so that while editing an XML of that particular DTD, omni complete presents a list of only vaild elements/attributes as per the DTD.
One thing I noticed is that the speed of completion varies, it was quite fast for /Java/HTML but slow for PHP and somewhere in between for C.
Attached are a few screen shots of Omni Complete in action.
| Omni Complete for C | Omni Complete for html |
|---|---|
![]() |
![]() |
| Omni Complete for Java | Omni Complete for php |
![]() |
![]() |
Another feature missing in Vim 6.x was tabs for editing multiple files. Although pre 7.0, Vim did support editing multiple files using the concept of buffers and vertical and horizontal splits, addition of tabs is welcome.This will definitely help in integrating Vim with other IDE environments such as Netbeans, Eclipse , Visual Studio etc.
One great feature about Vim tabs is the ease of moving from one tab to another. Simply in normal mode, type '[n]gt' to move to the nth tab. Also all commands that work on windows work on tabs with 'tab' appended to them. e.g. ':tabnew' .
Following is a screen shot for tabs.
This is an interesting concept, and could become very useful. Traditionally any application has a single Undo/Redo Stack, so after undoing a lot of work if you make new changes, all the redo stack is lost. Vim creates backups of undos at regular interval, so that you can recreate the file as it looked at last branch. The ':undolist' command shows all the undo branches.
How ever there are times when I want to undo a select steps but retain some changes. e.g. I make 10 changes, and undo 5, after that I want changes 9 and 10 redone, it is currently not possible and would require some sort of merge feature found in version control systems.
Vim 7.0 comes built-in with it's own grep, combined with the solid support for regular expressions, this is a handy feature for windows users who don't have access to external grep command. The internal grep command is invoked by ':vimgrep' and can recurse in to sub directories.
When ever the cursor moves over any of the following characters '<{[(' it's matching '>}])' is highlighted. However this depends on a command getting executed every time the cursor moves and may need to disabled on slow terminals.
Also 2 more options 'cursorline' and 'cursorcolumn' have been added which enable highlighting of the line and column on which the cursor is present. Following is a screen shot with matching [] and cursorline enabled.

Here is a list of other notable improvements. This list is by no means exhaustive, and a full detailed documentation can be found in Vim help. ':help version7' is your friend.
In conclusion Vim 7.0 continues to build up on top of, what was an already solid 6.x series. I have been running 7.0 (alpha and beta) releases for a long time now and finally with release of 7.0 , it will surely replace all 6.x installation on all my boxes.
The new features of Vim will help to embed it in bigger IDEs such as Netbeans, Eclipse, Sun Studio etc. Thus programmers can have best of both worlds, the power of Vim and convenience of an IDE.
Notes
For this review Vim 7.0 was compiled from source on a Linux box. The reason behind compiling from source was to enable every possible feature , as against using the binary release which has only a limited set of features enabled. Following was the options passed to the 'configure' script.
./configure –prefix=/usr –sysconfdir=/etc –localstatedir=/var –enable-perlinterp –enable-pythoninterp –enable-tclinterp –enable-rubyinterp –enable-cscope –enable-multibyte –enable-xim –enable-fontset –enable-gui=auto –with-features=hugh
Tags: omni complete, vim, vim7
Do you struggle to maintain a common configuration for dependencies (version #, type etc.),
between various modules of your multi-module maven 2.x project ?
There is a very easy way to control all your dependency related configurations from the parent ‘pom’ project.
Instead of specifying the same kind of configuration for dependencies over and over, in various modules, just
specify them once inside the <dependencyManagement> node of the parent pom.xml.
What ever configurations are done in the ‘dependencyManagement’ section of the parent pom.xml,
are automatically inherited by the child projects.
Typical configurations include a version number of the dependency artifact, a list of transitive dependencies
to exclude, when including this dependency, the default scope of the dependency, etc.
Infact when properly configured, any sub project needs to specify only the group-id and artifact-id of a required
dependency, everything else is inherited from the parent pom.xml.
Just think about it for a second, a clear simple way to have the same version of log4j jars in all your sub modules,
A clear way to have junit.jar scope set to ‘test’ in all sub projects. And when you need to change the version
of a dependency, you just need to do it in one place, and bam. every child project now referes to the newer version
of your dependency.
Here’s a code sniplet of ‘dependencyManagement’ block in one of my parent pom.xml
<project....>
......
<packaging>pom</packaging>
............
<dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commons.logging.version}</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>logkit</groupId>
<artifactId>logkit</artifactId>
</exclusion>
<exclusion>
<groupId>avalon-framework</groupId>
<artifactId>avalon-framework</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
..........
</dependencies>
</dependencyManagement>
<properties>
<commons.logging.version>1.1</commons.logging.version>
</properties>
</project>
As you can see, I have 2 things here, I have specified a default version that all subsequent children projects will inherit,
and I have also specified a bunch of transitive dependencies that I want to exclude from this dependency.
Now all a child project needs to do is
<project ....>
···<packaging>pom</packaging>
···<dependencies>
··· <dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
······</dependency>
···.....
···</dependencies>
</project>
Everything else is inherited from the parent, and when commons-logging is out with a new version, that I need to use
I need to change the version # in just one place.
WARNING Beware that any dependency specified in ‘dependencyManagement’ section is not an
actual dependency on either the parent project nor the child project, unless it is explicitly specified as one, in the regular
‘dependencies’ block.
So in short dependencyManagement is a place to configure all possible dependencies that your
sub-projects may have, but not a place to actually state a dependency. e.g. for the above configuration, a child project
will not have a dependency on commons-logging unless it includes it in its pom.xml.
Another thing to keep in mind, is that many IDEs that have the ability to work with maven projects (Eclipse, Netbeans etc),
might not give you this functionality of managing dependencies from ‘dependencyManagement’ block
, so you may have to do this part by hand.
In my case, where I use Netbean 6.0 IDE, the IDE picks up correct dependency
attributes from the parent pom, only if the files already have the stuff setup before opening the project. If I add a dependency
inside the pom.xml of an open parent project, and then refer to it in a open child project, the maven plugin gets confused, and
refuses to recognize the child project as a valid maven project. The only solution in that case is to restart the IDE :(.
Hope you have found this little piece of information helpful.
WAMP is the windows equivalent of the LAMP stack. LAMP stands for Linux (Operating System), Apache (Web Server), Mysql (Database), and PHP (Scripting Language). Under WAMP, instead of using Linux as the Operating System, you use one of the Microsoft Windows OSes such as XP, 2000 or 2k3.
Windows OSes since 2000 i.e. 2k, XP , 2k3 have been extremely stable as opposed to their predecessors. So if you are proficient in Windows, then there is no reason not to use it for web hosting. (barring security, but that’s another issue).
Secondly if you want to develop your site off line and then move it to a LAMP Stack, and you are not familiar with Linux, then WAMP serves as an ideal prototyping environment. You can do almost every thing in WAMP that you can do in LAMP.
WAMP is hosted at www.en.wampserver.com. Unlike LAMP where you have to install and configure each component seperately, wamp comes bundled in as one single installer, and installs every thing under one directory. WAMP also provides you with a System Tray Menu to start/stop configure various components. For someone new to web development this is a great feature to have.
To install WAMP, download and run the latest WAMP installer 1.6.3 from the site mentioned above. As of WAMP 1.6.3, it contains Apache 2.0.55 , PHP 5.1.4, MySQL 5.0.21 as the main components and also phpmyadmin 2.8.0.3 and sqllitemanager 1.2.0 as add-ons.
By default the installer will place every thing under C:\wamp. The installer also creates 2 services viz. ‘wampapache’ and ‘wampmysql’ for starting/stopping Apache and MySQL respectively. The installer creates a handy ‘System tray monitor’ for managing WAMP.
Once installed, if you open a web browser on your windows box, and type http://localhost/ you should see, something like this.
This confirms that you have successfully installed WAMP.
You can click the phpinfo() link to see details of your PHP environment. Also you can use the pre installed applications phpmyadmin and sqllitemanager to configure MySQL and sqllite respectively.
Next up Configuring and managing WAMP
One neat thing about WAMP is Apache, PHP and MySQL can be configured from one single ‘System Tray App’. No need to go digging in explorer to find the relevent files. You can also start/stop apache and MySQL services using the ‘System Tray App’.
The default configuration is sufficient to get started, but we are going to perform certain customizations.
First things first, the default WAMP install, creates a MySQL super-user (root) account with no password. This is OK for prototyping, but if you have an internet facing m/c, you should create a password for that a/c. This is easily done using the pre installed phpmyadmin web application.
Open the URL http://localhost/phpmyadmin/ in a web browser. This should bring up the phpmyadmin page. This is the starting point of controlling everything related to MySQL.
Click on the ‘Privileges’ link, that should bring up the user accounts page. Click on the icon besides the ‘Grant’ column, to edit root user’s properties.
On the following page, scroll down to ‘Change password’. Select the ‘Password’ check box and supply a password. Click ‘GO’ button when done. This should setup a password for the root a/c.
But we are only half done, now that the root a/c has a password, phpmyadmin application will not work unless you edit a config file and put the password in there.
To get phpmyadmin working again , open the file ‘C:\wamp\phpmyadmin\config.inc.php‘ using wordpad (any text editor). Change the line
$cfg['Servers'][$i]['password'] = ”;
to
$cfg['Servers'][$i]['password'] = ‘newly-created-password’;
This will make phpmyadmin work correctly again.
Next up Configure Apache
Configuration files for Apache, PHP and MySQL can be easily accessed using the system tray icon, as shown by the figure in left. Click on ‘http.conf’ to access apache’s configuration file.
We are not going to change much here. Scroll down till you see a bunch of ‘LoadModule xyz’ statements. Some of the Apache modules are commented out. Uncomment the following 3 modules by removing the leading ‘#’ 1) mod_status , 2) mod_info and 3) mod_rewrite.
mod_info and mod_status provide us with vital statistics regarding the apache server, (these shouldn’t be enabled on a production server). To be able to access the server info and status , we need to uncomment a few more lines.
First of change the line ExtendedStatus Off to ExtendedStatus On, next search for and uncomment lines between
<Location /server-status>...</Location>
and
<Location /server-info>...</Location>
This will enable us to get the server status and info by navigating to URLs http://localhost/server-status and http://localhost/server-info respectively.
If you install a PHP Content Management System (CMS) such as Drupal then it can use mod_rewrite module to output search engine friendly URLs.
In case you need to configure PHP (add/remove extensions), you can use the ‘System Tray Monitor’ or directly edit C:\wamp\apache\bin\php.ini file. Similary to configure MySQL edit C:\wamp\mysql\my.ini
Installing and configuring WAMP is really easy and straight forward. It is an ideal prototyping platform for any one who wishes to develop for the LAMP stack. And if you are feeling adventurous you can use WAMP as your final platform as well. I have also installed Drupal and Gallery on top of WAMP without problems.
Are you sure you are squeezing out all, that the bash shell can provide.Presented below are a few obscure things that bash can do, but chances are you may not have heard of them.
No I am not talking about completing command/file names. I am talking about completing arguments to
various commands, completing filenames based on application. This is one of the touted features of
‘zsh’, but unknown to many is the fact that it is also available in bash.
All you need to do is install bash-completion.
With bash completion installed you can use the TAB key to complete arguments to common commands like rpm, apt, find, grep etc. Also bash-completion will complete host-names
for ssh, scp, by looking up hosts inside your $HOME/.ssh/authorized_keys file. For rpm based distros, bash-completion will even lookup package names already installed.
The feature I find most handy is file-name completion based on the context of the command. e.g. if you type tar -zxvf and then press the TAB key twice, you will get a list of only files ending in .tar.gz or .tgz rather than a list of all files in the directory.
I bet a lot of you haven’t heard of this, but bash can indeed perform basic socket communication via /dev/tcp, /dev/udp. These are pseudo devices that bash uses to communicate with network sockets. In fact if you did ls -l /dev/tcp /dev/udp you will get a ‘No such file or directory’ error message.
So how to use them, we below I present 2 examples.
Here is a simple function you can put in your $HOME/.bashrc
that will check for headers of HTTP server.
headers() {
server=$1; port=${2:-80}
exec 5<> /dev/tcp/$server/$port
echo -e "HEAD / HTTP/1.0\nHost: ${server}\n\n" >&amp;amp;5
cat <5
exec 5<&amp;amp;-
}
Simply invoke it by bash# headers <servername or ip> <port>
The port number defaults to 80 if not provided.
Second example is a quick way to check if a port is open or not. You can always use netcat or telnet, but I find this easier.
testPort() {
server=$1; port=$2; proto=${3:-tcp}
exec 5<>/dev/$proto/$server/$port
(( $? == 0 )) &amp;amp;&amp;amp; exec 5<&amp;amp;-
}
Again invoke it by bash# testPort <servername or ip> <port> <protocol>
The protocol can be either tcp or udp and defaults to tcp.
Bash can perform arithmetic evaluations. They are much easier to using expr tool. Below are some examples.Note the absense of $ prefix for variable names.
((count++)) #increment value of variable 'count' by one.
((total+=current)) # set total = total+current.
((current>max?max=current:max=max)) # ternary expression.
^orig^repl^ replace ‘orig’ in previous command with ‘repl’ and execute the new command.cp filename{,.bak} Copy ‘filename’ as ‘filename.bak. mkdir -p dir{1,2,3}/subdir{1,2} Create dir1/subdir1 dir1/subdir2 dir2/subdir1 dir2/subdir2 dir3/subdir1 dir3/subdir2