Using /usr/local
30 November 2005 · 21 Comments · No tags
In ancient times, the dinosaurs ruled the earth. Amazon.com, with its then white background, default serif font, and unadorned submit buttons, sold a few programming-related books. Servers ran operating systems like SunOS 4.1.2 and AIX on expensive hardware. FreeBSD was still 386BSD, and the Linux kernel was just a gleam in some Finnish guy’s eye. You were working as a Sr. Systems and Network Administrator for an aerospace company’s corporate office.
At that time, computer hardware was expensive. Hard drives were very expensive, and their storage capacity - considered ample in those days - would be Lilliputian by today’s standards.
Enter Partitions
To get around the limitation of small and expensive hard drives, UNIX systems allowed for the connection of many hard drives (using an external SCSI interface, remember link-lights, terminators, and beloved bus-errors, kids?).
Administrators could partition hard drives into separate logical divisions for these different parts of the filesystem, and they could also use individual hard drives for this purpose. These hard drives would then become paths in the filesystem using mount points (directories that are actually references to a hard drive).
Today’s UNIX and UNIX-like systems (such as Mac OS X, Linux, FreeBSD, Solaris, etc.) still work this way. If one opens a Terminal window and runs a command like ls /, one would see a listing of the main folders on the system. On many UNIX systems, mounting drives has become automatic, and the mount points for the drives live in a folder called /mnt. In Mac OS X, they live in a folder called /Volumes. If one were to do an ls in these folders, one might see a list of the external (or remote!) drives connected to the machine.
Hard Drives as Mount Points
In the old days (and today too, if needed), setting mount points for drives was usually a manual process. One would edit a file like /etc/fstab (still around on most UNIX systems, but managed automatically) and hard-code the mount points for each drive.
On any UNIX system, typing mount at a prompt will show the currently-mounted filesystems and their mount points. Here’s what shows up for an old FreeBSD system you use (some extraneous information removed):
/dev/wd0s1a on / /dev/wd0s1e on /tmp /dev/wd0s1f on /usr /dev/wd0s1d on /var
Without getting into too much detail here, looking at that list, we can tell that there’s one hard drive in use here (the wd0 tells us that), but there are many partitions on that drive (the s1a, s1e bits stand for drive slices, a.k.a. partitions).
An administrator of this machine could, for example, see that the /var partition was filling up … maybe users aren’t pulling down their mail to their local machines but are leaving it on the server (a common problem in those days).
In response to this - and after weeks of pleading with their boss for the thousands of dollars it would cost for a 400MB SCSI-2 drive - the admin could drive in to work at 5am on Sunday morning, shut the server down, connect the new drive, boot up into single-user mode, partition and format the drive, copy the contents of the old /var folder over to it, rename the old /var folder to /var.old, set the mount point for the new drive to be /var in /etc/fstab, and then boot into multi-user mode.
Sounds fun, right?
The benefit of this would be that instead of a paltry 20MB /var partition on the primary system drive to hold everybody’s mail, the admin would now have a ginormous 400MB partition.
Certainly that much space would last a lifetime.
Introducing /usr/local (and FHS)
Today, especially for “normal” users, understanding drives and partitions this way is much less important. In fact, in most cases, knowing about the UNIX underpinnings of an operating system like Mac OS X doesn’t get you a whole lot … until you want to roll your own Ruby, Ruby on Rails and Lighttpd installation (the advantages of which are many, one of the main ones is detailed below).
Readers may be asking themselves: “Why do I need to know about partitions and drives in order to roll my own Ruby, Rails, and Lighttpd installation?”
To understand the importance of this, we need to understand one more thing about UNIX filesystems, namely the Filesystem Hierarchy Standard, or FHS.
The FHS sets up basic rules for use by UNIX and UNIX-like systems when mapping out a filesystem. Mac OS X breaks with this default in some places (as do many UNIX variants) but overall, most systems respect this organization system.
Running a Customized yet Still “Stock” System
Running with a heavily customized installation of your favorite operating system can make using your computer a more pleasant, and often more productive task, and installing third-party applications is almost always a necessity.
Mac OS X, for example, is smart enough to realize that you’ll want to install your own apps, and makes special accommodations for you to do this without doing any harm to the rest of the system. On OS X, just create a folder in your home directory named Applications, and OS X will “magically” give it the Applications icon, and treat it the same way it does with the “normal” Applications folder at the root of your hard drive.
In the same way, UNIX and UNIX-like systems make the same provision for you, using a method suggested by the FHS … the /usr/local folder.
The FHS defines the /usr/local as the “tertiary hierarchy for local data installed by the system administrator.” Translated into English, this means put apps you build yourself here.
Think of /usr/local as a “safe haven” for command-line, open source, and similar utilities and programs you download or build yourself. Just like Santiago in A Few Good Men ... it is not to be touched.
Using the /usr/local folder as the destination when compiling and installing command-line software (such as Ruby, Rails, Lighttpd, wget, Apache, etc.) is critical for many reasons but there’s one big one we’ll discuss here: System Updates and their system-wide impact.
Solving the System Update “Problem”
Mac OS X, Windows, commercial UNIX systems, and Linux distributions all make use of software updates to deliver newer (and theoretically improved) versions of their software to their users.
This process involves an automatic or manual process where the operating system checks for an update from the mothership, and then downloads and installs the update, which usually consists of newer versions of applications, bugfixes, files, etc.
These new components are often moved into place with brute force … regardless of what was there before. It’s possible (and probable) that any customizations one may have made to the system’s files, binaries, executables, or Applications can and will be overwritten at will by the software update … but only if these files were placed outside of their safe haven, /usr/local.
Imagine the scenario: a developer has just compiled and installed an updated copy of the most cutting-edge version of Ruby, which her software relies upon to function. But, not knowing, she accepted the default paths at compile time, and the binary now lives in /usr/bin.
Later, after the project launches and users are logging in, she notices that there’s a software update and lets it run. Unfortunately, she doesn’t see the note about “system binaries” being updated.
Suddenly, upon reboot, her software stops working and she can’t figure out why. Everything else seems fine, there are no errors.
It turns out that the update has actually overwritten the Ruby binary she’s compiled with a different version, and her software no longer works.
This could have been avoided if she’d installed the Ruby binary in a safer place, and set her shell and her software to use that binary.
In general, regardless of platform, software updates will respect the FHS’s designation of /usr/local as untouchable.
Using /usr/local
Using /usr/local is easy. There are only three things one needs to do:
Compile Using --prefix
When compiling command line utilities, programs, and system tools, tell the system to install things into /usr/local. Just append --prefix=/usr/local to the ./configure command in the build process.
Set The Path
By default, tell the system to look in /usr/local for files first by editing your path. On Mac OS X, either create or edit a file called .bash_login in your home folder (note the ”.”, it’s a hidden file) and add the following line to it:
export PATH="/usr/local/bin:/usr/local/sbin:$PATH"
Specify the /usr/local Prefix in Scripts
When writing scripts, specify the full path to the executable you’ve installed in the first line of the script. So to specify a Ruby binary in /usr/local/bin, one would use a line like this:
#!/usr/local/bin/ruby
That’s all there is to it.
Comments
Brian James · 29 December 2007 at 10:12 PM
I'm just getting started in learning Ruby, and I've been told that I need to learn some things about Apache and UNIX first. Understanding what to do in terminal and all as well. This post was very helpful in helping me grasp some of what I need to be doing. Thanks a bunch!
Using /usr/local « Any thing goes … · 03 January 2008 at 01:01 AM
[...] The following tip is taken directly from: hivelogic “ Using /usr/local is easy. There are only three things one needs to do: Compile Using [...]
Ryan · 05 January 2008 at 10:01 PM
/Ryan hangs his head and slowly walks away, giving up all hope of writing any cool web based apps himself
Notional Slurry » links for 2008-01-12 · 12 January 2008 at 01:01 AM
[...] Using /usr/local at Hivelogic (tags: Unix sysadmin programming MacOS tips) [...]
jack · 16 January 2008 at 08:01 AM
The usr/local directory seems to be missing in my leopard installation. Can I go ahead and create this 'local' directory, or should I go for opt/local instead?
Ben Friedman · 03 February 2008 at 03:02 PM
In my home directory under /Users, on Tiger, in iTerm, I only had the .bash_history file. No .bash_login file. Which makes me wonder how the system path is set. For the other newbies out there, use "ls -la" to see the hidden files in the directory.
When I type $PATH at the command prompt, I get ...
-bash: /bin:/sbin:/usr/bin:/usr/sbin: No such file or directory
I don't know why it's complaining about a missing directory or what that directory might be.
I then created .bash_login file using the "touch" command. I edited it using the "pico" command. While in pico, "^X" means hold the ctrl key and tap the x key. ctrl + o saves the changes.
Then I used the "less" command to view the file after I saved it. I see this...
export PATH="/usr/local/bin:/usr/local/sbin:$PATH"
To quit the "less" command, just hit your "q" key on your keyboard.
Now when I type $PATH at the command prompt, nothing has changed. I think I need to reload my bash environment variables but I don't know how. Anyway, I really find hivelogic helpful. Thanks Mr. Benjamin. Keep up the good work. Cheers.
-Ben, the newbie
Justin · 18 February 2008 at 06:02 PM
This is a great tutorial. yes! I am on Mac 0S X 4.11
But I cannot seem to get the .bash_login file to appear from a Terminal Command Line. When I type this in ..
mate ~/.bash_login
I get the command not found error. I have installed textmate and have the terminal preferences set to execute this command in the /bin/bash directory. I have created a file called .bash_login and placed in my USER home folder. I'm not sure if this is the same folder that is referred to as Home folder but in Mac Help it seems this is the case. So, I type this command ..
ls -la
to view the hidden files and .bash_login appears in the list but I can't get past this one error. Can anyone help me out on this?
steve · 24 February 2008 at 05:02 PM
Thank you for this concise explanation, Dan. By the way, I believe it is considered good form to use the following shebang in scripts:
#!/usr/bin/env ruby
rather than hard-coding the path to /usr/local/bin/ruby. That way, the same script can be installed on any system that has ruby, and the script will look to the environment to find the ruby executable that the target system prefers, whether it's in usr/local/bin/ or just /usr/bin.
Cheers,
-steve
Hivelogic: Installing Ruby, Rubygems, Rails, and Mongrel on Mac OS X 10.5 (Leopard) · 28 February 2008 at 12:02 PM
[...] source utilities (like Ruby and Rails) and why where they live is important in my article entitled Using /usr/local, but here are a few of the [...]
DM · 28 February 2008 at 02:02 PM
In many cases most C programs compile with the prefix already set to /usr/local, shortening the configure command for you. Lately I've been using a ``mkdir ~/local-installations'' approach where you set the prefix to /home/accountname/local-installations, for development or bleeding edge software at least. This way you can use specific user accounts and not worry about setting up custom permissions under the /usr/local area.
A related set of thoughts on this are by D.J. Berstein, the author of qmail; he advocates the /command and /package approaches, described under his Filesystem layout section: http://cr.yp.to/unix.html
chris · 28 February 2008 at 03:02 PM
I highly advise AGAINST using /usr/local...
INstalling all your apps into a single prefix directory eventually turn usr/local into nothing more than a junk drawer.
Want to remove an app? Good luck...
Want to update an app? Ok but how do you roll back if it's not functioning properly?
My advice use /opt or /usr/local, I prefer opt as the less typing the better.
./configure --prefix=/opt/APP-VERSION
ln -s /opt/APP-VERSION /opt/APP
example
./configure --prefix=/opt/apache-2.2.8
ln -s /opt/apache-2.2.8 /opt/apache
Now I can install newer versions and easily remove old versions.
No worries
No cruft...
Biggest pain in the ass is I need to update my PATH environment variable and update ld.so.conf. But being organized is priceless.
leonardc · 05 March 2008 at 01:03 PM
usr/local = Applications?
great stuff - but i am a bit confused: so, the Applications directory on a Mac is equivalent to usr/local on a unix system? so why would I want to create a usr/local directory on my Mac? (so that is why usr/local does not exist on my Mac by default?) couldn't I just install ruby on rails in my Applications folder with the same end result? Please help my confused little brain!
Mike · 06 March 2008 at 02:03 AM
I have this problem, when i typed ~/.bash_login i got
~/.bash_login permission denied..
I keep receiving that message, iam newbe.
leonardc · 11 March 2008 at 04:03 PM
ok, i've reread the article and posts and noticed this by DM:
"In many cases most C programs compile with the prefix already set to /usr/local, shortening the configure command for you."
So, this would be the main reason for creating a /usr/local directory? sorry for not paying more attention!
Luis Oscar Cruz · 12 April 2008 at 09:04 PM
I noticed I have installed ruby and rails on usr/bin; how do I move ruby and rails to usr/local/bin?
Herwart Schmidt-Joos · 07 May 2008 at 03:05 AM
The article is very helpful for everybody who's not born with UNIX.
Mac OS X is a UNIX related operating systems, which grows now during last 20 years. Beginning as NeXTSTEP in the 80's, current Leopard release of Mac OS X covers full-fledged UNIX function power in a high(est) sophisticated graphical user interface.
As described in this article, there's sometimes hard to decide, which version of UNIX standard application - like Apache, PHP, Ruby, Ruby on Rails ... – one should maintain on his system. Apple's automatic update policy sometimes doesn't fit ones requirements for his individual system environment, but keeps the OS on a system related up to date level.
There are other semi-automatic update concepts, from communities i.e. "MacPorts" and "FINK", which are really very helpful, providing this update job on a controlled way, activated by the user. But often they also don't provide the currently by the user required or latest software release. The important thing is, that they place their UNIX applications and all the updates in different paths. FINK uses "/sw" and MacPorts "/opt/local". So there's also no conflict to described "/usr/local" path, which is really never touched at all of this update policies.
In any case they will also adapt the PATH variable for their own. So at least if you use one of this, don't forget to set the PATH variable as required for your intentions.
I'm using this one:
export PATH="/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin:/sw/bin:/sw/sbin:$PATH"
This makes "/usr/local" to the place of first choice for UNIX software installations maintained myself.
Sundancefish · 30 May 2008 at 01:05 AM
I already have installed ruby, rails, other apps under /usr/bin, but I would like to move them to /usr/local/bin as you've describe in your tutorial, Could you show me how I can move it from /usr/bin to /usr/local/bin when it's already done?
Harry · 12 July 2008 at 03:07 PM
Hi, I hope someone can help me. I have been trying to log into mysql through my Terminal using
"Last login: Sat Jul 12 19:39:20 on console
Macintosh-5:~ harryadu-mfum$ mysql -u root --password=". I am using Leopard on an Intel Mac. Could anyone tell me the correct syntax please?
Peter cornell · 23 July 2008 at 08:07 PM
Harry,
You can do:
mysql -u root -p
Then mysql should prompt for your password.
Ciaran Wills · 04 August 2008 at 03:08 AM
/usr/local is great for installing third party utilities that aren't part of the system distribution, but I'd be very wary of installing anything there that's already part of your system.
Ask yourself why exactly you need a another version. When it needs an upgrade or security update, *you* are going to have to do that. And you have to deal with the potential headaches of having two installations of the same software on your system.
Basically you have to become sys admin for what's in your /usr/local, a burden that thankfully most OS's have taken off us nowadays. But if you need to be on the bleeding edge, that is the price.
justin · 04 August 2008 at 05:08 PM
I think I have to agree with Ciaran after having previously read this write-up and installed to /usr/local.
I had a 'weird problem' with capistrano not working in Rails - every time I typed cap it threw an error message like this: /Library/Ruby/Site/1.8/rubygems.rb:142:in `activate': can't activate net-ssh (= 1.1.2, runtime), already activated net-ssh-2.0.3 (Gem::Exception)
I played around with installing, removing, updating gems with no success, and then noticed it was calling /usr/bin/cap! However I did 'which cap' which returned /usr/local/bin/cap - very odd. So when I executed /usr/local/bin/cap it worked perfectly, while cap did not (EVEN though which says the local version is being called).
I still haven't solved this issue, but I've just read Ciaren's post and it really hit home: "And you have to deal with the potential headaches of having two installations of the same software on your system".




Sorry, comments have been closed.