It starts when some poor soul has written a script to do some thing or another, and happens to mention that it was called "/usr/bin/whatever".
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 religion.
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 /usr/local/bin!
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 /usr/local root@bilver # find . -print | wc 26724 26724 1016763 <<*** beats your 560!!!
/usr/local has all this besides just bin
<
total 77168 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 quite true.
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
<
total 274 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
<
total 8 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 © 2011-05-02 Tony Lawrence
Why bother with subroutines when you can type fast? (Vaughn Rokosz)
Wed Sep 16 16:07:30 2009: 6918 jtimberman
The correct answer of where to store all that stuff is in a software version control system like Git, Subversion, CVS or any of the other SCM/VCS tools out there. Then that should all be deployed to systems using a configuration management tool, whether that is Chef, Puppet, cfengine, Makefiles, Rakefiles, Capfiles or a homegrown ssh-for-loop solution.
Then it doesn't matter if you (or your client) wants to install in /usr/local, /opt, or /my_monkeys_play_here. You point things to the right path, and go. When the system is upgraded, you redeploy again, and everything goes into the correct location.
Wed Sep 16 16:14:08 2009: 6919 TonyLawrence
That doesn't answer the overwrite problem. Yes, you get your scripts back, but if they have overwritten newly born vendor scripts, you may break something else - and may have a heck of a time figuring out why.
If your redeploy is intelligent enough to recognize an overwrite, that helps, but then you still have to go chase the loose ends.
Better to put it in /my_monkeys_play_here
------------------------
Printer Friendly Version
Use and Abuse of /usr/local/bin Copyright © January 2000 Tony Lawrence
Have you tried Searching this site?
This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more.
Contact us
Printer Friendly Version