Which Linux distribution are you using?
For chkconfig to work correctly, the script in /etc/init.d must contain some special comments at the beginning of the script (before any other non-comment lines)
For distributions using traditional SysVinit-style boot, the minimum requirements are:
# chkconfig: <runlevels> <start-value> <end-value> # description: <description-text>
- <runlevels> is the set of runlevels where the script will be enabled by default after you run "chkconfig --add". If the service shold be disabled by default, this can be just a dash "-".
- <start-value> and <stop-value> will be the start/stop order values used when creating the links
- <description-text> is just some text you can write freely: the only requirement is that the line must exist.
Newer Linux distributions (e.g. RHEL 6) may use dependency-based booting, which requires a different style of comment block. Example:
### BEGIN INIT INFO # Provides: <service-name> # Required-Start: <services that must be running before this service can start> # Required-Stop: <services that this service requires when stopping> # Short-Description: <one-line description-text> # Description: <multi-line description-text> ### END INIT INFO
With this, the startup/shutdown order numbers can be changed automatically whenever the chkconfig command is used, so that the Required-Start and Required-Stop lines will be satisfied.
Both comment blocks can be present in the same service script: in that case, the new-style block will override the old one if the Linux distribution supports the new style. Otherwise, the new-style block will be ignored.
My guess is that satisfying the Required-Stop line in your tomcat startup/shutdown script required some adjustment of priority values, and "chkconfig tomcat stop" could not do that. But when you run "chkconfig --add tomcat", chkconfig is allowed to make more extensive changes, so it could create the stop link too.
By the way, if you are creating your own start/stop scripts or modifying some third-party generic SysVinit scripts for RHEL 6, there is another thing you should be aware of.
Even if the stop link is present, the RHEL 6 /etc/rc.d/rc script (= the script that uses the start/stop links to run the service scripts in the correct order) will check for the presence of a marker file in /var/lock/subsys. So, if your service script is named "tomcat", the service script should create a file named either /var/lock/subsys/tomcat or /var/lock/subsys/tomcat.init when starting the service, and remove it when stopping the service. Otherwise, the /etc/rc.d/rc script will assume that the service has already been shut down manually and will skip stopping the service.
Here's the part of RHEL 6 /etc/rc.d/rc script that is responsible for this logic:
[...] # First, run the KILL scripts. for i in /etc/rc$runlevel.d/K* ; do # Check if the subsystem is already up. subsys=${i#/etc/rc$runlevel.d/K??} [ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] || continue
[...]