learninfra · Linux · Networking · Kubernetes · System Design · AI Infrastructure · Exam blueprints · Drills

Environment & Dotfiles

Shell variables versus the environment, how PATH finds a program, which startup files each kind of shell reads, and why a command works for you but not under sudo, in a script or for a colleague.

An interactive Linux lesson: 21 steps, about 30 minutes, on a live simulation in your browser.

You are alice on web01, writing shipit, a small deploy helper for the shop. It reads one setting, SHOP_ENV, to decide where to deploy. Before you install it, look at where settings like that live.

SHOP_ENV=staging creates a shell variable: a name and a value held inside this one bash process. echo sees it, because $SHOP_ENV is expanded by this shell. bash -c starts a child shell, and the child prints []: it never got the variable.

What you will learn

  1. Two kinds of variable

    • A variable only this shell can see: A shell variable lives inside one shell process. No program the shell starts can see it.
    • Copied down, never up: export copies a variable into every child started afterwards. The copy flows down to children and never back up.
    • A variable for one command: VAR=value cmd changes the environment of one command. env -i starts a command with no environment at all.
  2. Finding the program

    • Break it: 126 is not 127: Exit status 127: nothing by that name was found. 126: a file was found but could not be executed.
    • The bare name: A dotfile is read once, when a shell starts. Editing it, or creating what it tests for, changes only shells started afterwards.
    • Two shipits: the first match wins: PATH is searched left to right and the first match runs. bash then remembers that location in its hash table.
  3. What a new shell reads

    • Login, interactive, neither: Login shells read the profile files, interactive non-login shells read ~/.bashrc, scripts and bash -c read nothing.
    • An alias you just added: Editing a dotfile changes nothing in shells that are already running. Start a new shell (exec bash) or source the file.
    • Break it: ~/.bash_profile wins: A login shell reads only the first of ~/.bash_profile, ~/.bash_login, ~/.profile. Creating one of the earlier names hides the later ones.
    • Drill: bring ~/.profile back
    • su and su -: half a login or a whole one: su gives you another user's identity in your current setup. su - gives you their login: their home, their dotfiles, /etc/environment.
  4. sudo, scripts and source

    • sudo shipit: sudo runs a command in a fresh environment and finds it along secure_path, not your PATH. What runs under sudo can be a different program with different settings.
    • Getting a variable through sudo: Name what crosses into sudo: sudo VAR=value cmd for one variable, sudo -E for all of them, a full path for the exact program.
    • Break it: an alias in a script: Scripts, cron and services read none of your dotfiles. Aliases, prompt settings and anything set in ~/.bashrc do not exist there.
    • source runs a file in this shell: source runs a file inside the current shell, so its cd and its variables stay. bash file runs it in a child, so they vanish.
    • A prompt that says where you are: PS1 is re-expanded before every prompt. Single quotes keep $VAR in it live; double quotes freeze today's value.
  5. Works for me, not for them

    • Break it: bash remembers a dead path: bash looks a command up in PATH once and remembers where it was. If the file moves, run hash -r or start a new shell.
    • Works for me, not for bob: To debug works-for-me, become the other user with a real login and compare: which program, which environment, which startup files, who started it.
    • Drill: give bob the setting
  6. Recap & playground

    • Cheat sheet
    • Playground