daveb@rtech.UUCP (06/15/87)
As Doug Gwyn noted, the Bourne shell ':' is a command, not a comment character. However, it is still what I suggest you put in the head of your shell scripts for maximum portability. It's clear you can't have a '#', because that implies csh on some kernels. You can't rely on '#!/bin/sh', because some kernels don't undertand it. (Yes, there are some that recoginize '#', but not '#!/..."). One option is to put a blank line at the beginning, which will result in Bourne shell execution. Unfortunately, blank lines have an annoying habit of being removed when someone casually edits a file. ---------------- easy to lose this line-> # submit -- run cmd in background, it's output to OUT nohup $* > OUT 2>&1 & If you put a ':' on the first line, WITH NOTHING ELSE, you won't accidentally delete the line and you will get /bin/sh. Why ':'? Because it's easy to type, innocuous, and usually a built-in making it cheap to use. ---------------- harder to lose this---->: # submit -- run cmd in background, it's output to OUT nohup $* > OUT 2>&1 & You are asking for trouble if you put comments on the line with the ':' ---------------- NO NO NO--------------->: submit -- run cmd in background, it's output to OUT nohup $* > OUT 2>&1 & -dB -- {amdahl, cbosgd, mtxinu, ptsfa, sun}!rtech!daveb daveb@rtech.uucp
chris@mimsy.UUCP (06/15/87)
In article <913@rtech.UUCP> daveb@rtech.UUCP (Dave Brower) writes: >... You are asking for trouble if you put comments on the line with the ':' > : submit -- run cmd in background, it's output to OUT > nohup $* > OUT 2>&1 & Of course, if you spell `its' correctly, this particular comment works after all :-) . In scripts for export, I use : Run this script with "sh" not "csh" as the first line. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: seismo!mimsy!chris
john@xanth.UUCP (06/16/87)
In article <913@rtech.UUCP>, daveb@rtech.UUCP (Dave Brower) writes: > It's clear you can't have a '#', because that implies csh on some kernels. > You can't rely on '#!/bin/sh', because some kernels don't undertand it. > (Yes, there are some that recoginize '#', but not '#!/..."). You say "kernels" above, but I hope you mean "distributions of UNIX operating systems" or something like that. The whole point of #! is that the ->kernel<- understands it and runs the specified interpreter, as opposed to just the # which the ->csh<- understands to mean "use the csh", and the newer Bourne shells just consider a comment. So yes, it's certainly true that there are plenty of versions of UNIX out there where the kernel does not understand #! but the csh understands # - all version of System V with the csh, for example. (If there are System V kernels that do #!, please let me know!) I think we should end this discussion with a quick summary of the situation. Here is a table describing which shell your script will be run by, depending on what it begins with, and where you're running it from. The "sh" here is a Bourne shell that uses "#" as a comment; if not, the situation's even worse. script r u n f r o m begins kernel knows #! kernel does not know #! with sh csh sh csh #! -- specified script -- sh csh # sh csh sh csh other sh sh sh sh (includ- ing :) So if you're writing a csh script, the best you can do is to start it with #! /bin/csh and hope no one tries to run it from the Bourne shell under a kernel that does not know #!. If you're writing a Bourne shell script, you should start it with something else, like a colon alone on the line, as Dave suggests, and it will always be run by sh. Only if you know the script will never go to a system that does not know #! should you use #!/bin/sh . -- John Owens Old Dominion University - Norfolk, Virginia, USA john@ODU.EDU old arpa: john%odu.edu@RELAY.CS.NET +1 804 440 4529 old uucp: {seismo,harvard,sun,hoptoad}!xanth!john
dhesi@bsu-cs.UUCP (06/16/87)
In several articles strategies for ensuring execution by a specific shell are discussed. Larry Wall's terrific installation scripts for patch and rn use the equivalent of following line to force execution by sh: export PATH || (echo "OOPS, trying again..."; sh $0; kill $$) There ought to be a way of doing the same thing for other shells. The penalty is the extra fork (or is it TWO extra forks?). Perhaps somebody could publish a patch to SVR3's shared library so the exec family of system calls/functions will test for #!, and modify the text of the requested command, before passing control to the kernel? -- Rahul Dhesi UUCP: {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!dhesi
jerry@oliveb.UUCP (06/20/87)
The important thing to remember when using : in sh is that it is a null command not a begin comment character. So the following gotchas apply: - The ":" must be followed by a white space or a sh metacharacter. : this is ok :>fu is also ok but will create the file fu :this is not ok because it looks for the command ":this". - The rest of the line will undergo normal filename, variable, and other metacharacter expansion. So: : Do I need this line? will fail when it tries to glob the question mark (assuming you don't have some 5 character file names that start with "line"). Also, as previously mentioned the quotes must be balanced, perentheses have special meaning, etc. - A simicolon will end it, not just the end of line. : This is ok; But this will try to execute "But" It is safest to enclose the entire line in single quotes ala: : 'this allows you to use ?()*$<>; without problems' The only problem that leaves you is figuring out why: : 'This line won't work' If you think of : as being a faster version of: /bin/echo>/dev/null arguments used but discarded You will have a lot less problems. Also interesting is that the : command always returns true so it is also a faster replacement for /bin/true. With a little work it can also replace /bin/false. Jerry Aguirre P.S. It is amazing the number of "experienced" shell programers who get confused looks when faced with a syntax like. <inputfile grep pattern >outputfile
wcs@ho95e.ATT.COM (Bill.Stewart) (06/23/87)
In article <767@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
: In several articles strategies for ensuring execution by a specific shell
: are discussed.
: Larry Wall's terrific installation scripts for patch and rn use the
: equivalent of following line to force execution by sh:
: export PATH || (echo "OOPS, trying again..."; sh $0; kill $$)
: There ought to be a way of doing the same thing for other shells. The
: penalty is the extra fork (or is it TWO extra forks?).
I generally write all my scripts in Bourne Shell, because I know they'll work
(relatively) portably. When it's important to use ksh, I use the following:
if [ "$RANDOM" = "$RANDOM" ]
then ## recovery script to feed itself to ksh
ksh -c "$0 $*"
exit "$?"
fi
The simpler approach of checking $SHELL doesn't work; SHELL is exported,
and some programs will drop into /bin/sh by default. ksh updates $RANDOM each
time it uses the value, so "$RANDOM" = "$RANDOM" will never be true in ksh, and
will (presumably) always be true in other shells.
Writing a good recovery script is hard; if the arguments to the program contain
white space or metacharacters, the $* will trash them. Sometimes it matters.
Is there a good equivalent of this technique for csh? I suppose one could
separate the program in to a csh file and a Bourne-shell front-end,
:
exec csh -c "$0.csh $*"
but it would be much nicer to have something self-contained.
--
# Bill Stewart, AT&T Bell Labs 2G-202, Holmdel NJ 1-201-949-0705 ihnp4!ho95c!wcs