24

Our sys admin installed a software application (Maven) on the server and told everyone to add the /usr/local/maven/bin/ folder to their path.

I think it could be more convenient to just link the few programs in that folder from the /bin folder (or other folder that everyone has in their path) like this:

ln -s /usr/local/maven/bin/* /bin

Is this correct? Are there some hidden side effects to my suggestion?

  • 2
    Per LSB you should add external packages under /opt. – vonbrand Feb 24 '14 at 19:29
31

On linking

You generally do not link /usr/local/* with /bin, but this is more of a historical practice. In general, there are a few "technical" reason why you cannot do what you're suggesting.

Making links to executables in /bin can cause problems:

  1. Probably the biggest caveat would be if you're system is having packages managed by some sort of package manager such as RPM, dpkg, APT, YUM, pacman, pkg_add, etc. In these cases, you'll generally want to let the package manager do its job and manage directories such as /sbin, /bin, /lib, and /usr. One exception would be /usr/local which is typically a safe place to do as you see fit on the box, without having to worry about a package manager interfering with your files.

  2. Often times executables built for /usr/local will have this PATH hard-coded into their executables. There may also be configuration files that are included in /usr/local as part of the installation of these applications. So linking to just the executable could cause issues with these apps finding the .cfg files later one. Here's an example of such a case:

    $ strings /usr/local/bin/wit | grep '/usr/local'
    /usr/local/share/wit
    /usr/local/share/wit/
    
  3. The same issue that applies to finding .cfg files can also occur with "helper" executables that the primary app needs to run. These too would also need to be linked into /usr/bin, knowing this might be problematic and only show up when you actually attempted to execute the linked app.

NOTE: in general it's best to avoid the temptation to link to one off apps in /usr/bin.

/etc/profile.d

Rather then have all the users provide this management, the admin could very easily add this to everyone's $PATH on the box by adding a corresponding file in the /etc/profile.d directory.

A file such as this, /etc/profile.d/maven.sh:

PATH=$PATH:/usr/local/maven/bin

You generally do this as an admin instead of polluting all the users' setups with this.

Using alternatives

Most distros now provide another tool called alternatives (Fedora/CentOS) or update-alternatives (Debian/Ubuntu) which you can also use to loop into the $PATH tools which might be outside the /bin. Using tools such as these is preferable since these are adhering more to what most admins would consider "standard practice" and so makes the systems easier to hand off from one admin to another.

This tool does a similar thing in making links in /bin; but it manages the creation and destruction of these links, so it's easier to understand a system's intended setup when done through a tool vs. done directly as you're suggesting.

Here I'm using that system to manage Oracle's Java on a box:

$ ls -l /etc/alternatives/ | grep " java"
lrwxrwxrwx. 1 root root 73 Feb  5 13:15 java -> /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.60-2.4.4.1.fc19.x86_64/jre/bin/java
lrwxrwxrwx. 1 root root 77 Feb  5 13:15 java.1.gz -> /usr/share/man/man1/java-java-1.7.0-openjdk-1.7.0.60-2.4.4.1.fc19.x86_64.1.gz
lrwxrwxrwx. 1 root root 70 Feb  5 13:19 javac -> /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.60-2.4.4.1.fc19.x86_64/bin/javac
lrwxrwxrwx. 1 root root 78 Feb  5 13:19 javac.1.gz -> /usr/share/man/man1/javac-java-1.7.0-openjdk-1.7.0.60-2.4.4.1.fc19.x86_64.1.gz
lrwxrwxrwx. 1 root root 72 Feb  5 13:19 javadoc -> /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.60-2.4.4.1.fc19.x86_64/bin/javadoc
lrwxrwxrwx. 1 root root 80 Feb  5 13:19 javadoc.1.gz -> /usr/share/man/man1/javadoc-java-1.7.0-openjdk-1.7.0.60-2.4.4.1.fc19.x86_64.1.gz

You can see the effects of this:

$ type java
java is /usr/bin/java

$ readlink -f /usr/bin/java
/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.60-2.4.4.1.fc19.x86_64/jre/bin/java

My $0.02

Making links in /bin, though plausible, would likely be highly discouraged by most sysadmins:

  1. Would be frowned upon because it's viewed as custom and can lead to confusion if another admin is required to pick up the box
  2. Can lead to a system becoming broken at a future state as a result of this "fragile" customization.
  • @slm You might want to modify your first paragraph. There are several technical reasons not to use a symlink. – jlliagre Feb 24 '14 at 7:55
  • @jlliagre - in looking at your A I'm not convinced that the admins don't own the /bin directory. Here's an example. On Red Hat distros that utilize RPM if a file already exists in /bin RPM will not install on top of as you've described, unless coxed to do so using the --replacefiles switch. So that's not really a technical reason. Same with other directories. I understand what you're saying about the OS "owning" /bin but it isn't as outright as you're stating. – slm Feb 24 '14 at 13:58
  • @jlliagre - also in my A I'm not encouraging anyone to create a link, merely stating they can if they choose to do so. I hate systems where things are done like that and typically curse the admin that's done so 8-). – slm Feb 24 '14 at 13:59
  • @slm They can (as they have sufficient privileges) but that doesn't imply this will work. Points #2 and #3 in my answer are still valid technical reasons not to create a link but to use the correct PATH, especially in the OP case. I would encourage you to mention them in your reply. – jlliagre Feb 24 '14 at 14:16
  • @jlliagre - added details per your feedback. – slm Feb 24 '14 at 15:12
7

Answering to the questions asked:

Is this correct?

No, it is a poor practice.

Are there some hidden side-effects to my suggestion?

Yes there are several side effects. Your suggestion might work or not depending on the application, and might regress or be broken in the long term.

There are sensible reasons not to create such a symbolic link:

  • Administrators do not "own" /bin (see note 1) as this directory belongs to the operating system/distribution developers. On the other hand /usr/local is a traditional location for software built by the local administrator, /opt/<packagename> being one for unbundled software. If you create a file or a link in /bin, there is a risk for it to be overwritten by a package installation, in your case an hypothetical maven package provided by the OS, which might lead to a regression if the one built locally is created from newer source code that the OS version. For example, SVR4 pkgadd , debian dpkg, red-hat rpm and slackware tarballs will all blindingly overwrite your symbolic link.

  • Some applications do look to the place where they are called to retrieve configuration files, plugins and similar resources. If you call the application by a symbolic link, its code might fail to follow it and then look for these resource files around /usr/bin where they are not.

  • There might be other binaries in /usr/local/maven/bin and not adding this directory to your PATH will make them unavailable. Removed as you already take that into account with your command by linking all potential commands.

  • The maven2 page tells to add this directory to your PATH (precisely: Add M2 environment variable to your path, e.g. export PATH=$M2:$PATH.) , by using a different approach, your are breaking that step so are going an unsupported way. Of course, if most users of a system are potential maven users, it would make more sense to set the PATH globally instead than on each and every .profile.

Note 1:

Slackware documentation:

   The /bin directory usually doesn't receive modification
   after installation. If it does, it's usually in the form
   of package upgrades that we provide.

Debian / Filesystem Hierarchy Standard

/bin/
   Essential command executable (binaries) for all users (e.g., cat, ls, cp) 
   (especially files required to boot or rescue the system)
...
/opt/
   Add-on application software packages 
   Pre-compiled, non ".deb" binary distribution (tar'ed..) goes here.
/opt/bin/
   Same as for top-level hierarchy

Solaris documentation:

/usr/bin
   Platform-dependent, user-invoked executables. These  are
   commands  users expect to be run as part of their normal
   $PATH. For executables that are different  on  a  64-bit
   system  than  on a 32-bit system, a wrapper that selects
   the  appropriate  executable   is   placed   here.   See
   isaexec(3C).  An approved installation location for bun-
   dled Solaris software. The analogous location for add-on
   system     software     or     for    applications    is
   /opt/packagename/bin.

Simple test showing Debian's dpkg doesn't preserve an existing link, even while the --force-overwrite option is not used:

# ls -l /usr/bin/banner
lrwxrwxrwx 1 root root 11 Feb 25 21:37 /usr/bin/banner -> /tmp/banner
# dpkg -i sysvbanner_1.0.15_amd64.deb 
Selecting previously unselected package sysvbanner.
(Reading database ... 236250 files and directories currently installed.)
Unpacking sysvbanner (from sysvbanner_1.0.15_amd64.deb) ...
Setting up sysvbanner (1.0.15) ...
Processing triggers for man-db ...
# ls -l /usr/bin/banner
-rwxr-xr-x 1 root root 11352 May  7  2009 /usr/bin/banner
  • Important indeed. It is quite unfortunate you accepted an answer that incorrectly states it is just an historical practice with no technical reasons to avoid ... – jlliagre Feb 23 '14 at 17:06
  • 1
    You are right, but, I accepted that answer because it gave me a practical solution that I used, which is, tell the sys admin to put the PATH modification command in /etc/profile.d . – Erel Segal-Halevi Feb 24 '14 at 7:38
  • I agree he gave a practical and correct solution but not to the two questions you asked ("Is this correct ? Are there side effects ?"). – jlliagre Feb 24 '14 at 7:55
  • 1
    jlliagre is fully right. This practice is not historical at all. It is rather a recent best practice. On the contrary on old Unixes everyone installed his piece of software directly in /bin or /usr/bin. Upon discovering the problems of hidden or distroyed system binaries (the most famous was test) the best practice to install non system binaries somewhere else was progressivly adopted. – daniel Azuelos Jun 1 '15 at 15:55
3

If you want to symlink, it would be better to symlink to /usr/local/bin. On my server, I used to install local software into /opt/NAME and symlink the binaries to /usr/local/bin.

0

An alternative to the two suggested methods is to create a shell script in /usr/local/bin that, when executed, executes whatever binary you specify in the script. For instance, using maven as an example, I would create a shell script in /usr/local/bin called maven that has a small script inside to execute the maven binary where it is located and pass any arguments to it:

#!/bin/sh
exec /usr/local/maven/bin/maven "$@"

This has the downside of having to do this for every binary you want to "link", but it allows you to call those binaries from the command line without needing to muck up your $PATH environment variable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.