Use and Abuse of /usr/local/bin
It starts when some poor soul has written a script to do some
thing or another, and happens to mention that it was called
Of course the hapless poster usually had no
real reason to mention its path, that was just an accident, or it
appeared in some other script that was being posted for
examination. No matter, the damage is done, for immediately some
defender of the faith is going to chide the poster and
sanctimoniously inform them that the proper place for home grown
scripts is /usr/local/bin. In some cases, that's all the poor
person gets: whatever the question originally was is forgotten and
only the placement issue is discussed.
Sometimes the original poster will object, especially when it
seems that their honor has been impugned and the respondent seems
to be looking down a very long nose at any person who would dare to
place scripts other than the One Holy Place. That's a mistake,
because defenders of the faith run in packs, and once the faith has
been questioned, they pile on in depth to convert the sinner. Those
who endure such attacks often end up converted themselves, and will
joyfully join in the next time someone wanders in spreading false
gospel. I call such people Localists.
But the truth is: it's all B.S. and the Localists preach a false
Yep, you heard me. It's crapola. Yes, you'll hear this nonsense
spouted by some of the most illustrious names in Unixdom, you'll
see it in the best books, and the arguments that are trotted out
will cause much sage head nodding and stroking of chins.
Nonetheless, it is all crap.
The reason it's crap is not because the arguments against
putting your scripts in /usr/bin are specious. They aren't, or at
least aren't entirely so. The basic argument is this: the stuff in
/usr/bin was supplied by the OS vendor. If you put stuff in there,
then when it comes time to upgrade, it's harder to do. But if your
stuff was in /usr/local/bin, we could just save that directory and
life would be wonderful. That argument by itself doesn't really
hold water, because it is trivial to restore your scripts by
restoring non-destructively- that is, don't replace anything from
the backup that's already there, but do bring back anything that
isn't. However, the Localists then warn (correctly) that commands
may move from release to release: what was in /usr/bin/ may now be
in /bin. So? That only requires a more intelligent restoration; I
have scripts that check for such conditions in my Upgrades article, and the concept can
be adopted to fit any circumstance.
The Localists aren't done yet, though. Their final card is that
some new OS command might happen to use the same name as your local
command, so the intelligent restoration fails, and when some other
script happens to call that name, it will now fail. Sounds
convincing now? Nope. Because in most cases, having it in
/usr/local/bin wouldn't have helped: that would usually be later in
the PATH, so the command would probably fail anyway. And who says
that some package you bring down from the net won't accidentally
use the same name as your command? So none of the Localist
arguments really work.
Just the same, it's probably NOT the best idea to put your
commands in /usr/bin. Organizationally, it makes better sense to
have them elsewhere, and it does help (a minor boost, but what the
heck) during upgrades. And if we get unlucky and the new OS usurps
our command's name for its own use, we're ahead of the game if it
already lives somewhere else. But that somewhere else should NOT be
The Localists Fallacy
The problem is simply that in this day and age, /usr/local/bin
suffers from the same problem that /usr/bin has. Anything you get
from the net invariably installs to /usr/local/bin. At the time I
wrote this article, my /usr/local/bin had 560 files in it- and most
of them aren't really "local"- somebody else wrote them, I just
installed them. When I upgrade, I usually have to upgrade those
things also. So every argument against putting your home grown
scripts in /usr/bin applies just as much to /usr/local/bin- same
problems, same arguments.
Therefor, I suggest that you put your home grown scripts in your
own directory structure: /usr/mystuff/bin or whatever, and further
that you NEVER assume that it is in $PATH in calling scripts, but
rather call it explicitly: /usr/mystuff/bin/whatever. This prevents
the theft of "whatever" by another set of programs, and if some
person upgrades the server years from now when you are long gone,
and does not notice /usr/mystuff/bin, the calling scripts failure
will immediately point them to the remedy.
It's fine to have your special place in $PATH; just be sure to be explicit
in any other scripts you write.
This protocol could also be a source of great fun. If you get
creative with your names (/usr/boopy/bin?), and happen to
accidentally include the full path in a newsgroup post, it's bound
to attract the attention of the Localists, but what can they say?
Perhaps, if you are lucky, they'll sniff that /usr/local/bin is the
"proper" place for your command, and then you can have some fun
tying them up with their own ropes. Personally, I think that could
be a lot of fun!
Bill Vermillion had some comments:
You mention you had 560 files in /usr/local/bin.
The BSD world makes great use of /usr/local. The more I work with
this the more I like it.
root@bilver # pwd
root@bilver # find . -print | wc
26724 26724 1016763 <<*** beats your 560!!!
/usr/local has all this besides just bin
drwxr-xr-x 23 root wheel 512 Nov 20 06:56 .
drwxr-xr-x 23 root wheel 512 Mar 26 09:12 ..
drwxr-xr-x 6 root wheel 512 Jul 4 2000 Acrobat4
dr-xr-xr-x 8 root wheel 512 Aug 8 2000 apsfilter
drwxr-xr-x 2 root wheel 15872 Apr 3 21:14 bin
drwxr-xr-x 4 root wheel 512 Jan 30 18:22 bind
drwxr-xr-x 2 root wheel 512 Jul 2 2000 cgi-bin
drwxr-xr-x 3 root wheel 512 Aug 20 2000 doc
drwxr-xr-x 4 root wheel 512 Jun 25 2000 domtools
drwxr-xr-x 11 root wheel 1024 Apr 2 11:37 etc
drwxr-xr-x 22 root wheel 5120 Apr 3 21:14 include
drwxr-xr-x 2 root wheel 1536 Feb 24 22:37 info
drwxr-xr-x 24 root wheel 5632 Apr 3 21:14 lib
drwxr-xr-x 4 root wheel 512 Apr 2 11:37 libexec
drwxr-xr-x 8 majordom majordom 512 Jan 10 10:39 majordomo
drwxr-xr-x 26 root wheel 512 Aug 6 2000 man
drwxrwxr-x 7 news bin 1024 Apr 5 11:04 news
drwxr-xr-x 2 root wheel 512 Aug 7 2000 newsspool
dr-x------ 2 root wheel 512 Aug 8 2000 private
drwxr-xr-x 8 root wheel 512 Aug 7 2000 samba
drwxr-xr-x 2 root wheel 1024 Mar 23 08:25 sbin
drwxr-xr-x 46 root wheel 1024 Feb 24 22:37 share
drwxr-xr-x 5 root wheel 512 Jun 25 2000 www
Not the lib, libexec, man, etc. In this arena
local means that they just aren't part of the base OS. And the old
routines about OS upgrades needing to change some of these isn't
I just upgraded the OS on a server remoted. I
cvsuped the sources, made them all, and performed 'buildworld'
which remakes every system program, because a lot of the times
there are new libraries. Then there is a 'mergemaster' which merges
all the startup files so you can edit as you go, replace or hold
them off. A reboot and you are running. The system was lightly
used, but live.
What I also like is the way the rc.d stuff runs.
There is small file used to override the system defaults, but under
/usr/local/etc there is an rc.d directory, which executes anything
that is executeable AND has an extension .sh. This ensure that all
local things are run only after the system is up. I like this
better than the Sys V Sxx numbering system.
Heres the /usr/local/etc
drwxr-xr-x 11 root wheel 1024 Apr 2 11:37 .
drwxr-xr-x 23 root wheel 512 Nov 20 06:56 ..
-rw-r--r-- 1 root wheel 5496 Mar 12 2000 Muttrc
-r--r--r-- 1 root wheel 2518 Jul 4 2000 a2ps-site.cfg
-r--r--r-- 1 root wheel 12878 Jul 4 2000 a2ps.cfg
drwxr-xr-x 2 root wheel 512 Oct 21 17:19 apache
drwxr-xr-x 2 root wheel 512 Jun 25 2000 cal
drwxr-xr-x 2 root wheel 512 Jun 25 2000 codepages
-r--r--r-- 1 root wheel 4993 Mar 12 2000 enscript.cfg
-r--r--r-- 1 root wheel 77 Mar 12 2000 esd.conf
-rw-r--r-- 1 bin bin 404 Mar 11 2000 ftpaccess.example
-rw-r--r-- 1 bin bin 534 Mar 11 2000 ftpconversions.example
-rw-r--r-- 1 bin bin 37 Mar 11 2000 ftpgroups.example
-rw-r--r-- 1 bin bin 190 Mar 11 2000 ftphosts.example
-rw-r--r-- 1 bin bin 69 Mar 11 2000 ftpusers.example
-rw-r--r-- 1 root wheel 756 Mar 11 2000 ipfm.conf
-rw-r--r-- 1 root wheel 33 Mar 12 15:30 line
-r--r--r-- 1 root wheel 97203 Mar 16 2000 lynx.cfg
-r--r--r-- 1 root wheel 97203 Mar 16 2000 lynx.cfg.default
drwxr-xr-x 2 root wheel 512 Jun 29 2000 lynx_doc
-rw-r--r-- 1 root wheel 1898 Mar 12 2000 mime.types
-r--r--r-- 1 root wheel 4441 Aug 6 2000 mtools.conf
-rw-r--r-- 1 root wheel 1883 Mar 11 2000 muttzilla.conf
drwx------ 2 pop daemon 512 Apr 2 11:37 popper
drwxr-xr-x 2 root wheel 512 Jul 4 2000 raddb
drwxr-xr-x 2 root wheel 512 Oct 22 1996 rc.d
drwxr-xr-x 2 root wheel 512 Aug 25 2000 rpm
lrwxr-xr-x 1 root wheel 26 Aug 25 2000 rpmpopt -> /usr/local/etc/rpm/rpmpopt
lrwxr-xr-x 1 root wheel 24 Aug 25 2000 rpmrc -> /usr/local/etc/rpm/rpmrc
-rw-r--r-- 1 root wheel 729 Mar 12 15:30 smb.conf
-rw-r--r-- 1 root wheel 9250 Mar 11 2000 smb.conf.default
-r--r--r-- 1 root wheel 6471 Mar 12 2000 sockd.conf.example
-r--r--r-- 1 root wheel 3079 Mar 12 2000 socks.conf.example
drwxr-xr-x 2 root wheel 512 Oct 21 09:45 ssh2
-r--r----- 1 root wheel 294 Mar 23 08:17 sudoers
-r--r--r-- 1 root wheel 716 Sep 11 2000 trafshow
-r--r--r-- 1 root wheel 3313 Aug 17 2000 wgetrc
-r--r--r-- 1 root wheel 200 Dec 20 17:43 xmlConf.sh
And the /usr/local/etc/rc.d
drwxr-xr-x 2 root wheel 512 Oct 22 1996 .
drwxr-xr-x 11 root wheel 1024 Apr 2 11:37 ..
-rwxr-x--x 1 root wheel 111 Mar 11 2000 apache.sh.hold
-rwxr-x--- 1 root wheel 51 Mar 12 2000 mysql-client.sh.hold
-rwxr-x--- 1 root wheel 133 Mar 12 2000 mysql-server.sh.hold
-rwxr-x--x 1 root wheel 374 Mar 11 2000 rwhoisd.sh.sample
-r-xr-xr-x 1 root wheel 392 Aug 8 2000 samba.sh
-r-xr-xr-x 1 root wheel 392 Mar 11 2000 samba.sh.sample
As long as the file ends in .sh it executes. A
quick rename makes them be on or off at next boot.
Publish your articles, comments, book
reviews or opinions here!
Got something to add? Send me email.
More Articles by Tony Lawrence
Find me on Google+
© 2011-05-02 Tony Lawrence