試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

bashの設定

  1. bashの設定ファイル
  2. 「set -o nounset」の注意点(gdmでログインできなくなる例)

bashの設定ファイル

(2007/6/26)初めに書いたときの内容とはかなり違う部分が出てきてしまったが、使い勝手は良くなっている。
ファイル名: ~/.bashrc

## ヒストリに関する変数
HISTSIZE=999999         # 保持数 0で無効
HISTFILESIZE=99999      # ファイルへの記録数 0で無効
HISTCONTROL=ignoreboth  # スペースorタブの開始行、前と重複する行は記録しない

## 色に関するコード(全て太字)
COLOR_DEFAULT='\e[0m'
COLOR_BLACK='\e[1;30m'
COLOR_RED='\e[1;31m'
COLOR_GREEN='\e[1;32m'
COLOR_YELLOW='\e[1;33m'
COLOR_BLUE='\e[1;34m'
COLOR_MAGENTA='\e[1;35m'
COLOR_CYAN='\e[1;36m'
COLOR_WHITE='\e[1;37m'

## プロンプト
  _PS1_1="${COLOR_MAGENTA}\d \
${COLOR_CYAN}\t \
${COLOR_YELLOW}\u \
${COLOR_GREEN}\w "
  _PS1_2="${COLOR_DEFAULT}\n\\$ "

## SSH接続時には情報を追加
if [ -n "${SSH_CONNECTION}" ]; then
#  _PS1_SSH="${COLOR_RED}(SSH)"
  _PS1_SSH="${COLOR_RED}$(echo ${SSH_CONNECTION} | awk -F\  '{printf "SSH("$1")"}')"
#  _PS1_SSH="${COLOR_RED}$(echo ${SSH_CONNECTION} | awk -F\  '{printf $1 "=>" $3}')"
fi
PS1=${_PS1_1}${_PS1_SSH+${_PS1_SSH}}${_PS1_2}

## エイリアス(これは例なので好みで編集)
alias pathlist='echo -e ${PATH//:/\\n}' # PATHのリスト表示
alias rm='rm -i'   # 削除確認
alias mv='mv -i'   # 上書き確認
alias cp='cp -i'   # 上書き確認
alias lh='ls -lh'  # ファイルサイズを見やすく表示
alias la='ls -A'   # 「.」と「..」以外の隠しファイル・ディレクトリも表示
alias ka='killall' # 短縮

alias s=sudo
## 端末のタイトル
case ${TERM} in
  xterm*|rxvt*|Eterm|aterm|kterm|mlterm|gnome*)
    PROMPT_COMMAND='\
echo -ne "\e]0;${PWD/${HOME}/~} ${USER}@${HOSTNAME%%.*}\007"'
    ;;
  screen*)
    PROMPT_COMMAND='\
echo -ne "\ek\e\\"; echo -ne "\e_${PWD/${HOME}/~} ${USER}@${HOSTNAME%%.*}\e\\"'
    unalias s
    # 使用法「t [command] [args...]」2つまで引数を含めてscreenのタイトルに反映
    function t ()
    {
      echo -ne "\ek$1${2+ $2}${3+ $3}\e\\"
      "$@"
    }
    # tと同様・sudoの短縮も兼ねる
    function s ()
    {
      echo -ne "\eks:$1${2+ $2}${3+ $3}\e\\"
      sudo "$@"
    }
    ;;
esac

## 設定(全てではないのでマニュアルを参照)
set -o notify          # バックグラウンドのジョブが終了したらその時点で通知
set -o noclobber       # リダイレクト(>, >&, <>)で既存ファイルを上書きしない
# set -o ignoreeof       # Ctrl+dを続けて10回までは押しても終了しない
# set -o vi              # viスタイルのコマンド行操作(デフォルトはset -o emacs)
# set -o nounset         # 未定義の変数を参照するとエラーを表示
shopt -s cdspell       # directory移動時の小さなtypoを修正
shopt -s checkhash     # ハッシュ表にあるコマンドについて実際に存在するかを確認
shopt -s checkwinsize  # 端末のウィンドウサイズを${COLUMNS}と${LINES}に反映
                       # 手元の環境ではデフォルト
shopt -s cmdhist       # 複数行のコマンドの全ての行を1つの履歴エントリに保存
# shopt -s extglob       # 拡張パターンマッチングを使用
shopt -s histappend    # 履歴を上書きせず追加のみ行う(手元の環境ではデフォルト)
shopt -s no_empty_cmd_completion # 入力が空の状態では補完・PATH検索をしない
shopt -s nocaseglob    # 「*」などのパス名展開で大文字小文字を区別しない
unset MAILCHECK        # メールチェックはしない

## 必要に応じてメッセージを表示(不要なら消して可)
echo -e "\
GNU Bash version ${COLOR_RED}${BASH_VERSION}${COLOR_DEFAULT}\
 on ${COLOR_YELLOW}${HOSTNAME}${COLOR_DEFAULT}\
 (${COLOR_MAGENTA}${MACHTYPE}${COLOR_DEFAULT})
"

## 使用しない変数を破棄
unset COLOR_DEFAULT COLOR_RED COLOR_GREEN COLOR_YALLOW COLOR_BLUE\
 COLOR_MAGENTA COLOR_CYAN COLOR_WHITE COLOR_BLACK _PS1_1 _PS1_2 _PS1_SSH

まとめて貼り付けたが、コメントで書いた説明のとおり。

  • プロンプトの項目は人それぞれなので、マニュアルを参照。例では、日付*1(マゼンタ)・24h表示の時刻(シアン)・ユーザ名(黄)・現在地(緑)の後、改行して$(rootなら#)を表示している。
  • プロンプトの最後の「\$」の直前に改行を入れると、コマンド行が広く使えて便利。
  • 色のコードの記述はプロンプト用とecho表示用と別のものを使う必要がある。共用しようとするとどちらかで不具合が出る。不具合がなくなったので訂正
  • 細い字を表示する場合は色のコードの「[1;」の部分を「[0;」に置き換える。が、目立たないのでおすすめはしない。
  • SSHでログインしたときには変数${SSH_CONNECTION}がセットされるので、判別と、プロンプト表示の中で使用している。

「set -o nounset」の注意点(gdmでログインできなくなる例)

GNU/LinuxのOSの中には、シェルスクリプトが使われている部分が結構あり、シェルにはbashが使用される*2ことが多いため、そのスクリプトによっては、未定義変数の参照をしている部分があることにより処理が止まってしまうことがある。*3手元の環境では、gdm*4によるログインで以下のようにエラーを吐いてログインできなくなった。
ファイル名: ~/.xsession-errors

/etc/X11/gdm/PreSession/Default: Registering your session with wtmp and utmp
/etc/X11/gdm/PreSession/Default: running: /usr/bin/sessreg -a -w /var/log/wtmp -u /var/run/utmp -x "/var/gdm/:0.Xservers" -h "" -l ":0" "(ユーザ名)"
/etc/X11/gdm/Xsession: Beginning session setup...
(bash開始時にメッセージを出力する場合、ここに表示される)

/etc/X11/gdm/Xsession: line 121: XKB_IN_USE: unbound variable

/etc/X11/gdm/Xsessionというスクリプトの中では、[ホームディレクトリ]/.xprofile[ホームディレクトリ]/.profileを参照しているため、そのファイルの中で未定義の変数を定義済みにしておくことで回避できる。
ファイル名: ~/.xprofile

XKB_IN_USE=
GDM_LANG=
DBUS_SESSION_BUS_ADDRESS=
SSH_AUTH_SOCK=

この問題の場合はこれで回避できたが、他のところで「unbound variable」による停止が起きた場合、スクリプトの中に直接「変数名=」と書いて修正する必要が出るかもしれない。
「set -o nounset」がトラブルの原因になりうることが判明したため、上に書いた.bashrcの中ではコメントアウトしておいた。
(2007/6/11)黒のカラーコードを修正
(2007/6/12)カラーコードの変数名を修正
(2007/6/14)「set -o unset」について追加
(2007/6/25)プロンプトの「\\$」と色のコードを修正・GNU screenで実行中コマンド名をタイトルにするためのコードを追加・SSH接続時の表示を修正など
(2007/6/26)GNU screenに渡すタイトルの形式を修正・不要な変数を削除・screenで3つまで引数を含めて実行コマンド名をタイトルに反映させる関数t,sを追加・エイリアス「s」の設定を調整など
(2007/6/27)linux端末上のscreenで${TERM}が「screen.linux」となるためcase文を微調整・SSH表示の処理を改良・sの定義を調整
(2009/11/2)履歴の保持/保存数に関する設定と記述を修正
(2015/1/12)manページのリンク先を修正

参考URL:

*1:日付の書式を細かく編集したい場合、「\d」の代わりに、dateコマンドを使用して「$(date +'%Y/%m/%d(%a)')」などとする。この中の書式はstrftime(3)のマニュアルを参照。なお、dateコマンドはプロンプト決定時の1度だけしか呼ばれないので、日付が変わっても表示が変わらないことに注意

*2:/bin/sh -> /bin/bashとリンクが張られている

*3:gdmのパッケージ作成側の問題

*4:gdmのバージョンは2.16.4