Shell login - profiles and scripts

From Helpful
Jump to: navigation, search
Linux-related notes
Linux user notes

Shell, admin, and both:

Shell - command line and bash notes · shell login - profiles and scripts · Shells and execution ·· find and xargs and parallel · screen and tmux
Linux admin - disk and filesystem · users and permissions · Debugging · security enhanced linux · health and statistics · kernel modules · YP notes · unsorted and muck
Logging and graphing - Logging · RRDtool and munin notes
Network admin - Firewalling and other packet stuff ·

Remote desktops
VNC notes
XDMCP notes

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

This is mostly about bash's behaviour, and tweaking it.

It doesn't touch much on shell programming or syntax.

Files that are sourced, and when

(See also X startup scripts)

Note The below mostly details the bash / bourne family.

Other shells, say zsh, ksh, csh, tcsh, and others, work differently enough to merit their own summary (By someone who uses them. Details welcome).


  • graphical shells often do not run login shells (verify)
which basically means you don't want to make the distinction of interactive and login yourself
in that you usually want put things you need for all your interactive shells in bashrc
  • also, assume profile gets run once per shell. bashrc also gets run on subshells (if you use them)
  • scripts aren't shells, and should explicitly source the environment they need
which often is nothing
but consider e.g. cron, batch queues, compilation (note: consider environment modules)
BASH_ENV is a nice tool for some cases
  • ssh can be an exception case, at least under the covers. But usually does what you want.

Technically: Login shell versus interactive shell

At a technical level this is about

interactive/not-interactive two separate properties, so technically there are four possibilities.

in practice you can often consider them one of three:

  • first on a tty (login+interactive)
'interactive login shell', 'login shell', 'initial login shell' usually refer to this.
those that are first on a shell, including hardware (text-mode) terminals
those specifically requested to be login, e.g. bash -l or bash -login (e.g. VNC's .Xstartup often does this)
shells implicitly created when switching users with
su - username
su username
gives a non-login shell)
sudo -i
(note: sudo's shorthand for login is -i, su's is -l. I consider that stupidly confusing.)
  • not first on a tty (non-login interactive)
shells launched by the user
graphical terminal programs invoke these by default(verify)
those specifically requested to be interactive, e.g. bash -i
su, unless you explicitly use - / -l / --login
  • script / non-interactive
aside from scripts themselves, examples are:
bash run from a shell script: that subprocess is always considered a non-interactive shell (even if it can access its tty) (verify)
commands invoked via bash -c (verify)
these do not implicitly read any configuration files (verify)
(can be login, typically is not - mostly related to ssh[1])

Footnotes to that:

  • GUI terminals tend to start interactive, not login shells
the argument seems to be when assuming you start one login shell with the display manager, you still get the "once per graphical session" behaviour (verify)
the other camp argues that a terminal window is a session, unrelated to the graphical one (also since graphical startup has its own rcfiles, e.g. xsession)
  • ssh somewhat manually imitates a local bash (and bash may be specialcased)
so usually it's exactly the same, but sometimes it needs coaxing to behave the same as local shells
  • tmux starts login shells, screen does not ( default, you can set these)
tmux's logic seems to be that new shells should more predictably pick up new config this way
  • some security-aware things like sudo and cron specifically avoid sourcing any of that


check for login shell

  • shopt
    will mention either
    login_shell on
    login_shell off
in a test, shopt -q is often nicer - it's silent and tells you in the return code
  • doing this in a portable way is a bit harder [2]

check for interactive shell

  • in bash, look for an i in the special bash variable
    , e.g.
  • in many shells, checking that a variable like PS1 also tends to work well
shopt -q login_shell   && echo 'Login' || echo 'Not login'
# or leading - in $- {{verify}}
[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'
# or
case $- in
   *i*) echo 'Interactive' ;;
     *) echo 'Not interactive' ;;

Distinctions between .bashrc and similar files


  • things that should run at most once per terminal go in profile, things that should be run in subshells should go to things like .bashrc
  • users can shove things in .bashrc
(though e.g. extending PATH is best put in your profile, because subshells will just add it again)
  • admins often want to put things in /etc, and should check exactly what the distro does
/etc/profile.d/, if it exists, is typically most convenient
  • scripts, cron, and possibly ssh can need more attention
  • a bunch of the distinctions (e.g. general profile versus bash_profile) are unimportant until people actively use shells other than bash - and most of them will know how to deal with the differences anyway.

More details:

  • profile is intended to be a sourced by login shells
    • ~/.profile
      for personal stuff (but see the next point)
    • /etc/profile
      for system stuff
      • /etc/profile.d/
        , if it exists, will be explicitly sourced from
This is added by some distros to make it a lot easier for package management to add/remove specific packages' lines
sourced once per terminal, when it's created, so not for subshells
should only contains things any /bin/sh understands (/bin/sh is often a link to bash, dash, or similar)

  • (there often isn't a shell-specific variant in /etc, basically for the "that any sh understands" reason)

  • bash_profile, and other specific-shell ones, are intended for run-once-per-terminal things that also need shell-specific syntax/features
e.g. bash looks for
and uses only the first it finds
which allows you options like
only having a .profile, shared between some shells (that are still bash-like enough to understand the syntax)
that mostly sources shared
and/or specific
(in that order)
..but frankly, try to keep this as minimal as possible - most things belong either in

  • bashrc is intended for every interactive bash shells (and gets sourced each subshell)
    • ...and by default not sourced from login shells - but most distros add a source ~/.bashrc to the relevant profile (~/.profile or ~/.bash_profile) because it's useful and often easier organization. (and some (e.g. OSX's Terminal) do not)
    • /etc/bash.bashrc
      for system stuff
    • ~/.bashrc
      are intended for interactive shells

In practice:

  • Many distros set up /etc and account skeletons (/etc/skel) where: (verify)
explicitly sources
explicitly sources
  • profile stuff (included by login shells) tends to be the most universal
  • bashrc will be there for all interactive shells
so aliases, EDITOR, prompt, etc. make sense here
  • For "add to environment" the profile/bashrc distinction matters less, because it tends to get inherited everywhere you want anyway
though PATH=$PATH:more is best placed in profile to avoid repeated adds

  • the applicable things in /etc/ will often specifically not do most of their work when they happen to be sourced from scripts.
via something like
[ -z "$PS1" ] && return
, or parts wrapped by
if [ "$PS1" ] theory you could have a specific section in there for just scripts.
It's generally not best practice, though, in part because it means that file needs more protection (e.g. avoid output unless
[[ $- == *i* ]]
. Also because:

  • scripts should never count on environment, at least not to run at all
so if you need specific environment, do it explicitly. Usually sourcing is best for your sanity
that includes PBS, MPI stuff
in some cases, a specific /etc/profile.d file might be well suited

Misc notes:

  • cron explicitly uses a restricted environment (and often runs scripts), so usually none of this applies

(which is a good idea for safety)

so explicitly include/source any env you need

  • You usually don't need to bother with login and logout rcfiles at all
  • .login
apparently the C-shell convention, practically the same as .profile
to keep things simpler, avoid unless you need it
  • .bash_login was apparently an early attempt to be more compatible with C-shell - that didn't really work out and you can ignore it

Which and when and conditions

(TODO: review and check)

 file                    used by what?            used when / notes
------------------  ------------------------  ----------------------------
/etc/profile               sh family            login shells at login
                                                  note: often excludes graphical shells

/etc/profile.d/*.sh        sh family            explicitly, from /etc/profile

~/.profile                 sh family            login shells at login 
                                                 (possibly indirectly, see e.g. bash_ptofile notes)
/etc/bashrc                                     interactive bash shell
or                           bash               often sourced from /etc/profile OR ~./bashrc
/etc/bash/bashrc                                Footnote (*1) for the case of SSH
~/.bash_profile              bash               login shells at login 
                                                Footnote (*2) on fallbacks

~/.bashrc                    bash               interactive shells
                                                often sourced from ~/.profile OR ~/.bash_profile

BASH_ENV                     bash               non-interactive (including scripts)
                                                  (note that setting it within a script is too late)


  • (*1) some distros compile bash to special-case SSH, to read bashrc even when non-interactive(verify)
  • (*2) When you have a combination of .bash_profile and .bash_login and .profile, it uses only the first in that list that it can find.
  • Graphical terminals are often non-login interactive, so don't count on them reading /etc/profile
Some setups are tweaked to do so intentionally
  • sh family shells are most of them, including sh, bash, zsh, csh, tcsh, pdksh, ksh, jsh and others (but e.g. excluding fish, wish)}}
  • each shell may also add their own files For example, bash has .bash_profile and others, tcsh has ~/.tcshrc, ksh and pdksh have ~/.kshrc, zsh uses /etc/zshrc, /etc/zprofile, /etc/zlogin, /etc/zlogout, /etc/zshenv, ~/.zprofile, ~/.zshrc, ~/.zlogin, ~/.zlogout, ~/.zshenv, and so on. The logic to them may vary
  • there are further conventions, such as
    • /etc/environment (more a config file than a shell file)
    • ~/.pam_environment (similar, named such because it's handled by PAM's pam_env plugin)

If you want to know what exactly your specific shell is doing and sourcing, you can watch it open files with something like

strace -e trace=open  bash -l -c echo  2>&1 | egrep -v '(/lib|/proc|locale)'
where the -l in this example specifically tests a login shell (-c echo just makes the new shell quit after it does nothing worth mentioning)

See also:

  • this for more bash details.
  • this for more general details.
  • this for details for other shells.

TODO: read:



It seems that this is only ever read by PAM. It reads and sets the contents in the environment, before loading your shell.

This means

  • it is useful environment setting for all shells, including exotic ones.
  • it's a config script parsed for its key=value lines, not an executed shell script.
  • This file only gets applied when authenticating (using PAM)
The next graphical login will.
A ssh to localhost will.
Running bash (-i or -l) won't.

Config files

Potentially useful fragments for your bashrc and bash_login

Note: The difference between bashrc and bash_login is that bashrc is for interactive shells (including xterms, I believe), and the second for login shells (including screen windows).

In practice you may want to put things into both, or create a script of common things that you call from both.

grep results in color

When it is not the system default, you can get grep to output colors when it is the main command (not when used in a pipe, based on autodetection), using:

export GREP_OPTIONS='--color=auto'

If you want it even in pipes you can set it to always. Can be nice e.g. for less, but not everything you pipe into understands the escape codes. Arguably always is best used in aliases, not as a default.

You can change the colors it uses using GREP_COLORS (or the deprecated GREP_COLOR), in which you can set the color of various different parts of the grep results; see the man page.

History stuff

Searching the history

CtrlR is usually what you want (searches from most recent to older)

If you want another match, press CtrlR again.

Note that if you press enter you immediately execute the command; you often want to press an arrow key or Tab instead so that you can edit it first.

Cleaner history

You can specify things that should not be logged, which can be handy when arrow-upping for recent interesting commands as well as using Ctrl-R to search it.


export HISTIGNORE="&:cd:mc:top:htop:exit:mutt:ls:[bf]g *|[bf]g"

In this example:

  • The
    means/matches 'the previous line', which avoids adjacent duplicates from being logged.
  • most commands here are matched exactly, i.e. when you add arguments they are still saved.
  • ...whereas bg and fg are explicitly ignored for all cases.


  • is a colon-sperated list of options that further controls how and what to save
  • ignoreboth
    shorthand for ignorespace:ignoredups
  • ignorespace
    Lines that start with a space are not saved
  • ignoredups
    causes lines matching the previous history entry to not be saved. A value of
  • erasedups
    previous lines matching current line are removed from history before the current line is saved.

Longer history


  • the amount of recent history entries that a bash process keeps
  • default: 500
  • if unset / empty string, it has no limit


  • the amount of a shell's own history, in lines, to write to HISTFILE (when the running shell exits)
  • default: value of HISTSIZE, unless set
  • unsetting it means 'don't truncate after saving' (you may want to set up log rotation)
  • 0 means truncate to empty file


  • the file that the the running shell writes its own history to (when it exits)
  • note: unsetting means 'don't save this shell's history'
  • default: ~/.bash_history

histappend (shell option) - append to central history instead of replacing it

The basic behaviour:

  • On startup, bash loads HISTFILE
apparently the most recent HISTFILESIZE lines (verify)
  • each line is saved to in-memory history (adhering to HISTCONTROL and HISTIGNORE)
  • When it exists, bash
    • writes its own in-memory history to HISTFILE (overwrite/append, according to histappend)
    • then truncates that file to have at most HISTFILESIZE lines (unless HISTFILESIZE is not set)

You can force bash to write to and update from HISTFILE using history -a; history -n

(I doubt there is file locking going on, so PROMPT_COMMAND=’history -a; history -n’ might lead to occasional clobbering(verify))

Note on export, setenv, etc

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

In bash, export replaces a variable in the current environment. Other shells may use setenv or set.

#usually written as:
export PATH=$PATH:/bla/bla
#which is equivalent to a local set followed by an explicit export
export PATH

Export means that it will inherit (get copied) to subenvironments. (I remember there being some pesky details. I should check up on them.)

Useful things to export include:

  • path to look for things to execute (PATH)
  • almost everything in profile/bashrc files, e.g.
program defaults (e.g. GREP_COLOR=auto, LESS="-aXz-5j3", etc.)
programs' home directories (eg. GMT_HOME, GRASS_HOME, JDK_HOME)
an added directory to have private libraries (LD_LIBRARY_PATH)
compiler options (CFLAGS, CPPFLAGS, LDFLAGS for adding additional include and library paths when you want to compile things)

Setting PATH

Fairly simple. To add /etc/local/bin/myprogrambins/ and your $HOME/bin to the PATH, for example, do:

export PATH=$PATH:/etc/local/bin/myprogrambins/:$HOME/bin

This preserves the current path and appends the new one. It is a safe default to add to the end of this list in case of name collisions; the first match in the list will be used. This can be exploited for good (perhaps sneaking in colorgcc as default gcc behaviour) and evil (many other cases).

It is not advised to do:

export PATH=$PATH:.

...just to get windows/DOS-like behaviour in that you can run executables from the current directory without having to append a ./. You may get randomly strange directory-dependent behaviour. Doing this ranges from useful-when-careful to annoying to a potential security problem.

Terminal type

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

There have been various terminals over the years, with varying capabilities. Consider

  • terminal hardware, those heavy plastic things and
  • terminal software, which includes
    • remote logins (e.g. SSH)
    • local/remote graphical logins (xterm, rxvt, gnome-terminal, konsole, OSX terminal, etc.)
    • terminal hosters/proxies (e.g. screen, tmux, hurd)
    • specific terminal software (consider e.g. cygwin, windows telnet)

Everything worth anything has VT100 compatibility, as it became the de-facto basic set of features.

Most things used now have more to add, but may do it in very specific ways. In pratice, this means we need a terminal to tell us what it is, whether they support a particular feature (say, color, scrolling back, drawing), and how to use it with them.

In *nix, the client advertises most of its capabilities by setting a name in the TERM environment variable. A name maps to a set of features, so the commonly used names don't really mention what a terminal is, but what it supports (which also means you should only set a TERM you the terminal emulator actually supports). (on *nices this is handled via termcap).

Some TERMs:

  • vt100 for the most basic vt100
most things are capable of more
  • linux seems typical for text-mode shells
roughly "vt220 and colors"(verify)
  • xterm is a basic shell under X
roughly "vt220 and colors"(verify)

  • rxvt is a specific X shell with a few more capabilities than xterm
also used by similar graphical shells.
There are different sets for gnome-terminal, konsole, and others, though they may also just set xterm-256color or such. You rarely deal with these directly though.
  • screen is what each term in a screen gets. Seems to be fairly basic VT100, plus some extras?
You can configure screen to report itself as something else, e.g. xterm-color.
screen itself looks for a termcap entry called screen.$TERM

  • putty (basically VT102 plus a few spected features?)
  • vt100-putty (or putty-vt100?)
  • putty-256color
  • konsole

For many there are variations, like having/lacking colors.

There are many hardware-specific entries that you'll probably never set/use directly.

Look at your /etc/termcap

Some pragmatics:

  • If F1..F12, numpad keys, Backspace, Delete, Home, End, or such don't work (produce garbage), you probably need to tweak TERM
  • things should test for prefixes, because it's now common to do things like:
  • PuTTY defaults to xterm
If shelling to linux, you may be better off using linux (I had troubles with various keys that were fixed this way)
putty may work even better (verify)
  • if you tweak things in login scripts, TERM tests should often be 'starts with', not 'is', because variations tend to be -tacked-on

You can change program behaviour based on TERM values. For example:

case $TERM in
       PS1="[fancy term] \u on \h \$ "
       alias ls='ls --color=auto '
       PS1="[other term] \u on \h \$ "


  • applications may also look at TERM to choose what to do, in particular if they do colors or fancy drawing.

Some applications may work better when forced/restricted to behave according to a specific TERM. For example,

alias mc='TERM=xterm mc'

...which is also how I discovered (without logging out and in a bunch) that mc seems to work better with putty than linux.

setting your prompt

(See also e.g. [3])

You usually see what is set in PS1, and you see PS2 if you have multi-line strings and the sort. You're not likely to ever see PS3 or PS4.

It looks like the internal prompt variables (user, host, working directory, date, time, and things like \$; see PROMPTING in man bash) and escapes are evaluated after each shell command you give, while not everything is, and possibly not under all conditions. See the PROMPT_COMMAND for a workaround.

Funky things

Note on using/printing escapes

You can use escape sequences to give ANSI color commands, set the xterm title, move/save/restore the cursor, command a wrapping screen, and other such things.

Note on \[ and \]

Bash and some other shells (which?(verify)) treat
as "from here to a
I shall interpret escapes"
, so that's where you usually put them.


  • These ranges are not counted as printable characters (shouldn't be), which matters in line wrapping behaving sensibly.
  • When you take take values from somewhere to be displayed as part of the prompt (expansion of hostname, cwd, etc.), you want values outside such a range, both for correct wrapping and to avoid strange interactions. If you want to do something to such values, add a sequence before and one after.
  • There are escape sequences that contain
    and those that contain
    . Yes indeed, that's bloody confusing :)

Note on \e versus \033

is a shell-specific (probably bash-specific (verify)) way of saying "I want a literal ESCape control character here." A more compatible and slightly harder to read alternative is
(ESC is 033 in octal, 1B in hex, 27 in decimal) Similarly,
is an alternative to

If you want to experiment with escapes, you may want to know that you can force echo to interpret escapes by using -e, and sometimes -n, 'don't append newline' ). Note however that echo doesn't know \[ and \].

Funky things: Setting the shell's title

ESC, ], 0, ;, titlestring, BEL

The text inside is interpreted by teminals that understand titles, such as most graphical terminals.

For example, you could prepend this to your real prompt:

for something like

Funky things: setting the screen window's title

ESC, k, titlestring, ESC, \

This is the title you see when you list the screens (using Contol-a "), and can set using Control-A Shift-A.

For a prompt, and with escaping inside a "-quoted string, this works out to, for example:

\[\033k \u, in \w \033\\\]

When you also want to make screen change the X window(-as-in-graphical-window) title according to which screen you are in, you want to tell screen to use its hardline tricks, via .screenrc. See the basic example at screen.


Note that since some older and barer terms may respond badly you should put fancy stuff on a condition, by using something like the following in your bash startup:

case $TERM in
      PS1="\[\033]0;\u on \H\007\]\[\033k\]\w\[\033\\\\\]\u@\H:\[\033[1;37m\]\w\[\033[37m\] \$ "
      PS1="\[\033]0;\u on \H, in \w\007\]\u@\H:\[\033[1;37m\]\w\[\033[37m\] \$ "
      # avoid funky things when you are not sure about the capabilities:
      PS1="\u@\H:\w \$ "

You may want \w (working directory) if you come from windows/DOS or perhaps regardless, though you get used to the non-clutter and remembering where you are. I just decided this format may be useful as it mimics the format scp uses, so it could be useful for copying things about.

If you want to set both screen's window titles and set the window window title, you could e.g.

  • 'user on host' in the window title via PS1
  • set the working directory as the screen window title,
  • use screen's hardstatus feature to prepend <something like>'[0: /var]'</tt> (that is, '[screenwindownum: screenwindowtitle]' ) to the window title.

The result is that screen shows "/var/www" and the whole window shows "[0: /var/www] root on sparrow"

You could have something like:

Extra evaluation

Setting PROMPT_COMMAND allows you to evaluate/execute something before every command -- though note that this is potentially slow.

For example, you could do
PROMPT_COMMAND="echo -n 'Groups: '; id -G -n"

A common use is to change PS1 every prompt, for example...

  • showing the current directory's size
  • make the prompt/title change with variables that aren't part of the \u-style thing bash itself replaces
  • showing the last command's return code ($? in bash)
  • using whoami to show things in red if you're root (though it's simpler to have root's profile/bashrc could just set this explicitly)

You can set the PROMPT_COMMAND variable to

  • a string to evaluate, including the path to a script
  • a bash function, so you can write potentially involved code, such as the following excessive example:
promptFunc() { 
  case $TERM in
      PS1="\[\033[0;32m\][\D{%a, %H:%M}] \[\033[1;34m\]\u@\H\[\033[0m\]:\[\033[1;37m\]\w\[\033[0m\] " ;; 
      PS1="[\A] \u@\H:\w " ;;
  # size of immediate entries (i.e. recursive)
  DIRSIZE=$(ls -l | awk '/^[dlpscb\-][rsS\-][wsS\-][xtT\-]/{totalsize+=$5} END{printf("%d",totalsize)}');
  if [ $DIRSIZE -ge 1073741824 ]; then
    if [ $DIRSIZE -ge 1048576 ]; then
      if [ $DIRSIZE -ge 1024 ]; then
  PS1="${PS1}($DIRSIZE) "
  #append a red [root] if we are root
  if [ `whoami` == "root" ]; then 
    PS1="$PS1\[\033[31m\][root]\[\033[0m\] "
  PS1="${PS1}\$\[\033[0m\] "


  • the fact that ls -l will happen all the time will make changing to directories with very many entries rather sluggish.
  • it might be more robust to do the dirsize based on find ./* -prune -type f -printf "%s\n"

Colored text

See Escape_sequence_notes#ANSI_color

See also

setting DISPLAY

Note that it is easy to mess with other logic to this effect, from the system or from ssh -X.

keybinds and convenience settings


aliases, functions

See some examples at Command_line_intro,_some_common_utilities#Shell_aliases_and_functions

Arguably some should be system-wide scripts.

Colored ls

listens to
  • environment variable LS_OPTIONS for whether/when to use colors, probably export LS_OPTIONS='--color=auto'
  • environment variable LS_COLOR for which colors to use

You may prefer to use dircolors for easier debugging of the contents of LS_COLOR. dircolors reads its own configuration file and produces the sh-style/csh-style environment set line you'ld want in your profile.

When fiddling with dircolors and you want to set it within the current shell, you can do something like:
eval `dircolors -b /etc/dircolors`
(the -b is for bash, -c is for csh. This is purely about how to set the environment variable)

There will often be some logic in the system-wide bashrc (or comparable for other shells) that calls dircolors and evaluates its output. It may prefer


and fall back to: (verify)


You can find defaults and examples in various places.

(See also LS_OPTIONS for other ls formatting options. I like -p)


Potentially useful scripting lines

See also Command_line_and_bash_notes#Shell_conditionals_and_scripting for more general sh/bash syntax notes

"stop now if we don't have this command"

tl;dr you want something like:

command -v pidof >/dev/null || { echo "cannot find pidof, aborting."; exit 1; }

While which seems the obvious choice, it is not as well behaved as you think.

There are other things that effectively do the same, that are shell builtins (so also avoid a process). If you want to support at least bash and <tt>sh, then command -v seems best behaved (defined by POSIX).

(Thanks to this stackoverflow summary)

error/default value if not specified

See Command_line_and_bash_notes#Error_if_not_set

Other shell tricks

special home directory files


Various mail daemons can be configured to look for this file when email is delivered to an account. If the file exists, the contents are treated as the mailboxes and/or email addresses to deliver the mail for.

It is faily common to forward(-and-delete) to a single remote email address, though you can also leave a copy in the account, etc.

See also:


This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

You can suppress the login banner by placing a file named .hushlogin in your home directory.

This seems a convention followed by various motd style things, but not by everything.

Other bash notes

Special variables

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)
$0	           script name
$1, $2, $3, etc.   first argument, second, third, etc. You may prefer ${1}, ${2}, etc.
$*                 List of all variables entered at the command line ($1 onwards; no $0)
$@                 similar to $* - differs how?  Peferable over $* ?
$#                 number of command line arguments
$$                 PID of the current shell
$!                 PID of the most recent (background?) command
$?                 Exit code of the last (foreground/pipe) command 
$-                 current shell options, see 

You may also care about Command_line_and_bash_notes#Conditional_replacement

exit from sourced file

e.g. if [ -n "___SOFTSETONCE" ]; then return; fi