Shell vs. Java: Overcoming the Challenges of Shell Scripting for UNIX Installations

 Introduction

A shell is a command-line interpreter that takes and executes commands, and in doing so, implements a programming language commonly referred to as “shell scripting.” Shell scripting is traditionally used by UNIX system administrators to automate the execution of system tasks, but developers also use shell scripts to create enterprise-level software installations, and that is where problems occur.

This white paper highlights the major difficulties with attempting to develop UNIX installations using shell scripts. It focuses on shell scripting as a language and how it is used in the context of UNIX installation development. It also discusses how Java is being used as a successful alternative to shell scripting for enterprise installations.

Finally, this white paper details how the tools in InstallAnywhere®, the multi-platform installation tool from Flexera Software, can help developers overcome the inherent problems with shell scripting and create highquality multi-platform installations ideal for enterprise environments.

UNIX Installations: The Tar-Ball Archive

Most UNIX shell-based installations are constructed using a “tar-ball” (tar archive) paradigm. A tar file is delivered whose contents include a shell script and the files to be installed. For the most part the files are stored in a structure mimicking that of their final destination. This potentially means that a single copy (cp) command is invoked to copy the entire directory to the home directory. All necessary configurations are done with the help of commands such as “sed”, “awk”, and so on. The user interface provided is console only.

By and large, the above scenario is acceptable for simple applications. However, it becomes very hard to follow when even the most straightforward enterprise installations are attempted. If the installation you are attempting to construct is required to configure application servers, databases, or Web servers, shell-based installations are rarely a viable delivery option. This delivery mechanism becomes more difficult when you reanalyze how the tar archive is built. The configuration management team has to produce a directory structure that will mimic the final destination.

In addition, it is well known that tar-ball installations are not user-friendly to regular users. This is due to the absence of visually guided installations, as is the accepted standard for Windows applications. As a result, they often introduce barriers to user adoption of applications, and may even cause problems with the installation and maintenance of the applications.

UNIX Installations: The Way They Ought to Be

Installations, regardless of the targeted operating system, should be easier to implement. The “tar-ball” file archive structure should not be decided upon by the build system. This should be loosely packaged so that the installation can make the final decision on how the final file structure should look.

The installation technology used should be based on a more robust language with built-in parsing capabilities for XML, Java properties files, and so on. Finally, the installation should give the user the option of running the installation in a graphical mode.

Ultimately, customers and installation developers want the same thing, a robust installation system. However, their perspective is different. The customer cares about the final product, whereas the developer cares about the development environment needed to produce UNIX installations. The following lists are a subset of requirements as demanded by customers and installation developers.

For customers:

  • Ease of use – Most customers want an easy way to interact with an installation, preferably one that is visually guided, such as those offered by Windows.
  • Single point of initiation – An end user attempting to invoke your installation should not be confronted by a plethora of installation options. A single native launcher should suffice.
  • Native look and feel – It is important that users receive an installation that looks and feels like any other application targeted for that particular operating system.
  • Get the product installed – The ultimate goal of the installation is to get the product installed and configured.

For installation developers:

  • Single point of development – A true cross-platform development platform that would allow the developer to maintain a single code base for numerous platforms.
  • The development environment should use a familiar language, preferably object oriented – To allow extensibility, the installation development tool should enable the developer to extend it.
  • Operating system abstraction – When developing cross-platform installations, the developer should focus on product installation and configuration tasks and not how each operating system works.

Analyzing the Shell Scripting Environment

The concept of shell scripting was introduced to help system administrators automate low-level shell commands. For a long time most companies have used shell scripts as delivery mechanisms (that is, installations), which, for the most part, worked well. Since shell scripts are delivered in clear, readable ASCII, they can potentially expose implementations that can pose as security holes.

Unfortunately, that is not the only weakness shell scripting exposes. The following sections highlight why shell scripting does not scale when enterprises attempt to use it as an installation development platform.

The Development Environment

Shell is littered with hard-to-understand regular expressions and lacks a true integrated development environment (IDE). It often takes a truly senior UNIX developers to properly handle such complex scripting environments. Consider the following syntax:

CURRENT_USER=`whoami | awk ‘{print $1}’`
if [ “$CURRENTUSER” != “root” ] && [ “$CURRENT_USER”
!= “admin” ]; then printf “To install, you need admin
rights\n” | tee -a install.log f

If you take a closer look, you will notice how awkward the if-statement really is. If you play with the white-spacing in the if-statement, you may receive an error similar to this one:

./install.sh: line 2: [CURRENT_USER: command not found]

Although this may not seem like a big problem, imagine what would happen if someone in the field ran your installation and received the same error. Only this time the error occurs at line 4559. Debugging is not available unless you type:

% sh -x install.sh

The above does not yield results that someone with limited shell-scripting knowledge can understand.

The problem is worsened when the script contains a statement similar to myvar=`cat $1`. If $1 is not initialized, the script will be stuck. Of course, a diligent programmer doesn’t allow this to happen, but if it does happen, debugging can be a nightmare.

Other issues with the script come to light when you consider the problems associated with localization and permissions (“To install, you need admin rights\n”), and dealing with a nonstandard logging (to install.log) mechanism.

The point of this exercise was to show how difficult it can be to develop elaborate enterprise installations using shell.

Interoperability

Even though shell was never intended for large development, shell scripting is sometimes used to create large installation projects, such as enterprise installations. These installations need to directly communicate configuration settings to the product being installed. For shell-based installations, this is done using input files or the command line. Error handling, for the most part, is done using return codes.

Unfortunately, return codes are not always reliable. Sometimes a command may return 0 when in fact it should return anything but 0. Extra steps need to be taken to ensure reliability, which can turn into unnecessary complex ifstatements that make interoperability all the more difficult.

Sharing Code

When developing large-scale enterprise installations, you can expect more than one developer to work on the same code. Your plan, of course, is to develop reusable libraries that can be used across the installation system. However, shell was not designed with that in mind. Shell is for the most part used to automate administration tasks such as “empty the temp space” or “manage users.” It was designed to deal with low-level tasks, not code sharing.

Portability

Not all UNIX environments are created equal. Some commands work in every UNIX environment; some do not. Sometimes commands such as “pidof” do not exist in environments other than Linux. Furthermore, some utilities do not share the same command-line arguments across all UNIX implementations. Besides, would you like to learn all the command-line options offered by UNIX commands such as “ls”? To account for portability, a great deal of code must be written.