27 Comments

  1. Esc

    Respect, wow

  2. Duke

    Engineering precision. Nice job!

  3. Vernon Van Steenkist

    A couple of my favorites.

    set -o vi

    This command puts your shell in vi keybindings mode (normally it is in Emacs keybindings mode). Especially useful if you use a keyboard that doesn’t have arrow keys like an IPhone or IPad. Good quick tutorial and references at

    https://catonmat.net/bash-vi-editing-mode-cheat-sheet

    Automatically add sub-directories to your PATH

    export PATH=$PATH$(find $HOME/.scripts -not ( -name CVS -prune ) -type d -printf “:%p”)

    This command adds all the sub-directories in $HOME/.scripts which contain my personal scripts to my PATH while excluding the CVS version control directories.

    Also, if you quickly don’t want to run the alias version of a command, just put a backslash in front of it. For example

    \ls

    will output a directory listing without all the color etc directives that you put in you alias version of ls.

  4. geirha

    Never export CDPATH! You’ll get some unpleasant surprises when a script using cd accidentally hits a path from CDPATH

    • Hello @geirha,
      Thank you for the information. Could you possibly elaborate on the “unpleasant surprises” for everyone’s edification?

      Stephen

      • geirha

        Sorry, I meant to link to the pitfalls page. Here:

        https://mywiki.wooledge.org/BashPitfalls#pf48

        In short, if cd gets a hit in CDPATH, it will output the absolute path of the directory it ends up in (to alert the user it “ended up” elsewhere), which causes breakage if a script is using cd as part of a command substitution

        • Hello,
          Thanks for the link. I corrected the article to reflect your advice. I could see this being a problem under certain situations.

          • geirha

            You should also move it to .bashrc. .bash_profile is only meant to be read during login, so it’s mainly useful for setting environment variables like PATH, not for setting variables that configure your interactive session like HISTSIZE, PS1 and CDPATH.

      • Jan

        Hi Stephen,

        geirha possibly refers to the following:
        https://mywiki.wooledge.org/BashPitfalls#export_CDPATH.3D.:.2BAH4-.2FmyProject

        • Stephen Snow

          Thank you @Jan,
          I think exporting CDPATH is fine since the potential error would really be a problem of the script writer as opposed to a problem with CDPATH being exported. The script writer should never assume anything about the environment of the system beforehand. When I write scripts for a specific function on my system, I know the environment and write with that in mind, but not so for generic scripts I am sharing with others. Therefore I then have to account for the potential pitfalls within the script or with specific instructions on how to use it.

    • Steve

      Additionally, always have “.” as the first component of your CDPATH variable, else you shall see surprising behaviour (eg; you have, ~/images and CDPATH=~/Projects/. Now, if you are in ~ and do ‘cd images’ you will end up in ~/Projects/images, if it exists)

  5. Robin Meade

    I like how the author followed the best practice of putting PATH customizations in

    .bash_profile

    , which is where Fedora always put them prior to this commit: https://src.fedoraproject.org/rpms/bash/c/739b272e5f5d10cf27a847a44d09eb7f4b6ec89b?branch=master

    • Putting PATH in the login profile makes more sense to me as well. Especially when you understand that environment variables are always inherited by sub-processes. It is inefficient and you shouldn’t need to recreate or redefine a bunch of variables every time you spawn a shell. Doing that is also quite error-prone as can be seen from commit https://src.fedoraproject.org/rpms/bash/c/e3b3cd9cec4a3bd12a792536c0ea131f5ba5bd72?branch=master.

      I also don’t like that /etc/bashrc gets sourced from /etc/profile or that everything under /etc/profile.d gets sourced by both /etc/profile and /etc/bashrc. Everything sourcing everything else, multiple times, seems like a bit of an inefficient mess. And I’ve seen plenty of cases where scripts under /etc/profile.d ended up creating massively long environment variables as well because of this problem (it’s not just a problem for the PATH environment variable). And what if I place a script under /etc/profile.d that does something like a file system mount? Would I potentially end up with infinite mounts on top of each other? Would I have to wait on the mount to complete every time a bash shell gets spawned?

      What if, for efficiency’s sake, I want to spawn a bash login shell with the just the minimal login environment defined, but I don’t want to run all the start-up scripts that every installed program has dropped under the /etc directory? From the documentation, it would seem like bash –norc ought to do that, but the way everything is sourced (multiple times) from everything else, it appears that that option to the bash command is completely meaningless at this time.

      I think a much cleaner design would be to simply source ~/.bash_profile once on bash login shells (falling back to /etc/profile if that doesn’t exist). And to always source ~/.bashrc (falling back to /etc/bashrc if that doesn’t exist). ~/.bash_profile should be for stuff that should only be run once and ~/.bashrc should be stuff that should be run every time.

      Just my two cents.

      • Hello Gregory,
        Multiple sourcing is a poor practice, and there is a check in /etc/bashrc to prevent dual sourcing it but not in ~/.bashrc. I chose to present the tips as the GNU Bash manual indicates. For example, the documentation purposely shows alias’s and functions in /etc/bashrc and ~/.bashrc and this is noted in comments in the profile files /etc/profile and ~/.bash_profile as well.
        From /etc/profile …

        
        
                    # Bash login shells run only /etc/profile
                     # Bash non-login shells run only /etc/bashrc
                     # Check for double sourcing is done in /etc/bashrc

        Stephen

        • Yeah, those comments seem inaccurate at the least. If they were true, how would ~/.bash_profile and ~/.bashrc get called? I know they aren’t called from the global scripts.

          That check for double sourcing appears unreliable/bogus too. What if I run “bash –login” followed by “bash –login”? Since the only double sourcing check in done in /etc/bashrc, and since everything under /etc/profile.d is sourced from /etc/profile, all the scripts under /etc/profile.d will still get double sourced.

          I suspect there should really be a /etc/bashrc.d in addition to /etc/profile.d so that there would be a cleaner divide between the two types of scripts rather than all the stuff under /etc/profile.d getting run many many many times over every time a bash script is run somewhere.

          Again, just my two cents. There may well be some details of which I am unaware that make a cleaner divide between run-once and run-always scripts impractical.

    • The article was more about Bash than Fedora per se. I didn’t mean to give the impression that you should follow everything I typed there verbatim. In fact I would expect those interested to review the material, read the links to get more informed, then customize their system to their own needs. What I was trying to get across specifically was the order of startup, what files are or could be accessed then, and how might you do some customization to suit your workflow and use case needs.

  6. George N. White III

    In these days of projects with participants spread across multiple organizations and using different linux distros it is worth mentioning a common source of confusion when fedora users interact with debian/Ubuntu or macOS users. It is helpful to realize that users of other distros may have dash (default system shell on debian) or zsh (default user shell on recent macOS).

    • Hello, and thank you for noting there are different default shells in use by other Linux Distro’s as well as Mac’s. I had originally opened this article stating that there is a large variety of choice of shell to use even in Fedora, but the focus would be on Bash, and it’s use within the context of a Fedora system. The broader topic of different shells, and their relative benefits/drawbacks would be a rather large (amount of) content (for a magazine article) if you wanted to attempt to do the topic justice. It would likely need to be a multi-part series. Generally, as a preference, I use zsh on my Fedora system. For this article and some time leading up to it, I have been using Bash.

  7. John

    Please correct me if I’m wrong but in Wayland the ‘profile’ scripts are no longer sourced.

  8. For anyone who might be interested, I’ve found that an easy way to block a lot of the double sourcing is to add the following line to /etc/profile.d/sh.local:

    BASHRCSOURCED=Y

    The above will block /etc/bashrc from ever being run, however, so if you use it, you will need to duplicate anything in /etc/bashrc that you want in your ~/.bashrc. For me, this amounted to the following:

    umask 022
    
    shopt -s checkwinsize
    shopt -s histappend
    
    history -a
    

    You want to keep ~/.bashrc very minimal because everything in it is run every time bash is executed (without the –norc parameter).

    I’ve also tweaked my ~/.bash_profile and added a /etc/profile.d/ps1.sh to set the bash prompt for login shells. The end result of editing these four files is that now when I run just bash (or when a bash script is run), there is no chance that any of the content under /etc/profile.d will be re-evaluated. This is easily verified because spawning a non-login bash shell reveils the default bash prompt (because /etc/profile.d/ps1.sh was not sourced). Below are the four files I’ve changed in their entirety. This is just an experiment at this time, so there may be problems with this setup that I have not noticed yet.

    /etc/profile.d/sh.local

    #Add any required envvar overrides to this file, it is sourced from /etc/profile
    BASHRCSOURCED=Y
    

    /etc/profile.d/ps1.sh

    if [[ $- == *i* ]]; then
       PS1="[\$PWD]\\$ "
    fi
    

    ~/.bash_profile

    export HISTCONTROL=ignoreboth
    export HISTSIZE=5000
    export HISTFILESIZE=-1
    
    if ! [[ $PATH =~ :$HOME/bin$ ]]; then
       export PATH=$PATH:$HOME/.local/bin:$HOME/bin
    fi
    
    if [[ -f ~/.bashrc ]]; then
       . ~/.bashrc
    fi
    

    ~/.bashrc

    umask 022
    
    shopt -s checkwinsize
    shopt -s histappend
    
    history -a
    

    I’ve also set gnome-terminal to always run bash as a login shell. This makes sense because the shell that gnome-terminal starts is never the child process of another bash shell — it cannot inherit an already initialized bash environment, so it needs to be run as login shell each time.

    • Robin Meade

      Cool! Thanks for writing that up.

      I don’t find the need to set gnome-terminal to always run bash as a login shell. On my system, gnome-session is run by a bash login shell. My process table shows:

      /usr/bin/ssh-agent /bin/sh -c exec -l /bin/bash -c "/usr/bin/gnome-session"

      I do need to log out and back in for changes to my .bash_profile to take effect; that’s the only downside I see to not setting gnome-terminal to always run bash as a login shell.

      • Yeah, it looks like you have a somewhat non-standard setup there where gnome-session is a child process of a bash login shell.

        I think your best option to get around having to logout and back in in that case would be to create something like ~/.gnome-terminal that ends with “exec bash”. Then set as a custom command for gnome-terminal something like:

        /bin/bash -c “source $HOME/.gnome-terminal”

        instead of your login shell. I haven’t tested such a setup, but it should give your a third option for where you can place configuration settings that would not require you to log out and back in (and also would not get run every time bash is run).

        Just an idea,
        gb

        • Just realized that you should probably check for the existence of the file first, so maybe something more like:

          /bin/bash -c "if [[ -r $HOME/.gnome-terminal ]]; then source $HOME/.gnome-terminal; else exec /bin/bash; fi"

          And if you want to eliminate the requirement that ~/.gnome-terminal end in “exec bash”, maybe something like:

          /bin/bash -c "if [[ -r $HOME/.gnome-terminal ]]; then source $HOME/.gnome-terminal; fi; exec bash"
          • Robin Meade

            OK, thanks Gregory. I was running Gnome using X. But with Wayland, bash is still executed as a login shell when gnome-session starts. See https://gitlab.gnome.org/GNOME/gnome-session/-/blob/master/gnome-session/gnome-session.in Anyway, I’m OK with needing to log out and back into my Gnome session to pick-up any changes to environment variables that I set in my ~/.bash_profile.

            • Interesting. I too now see that gnome-session is listed as being spawned from a bash login shell. However, experiments suggest that gnome-terminal is not a child of that bash login shell. I still have to set gnome-terminal to run bash as a login shell to get the content under /etc/profile.d processed (e.g. PS1) with my setup.

              What I can make of the output of pstree seems to suggest that gnome-terminal is being spawned directly from systemd somehow (or perhaps from DBus as the article Steven linked earlier suggests).

  9. smeagol

    export HISTTIMEFORMAT=”%m/%d/%y %H:%M:%S ”

    ^^ this is what I use. Do you like it? Can it be improved upon?

Comments are Closed

The opinions expressed on this website are those of each author, not of the author's employer or of Red Hat. Fedora Magazine aspires to publish all content under a Creative Commons license but may not be able to do so in all cases. You are responsible for ensuring that you have the necessary permission to reuse any work on this site. The Fedora logo is a trademark of Red Hat, Inc. Terms and Conditions