Packaging Scripts with Distributions

As of release 4.6, Corus allows packaging scripts that are executed on the server-side (that is, at the Corus node) to further automate application lifecycle.

These scripts are expected to have a file name that is predefined, and must be packaged under the META-INF/scripts directory of the distribution. Each script is meant to be invoked at specific points in time. Execution of these scripts is not automatic: it must be triggered by the system administrator using the CLI - or programmatically through the REST API.

Supported Scripts

Three types of scripts are supported (the only one that is mandatory is pre-deploy.corus):

  • pre-deploy.corus: this script is invoked by Corus prior to the distribution being deployed. Typically, such a script is meant to do archiving, delete old configuration (process properities, etc.), undeploy the current version of an application prior to deploying the new one, etc.
  • post-deploy.corus: this script is executed after the distribution has been successfully deployed. Processes corresponding to the "new" distribution would typically be started in this script.
  • rollback.corus: this script is executed if an error occurs at deployment time. It also can be invoked at any time after deployment, through the rollback command. This script is meant to allow cleaning up all traces of the current version - logic should be present in the script that allows switching back to the previous version - such as unarchiving the previous configuration.
The fact that the pre-deploy.corus script is mandatory does not mean one must be present in all distributions. Only when the execution of such packaged scripts by sysadmins is performed should the script be there. For a distribution in the context of which that feature is not used, no script needs being present.

Call Sequence

As was mentioned previously, execution of the scripts is not automatic. It must be triggered at deployment time, through the CLI or using the REST API. In the CLI, the deploy command takes a -r option, which stands for "run scripts". Here's an example:

deploy -r -cluster

When script execution is triggered this way, Corus will proceed to running the scripts upon receiving the distribution:

  1. It unzips the distribution as it does normally.
  2. It loads the pre-deploy.corus script and executes it (that script is mandatory).
  3. If execution of the pre-deploy.corus script fails, Corus attempts executing the rollback.corus script. If the rollback script is absent, Corus does not attempt executing it. At that point, the deployment has failed and remediation by system administrators should ensue.
  4. It loads the post-deploy.corus script (if present) and executes it. Again here, if execution of that script fails, Corus will attempt executing the rollback.corus script (if it exists).

If deployment proceeds normally (that is, no error occurs), a rollback can always be invoked later on. To that end, the rollback command is provided, and its syntax is as follows:

rollback -d <distribution_name> -v <distribution_version> -rev <rev_id>

Simply, this command will run the rollback script (rollback.corus) packaged with the given distribution. See the Putting It Together section for more details.

Script Environment

The pre-deploy.corus, post-deploy.corus, and rollback.corus scripts are expected to be packaged under the META-INF/scripts directory of the distribution being deployed.

When either of the above scripts is executed, it is assigned the directory corresponding to the root of the distribution as a base directory. If the commands in the scripts attempt accessing file resources that were packaged in the distribution, they can use relative paths, and assume that such paths will be resolved relatively to the root of the distribution.

For example, say we have the following:


Our pre-deploy script can push the file using the following command:

conf add -p conf/application.propertie


It is common to parametrize scripts with variables. These parameters are available to be used in such a context:

  1. user.dir: corresponds to the directory that is the root of the unzipped distribution (the "base directory" assigned to the script, as explained previously).
  2. the name of the distribution being deployed.
  3. corus.distribution.version: the version of the distribution being deployed.
  4. Corus' system properties.
  5. Corus' environment variables.


Simply put: command clustering is disabled when scripts are executed within Corus. That is, even if your use the -cluster option with your commands, it will have no effect.

Putting It Together

To better put things into perspective, here's an example: let's take into consideration an application packaged according to the following structure - we're omitting the parts that are non-essential to this exercise:


The next sub-sections explain the scripts appearing in the above layout.

The sources for the samples provided in this section can be found in Github


Here's the content of the pre-deploy.corus file:

echo "=> Killing current processes..."
kill all -w
echo "=> Cleaning up current configs - and archiving for eventual rollback"
archive previous
port del -n *	
conf del -p *

echo "=> Undeploying current distribution (archiving previous distribution for eventual rollback)"
undeploy all -rev previous
undeploy -e *

The first command kills all currently running processes. Then, we're archiving the current configuration kept in Corus (process properties, port ranges, tags, execution configurations) in case we need to do a rollback (which is explained further below).

Also we're undeploying all previous distributions, but leaving the latest as backup, also in case we roll back.

As a last step, we're cleaning the field for the distribution being deployed: we're undeploying all current execution configurations, and deleting the current port ranges, process properties, and tags (remember these have been archived, so they're not lost and we can unarchive them later if needed).


The post-deploy.corus file goes as follows (these steps could be in the pre-deploy file as well, but we've left the pre-deploy to cleaning up the "previous" distribution):

echo "=> Deploying config"
port add -n http -min 8100 -max 8105
conf add -p app.xms=32m
conf add -p app.xmx=128m
conf add -p app.xms=64m -c taggedServer
conf add -p app.xmx=256m -c taggedServer
conf add -p app.gc.log.type=PrintGCDetails
conf add -p app.gc.log.file=${corus.process.dir}/gc.log
deploy -e exec.xml
exec -e servers
echo "=> Proceeding to sanity check"
http check -p http -m 10 -t 6 -c /ping -cluster ${}:${corus.server.port}

When this script executes, our distribution has already been added to Corus automatically. We're only left with pushing our complimentary configuration (process properties, tags, port ranges, and execution configurations).

As a last step, we're triggering the startup of the processes corresponding to the execution configuration.


Now, the content of our rollback.corus file: the goal is to set things to what they were prior to deployment, including starting the processes corresponding to the "previous" distribution.

echo "=> Killing processes..."
kill all -w
echo "removing config"
port del -n *
conf del -p *
undeploy -e *

echo "=> Unarchiving previous state"
unarchive previous
deploy -rev previous

echo "=> Starting process(es)"
exec -e servers

After having killed the new processes, and undeployed our distribution and execution configuration (corresponding the version being rolled back), we're re-enabling the "previous" configuration (using the unarchive command), and executing the "previous" processes.

Note that the undeploy command used above, which undeploys the distribution being rolled back, is not necessary: as part of the rollback, Corus will automatically insure that the distribution is removed.


The rollback.corus script is executed at deployment time, if a problem occurs deploying the new distribution. But it can also be invoked at any time after deployment, both through the CLI and the REST API. Using the CLI, one can invoke the rollback for a given distribution in the following manner:

rollback -d <distribution_name> -v <distribution_version> -rev <rev_id>

If there's no distribution for the given name and version at the node(s) you're targeting, the command will result in an error. As a workaround, you can use rollback in conjunction with the match command - for example:

match apply trigger_rollback.corus 2.0 ls -d myapp -v 1.0 -cluster