インストール - Bash

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

Bashは、GNUプロジェクトのシェル(Bourne Again SHell)である。
Kornシェル(ksh)やCシェル(csh)の便利な機能を取り入れたsh互換のシェルである。

IEEE POSIX P1003.2 / ISO 9945.2 Shell and Tools規格に準拠したシェルであり、プログラミングと対話的な使用の両方において、shよりも機能的に向上している。
また、ほとんどのshスクリプトはBashでそのまま実行することができる。

Bashが提供する主な機能を、以下に示す。

  • コマンドラインの編集。
  • コマンド履歴のサイズの変更。
  • ジョブの制御。
  • シェル関数とエイリアス機能。
  • サイズ無制限のインデックス付き配列。
  • 2から64までの任意の基数の整数演算。



Bashのインストール

パッケージ管理システムからインストール

パッケージ管理システムからBashをインストールする。

# RHEL
sudo dnf install bash

# SUSE
sudo zypper install bash

# Raspberry Pi
sudo apt install bash


ソースコードからインストール

Bashのビルドに必要な依存関係のライブラリをインストールする。

# RHEL
sudo dnf install ncurses-devel

# SUSE
sudo zypper install ncurses-devel

# Raspberry Pi
sudo apt install libncurses-dev


Bashの公式Webサイトから、Bashのソースコードをダウンロードする。

tar xf bash-<バージョン名>.tar.xz
cd bash-<バージョン名>


次に、Bashをビルドおよびインストールする。

mkdir build && cd build

../configure --prefix=<Bashのインストールディレクトリ> \
--with-installed-readline --with-included-gettext --enable-array-variables --enable-multibyte \
--enable-job-control --enable-debugger --enable-brace-expansion --enable-arith-for-command \
--enable-history --enable-progcomp --enable-alias --enable-help-builtin

make -j $(nproc)
make install



Bashの使用

Bashを利用可能なシェル一覧に追加する。
ここに追加することで、chshコマンドでシェルの変更が可能となる。

echo "/<Bashのインストールディレクトリ>/bin/bash" | sudo tee -a /etc/shells


次に、ユーザのシェルを変更する。(コマンドを実行するとパスワードの入力が必要となる)

chsh -s /<Bashのインストールディレクトリ>/bin/bash


再ログインまたはPCを再起動する。


コマンドの履歴を保存しない

まず、~/.bash_historyファイルを削除する。

rm -rf ~/.bash_history


次に、メモリ上に残っているコマンド履歴を削除する。

history -c


~/.bashrcファイルに以下に示す設定を追記する。

vi ~/.bashrc


export HISTFILESIZE=0
export HISTSIZE=0
unset  HISTFILE


設定を反映させるため、再ログインまたはPCを再起動する。


Bashの設定例

~/.bashrcファイルを作成して、以下のような設定を記述する。

 # ~/.bashrcファイル
 
 # Ctrl+Dでシェルを終了しない
 set -o ignoreeof
 
 # 既存のファイルをリダイレクトで上書きしない
 set -o noclobber
 
 # ディレクトリ名だけで実行する時、cdコマンドの引数で指定したものとして実行する
 shopt -s autocd
 
  # コマンドの重複を履歴に残さない
 export HISTCONTROL=ignoredups
 
 # 空白から始めたコマンドを無視
 export HISTCONTROL=ignorespace
  
 # コマンド履歴に残さないコマンド群
 HISTTIMEFORMAT='%Y%m%d %T   ';
 export HISTTIMEFORMAT
 
 # エイリアスの設定
 alias cd='cd -P'
 alias rm='rm -i'
 alias cp='cp -i'
 alias mv='mv -iv'
 alias ls='ls -hlF --color=auto'
 alias cat='cat -n'
 alias less='less -n'
 alias clear='clear && echo -en "\e[3J"'
 alias en='LANG=C LANGUAGE=C LC_ALL=C'
 alias lgrep='ls -ahlF | grep'
 alias igrep='sudo zypper search -i --detail'
 alias repoclean='sudo zypper clean -a && sudo zypper --gpg-auto-import-keys refresh && sudo zypper refresh'
 alias nano='nano -lmS'
 alias snano='sudo nano -lmS'
 alias skate='kdesu /usr/bin/kate'
 alias startnw=' sudo systemctl stop wickedd wicked; sudo systemctl start NetworkManager'
 alias startwicked=' sudo systemctl stop NetworkManager; sudo systemctl start wickedd wicked'
 alias kde=' echo <パスワード> | sudo -S systemctl restart graphical.target'
 alias gnome=' echo <パスワード> | sudo -S systemctl restart graphical.target'
 alias udesktop='update-desktop-database $HOME/.local/share/applications'
 alias uoff='dbus-send --print-reply=literal --system --dest=org.freedesktop.login1 /org/freedesktop/login1 "org.freedesktop.login1.Manager.PowerOff" boolean:true'  # シャットダウン
 alias ureboot='dbus-send --print-reply=literal --system --dest=org.freedesktop.login1 /org/freedesktop/login1 "org.freedesktop.login1.Manager.Reboot" boolean:true' # 再起動
 
 # KDE Plasmaの再起動
 alias plasma='/usr/bin/kquitapp5 plasmashell; plasmashell > /dev/null 2>&1 & disown; sleep 2; exit'
 #alias plasma="killall plasmashell; plasmashell > /dev/null 2>&1 & disown"
 
 # GNOMEの再起動
 alias gshell='killall -3 gnome-shell > /dev/null 2>&1 & disown; sleep 2; exit'
 
 # VS Codeをスーパーユーザ権限で起動
 alias scode='code --user-data-dir='<VSCodeのプロジェクトディレクトリ>''
 
 # SUSEの情報を出力
 alias suse='cat /etc/SUSE-brand'
 
 # 各SSHの接続
 alias sshpi='ssh <ユーザ名>@<ホスト名またはIPアドレス> -p <ポート番号> -i <暗号鍵のフルパス名>'  # Raspberry Pi向けSSH接続の設定
 
 # KVMの起動と停止
 alias startkvm='sudo systemctl restart libvirtd'
 alias stopkvm='sudo systemctl stop libvirtd && sudo systemctl stop libvirtd.socket && sudo systemctl stop libvirtd-admin.socket && sudo systemctl stop libvirtd-ro.socket'
 
 # FreeRDPをインストールしている場合
 alias rwin10='/<FreeRDPのインストールディレクトリ>/bin/xfreerdp /u:<仮想マシンのユーザ名> /p:<パスワード> /w:1600 /h:900 /sound:latency:400 /drive:suse,<共有するディレクトリ> /v:192.168.122.130'
 
 # SUSEが仮想マシンの場合
 alias mhgfs='sudo vmhgfs-fuse -o allow_other .host:/Common /mnt/hgfs'
 alias uhgfs='sudo fusermount -u /mnt/hgfs'
 
 # コマンド履歴に残さないコマンド群
 ## SUSEがホストの場合
 export HISTIGNORE="fg*:bg*:history*:cd*:ls*:cat*:less*:more*:grep*:lgrep*:igrep*:startkvm:stopkvm:repoclean*:suse:which*:clear:man*:repoclean:startx*:exit:"
 ## SUSEが仮想マシンの場合
 export HISTIGNORE="fg*:bg*:history*:cd*:ls*:cat*:less*:more*:grep*:lgrep*:igrep*:startkvm:stopkvm:repoclean*:suse:which*:clear:man*:repoclean:startx*:exit:mhgfs:uhgfs"
 
 # プロンプトの表示形式
 PS1='\e[0;31m\u\e[0m@\e[0;32m\h\e[0m(\t) [Path \w] \n> '
 
 # 変数FIGNOREのカスタマイズ
 # ディレクトリ名およびファイル名を設定する場合、補完対象から除外される
 export FIGNORE=.svn:${FIGNORE}
 
 # mkdirとcdを同時実行
 function mkcd()
 {
    if [ "$#" -eq 0 ]; then
       echo "Too few arguments!"
    elif [ "$#" -eq 1 ]; then
       if [ -d $1 ]; then
          echo "$1 already exists!"
          cd $1
       else
          mkdir -p $1 && cd $1
       fi
    else
       echo "Too many arguments!"
    fi
 }
 
 # カレントディレクトリに存在するディレクトリとファイルの検索
 function lgrep()
 {
    if [ "$#" -eq 0 ]; then
       echo "Please specify Regular Expression."
    elif [ "$#" -eq "1" ]; then
       OLDIFS=$IFS
       IFS=$'\n\t'
 
       for OBJECT in $(\ls -A --group-directories-first | \grep -iE "$1")
       do
          ls -AdhlF $OBJECT
       done
       unset OBJECT
 
       echo ""
 
       IFS=$OLDIFS
    else
       echo "Too many arguments!"
    fi
 }
 
 # パターンにマッチするファイル内容を検索する
 function datagrep()
 {
    if [ "$#" -eq 2 ]; then
       local IFS_BACKUP=$IFS
       IFS=$''
 
       for OBJECT in $(\find . -type f -name "${1}" -print0 | \xargs -0 \grep -inE "${2}")
       do
          echo "${OBJECT}"
       done
 
       echo ""
 
       IFS=$IFS_BACKUP
    elif [ "$#" -eq 3 ]; then
       # 第1引数で指定したディレクトリが存在するか確認する
       if [ ! -d "$1" ]; then
          echo "Not Exist Directory $1" 1>&2
          return 1
       fi
 
       local IFS_BACKUP=$IFS
       IFS=$''
 
       # 現在のカレントディレクトリを一時的に保存する
       local CURRENTDIR=$(\pwd)
 
       # 第1引数で指定したディレクトリに移動する
       cd "${1}";
 
       # 第2引数で指定したパターンを使用して検索する
       for OBJECT in $(\find . -type f -name "${2}" -print0 | \xargs -0 \grep -inE "${3}")
       do
          echo "${OBJECT}"
       done
 
       # カレントディレクトリに戻る
       cd "${CURRENTDIR}"
 
       echo ""
 
       IFS=$IFS_BACKUP
 
       unset -v OBJECT
    else
       echo "Specify Arguments." 1>&2
    fi
 
    return 0
 }
 
 # manコマンドの結果をfirefoxで閲覧
 function manh()
 {
    if [ "$#" -eq 0 ]; then
       echo "Too few arguments!"
    elif [ "$#" -eq "1" ]; then
       man --html=firefox $1 &
    else
       echo "Too many arguments!"
    fi
 }
 
 # KVMの起動
 function startkvm()
 {
    local KVM_STATUS=$(sudo systemctl status libvirtd | grep "Active:" | grep -ie "dead")
    if [ -n "KVM_STATUS" ]; then
       sudo systemctl start libvirtd
    fi
 
    local NETWORK_STATUS=$(sudo virsh net-info default | grep -ie "起動中" -ie "Active" | grep -ie "no")
    if [ -n "$NETWORK_STATUS" ]; then
       sudo virsh net-start default
    fi
 }
 
 # KVMの停止
 function stopkvm()
 {
    local NETWORK_STATUS=$(sudo virsh net-info default | grep -ie "起動中" -ie "Active" | grep -ie "yes")
    if [ -n "$NETWORK_STATUS" ]; then
       sudo virsh net-destroy default
    fi
 
    local KVM_STATUS=$(sudo systemctl status libvirtd | grep "Active:" | grep -ie "running")
    if [ -n "KVM_STATUS" ]; then
       sudo systemctl stop libvirtd libvirtd.socket libvirtd-admin.socket libvirtd-ro.socket
    fi
 }
 
 # Apache2とMySQLの起動
 function startlamp()
 {
    local APACHE2_STATUS=$(sudo systemctl status apache2 | grep -ie "Active:" | grep -ie "dead")
    if [ -n "APACHE2_STATUS" ]; then
       sudo systemctl start apache2
    fi
 
    local MYSQL8_STATUS=$(sudo systemctl status mysql | grep -ie "Active:" | grep -ie "dead")
    if [ -n "MYSQL8_STATUS" ]; then
       sudo systemctl start mysql
    fi
 }
 
 # Apache2とMySQLの停止
 function stoplamp()
 {
    local APACHE2_STATUS=$(sudo systemctl status apache2 | grep "Active:" | grep -ie "running")
    if [ -n "APACHE2_STATUS" ]; then
       sudo systemctl stop apache2
    fi
 
    local MYSQL8_STATUS=$(sudo systemctl status mysql | grep "Active:" | grep -ie "running")
    if [ -n "MYSQL8_STATUS" ]; then
       sudo systemctl stop mysql
    fi
 }
 
 # 環境変数PATHの設定
 function SetPATH()
 {
    OLDIFS=${IFS}
    IFS=$':'
    
    BEFORE_HOME='$HOME'
    AFTER_HOME=${HOME}
    PATH_NAME=$(echo ${1//${BEFORE_HOME}/${AFTER_HOME}})
    
    SLASH=$(echo ${PATH_NAME: -1:1})
    if [ ${SLASH} = "/" ]; then
        LENGTH="${#PATH_NAME}"
        let LENGTH=${LENGTH}-1
        PATH_NAME=$(echo ${PATH_NAME:0:${LENGTH}})
    fi
    
    if [ ! -d ${PATH_NAME} ]; then
        echo "No Exist Directory"
        return 1
    fi
    
    EXIST_FLAG=0
    for VALUE in ${PATH}
    do
        if [ ${VALUE} = ${PATH_NAME} ]; then
            EXIST_FLAG=1
            break
        fi
    done
    
    if [ ${EXIST_FLAG} -eq 0 ]; then
        export PATH="$PATH_NAME:$PATH"
    elif [ ${EXIST_FLAG} -eq 1 ]; then
        echo "Already Exist ${PATH_NAME} in PATH " 1>&2
    fi
    
    unset -v OLDIFS SLASH LENGTH BEFORE_HOME AFTER_HOME PATH_NAME EXIST_FLAG VALUE
    
    IFS=${OLDIFS}
    
    return 0
 }
 
 function SetLIBRARY()
 {
    OLDIFS=${IFS}
    IFS=$':'
    
    BEFORE_HOME='$HOME'
    AFTER_HOME="$HOME"
    PATH_NAME=$(echo ${1//${BEFORE_HOME}/${AFTER_HOME}})
    
    SLASH=$(echo ${PATH_NAME: -1:1})
    if [ ${SLASH} = "/" ]; then
        LENGTH="${#PATH_NAME}"
        let LENGTH=${LENGTH}-1
        PATH_NAME=$(echo ${PATH_NAME:0:${LENGTH}})
    fi
    
    if [ ! -d ${PATH_NAME} ]; then
        echo "No Exist Directory"
        return 1
    fi
    
    EXIST_FLAG=0
    for VALUE in ${PATH}
    do
        if [ ${VALUE} = ${PATH_NAME} ]; then
            EXIST_FLAG=1
            break
        fi
    done
    
    if [ ${EXIST_FLAG} -eq 0 ]; then
        export LD_LIBRARY_PATH="$PATH_NAME:$LD_LIBRARY_PATH"
    elif [ ${EXIST_FLAG} -eq 1 ]; then
        echo "Already Exist ${PATH_NAME} in PATH " 1>&2
    fi
    
    unset -v OLDIFS SLASH LENGTH BEFORE_HOME AFTER_HOME PATH_NAME EXIST_FLAG VALUE
    
    IFS=${OLDIFS}
 }
 
 # 環境変数PATHの重複を削除する
 function DeleteDuplicate()
 {
    if typeset -A &>/dev/null; then  # 連想配列が使用できるか確認する
        # 使える場合
        typeset -A _paths
        typeset _results
 
        while read -r _p
        do
            if [[ -n ${_p} ]] && (( ${_paths["${_p}"]:-1} )); then
                _paths["${_p}"]=0
                _results=${_results}:${_p}
            fi
        done <<<"${PATH//:/$'\n'}"
  
        PATH=${_results/:/}
  
        unset -v _p _paths _results
    else
        # 使えない場合はawkを使用する
        typeset _p=$(awk 'BEGIN{RS=":";ORS=":"} !x[$0]++' <<<"${PATH}:")
        PATH=${_p%:*:}
  
        unset -v _p
    fi
 }