#!/bin/sh vs #!/bin/bash -- script executes differently; each way = different bugs
So far I haven't found the exact answer I'm looking for; I don't even really know what the question is :scratch: though various mailing lists and threads elsewhere tell me that when bash is invoked by the #!/bin/sh method, it starts in some sort of sh compatibility mode.
I presume that this would mean that a script written to be invoked with bin/sh would be compatible with other shells, not just bash and not necessarily just on Linux. Anyhow... So, keeping in mind that I'd like to if at all possible be sure my script will work on all sh or bash shells, consider the following: I have been trying to debug a weird problem involving a gawk statement. I've been fiddling with this weird problem for days now. My script starts with #!/bin/sh. Now, in an effort to debug, I tried running the script with a commandline like: shell# bash -x ./script instead of the ./ usual; I discovered that the FIRST weird gawk problem does not occur now. Instead, a different gawk statement acts weird, AND/BUT: The script executes to completion, terminating with an error because of the GARBAGE input I gave it. Why should it not execute to completion? Because I am testing its sanity checks which make the script fail if given garbage input. So to test, I give it garbage input and run it. When started with /bin/sh the gawk problem screws the works long before execution would otherwise terminate, and when I start it with /bin/bash the gawk works fine, but a bunch of other crap all fails, the garbage is ignored, and the script runs to completion :/ What to do?? I don't know if I'm looking for an absolute answer, but for now, what are the big implications/differences between /bin/bash and /bin/sh? Have you run into a situation like this? FWIW, the pesky gawk line is like so: Code:
ip=$(echo $1 | gawk -v FS=. '/\//{ gsub("/",".") ; print and($1,$5)"."and($2,$6)"."and($3,$7)"."and($4,$8) }' ) Code:
get_if_from_ip () { Watch this bunch of console output when via # sh -- I sedded a $LINENO and/or small message echo onto every line of the script, so nearly every line outputs a line number to the console -- everything below comes from the script, except the bold text: NOTE: IP address gummed up for safety reasons. Quote:
Quote:
So I suppose, there are two questions here: 1) What's the big diff's between bash and sh; and 2) How does bash vs sh affect interpretation + execution of things like gawk statements, shell expansion, etc.? Website links are welcome. 3) Does anyone see anything about that gawk statement way up there, that might cause it to act weird under any circumstances? It runs fine in the console (bash). And if all the above makes no sense at all to you, and you have not one iota of a clue as to wth is going on here in the least, or you have never heard of bash, please reserve funny commentary for a bit later, after there has been maybe some educated feedback :) -- thank you! PS - This post is part <rant> and part post ;) and may not make much sense -- after all the copying, pasting & explaining, I'm lost... And, maybe there's some little simple obvious thing(s) I've missed in here, that would eliminate all this weirdness. NOTE: there are typos/brainos above somewhere. Sasha |
/bin/sh is usually a pointer to a shell.
Code:
# ls -l /bin/sh |
FWIW, I am FINALLY starting to figure out wth is going on with the script, though I have not yet tested my findings using the different shell invocations;
The large part of my trouble involves (our old favorites!) different instances of when/where to use quotes/backticks/brackets: Quote:
When the proper items are not surrounding the expansion stuff, WEIRD things happen: other lines of the script get sucked into the expansion process.. Likely there's more, but this is where I'm at this moment. |
Have you seen The Advanced Bash Scripting Guide? It might give you some guidance on some of the things you're doing.
Regards, Alunduil |
Hello Sasha :)
Bash behaves differently when invoked as sh as detailed here (scroll down to "Invoked with name sh") where it says "When invoked as sh, Bash enters posix mode after the startup files are read". Details of differences: bash/POSIX. If tracing (-x) propagates to pipelines (by definition including single commands) in $( ) and ` ` then the output from var="$( <pipeline> )" and var="` <pipeline> `"includes the trace output and almost certainly breaks the script. It used to behave this way in ksh and POSIX shell and, anyway a lot of trace output is befuddlifusing so I got out of the habit of using it and now insert set -x and set +x around the section to be debugged. |
Using backticks instead of $() should help. If you really want to write it so it is portable, then run it using dash or ash. dash claims to be completely POSIX-compatible. Even when running bash as 'sh' it will still have capabilities which are not compatible with other shells.
|
Quote:
As for the script, I think you might want to look for a better way to do it, maybe with awk. |
Might be worth trying
Code:
ip="$(echo $1 | gawk -v FS=. '/\//{ gsub("/",".") ; print and($1,$5)"."and($2,$6)"."and($3,$7)"."and($4,$8) }' )" |
bash debugging.
Quote:
Quote:
One handy thing I have found though, to be used when running with -x turned on, is to set your PS4 prompt like so: Code:
export PS4='(LINE:${LINENO} FUNC:${FUNCNAME[0]} [shlvl:${SHLVL} subsh:${BASH_SUBSHELL} error:$?] At this time, I'm back to where everything works perfectly -- a significant part of my problem, was that, a couple days ago, I merrily went willy-nilly putting double-quotes around a bunch of $(...) operations; it screwed a lot of stuff. :scratch: dunno how many times I have to learn that lesson: Change ONE thing, then test!! Thanks! Sasha |
Quote:
Quote:
|
Quote:
the problem was in (for example) [ bracketed tests ] when there was multiply-embedded shell substitution or expansion, such as: [ "$(eval echo \${${some_thing[x]}})" ] in cases like this, the expansion/substitution failed, causing very bizarre results. PS - what's MMC? Sasha |
sounds like you're having fun. I've got a couple of suggestions that may(!) help.
1.double brackets [[ ]] is generally more robust Quote:
2. if I get to the point where I need serious debugging info I use set -xv just before the trouble, or just as the 2nd line after the shell declaration; and you can turn them off in the usual *nix way set +xv |
Quote:
|
OK, cool -- thanks you guys for the tips about the double brackets; I've read of it MANY times but never found that I actually needed to do it, although I have encountered the operator errors within the [ .. ] constructs, and generally got around it by switching operator type, such as from | to -o or from != to -ne. I always wrote this off as bash telling me that I was using the wrong operator for the type of variable, i.e. trying to compare $string to $integer ]. I had pretty much given up on < > and switched to -lt -gt instead, but this double-bracket thing will have me re-examining this stuff.
:cool: Thanks!! Sasha |
For doing stuff that's mathematical, it's actually better to use (()) arithmetic test construct
|
All times are GMT -5. The time now is 09:53 AM. |