How To Adopt 10 'Good' Unix Habits
An anonymous reader writes to mention an article at the IBM site from earlier this week, which purports to offer good Unix 'habits' to learn. The ten simple suggestions may be common sense to the seasoned admin, but users with less experience may find some helpful hints here. From the article: "Quote variables with caution - Always be careful with shell expansion and variable names. It is generally a good idea to enclose variable calls in double quotation marks, unless you have a good reason not to. Similarly, if you are directly following a variable name with alphanumeric text, be sure also to enclose the variable name in square brackets ([]) to distinguish it from the surrounding text. Otherwise, the shell interprets the trailing text as part of your variable name -- and most likely returns a null value."
export POST="first"
www.isoHunt.com
An anonymous reader writes to mention an article at the IBM site from earlier this week, which purports to offer good Unix 'habits' to learn.
I seriously doubt reading this article is going to get anyone to start showering on a regular basis.
Push Button, Receive Bacon
or even better -- use perl.
...is so littered with basic errors that it really shouldn't be recommended to anybody. How is 'tar xvf -C tmp/a/b/c newarc.tar.gz' expected to work, for example? Quote variables with square brackets? Running subshell commands using ; instead of && ? No mention of 'xargs -0' ? Don't pipe from cat to grep? Does anybody actually care that people do this (primarily so that the syntax is consistent between a munged- and unmunged-grep, and also such that the order of the command-line is logical from a human point of view)? Plus, of course, it's possible that cat | grep could yield better performance than grep alone: if cat uses mmap() to efficiently read the input files, and the kernel's pipe implementation is good, then it could do better than a grep implementation alone that simply read()s the files.
OK, I agree. Please provide a concise Python script that unpacks a tarball (a .tar.gz or .tar.bz2 file), copies new files in to a said tarball, patches based on the contents of said new files, runs make from various directories in said extracted tarball, and then changes the name of the top-level directory created by the tarball to a new name and repacks the tarball.
Or a concise Python script that opens up a text file of URLs, and extracts the files listed in the URLs:
#!/bin/sh
for a in $( cat file | awk '{print "'\''" $0 "'\''"}' ) ; do
wget $a
done
Python has it place, and is far better for medium to large projects, and projects where the code needs to be maintainable. Shell, however, works a lot better for automating UNIX tasks than Python does. Not to mention embedded systems: I can compile Busybox to have both a good shell and all of the commands that one would run from shell scripts (including grep, cut, sed, and, yes, awk) in only about 300k. A Python binary is about a megabyte big, and you need about ten megabytes to fit all of the libraries Python 2.4 comes with.
Comment removed based on user account deletion
I am so glad that he showed what a difference can make, because I was *really* getting annoyed at having to wait that extra
If I've got a simple task to do (eg the text-file-of-URLS example) then I knock it up in shell script. By the time that simple task has feature-creeped up to more than 20 lines I start to wish I'd written it in Perl. So I rewrite. By the time that Perl script has crept up to more than 200 lines I start to wish it was written in Python. So I rewrite. By the time that Python script has crept up to 2000 lines I start to wish I'd farmed the job out to a team of programmers, and I give up caring what language its written in and make them do it as a web service. Then I write a small shell script to call their web service. When that shell script has feature-creeped up to more than 20 lines...
1. Don't rm with an absolute path because you could easily
/tmp/dir
/tmp ; rm -r -f dir)
/tmp ; sudo rm -r -f dir)
/path$
#rm -r -f / tmp/dir
when "all" you wanted was
#rm -r -f
instead do this:
#(cd
or even better use sudo if you have it:
$(cd
2. When logged on as root or when using sudo on a production system think things over
at least twice before hitting enter.
3. Make sure at all times you're on the right machine, logged on as the right user in the right directory.
Set up your shell prompt to look like this user@host
Especially the habit of using || and && on command line seems ridiculous to me. These have room in two situations:
- scripts
- commands that take long enough that you go have a coffee.
This makes sense:
make install && lilo && reboot
This doesn't:
cd tmp/a/b/c || mkdir -p tmp/a/b/c
If you fail the first part, well, you typed " || " instead of pressing enter.
If you succeed the first part, you typed " || mkdir -p tmp/a/b/c" without a bloody reason.
Type first part. Press enter. Observe result.
If necessary, type the second part, otherwise correct the first without baggage of the second one hanging around.
45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B2
This code is not pure shellscript : it uses awk and wget to get the job done...
A Python equivalent might be :
It's not that much longer, it's much easier to read and less error-prone (especially the awk part), and it uses fewer external utilities.
To me, the *only* advantage of shellscript is that it's the only language that you are sure to find on any Unix system.
- ${VAR:-text if $VAR is empty}
- ${VAR:=text if $VAR is empty and set VAR to this}
- ${VAR:+text if $VAR is set}
- ${#VAR} -> length of $VAR
- ${VAR#pattern} or ${VAR##pattern} -> remove match of pattern from beginning of $VAR (## -> longest match)
- ${VAR%pattern} or ${VAR%%pattern} -> remove match of pattern from end of $VAR (%% -> longest match)
There are other formats (see the man page), but these are the ones I use the most. Eg:No shit, Sherlock! You have clearly never worked in a large organisation, where - believe it or not - you, as a standard user, do not actually get to insist that the already-overworked IT department jump through bureaucratic hoops to install your favourite bloated scripting language, unless you have a damn good business case for it. And probably not even then.
Hint: if the task you want that scripting language to accomplish is trivial to achieve with a simple shell script, you don't have a good business case.
* This doesn't apply to wget, obviously, but if your platform really has no standard alternative, you are more likely to persuade IT to install something small and simple like wget, fetch, curl, etc. than a complete programming environment like Python.
Um, whats wrong with
wget -i filename
Or have I missed something?
Monkeyboi
As has been pointed out, this article is riddled with errors. It's also not very interesting. So in the interest of perhaps actually providing some interesting tips:
/).
/etc/modules.autoload.d/kernel-2.6 /etc/m*a*d/*6
/etc/m* -> /etc/mail /etc/m*d -> /etc/modules.d /*/m*/*6 -> /etc/modules.autoload.d/kernel-2.6, and /etc/modules.d/i386 (not quite!)
In scripts, prefix dangersous commands with an 'echo' for a test run (So you can catch all those rm -rf
Single quotes are the best quotes for plain strings. The only reasion to use double quotes is if you need to quote a variable or a single quote.
Completion is fun, but using wildcards is more flexible (though you'll only want to use benign commans like cd, less, etc):
nano
nano
Note that the use of subpaths reduces the amount of flexibility.
cd
cd
nano
Finally, as a comment for the article, using:
test -e $DIR || mkdir -p $DIR
is much better than their suggestion and probaly faster anyway. Though I'd just do "mkdir -p $DIR" and maybe "&>/dev/null" under most circumstances anyway.
That's all I can think of at this point. Anyone else have tips?
-- "You can lead a yak to water, but you can't teach an old dog to make a silk purse out of a pig in a poke" - Opus
Wow, do you think you could be just a little bit more polite next time?