Sunday, March 27, 2011

Nginx and Apache

So I have started playing around with Nginx a bit, normally I am an Apache user. It seems to be the latest fad in web servers for the ruby on rails community. It’s a constant rotation. Last year it seemed that the web server of choice was lighttpd, I am sure for some it still is. Before mongrel, fastcgi was the way to connect your rails app to your web server, whether it be Apache or lighttpd. The first thing I noticed was the difference in the configuration files. They seem organized more like a script or etc rather than a normallinux configuration file. Overall it was pretty easy to replicate my Apache configuration files. I got gzip and expires rolling too. Anyway I will hopefully be putting some performance tests together, as soon as I do I will post them. Here’s a little test … Apache, Nginx head to head with Apachebench. I used a static file for the tests, robots.txt. From this easy test it seems that Nginx is pretty quick. Hopefully, there will be more to come.

Nginx:

Server Software: nginx/0.5.35
Server Hostname: HOST
Server Port: 80

Document Path: /robots.txt
Document Length: 204 bytes

Concurrency Level: 200
Time taken for tests: 1.503728 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 494984 bytes
HTML transferred: 204408 bytes
Requests per second: 665.01 [#/sec] (mean)
Time per request: 300.746 [ms] (mean)
Time per request: 1.504 [ms] (mean, across all concurrent requests)
Transfer rate: 321.20 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 17 91 43.3 99 174
Processing: 25 165 188.4 123 1140
Waiting: 18 135 141.9 113 1004
Total: 67 257 188.8 231 1175

Percentage of the requests served within a certain time (ms)
50% 231
66% 282
75% 290
80% 298
90% 475
95% 605
98% 1018
99% 1162
100% 1175 (longest request)

Apache:

Server Software: Apache/2.2.3
Server Hostname: HOST
Server Port: 80

Document Path: /robots.txt
Document Length: 204 bytes

Concurrency Level: 200
Time taken for tests: 8.891118 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 504510 bytes
HTML transferred: 205020 bytes
Requests per second: 112.47 [#/sec] (mean)
Time per request: 1778.224 [ms] (mean)
Time per request: 8.891 [ms] (mean, across all concurrent requests)
Transfer rate: 55.34 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 30 231.0 8 2999
Processing: 2 437 1153.2 164 8745
Waiting: 1 422 1115.7 162 8745
Total: 69 468 1175.9 169 8770

Percentage of the requests served within a certain time (ms)
50% 169
66% 182
75% 197
80% 223
90% 271
95% 4658
98% 4675
99% 6005
100% 8770 (longest request)

Apache vs Nginx : Web Server Performance Deathmatch

Deathmatch may be an overstatement but here are the results from some performance benchmarking.

The Setup:

Server:

  • CENTOS 5.1
  • Dual 2.4GHz Xeon CPUs
  • 4GB RAM
  • RAID5 (4 x 15k disks)
  • Server and test client were connected via a consumer grade 10/100 switch

Configurations:

  • Basic static vhost
  • Keepalive turned on and with timeout of 15 seconds
  • GZIP turned on

I used autobench to perform the tests. Basically this is a perl script that sits on top ofhttperf and will run multiple tests in succession outputing the results to CSV. Awfully convenient.

All the tests were run against the same robots.txt file. Autobench ran the following command 20 times incrementing the request rate by 10 each time. I started at 10 requests per second and went up to 200.

httperf –timeout=5 –client=0/1 –server=HOST –port=80 –uri=/robots.txt –rate=X –send-buffer=4096 –recv-buffer=16384 –num-conns=5000 –num-calls=10

I performed two samples and arbitrarily used the second as the results shown here. At the bottom of this post I will have spreadsheet containing the data from these tests so you can check out all the results.

The Results:

Both web servers performed well in all the tests and had no issues completing the requests. So I will not mention the metrics that they finished very closely on, only the ones that they did not have similar results.

There were three httperf related tests that Nginx and Apache differed on more than small amount, reply rate, network I/O and response time.

This one really piqued my interest. It seems strange to me why we would see such a result from Apache. In both tests there was a big difference at the 700 request mark. Statistically the difference was only on the max reply rate. The average and minimum are within a few tenths of a percent consistent through the tests. The max for Apache in the first test was 734.7 and in the second 758.7, standard deviations of 13.9 and 22.9 respectively. I suppose the real question here is whether or not this is my test or how Apache acts. If it is the later it seems strange that dealing with 700 requests would be any different than dealing with 800. From 800 requests to 2000, the larger differences in these results seems more realistic, controlled and gradual.

The network I/O graph I find interesting mostly because I don’t know how to take it. On one hand it seems Apache is simply using more bandwidth to do the same number of requests as Nginx. Which would seem bad. On the other it could just mean that Apache does a better job of consuming and using the available pipe. Which would seem good. My hunch is that it is the former.

The response times are also interesting since Nginx responds consistently at 0.4 ms. I am not sure why this is since I don’t know the internals to Nginx but I imagine that it is something that is built into how it deals with requests.

While the httperf tests were running I collected sar data from that time. The results show that Nginx uses a good amount less CPU and produces equally less load.

Apache:

CPU:

Load:

Nginx:

CPU:

Load:

Thats all I got, pretty cool. Nginx seems to compete pretty well with Apache and there doesn’t seem like there is a good reason not to use it especially in CPU usage constrained situations (ie huge traffic, slow machines and etc).

Here’s my results spreadsheet for the detailed results of each httperf metric.

Friday, March 25, 2011

Apache Server Status & Error Codes

THE APACHE SERVER STATUS & ERROR CODES

Successful Client Requests
200OK
201Created
202Accepted
203Non-Authorative Information
204No Content
205Reset Content
206Partial Content
Client Request Redirected
300Multiple Choices
301Moved Permanently
302Moved Temporarily
303See Other
304Not Modified
305Use Proxy
Client Request Errors
400Bad Request
401Authorization Required
402Payment Required (not used yet)
403Forbidden
404Not Found
405Method Not Allowed
406Not Acceptable (encoding)
407Proxy Authentication Required
408Request Timed Out
409Conflicting Request
410Gone
411Content Length Required
412Precondition Failed
413Request Entity Too Long
414Request URI Too Long
415Unsupported Media Type
Server Errors
500Internal Server Error
501Not Implemented
502Bad Gateway
503Service Unavailable
504Gateway Timeout
505HTTP Version Not Supported

Secure your SSH server with Public/Private key authentification

Open SSH is the most widely used SSH server on Linux. UsingSSH, one can connect to a remote host and gain a shell access on it in a secure manner as all traffic is encrypted.

A neat feature of open SSH is to authenticate a user using a public/private key pair to log into the remote host. By doing so, you won't be prompted for the remote user's password.

This tutorial will describe how to create a SSH public/private key pair, how to enable key based authentication and finally how to disable password authentication.

Even though SSH is secured, there is tons of brute force attacks against SSH server which will attempt to gain access to your machine.
By using key based authentication and by disabling the standard user/password authentication, you will reduce the risk of having someone gaining access to your machine.

This tutorial suppose that you already have your remote machine running a SSH server. If not, make sure your remote host has openssh server.

On Debian Stable, you need to install:

#apt-get install ssh

which will result in having both SSH server and SSH client installed.

On Ubuntu and Debian Unstable the client and server packages are separate. Therefore, you will at least need:

$sudo apt-get install openssh-server

On the server and:

$sudo apt-get install openssh-client

On the machines connecting to the server (i.e the clients)

Now let's generate the key pairs.

1. Generating A SSH Key Public/Private Key Pair

Before we can even authenticate to the remote machine using key based authentication, we need to create a public/private key pair. To do so, simply trigger:

user@host$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
The key fingerprint is:
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX user@host

Mind that if you leave the passphrase empty, anybody getting you private key (/home/user/.ssh/id_rsa) will be able to connect to your remote host.

I would recommend that you enter a passphrase, this passphrase will be use to "unlock" the key, mind that this passphrase is not related to the remote user password.

You can define another filename to save your keys to. This become handy when you have a different set of key pairs to different hosts

By now, you should have id_rsa and id_rsa.pub in ~/.ssh directory.

id_rsa is the so called private key. id_rsa.pub is the public key, the one you are going to upload on your server in order to be able to gain access to the remote machine using key authetication.

Do not share your private key, this key has to be your own, nobody but you will need to use it.
The need of a passphrase will save you a lot of trouble in case you lost it.

Now that we have our public/private key pair ready, we need to upload it to the remote machine and enable access with it.

2. Adding The Public Key To The Authorized Key

In the first place, we need to upload the key to the remote machine:

user@host:~$ scp ~/.ssh/id_rsa.pub remoteuser@remotehost:~/

Now, the public key is uploaded, let's add it to the authorized keys. To do so, we are going to connect to remotehost as remoteuser and add the key at the end of file ~/.ssh/authorized_keysand delete it once added:

$ ssh remoteuser@remotehost
remoteuser@remotehost's password:
remoteuser@remotehost:~$ cat id_rsa.pub >> ~/.ssh/authorized_keys
remoteuser@remotehost:~$ rm id_rsa.pub
remoteuser@remotehost:~$ exit

Now, we need to configure the remote SSH server to accept authentication by key pair. This is usually enabled by default. If not, the next section will cover how to activate key based authentication.

3. Activating Key Based Authentication On The Server

To do so, we need to connect as root on the remote machine. This can be achieved either by connecting to root directly:

$ ssh root@remotehost

or by connecting to the remote machine with a normal user:

$ ssh remoteuser@remotehost

and the either (usually for Ubuntu boxes):

remoteuser@remotehost:~$ sudo su -

or (Debian boxes)

remoteuser@remotehost:~$ su -

depending on your default settings.

Now open and edit /etc/ssh/sshd_config and make sure you have the following line:

RSAAuthentication yes
PubkeyAuthentication yes

Then reload your configuration:

# /etc/init.d/ssh reload

Okay, now you should be able to connect to remoteuser@remotehost without supplying a password (but the passphrase of you private key if you supplied any) by simply typing the following:

user@host:~$ ssh remoteuser@remotehost
remoteuser@remotehost:~$

Or, if your private key file is not the standard ~/.ssh/id_rsa, you can inform ssh by using the -iswitch as follow:

user@host:~$ ssh -i /path/to/private/key remoteuser@remotehost

Once you are sure that you can log into the remote host using your private key, we can safely disable the username/password authentication.

4. Disabling Authentication By Password

In order to disable authentication by password, we need to connect as root on the remote machine. On connected, go and edit/etc/ssh/sshd_config and make sure you have the following setting:

....
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
...

and reload SSH configuration file:

# /etc/init.d/ssh reload

Now, open a new shell and connect the remote host using your private key:

user@host:~$ ssh remoteuser@remotehost
remoteuser@remotehost:~$

and check that you can't connect without a key anymore:

$ cd ~/.ssh
$ mv id_rsa id_rsa.bck
$ ssh remoteuser@remotehost
Permission denied (publickey).
$ mv id_rsa.bck id_rsa

If you get rejected with Permission denied (publickey). it means it is all good and your ssh server is protected against brute-force attacks.

5. Conclusion

By authenticating yourself using a public/private key pair and by disabling authentication by password you will considerably reduce the chance an attacker gain access to your remote machine.

It is wise to provide a passphrase when creating your key pair, this way, even if somebody get a copy of your private key, you will reduce the risk of having him gaining access to your remote machine.

MySQL Cheatsheet

Selecting a database:  mysql> USE database;  
Listing databases:  mysql> SHOW DATABASES;  
Listing tables in a db:  mysql> SHOW TABLES;  
Describing the format of a table:  mysql> DESCRIBE table;  
Creating a database:  mysql> CREATE DATABASE db_name;  
Creating a table:  mysql> CREATE TABLE table_name (field1_name TYPE(SIZE), field2_name TYPE(SIZE)); 
               Ex: mysql> CREATE TABLE pet (name VARCHAR(20), sex CHAR(1), birth DATE);  
Load tab-delimited data into a table:  mysql> LOAD DATA LOCAL INFILE "infile.txt" INTO TABLE table_name; (Use \n for NULL)  
Inserting one row at a time:  mysql> INSERT INTO table_name VALUES ('MyName', 'MyOwner', '2002-08-31'); (Use NULL for NULL)  
Retrieving information (general):  mysql> SELECT from_columns FROM table WHERE conditions; All values: SELECT * FROM table; Some values: SELECT * FROM table WHERE rec_name = "value"; Multiple critera: SELECT * FROM TABLE WHERE rec1 = "value1" AND rec2 = "value2";  
Reloading a new data set into existing table:  mysql> SET AUTOCOMMIT=1; # used for quick recreation of table mysql> DELETE FROM pet; mysql> LOAD DATA LOCAL INFILE "infile.txt" INTO TABLE table;  
Fixing all records with a certain value:  mysql> UPDATE table SET column_name = "new_value" WHERE record_name = "value";  
Selecting specific columns:  mysql> SELECT column_name FROM table; 
Retrieving unique output records:  mysql> SELECT DISTINCT column_name FROM table;  
Sorting:  mysql> SELECT col1, col2 FROM table ORDER BY col2; Backwards: SELECT col1, col2 FROM table ORDER BY col2 DESC;  
Date calculations:  mysql> SELECT CURRENT_DATE, (YEAR(CURRENT_DATE)-YEAR(date_col)) AS time_diff [FROM table]; MONTH(some_date) extracts the month value and DAYOFMONTH() extracts day.  
Pattern Matching:  mysql> SELECT * FROM table WHERE rec LIKE "blah%"; (% is wildcard - arbitrary # of chars) Find 5-char values: SELECT * FROM table WHERE rec like "_____"; (_ is any single character)  
Extended Regular Expression Matching:  mysql> SELECT * FROM table WHERE rec RLIKE "^b$"; (. for char, [...] for char class, * for 0 or more instances ^ for beginning, {n} for repeat n times, and $ for end) (RLIKE or REGEXP) To force case-sensitivity, use "REGEXP BINARY"  
Counting Rows:  mysql> SELECT COUNT(*) FROM table;  
Grouping with Counting:  mysql> SELECT owner, COUNT(*) FROM table GROUP BY owner; (GROUP BY groups together all records for each 'owner')  
Selecting from multiple tables:  (Example) mysql> SELECT pet.name, comment FROM pet, event WHERE pet.name = event.name; (You can join a table to itself to compare by using 'AS')  
Currently selected database:  mysql> SELECT DATABASE();  
Maximum value:  mysql> SELECT MAX(col_name) AS label FROM table;  
Auto-incrementing rows:  mysql> CREATE TABLE table (number INT NOT NULL AUTO_INCREMENT, name CHAR(10) NOT NULL); mysql> INSERT INTO table (name) VALUES ("tom"),("dick"),("harry");  
Adding a column to an already-created table:  mysql> ALTER TABLE tbl ADD COLUMN [column_create syntax] AFTER col_name;  
Removing a column:  mysql> ALTER TABLE tbl DROP COLUMN col; (Full ALTER TABLE syntax available at mysql.com.)  
Batch mode (feeding in a script):  # mysql -u user -p <> source batch_file;  
Backing up a database with mysqldump:  # mysqldump --opt -u username -p database > database_backup.sql (Use 'mysqldump --opt --all-databases > all_backup.sql' to backup everything.) 
(More info at MySQL's docs.)

Thursday, March 24, 2011

How do Packets Travel? What’s the Force behind the Internet or WAN?

A mystery-seeking mind often wonders how does the internet work? What causes the packets to travel? What is it that pushes the packets or causes the spark, if you will?

Well the answer lies in the basics of Network Communications & the depths of Laws of Physics. Here is a scenario: you open up an internet browser & type in a URL. Here is what happens from Network/Physics perspective –>

As soon as you open the browser & type in the URL, a slue of network packets travel from your PC to the Local Area Network or LAN. Here it is piece by piece, in terms of what happens:

  • Application Layer (Layer 5, 6 & 7) sends a request to Transport Layer i.e. Layer4 of the OSI Model (http://en.wikipedia.org/wiki/Osi_model)
  • Layer4 creates a network socket by combining source ip, destination ip and a TCP or UDP Port # associated with the request. (http://en.wikipedia.org/wiki/Network_socket)
  • Layer3 on the LAN segment gets the request from Layer4 & sends the IP information down to the LAN device (switch).
  • LAN Switch grabs the info & processes the data by forwarding it to the WAN device i.e. Router (could be DSL modem, cable modem, t1 etc.)
  • Router grabs the Layer3 info & forwards the request over to Layer2 device i.e. WAN device on the provider network. It could be an ATM or a Frame Relay switch.
  • The provider then forwards the request to the requested host on the internet i.e. a server you are trying to access. That’s the server you requested to connect to when you typed in the URL in your browser.
  • The server replies back to the provider, then the provider forwards the reply back to you.
  • The Router (WAN device) in your network forwards the information back based on the network socket info & eventually you get to see the site you requested.

Now the above-mentioned explanation is a very high-level overview of basic internet (WAN) communication. However, there is a big mystery about Layer1 that typically remains un-explained. I will try to address this here to the best of my knowledge:

There you go. Here is an answer to the mystery force causing the information to flow through wires across the globe. If you want to dig even deeper & zoom into each electron to get a sub-atomic picture, go for it. Here is the link:
http://en.wikipedia.org/wiki/Sub-atomic_particle

If you grab a magnifying glass & zoom into each sub-atomic particle (like Electron) you will find out that there is something called “energy flakes or strings” that compose the Electron to define its physical characteristics. Everything in this world that physically exists on a super-microscopic level is made up of these energy strings. Here is the link for the curios:
http://en.wikipedia.org/wiki/String_theory

Most Common TCP/UDP – Transport Layer Ports!!!

How DNS Works?


DNS = Domain Name System or Service or Server

DNS resolves/maps a Name to an IP address

The diagram below describes the functionality of DNS. It also elaborates on what goes on behind the scenes once you type in a certain URL (Uniform Resource Locator) or a web address in your browser. The whole DNS process is based on the following 2 components:

  • DNS Query (Question)
  • DNS Reply (Answer)


Friday, March 18, 2011

Redhat Official Documentation

http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/index.html

Mindmap of the Ubuntu Feisty Fawn Boot Process


In order to get a better grasp on the Ubuntu’s boot process, and the boot process of Linux in general, I have created a mind map of the process. Eventually I plan to trace the scripts run by the init sequence (Upstart) and gdm (Gnome Display Manager) log in process. Please do point out any inaccuracies:


Tuesday, March 15, 2011

Useful Blog Websites

http://rrwm.wordpress.com/category/web-servers/



Tomcat Install (under linux)

Introduction

Well, here we are again :) Installations! This time I’m installing Tomcat (not sure which version yet – possibly 6.x ) on a linux box. Of course, there’s a bit of head scratching and finding out exactly what we need to do prior to install.

So, we have a vanilla system. It has apache running but has never seen hide nor hair of anything like java. So first I have to download a jdk – sounds simple ? Well, it should be – but like many people I tend to get a bit confused when it comes to navigating Sun’s java site. So many varieties of jdk, sdk, jre with or without beans and whatever new “technological methods” Sun have come up with. Occasionally conflicting documentation (search for jdk linux – you get instructions telling you to install obsolete software … or is it obsolete ? I’ve no idea)

Installing Java

As I’m not sure I have access to compilers and the like (a legacy policy of never putting any sort of development malarkey on a front-facing server) I’m going to have to pick a binary install; which should work fine without any issues… I hope!

(fortunately, if there are any issues – this is a soon-to-be-decommissioned box that is just sitting around spinning it’s wheels, so to speak; so it’s not going to take down any “mission critical” applications … at least… it shouldn’t do :) )

In this instance, I’ve decided upon the Linux binary distribution of the Java SE Development Kit 6 (update 6) (I’d give a link to the page on java.sun.com but that looks to be generated via session variables on a by-user basis)

jdk-6u6-linux-i586.bin

(from the page http://java.sun.com/j2se/1.5.0/install_jdk150-nb40_linux.html we are told to set the permissions on the file so we can execute it; they say chmod 755 jdk*.bin although my preferred method ischmod u+x jdk*.bin (but that’s just me … oh, and I’m just being lazy – you can type the whole jdk filename in if you want (or if you have lots of jdk’s in the folder and don’t want them all to be executable :) )))

let’s run the executable

./jdk-6u6-linux-i586.bin

Good grief ! That’s a long user agreement… I really should read it one of these days, I heard rumours of them smuggling clauses allowing them to take your first born son … but… life’s too short :) and generally they could be summarized into a simple statement

“you agree to not do anything naughty – like stealing things , we’ll find out and catch you you know.”

to which, we have to say “yes” (surely we should be able to say “no, we don’t agree” and still use the software? Are these things really binding? I don’t know… anyway… I’m digressing )
of course, once it gets to the end “Java(TM) SE Development Kit 6 successfully installed”

So what have I got ?

in the directory I ran the jdk in, there is now a folder “jdk1.6.0_06″ ; to make upgrades (hopefully) easier, I’ll make a symbolic link to this directory

ln -s jdk1.6.0_06 java

I’ll now set up some environment variables (so we know where to find things)

emacs /etc/profile

(or feel free to use vi or whichever text editor you prefer)
Assuming you’ve not done anything to tweak the default profile, there will be a line in the file that says something like

export PATH DISPLAY LESS TERM PS1 PS2

before this line I’ll add the following

JAVA_HOME=/[path to java install eg. /usr/local/java]
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=$JAVA_HOME/lib

and then on the end of this line I’ll add JAVA_HOME and CLASSPATH
i.e.

export PATH DISPLAY LESS TERM PS1 PS2 JAVA_HOME CLASSPATH

that done, I can type . /etc/profile which’ll re-set the environment variables (which can be proven by typing java -version ); which in turn means we can now run java. Now to install tomcat. Let’s try tomcat 6…

Installing Tomcat 6

First to download our copy of tomcat. http://tomcat.apache.org/download-60.cgi (Question: Why aren’t there any “linux” versions listed ? Answer: Because it’s java! The same package as is installed on windows will work on Macs, unix boxes and all sorts of places – probably even your hand-held device (assuming it has space for it!)

We’ll download the tar.gz version (tar being a unix standard “tape archive” (remember unix principles 101?) and gz being the gzip compression format (as tar archives are uncompressed by default – remember? Were you listening ? :) )) at the moment, the latest archive is http://www.smudge-it.co.uk/pub/apache/tomcat/tomcat-6/v6.0.16/bin/apache-tomcat-6.0.16.tar.gz (note that this is linking to one of the many mirror sites used for distribution of the apache/jakarta projects)

change directory to your installation folder – e.g. cd /usr/local
decompress the archive – gunzip apache-tomcat-6.0.16.tar.gz
untar the archive – tar -xmvf apache-tomcat-6.0.16.tar

(alternatively, you can miss out the decompressing stage and instead use tar -xmzvf (the z is for decompress gzip format)

we’ll make another symbolic link now, to make it (hopefully) easier to upgrade

ln -s apache-tomcat-6.0.16 tomcat

in the tomcat directory there will be a folder called “RUNNING.txt” – the following notes are derived from that…

First I’ll edit the /etc/profile file again and add in a new environment variable for “CATALINA_HOME” (this will point to the installation folder) and ensure that the variable gets exported – similar to the JAVA_HOME

in theory, we should now be able to start up tomcat and see it running on port 8080 – cd $CATALINA_HOME/bin and type ./startup.sh

When I tried this just, it complained about being unable to find a file … “setclasspath.sh” – which is strange as it is right there… Let’s try and troubleshoot a little bit…

(A quick search online provides an answer to this – on the tomcat wiki )

We have to edit the catalina.sh and setclasspath.sh files and add the following lines (to the beginning)

BASEDIR=/[path to your tomcat install]
CATALINA_HOME=[/path to your tomcat install]

we can then try again – cd /path to tomcat/bin
./startup.sh

if everything works okay, we should then be able to type

ps guax | grep java

which’ll show the process (note, versions of ps differ from system to system; so if you get an error, you can always try ps -guax or some other combination – remember the system manual is your friend :) man ps )

we can now try and display the site – in a web browser, point it to the server on port 8080 – if everything has worked (as it has in my case) you’ll get the default tomcat server page/documentation/examples.

And as everything has worked so far – I think it’s a good time to take lunch :)
More later!

Well, that was lunch… back to the install.

After all that work, we should have a working version of tomcat. However, we don’t have any users set up – so how do we manage our applications (etc) ? Well, first things first, let’s create a role in the

[tomcat root]/conf/tomcat-users.xml file.

it should look something like this





once you have made the changes, you’ll need to restart tomcat
/[tomcat root]/bin/shutdown.sh

(wait a few moments – you can type ps guax|grep java to see if the process has stopped before running)

/[tomcat root]/bin/startup.sh

to start the service up again.

You can check in the /[tomcat root]/logs/catalina.out file to see if there are any errors generated .