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).


tl;dr:

  • yes, this is a bit of a pain
  • scripts should explicitly source the environment they need
which often is nothing
but may be some from e.g. cron, and more from e.g. batch queues and compilation
BASH_ENV is a nice tool for some cases
  • graphical shells often do not run login shells (verify)
so put things you need for all your interactive shells in bashrc
  • profile gets run once per shell, bashrc also gets run on subshells (if you use them)
  • ssh can be a funny one, at least under the covers. But usually does what you want.


But first: Login shell versus interactive shell

At a technical level this is about

login/not-login
interactive/not-interactive

...as 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.
includes
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)
includes
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
examples are:
A shell running 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 be 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)
but many argue that a terminal window is a session (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
  • tmux starts login shells, and screen does not (but you can set that)
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


Checking

check for login shell

  • shopt
    will mention either
    login_shell on
    or
    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' ;;
esac

Distinctions between .bashrc and similar files

tl;dr:

  • most users can shove things in .bashrc
  • admins should check exactly what the distro does
though can generally put stuff in /etc/profile.d/something
  • 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 that do know will how to deal with differences.



More details:

  • profile is intended to be a sourced by login shells
once per terminal when it's created, and not for subshells
and should only contain things any /bin/sh understands (/bin/sh is often a link to bash, dash, or similar)
    • ~/.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
        /etc/profile
This exists to make it easier for package management to identify and add/remove their lines, because


  • bash_profile, and other specific-shell ones, are intended for profile stuff that need shell-specific syntax/features
bash looks for
~/.bash_profile
,
~/.bash_login
,
~/.profile
and uses only the first it finds
which allows you the options of
only having a shared .profile
having
~/.bash_profile
that mostly just sources
.profile
and
.bashrc
(in that order)
to keep things simpler, keep this minimal - most things belong either in
.profile
or
.bashrc


  • bashrc is intended for every interactive bash shells (and gets run each subshell)
    • /etc/bash.bashrc
      for system stuff
    • ~/.bashrc
      are intended for interactive shells


In practice:

  • Many distros set up /etc and account skeletons (/etc/skel) so that: (verify)
/etc/profile
OR
~/.bashrc
explicitly sources
/etc/bashrc
~/.profile
OR
~/.bash_profile
explicitly sources
~/.bashrc
  • 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" ]
...in 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)


Notes:

  • (*1) some distros compile bash to special-case SSH, to read bashrc even when non-interactive(verify)
https://superuser.com/questions/789448/choosing-between-bashrc-profile-bash-profile-etc
  • (*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:

Non-bash

/etc/environment

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.

Example:

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.


Also, HISTCONTROL

  • 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

HISTSIZE

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

HISTFILESIZE

  • 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


HISTFILE

  • 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
PATH=$PATH:/bla/bla
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:
xterm+88color
xterm-88color
xterm+256color
xterm-256color
putty-256color
screen-256color
  • 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
    putty*|screen*|xterm*|rxvt*)
       PS1="[fancy term] \u on \h \$ "
       alias ls='ls --color=auto '
       ;;
    *)
       PS1="[other term] \u on \h \$ "
       ;;
 esac

Notes:

  • 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.

Notes:

  • 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

\e
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
\033
(ESC is 033 in octal, 1B in hex, 27 in decimal) Similarly,
\a
is an alternative to
\007
(BEL).


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:

"[\033]0;\u@\H:\w\007\]"
for something like
root@example.com:/var

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.

Example

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
   screen*)
      PS1="\[\033]0;\u on \H\007\]\[\033k\]\w\[\033\\\\\]\u@\H:\[\033[1;37m\]\w\[\033[37m\] \$ "
      ;;
   xterm*|rxvt*)
      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 \$ "
      ;;
esac

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
    xterm*|rxvt*|screen*) 
      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 " ;;
  esac
 
  # 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
     let DIRSIZE=$DIRSIZE/1073741824;DIRSIZE="${DIRSIZE}GB"
  else 
    if [ $DIRSIZE -ge 1048576 ]; then
      let DIRSIZE=$DIRSIZE/1048576;DIRSIZE="${DIRSIZE}MB"
    else 
      if [ $DIRSIZE -ge 1024 ]; then
         let DIRSIZE=$DIRSIZE/1024;DIRSIZE="${DIRSIZE}KB"
      else
         DIRSIZE="${DIRSIZE}B"
      fi
    fi
  fi
  PS1="${PS1}($DIRSIZE) "
 
  #append a red [root] if we are root
  if [ `whoami` == "root" ]; then 
    PS1="$PS1\[\033[31m\][root]\[\033[0m\] "
  fi
 
  PS1="${PS1}\$\[\033[0m\] "
}
PROMPT_COMMAND=promptFunc

Notes:

  • 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

ESC, [, colorcode, m.

You will often see ESC as either

hex:
\x1b
octal:
\033


Some of the more interesting and better-supported codes (search for Select Graphic Rendition)

  • specify multiple codes at once, separated by ;
  • prepend 3 to a color number: set foreground
  • prepend 4 to a color number: set background
  • 1: bright foreground color
  • 0 clears to default colors/no bright/underline(verify)
useful to start a sequence, because by default you only change the current state
also useful in itself, e.g. to stick at the end of a colored prompt
  • 4: set underline
  • selective clearing:
39 default foreground color
49 default foreground color
22 clears bold
24 clears underline


Color numbers:

  • 0 black (bright black is how you get dark gray),
  • 1 red
  • 2 green
  • 3 yellow (non-bright yellow is brown or orange on some schemes),
  • 4 blue
  • 5 magenta
  • 6 cyan
  • 7 light grey (bright light grey is how you get 'real' white)


Some examples:

  • 35
    sets the foreground to magenta
  • 37;44
    is grey on blue
  • 1;37;44
    is white on blue
  • 1;33;45
    is bright yellow on magenta
  • 0;35
    clears foreground and background flags and colors, then sets the foreground to magenta
  • 0;1;35
    same but with bright magenta
  • 0;1;4;35
    same but also underlined
  • 1;47;30
    is grey (bright black) on white

To play around in a prompt, try something like:

printf "\x1b[0;1;33;45mtest\x1b[0m\n"


256-color

Set with

38;5;fgcolor
48;5;bgcolor

For example, to test support you could do:

for i in {0..255} ; do
    printf "\x1b[38;5;${i}mcolour${i}\x1b[0m\n"
done

The colors can be summarized

0x00-0x07:  standard colors       (as in ESC [ 30–37 m)
0x08-0x0F:  high intensity colors (as in ESC [ 90–97 m)
0x10-0xE7:  6 × 6 × 6 = 216 colors: 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
0xE8-0xFF:  grayscale from black to white in 24 steps


Truecolor

A bunch of terms (xterm, konsole, libvte derived including gnome's) will also allow truecolor: 8-bits-per-channel RGB foreground and background:

38;2;red;green;blue
48;2;red;green;blue

e.g.

printf "\x1b[38;2;200;200;244test\x1b[0m\n"


See also

setting DISPLAY

http://www.tldp.org/LDP/abs/html/sample-bashrc.html

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

keybinds and convenience settings

http://uzix.org/bashrc.html

http://www.tldp.org/LDP/abs/html/sample-bashrc.html

shopt


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

GNU
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

~/.dircolors

and fall back to: (verify)

/etc/dircolors
/etc/DIR_COLORS

You can find defaults and examples in various places.


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

Unsorted

http://www.faqs.org/docs/abs/HTML/files.html

http://www.mcs.vuw.ac.nz/technical/TechNotes/tn105/tn105-bashrc.html

http://aplawrence.com/Detective/shbash.html


http://aplawrence.com/Forum/dhart1.html

http://dev.gentoo.org/~ciaranm/configs/bashrc.html

http://davekaufman.net/node/246

http://www.ats.ucla.edu/at/beowulf/getting_started/user.bashrc.htm

http://overtone.org/articles/bashrc.php

http://www.chpc.utah.edu/docs/manuals/user_guides/arches/code/chpc.bashrc~

http://www.cs.swarthmore.edu/help/UU3/bashrc.html

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

.forward

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:


.hushlogin

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 logic, but not by everything.



Check whether program is already running

If you're checking for a copy of yourself:

  • if you've set up as a service, [Systemd#Service_management use its status]


  • the more robust way is to actually communicate it
e.g.
run a very basic socket on a predetermined that mainly just answers yes or no.
use a pidfile
  • less robust/portable
pidof `myname` (caveats around process naming)
inspect ps output (may vary over time / between systems)
inspect /proc (may vary over time)


  • if you're graphical, you can use DBus

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


You may also care about Command_line_and_bash_notes#Conditional_replacement

exit from sourced file

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