TN0086: Use of "/usr/local/products" now deprecated

This article will discuss the issues related to the /usr/local/products area on many Fermilab systems; the history of how and why it was established, the unanticipated problems with the approach, and the varied directions we are taking to move away from that solution.


History

In the past, several of us in the UAS group attempted to simplify the process of building various products by establishing a "/usr/local/products" directory tree on systems using our products, and having "ups configure" actions which created symbolic links in that area. The software was then free to use compiled-in pathnames that pointed to /usr/local/products. Also, scripts could use invocation lines like:
    #!/usr/products/xxx/current/bin/executable
to make a script for that product executable, and many folks started in that direction.

Problems

The solution looked good at first, when we used it on systems where one product install went with one /usr/local filesystem, until we began moving to centralized, shared products areas, in particular under /afs.

Then the problem became that there were many more /usr/local areas than there were products areas, and in fact we did not know where all of the different /usr/local areas were.

A system where the software had not been configured did not operate properly. Also there was a tendency for /usr/local to be destroyed (and re-created without /usr/local/products) when systems were re-installed or upgraded, once again causing products in the central area to be cease working on some systems.

Because of these problems, we are moving away from using the /usr/local/products area, and actively pursuing other means of solving these problems.

New solutions:

Without /usr/local/products, (or some equivalent, compiled-in path which would suffer similar problems) most UPS products must be setup in order to work at all. Also, there is no longer any specific pathname which can be counted on to locate a given interpreter to make a script (i.e. a perl script, python script, etc.) executable. These problems are not insurmountable however, and several approaches are currently being used, depending on the situation.

Approach 1 - /usr/bin/env for products already setup

If a product is setup, then the only problem in making a script executable is having it locate the interpreter. However, since setting up the product generally puts the interpreter in the command search path, there turns out to be a low-overhead, easy solution to finding it; start your script with:
	#!/usr/bin/env interpreter
(where interpreter would be "perl" for perl scripts, "python" for python scripts, etc.) The "env" program will run the first copy of "interpreter" on your command search path, and your scripts are executable.

This solution has drawbacks in areas where getting the product setup is difficult, and it also limits the ability to turn on extra interpreter command-line options in the #! line of the script.

Where it is usable, the UAS group recommends this as the best solution for most cases, because your scripts also work in environments like CERN's ASIS, where products are essentially "always set up", or where non-ups versions of products are installed in a "usual" place on a university or other off-site system.

Approach 2 - "wrapper" scripts

A wrapper script is usually a shell script which sets up the ups environment, sets up a given product, and then invokes the appropriate commands. For example:
	#!/bin/sh
        . /usr/local/etc/setups.sh
	setup myproduct
        exec mycommand "$@"
is a script which uses the /usr/local/etc/setups.sh script to get the ups "setup" facilities imported, sets up a given product, and runs a given command with the command line arguments given to the script. This approach works well when the setup time is not critical.

This approach has drawbacks in that it is not usable on many off-site systems, even ones running UPS, where /usr/local may not be writable by the folks maintaining ups products.

Approach 3 - "trampoline" executables

For several packages like "perl" and "python", there is an existing base of tools which are invoked from system environments like mail .forward files, cron jobs, etc. where getting a product setup before a script is invoked is just not practical, and wrapper scripts like those in the preceding section may be unacceptably slow to start up.

For these sorts of products, the UAS group is providing "trampoline" executables, installing them in /usr/local/bin where possible, which get the appropriate path names stuffed into them at "ups configure" time (e.g. when a product is first declared), and can then be installed in any place you want. They have the benefit that you can put

	#!/path/to/trampoline
in a script, and a the script is then executable. This gives you back the flexibility to put in command line options in your #! lines, and reduces the setup overhead, but provides maintenance effort for the product maintainers.
This document written by Marc Mengel, massaged by Lauri Loebel Carpenter.
Last updated: 13 October 1998.
For more information, contact uas-group@fnal.gov