Bashism in /etc/rc.d/rc.S
as an experiment (and to get rid of bash) i changed /bin/sh to point to /bin/mksh.
the boot process fails at line 109 in /etc/rc.d/rc.S: eval LUKSARRAY=( $line ) This line, and the following lines LUKS="${LUKSARRAY[0]}" DEV="${LUKSARRAY[1]}" PASS="${LUKSARRAY[2]}" OPTS="${LUKSARRAY[3]}" look like bash code to me. Affected is X86_64 current and i686 14.1. I am not an shell expert, can someone confirm this? Or provide a simple solution? Otherwise I will sot down and write a patch to solve this issue. heiko |
Why would you switch to the korn shell?
If you think that little bashism is bad, just wait... nearly all the startup scripts have bashisms in them. I could understand switching to something like ash or busybox (useful for very small distributions)... but the korn shell? |
Yep, unfortunately a number of important Slackware initscripts contain bashisms. :(
Gilbert did some nice work on POSIX compliant startup-scripts a while back, which you may find useful: http://www.linuxquestions.org/questi...1/#post5156115 Only problem is that once you start making changes like this you're stepping outside of "Official Slackware" and that may make your system maintenance more difficult when Pat ships a new set of init-scripts. |
Quote:
|
Quote:
i don't mind using bash for the rc scripts, but if bash is required a "/bin/bash" shebang line should be used instead of "/bin/sh". |
Well, I think that Pat just follows the old saying here "if it ain't broke, don't fix it". If he were to rewrite all the init scripts from scratch, maybe he would use another syntax here and there. But there is no need for that as far as I know (please no more flame war about _you_know_what_).
|
I giggled when I saw this recently.
From pm-functions (part of pm-utils) Code:
#!/bin/sh BTW There are also bashisms in the code, despite the /bin/sh shebang. Removing bash is a larger task than just looking at the init scripts. |
Quote:
You'd remove bash at your peril. I added bashisms into the initrd 'init' script because it meant I could achieve a string manipulation inside of bash rather than forking to some other utilities. In my opinion since you're using a particular language which is mandated to be present, you should exercise its abilities where possible - particularly if it helps improve efficiency. If these scripts were intended to be used outside of Slackware then it would make sense to make them as POSIX compliant as possible to maximise their usability. But they aren't. |
Quote:
|
Any initrd is a special case. In this case, whether you mean the intrd from the installer, or one generated by mkinitrd, bash is not included. rc.S and all other init scripts are not used by the initrd. Any scripts run by the initrd will be busybox/sh compatible -as are doinst.sh scripts.
|
Quote:
Quote:
Quote:
|
Quote:
|
About the only place I would expect bashisms to be rare would be those multi-platform packages that are expected on things like AIX and SunOS. Though even there, bash is also frequently installed on the system.
|
Quote:
First, the LUKSARRAY array is created via: Code:
cat /etc/crypttab | grep -v "^#" | grep -v "^$" | while read line; do ... ; done On a secondary note, that could be replaced with: Code:
egrep -v '(^#|^$)' /etc/crypttab | while read -r line; do ... ; done Quote:
I see a related thread in the "Similar Threads" section and it asks "anyone uses ash as /bin/sh?" which is probably the closest to a POSIX/bourne shell that Slackware has. There are some things that aren't part of the bourne shell or defined by POSIX in the almquist shell (local for example), but it's pretty close. |
I actually don't mind bash when it's running in bash mode, and some of the bashisms are actually quite useful. It's when it's trying to take on its POSIX persona when run as 'sh' that you start to hit problems, particularly around shell invocation.
BTW, doesn't debian use 'dash' to provide their /bin/sh? |
Perplexed!
Quote:
|
Bash is the default system shell of GNU/Linux and bsd/sysvinit because it uses universal shell scripting compliance methods when booting the machine.
You are not limited to using just Bash within the GNU/Linux environment on user accounts, but the administrator(root) should always use Bash natively. Although the Korn Shell may be more POSIX compliant, it is not truly geared to run the low level system administrative functions Bash does any more. While some books say you can replace the Bourne Shell with the Korn Shell, it is actually not recommended you do so. To fix the problem is simple... use Bash for root and boot, and set up your user account(s) to use Korn Shell. |
Quote:
Quote:
|
Well, I fixed the ones that I need to use ash, and everything seems to work ok so far.
I used: http://sourceforge.net/projects/checkbaskisms/ with the '-p -x' mode. It usually involves changing: '-a' to '] && [' and '-o' to '] || [' fixing sourced with parameters: '. /etc/rc.d/rc.mysqld stop' becomes just '/etc/rc.d/rc.mysqld stop' fixing files run explicitly with 'sh': 'sh /etc/rc.d/rc.messagebus stop' becomes just '/etc/rc.d/rc.messagebus stop' 'echo -n' or -en becomes 'printf' '&>/dev/null' becomes '>/dev/null 2>&1' which is much more portable get rid of '$' in front of strings: '$"Usage: $0 {start|stop|restart|reload|status}"' becomes '"Usage: $0 {start|stop|restart|reload|status}"' get rid of 'local', although it probably will still work with ash use just "$@" in rc.sysvinit startup() in rc.S expand '/bin/rm -f /etc/mtab{,~,.tmp} && /bin/touch /etc/mtab' into '/bin/rm -f /etc/mtab /etc/mtab~ /etc/mtab.tmp && /bin/touch /etc/mtab' which is what it would expand to anyway Things I removed: rc.inet1 is unexecutable as I already use network manager the rc.S LUKS part using arrays, I don't even use LUKS, but you could fix it up using cut or awk. init.d/functions, it is very hard to fix and useless in most cases (except rc.cgred) EDIT: Of course I also changed '#!/bin/sh' to '#!/bin/ash'. I did NOT relink /bin/sh, because that may break a lot of scripts, not my scripts tho. |
Quote:
http://www.unix.com/answers-to-frequ...nt-shells.html Bash is able to do Process Substitution whereas Korn Shell can not. All I know is every book I've read or question that I've seen here all say that you should always uses Bash for the system/root shell and turn the user accounts over to their own shells. |
Quote:
Code:
Last edited by Perderabo; 12-07-2003 at 01:24 PM.. Quote:
Code:
bash-4.2# grep -r -e '<(' -e '>(' /etc/rc.d|wc -l Quote:
|
Quote:
I'd really like an authoritative answer to the questions I posed, from someone who understands the ins and outs of changing the default system shell. If Bill Rosenblatt and Arnold Robbins in their definitive guide to the Korn shell say you can safely replace the system Bourne shell with the Korn shell why are people here saying you most certainly cannot? I'm thoroughly confused about this now. |
Quote:
That statement is very badly out of date (evidence: they refer to "Bourne shell" instead of the Posix shell), and was only ever intended to apply to commercial Unixes (evidence: ksh was not available under a free licence for many years). Sorry to knock your gods off their pedestal. |
Quote:
Thanks for your uninformed opinion. It's nice to know there are people around who understand the contents of a book better than I do, even though they've never actually had that book open before their eyes. It seems Linux elitism is alive and kicking even in the Slackware forum. A sad day indeed. I'm out of here. |
Quote:
It can hardly be news to you that loose statements in a book written in 1993 don't really grok Linux, which first saw the light of day in... 1991. The O'Reilly book is not ksh. FYI I personally consider ksh to be vastly superior to bash in many regards, and that it's highly regrettable that AT&T killed any hope of wide adoption by hanging onto a restrictive licence until long after bash became impossible to dislodge, but hey, apparently I'm an uninformed elitist, so what would I know. |
Quote:
You usually use them to avoid this problem (without having to resort to named pipes) Code:
gazl@ws1:~$ seq 1 3 | while read value Using these bashisms you would write it as Code:
gazl@ws1:~$ while read value Thing is, you don't need this in ksh anyway, because it treats the scope of the variables differently to bash. Code:
$ seq 1 3 | while read value Code:
if [ -z "$PKGPATH" ]; then # set default PKGPATH if it is not already set. Here's another example from further down in the same script where I use them for a purpose unrelated to escaping the scope of a while loop: Code:
sort -u -k 1,1 <( cut -f1 -d ' ' "installed.list" ) \ Code:
cut -f1 -d ' ' installed.list available.list | sort .... | join ... | join ... > As I said above the main reason you tend to need them in bash is because bash does strange things to pipelines. ;) |
The problem is simply this... Most shell scripts are written in a syntax for Bash. For this, blame the guy who wrote the script. While for every day usage you can use any other shell, typically any system boot scripts are written for Bash syntax.
To effectively switch to korn shell you should evaluate the scripts and audit the syntax to match for korn shell. |
I work in a mixed Solaris / Red Hat Shop - but it was originally all Sun/Solaris - and the system shell for most the in-house work is Korn. Not surprising, but quite a few 'Kornisms' exist in our scripts. I can't say that I've ever looked carefully into which shell is used by the init scripts; but I wouldn't be suprised to learn all the Solaris hosts use ksh while all the Red Hat hosts use bash. I don't think it's elitism; just momentum. Between the two shells, I prefer Korn myself - probably that momentum thing. Occasionally, Ive had to debug Bash scripts; unless management tells me otherwise, I leave them as Bash scripts. So long as they're portable enough to run on both sets of hosts, everything's good.
Just an opinion |
ksh isn't 'less fit' for use as a system shell; it just won't work in Slackware because no effort was made to maintain POSIX compliance in init/administration scripts. The same may be said of various other Linux distros, though there certainly may be some that can cope (Debian does use 'dash', or at least used to, so I wouldn't be surprised if you could get ksh to work with minimal effort if any). The BSDs don't tend to rely on bash at all.
So continue using ksh if you want (there's nothing inherently wrong with it), but don't expect to be able to remove bash entirely *in Slackware*. In the end, POSIX shells are simply much less capable than full-fledged bash, ksh, zsh, etc., and it is way easier to add little shell-specific commands (often without realizing it) than to remain POSIX compliant (unless the script is trivial). And simply because bash is the most popular shell in Linux distros (by far), you are likely to encounter shell scripts with bashisms. If you are willing to fix every script you happen to come across (either in the distro you use or third-party scripts from the internet), then you can use any shell you like. |
Well someone's got to answer the questions...so here goes:
Quote:
If you replace the #!/bin/sh line with #!/bin/ksh they will still work. The current topic the OP mentioned is that some Slackware scripts have #!/bin/sh but they use bashisms so #!/bin/sh should really be #!/bin/bash, or for a little portability, #!/usr/bin/env bash. Quote:
Quote:
Quote:
|
I think FreeBSD uses csh.
|
This is annoying. I've should have chosen another title (like "wrong /bin/sh shebang line in /etc/rc.d/rc.S" or so).
All I wanted to say was: 1. There is Bash code in /etc/rc.d/rc.S. 2. This file has a "/bin/sh" shebang line, which is wrong. 3. The fix is easy - change /bin/sh to /bin/bash. i am serious about this matter, as rc.S is one of the most importants scripts. I'd really like to read an oppinion from Pat about that, but I think he won't wade through all the "ksh vs. bash" pages. |
Quote:
Code:
~$ ls -l /bin/sh |
Quote:
|
Quote:
User accounts on my systems (and those that I've administered over time) have defaulted to /bin/ksh (users are free to change to BASH if they want, most haven't). Haven't had too many complaints. Leaving system software (including all start up, shut down, rc's alone) to execute as /bin/sh (which, yeah, is BASH, not actual sh) is no problem; things work if you let them. There is no reason to remove BASH, leave it there, just don't use it -- just change the account shell in /etc/passwd from /bin/bash to /bin/ksh and life is good. Wouldn't mess with the system accounts (except root which is /bin/ksh on all my systems). I would note that the above has never resulted in any difficulties whatsoever. Hope this helps some. |
Quote:
Code:
If bash is invoked with the name sh, it tries to mimic the startup Perhaps bash *shouldn't* execute the code you're referring to if it's mimicking the behavior of 'sh' - maybe you should check with the authors of bash? |
Quote:
I'm not sure what you mean when you say the O'Reilly book is not ksh. I'm half-way through the book and it certainly seems to be all about the official Korn shell, ksh93, to me. Quote:
|
Quote:
if i read it right something like http://stackoverflow.com/questions/5...tring-variable and a counter there is maybe a better solution but none comes to mind there is more bashism in inet scripts and more also shutdown scripts use "kill" that is the gnu /bin/kill in bash but builtin in ksh so you'd need to change that to /bin/kill or change the flags to be posix so ksh don't fail |
There is also the issue of future proofing. If smash (the new Super Mega All-in-one shell) came along, then a simple change 'ln -s /bin/smash /bin/sh' would allow the init scripts to continue to function.
|
Quote:
The book's statement that misled you, and at least one more like it, should clearly have been excised from the 2002 revision. They were not. That's what confused you. Please don't keep shooting the messenger; it hurts, actually. Quote:
When I criticise one statement in the O'Reilly book, I am not criticising ksh, nor am I trashing the whole of the O'Reilly book, nor am I trashing *you* *personally*. Quote:
|
Quote:
But try this: create yourself a test user with /bin/sh specified as its login shell. When you login from the login prompt on a console, everything works as expected, bash starts in POSIXLY_CORRECT mode and runs the POSIX startup scripts. Now, try a "su - testuser" instead: bash will start in its normal native mode, not POSIX mode. The reason for this, is that bash looks at argv[0] to see whether it is running as 'sh' or not, but when started by 'su' argv[0] is 'su' and bash has no way of knowing what mode to start in. Its approach is fundamentally flawed. This is why I was saying above that I have no problem with bash when it's run in its native bash mode, but its not a good choice to use for the POSIX /bin/sh. So, we have the strange situation on Slackware where a user wanting a POSIX shell can't use /bin/sh as their default shell because it wont work correctly. I accept that this is only a edge-case that the typical user will remain blissfully ignorant of, but stuff like this gets under my skin. |
Quote:
But in the other hand if the user doesn't know that invoked as sh bash behaves as a POSIX shell he or she we will invoke it with the --posix option anyway (just kidding :) |
Quote:
My personal opinion of the standard 'sh' is that if you ever had the misfortune to have it as your shell on Solaris, one of the first things you did was to find a binary package of 'bash' and compile or install it :-) I recall one of the first things I had to do with 'sh' was: stty erase <press backspace> I did like Solaris though. |
Ahh yes, the old backspace/del issue. Used to have to muck about with that on AIX too. :) But that's more to do with the terminal and tty layer than the shell. It's only because bash uses readline for its command line input that you don't see the problem in bash, but have the wrong terminal setting and you can still see the escape codes appear in stdin when you hit backspace when running programs that read directly from stdin without readline, even when started under bash.
Code:
gazl@ws1:~$ od -tx1c "stty erase ^H" can still be used to fix that, but if you get the right settings in your terminal it's not necessary. I use these Xresources for xterm: ?.vt100.metaSendsEscape: true ?.vt100.backarrowKey: false |
Quote:
Quote:
|
Quote:
Morris L. Bolsky, David G. Kornm, The KornShell Command and Programming Language (Englewood Cliffs, NJ: Prentice Hall, 1989, IDBN 0-13-516972-0), Copyright 1989 AT&T Bell Laboratories.
|
sh, bash, ksh and other contraversies
Hi,
I have been around for more years than I care to think about so my opinions may not be worth much ... ravings of an old fart ... BUT:- I think it is good practice (when considering shell scripts) that the shebang line reflects the nature of the script so if it uses so-called "bashisms" then use #!/bin/bash, even though you may consider it unnecessary because sh is linked to bash. For those who indulge in AIX, you will notice that although it uses the Korn shell for it's init scripts, /bin/ksh is the old pre-93 ksh (the ksh that shipped with the original AIX) and post-93 ksh is included as ksh93 ... I hope this is accurate .. it has been a while since I used an AIX system. I use ksh as my login shell .. have done this from 1989 onward .. and in order to use ksh when I su to "root", I have a specific username (kroot) which is uid 0 with /bin/ksh as it's login shell. This leaves username "root" as whatever is the specified on the system I am using, specifically so that init scripts run as designed (not just as coded!). What are these ravings all about, you may ask ... well, getting all hot and bothered over which shell does what and how much is not worth it ... they all have their advantages and disadvantages so "horses for courses". On the other hand, don't get me started on "csh" :-) As always, YMMV cheers pete pete hilton saruman@ruvolo-hilton.org |
Quote:
|
Quote:
my experience is from replacing bash with ash, for fun guess assuming arrays are bash specific was false oh well, you learn something every day |
Quote:
Quote:
Quote:
The shell specified in /etc/passwd is the shell program you get when you work on the console or open a terminal, be that sh, bash, ksh, whatever else tickles your fancy. If you're executing programs as UID 0, you're going to be the god of the machine; if you execute them as you, well, you're going to be you (and won't be able to cause much damage, eh?). Place I worked for, oh, about 12 years (a Sun farm) insisted that all users had to use C-Shell (which was written at Berkeley (IIRC) when all of 'em were dropping acid and smoking weed: how else would they have come up with that mess! :rolleyes: Because I was the only non IT guy with a Sun work station, I ran my own stuff my own way (and insisted that my log in shell be KSH on every other system). Of course non of the shell programs were written in C-Shell (thankfully), we wrote all of 'em in Bourne or Korn and things worked (and are still working I've been told) just fine, thank you very much (been retired about five years). My complaint with BASH is simple: it violates the founding principles of Unix (and, thus, Linux) as postulated by Doug McIlory (see below for that). Bourne and Korn have not changed over the years (well, Korn a tiny little bit from '89 to '93 plus a twiddle here or there, Boune not at all since like forever). BASH? They keep screwing with it, adding more and more and still more "functionality" and bells and whistles, right down the rosy path to incompatible older shell programs and broken systems. I suppose it is a good feature to have BASH behave itself with the #!/bin/sh; be an awful mess if it didn't. You know that psychology thing? Glass half full or empty? Engineer: neither; the glass is too big (to do what it needs to do). I still write pretty much everything in C. I learned C++ (and learned, right quick, that I didn't really care for it all that much and don't really ever use it unless forced to). I will continue to write shell programs in KornShell simply because I have not found anything else worth a damn. I do so love being an old fart. |
All times are GMT -5. The time now is 02:11 AM. |