On Mon, Dec 31, 2001 at 12:04:39AM -0500, John P Verel <[EMAIL PROTECTED]> wrote: [...] | > Perhaps I'm missing something here. Aren't the path modifications in | > /etc/profile conditional? If they are already in the users path, they | > shouldn't be added again. That being the case, re-sourcing that file | > shouldn't affect your path. [... and other shell init stuff earlier in the thread ...]
Last October I ranted a bit about the startup scripts in the "Is Red Hat heading down the wrong road?" thread. They are inefficient and overdone (being redone in the /etc/bashrc! Geez!) Just for your amusement I repost that rant here, which details some of the things done wrong. Cameron Simpson, DoD#743 [EMAIL PROTECTED] http://www.zip.com.au/~cs/ ---------------------------------------------- Date: Sat, 13 Oct 2001 17:19:15 +1000 From: Cameron Simpson <[EMAIL PROTECTED]> To: [EMAIL PROTECTED] Subject: Re: Is Red Hat heading down the wrong road? Message-ID: <[EMAIL PROTECTED]> References: <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> <3BC62C27.29850.DD84C@localhost> In-Reply-To: <3BC62C27.29850.DD84C@localhost>; from [EMAIL PROTECTED] on Thu, Oct 11, 2001 at 11:32:55PM +0200 Me> There are things I dislike about the RedHat stuff. I'd like to fix a lot Me> of their shell scripts; some are a bit inept (they do a lot of "if ... | Me> grep ..." where a case statement would be much faster and easier to read Me> to boot) and their bash system startup files are a nightmare. Flatout Me> wrong. But we fix that in our post-install stuff anyway now we know. Rodolfo> Hey Cameron, you wanna elaborate on this? Love to learn something here. On Thu, Oct 11, 2001 at 11:32:55PM +0200, Leonard den Ottolander <[EMAIL PROTECTED]> wrote: | Just my thought. Cameron, please share some of your insights with us. Ok, since I did a bit of a dummy spit. I had been putting this off until I had a vanilla redhat machine to hand, because our fix here is to simply truncate /etc/bashrc and /etc/zshenv. It's amazingly effective but mangles the evidence :-( ////////////////////// The first remark was about so many of the redhat /etc/profile.d files and a few of the /etc/init.d file which say variants on this: if ! printenv PATH | grep -q $kdepath ; then (from /etc/profile.d/kde.sh) which is testing for the absense of $kdepath in $PATH. Firstly: "!" is a bashism - many other shells don't like it. Since these files (in /etc/profile.d) are sourced by ALL Bourne style shells these dialect specific things _must_ be avoided or things will break. Secondly, you'll note that "!" here depends upon being the same level of precedence as the "if" word itself: is applies to the entire command list (which pipe-as-a-whole). Ugly, since this violates how damn near every other command works. It just mucks with one's mental model of the shell. Thirdly, this is very inefficient. It requires a pipe and two subprocesses, thus two forks and one exec(). And also a lot of waiting around while first the echo runs and quits, and then the grep runs and quits. Consider instead: case ":$PATH:" in *:"$kdepath":*) ;; # already present *) # missing ... do stuff here ... ;; esac No forks, no execs, no waiting. And depending on your indenting style, just as readable if not more so. BTW, that :$PATH: isn't some little known weird shell syntax, it's just the $PATH with colons either side so that the pattern match on *:$kdepath:* will work even if $kdepath is right at the front or back of $PATH. ////////////////////// But the above merely annoys me for being a bit inept. What really really pisses me off is /etc/bashrc. Come, let us read: # are we an interactive shell? if [ "$PS1" ]; then Not even one line into the code it begins! Clue: testing $PS1 is _not_ a test for an interactive shell! You look at $- for that, and look for an "i", thus: case $- in *i*) # yes I'm interactive Testing $PS1 is totally dependent on having a pure and untrammelled RedHat vanilla install. Anyone may have set PS1 arbitrarily earlier. Or unset it! (Certainly here this test started breaking almost immediately for us.) What I think their idea was was that the user only gets $PS1 from /etc/profile or something like that. But no such thing is true. Perhaps it is set _only_ in the .bashrc? After all the thing's only of use in an interactive context. Or perhaps they were thinking that a noninteractive shell won't have $PS1. But plenty of people set it and export it, and may also put it in places like ~/.ssh/environment so that it's there for any shell they invoke through ssh or such. Anyway, basicly false whatever their logic was. They should be testing $-. But also, /etc/bashrc is, IIRC, _only_ sourced by interactive shells anyway. So you don't need to do the test at all! Back to the bashrc: if [ -x /usr/bin/tput ]; then if [ "x`tput kbs`" != "x" ]; then # We can't do this with "dumb" terminal This is a bit weird. Testing for an absolute path (which, admittedly, is the only thing they can test) then not using that path explicitly when they run tput. Suppose the $PATH is different? Doesn't have /usr/bin maybe? I'm just niggling here. stty erase `tput kbs` elif [ -x /usr/bin/wc ]; then if [ "`tput kbs|wc -c `" -gt 0 ]; then # We can't do this with "dumb" terminal stty erase `tput kbs` fi fi fi This is more weird. Firstly, this is inefficient. They seem to be seeing if "tput kbs" outputs anything, and then using it if so. But that runs tput twice. Secondly, they should be quoting the output of the tput in the "stty" line - after all the whole point of using tput is that we don't know what the preferred erase char is here, so it could be _anything_. Just niggling that one. Thirdly, the second tput test: if [ "`tput kbs|wc -c `" -gt 0 ]; then # We can't do this with "dumb" terminal appears to be doing exactly what the first one did. Why twice? Possible alternative code: if [ -x /usr/bin/tput ]; then kbs=`tput kbs` [ -n "$kbs" ] && stty erase "$kbs" fi Shorter, faster, robust, and easier to read. Now let us skip to the code which truly offends: if [ "x$SHLVL" != "x1" ]; then # We're not a login shell for i in /etc/profile.d/*.sh; do if [ -x $i ]; then . $i fi done fi Leaving aside the $SHLVL test which I think is correct for what it's doing, WE ALREADY DID THIS STUFF! In /etc/profile! We SHOULD NOT be doing it again! Gross gross waste of time and cycles! There are two reasons I can imagine this code exists: - maybe some of those scripts make aliases or shell functions: unexported pershell thingies. Well frankly, that should be in a separate file, eg /etc/shellrc.d/whatever. - my prime suspect is the GUI login Let me elaborate on that, because it's a major difficulty that every X11 GUI login presents, which can be worked around properly but is usually worked around very badly, like the above code. In the GUI logins, /etc/profile is generally not run by the support script which fires up the rest of the session in vanilla installs. This is, in my well known to really very humble opinion, a bad thing. The upshort is that new ternimals must either be login terminals, incurring a startup cost for every new window (ick - windows should be cheap cheap cheap!), or be plain shells which lack all that handy environment that /etc/profile should have set up. Often they are plain shells, and people naively source /etc/profile (or its guts in some less centralised and maintained form - you should see the horrors in many ASIC engineers' .cshrc files), basicly making them as expensive to invoke as login shells without the redeemiing features. Why the difference and the consequent ugly hacks? A "normal" console login runs a login shell, pure and simple: it sources /etc/profile and ~/.profile (or ~/.bash_profile) and so the command environment you expect is set up. If you then start an X11 session with startx or xinit, it then runs your .xinitrc (or the system default if you haven't got one), and because this all descends from your login shell everything run therein has the normal environment. With the advent of the GUI login via XDM this scheme goes out the window to some extent. Firstly, they generally don't source /etc/profile during their startup by default. Secondly, because some people don't have Bourne shells you can't just source /etc/profile and ~/.profile naively - they may not be appropriate. (This isn't an issue with a console login because the shell itself takes care of this in login mode; under the GUI we're trying to address this from a script). Thirdly, many ~/.profile files (and a few naively coded system /etc/profile files) imagine they're talking to an interactive terminal and do interactive things, like ask questions of the user. So even in general they can't blithely source the right things. So in general, the GUI doesn't even try. Because of this, unless the user has done something special themselves the environment the user's GUI clients run under is vanilla and spartan. Ugly! So what happens? Instead of biting the bullet like a fascist sysadmin would and writing a script to source the right things for whatever shell the user has and living with users shooting themselves in the foot if their startups do interactive things, we find code like the above in the /etc/bashrc or wherever which says "oh just go and do all this work anyway". Now, most GUI logins provide a hook of some kind for sourcing an arbitrary script at startup, prior to running the desktop stuff. For example, CDE sources ~/.dtprofile if it exists. So you can put: . /etc/profile . $HOME/.profile in that if you like. The GNOME and KDE desktops, I believe, have similar hooks. If you care, I yabber about this a bit over here: http://www.zip.com.au/~cs/answers/x11-one-size-fits-all.txt In short, rather than polluting the /etc/bashrc with gratuitous stuff which should have happened at login (i.e. at desktop startup time), it is far far better to source /etc/profile et al during the desktop startup and leave the bashrc streamlined. (For example, ours is empty here!) /////////////////////// So the main point of my rant here is that /etc/profile et al should be run ONCE and ONCE ONLY in any given login session, GUI or otherwise. The redhat stuff does not aim for this, and makes your machine seem slower than it needs to be. It also means that if you've made yourself a nice uncluttered $PATH and so forth for whatever reason, the /etc/bashrc will go and crud it up again for you! The only thing of any use in the existing /etc/bashrc is the tput thing, and personally I don't do that either. "stty erase ^h" does me fine. Well, that's my ranting done for now. Cheers, -- Cameron Simpson, DoD#743 [EMAIL PROTECTED] http://www.zip.com.au/~cs/ Since we invented the mouse, the GUI, the laser printer, ... - _AppleNews_ August 1999 _______________________________________________ Redhat-list mailing list [EMAIL PROTECTED] https://listman.redhat.com/mailman/listinfo/redhat-list