勉強日記

チラ裏

LPIC あずき本v5.0 ch7 シェルとシェルスクリプト


シェル環境のカスタマイズ

環境変数とシェル変数

  • 環境変数
    • シェル自身と、そのシェルから起動されるすべてのプロセスに引き継がれる
    • 代表
      • PATH
      • HOME
  • シェル変数
    • そのシェル内でのみ有効
  • export
  • env, printenv
CLUTTER_IM_MODULE=xim
LS_COLORS=
LESSCLOSE=/usr/bin/lesspipe %s %s
XDG_MENU_PREFIX=gnome-
LANG=ja_JP.UTF-8
...
  • オプションがない場合、envprintenvに違いはない
env > env
printenv > printenv
diff env printenv
55c55
< _=/usr/bin/env
---
> _=/usr/bin/printenv
  • printenvでは、環境変数名を指定すると、それのみ表示する
printenv HOME
/home/wand
env HOME
env: `HOME': そのようなファイルやディレクトリはありません
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:gnu_errfmt:histappend:interactive_comments:progcomp:promptvars:sourcepath
...
__expand_tilde_by_ref () 
{ 
    if [[ ${!1} == \~* ]]; then
        eval $1=$(printf ~%q "${!1#\~}");
    fi
}
...
  • シェル変数と関数とに区別はない

シェルのオプション

  • setコマンドで各種オプションを確認・オン/オフ
set --help
    Set or unset values of shell options and positional parameters.
    
    Change the value of shell attributes and positional parameters, or
    display the names and values of shell variables.
    
    Options:
...
      -o option-name
          Set the variable corresponding to option-name:
              allexport    same as -a
              braceexpand  same as -B
              emacs        use an emacs-style line editing interface
...
    Using + rather than - causes these flags to be turned off.
  • 一覧
set -o
allexport        off
braceexpand     on
emacs           off
errexit         off
errtrace        off
functrace       off
hashall         on
histexpand      on
history         on
ignoreeof       off
interactive-comments    on
keyword         off
monitor         on
noclobber       off
noexec          off
noglob          off
nolog           off
notify          off
nounset         off
onecmd          off
physical        off
pipefail        off
posix           off
privileged      off
verbose         off
vi              off
xtrace          off
  • おもなやつ
オプション shorthand 説明
allexport -a 作成・変更した変数を自動的にエクスポートする
emacs emacs風のキーバインドにする
ignoreeof Ctrl + Dによってログアウトしないようにする
noclobber -C 出力リダイレクトによる上書きを禁止する
noglob -f メタキャラクタを使ったファイル名展開(file name generation)を無効にする
vi vi風のキーバインドにする

-o allexport, -a

      -a  Mark variables which are modified or created for export.
  • 有効にしてみる
set -a
set -o
- allexport       off
+ allexport         on
  braceexpand       on
  emacs             off
...
  • シェル変数作ってみる
HOGE=3
printenv HOGE
3
  • allexport無効化する
    • -oの逆、+o
set +o allexport
set -o
- allexport       on
+ allexport         off
  braceexpand       on
  emacs             off
...
  • 既にexport済のものは更新される
HOGE=5
printenv HOGE
5
  • 新しく作ったシェル変数はexportされない
PIYO=3
printenv PIYO



エイリアス

  • エイリアス機能
    • コマンドに別名
    • コマンドとオプションをひとまとめに
  • 環境変数lessページャで表示するやつ
alias envless='env | less'
envless
CLUTTER_IM_MODULE=xim
LS_COLORS=
HOGE=5
...
  • けす
unalias envless
envless
envless: コマンドが見つかりません
  • もとの名前を隠すこともできる
alias ls='ls -l'
ls
合計 84
-rw-r--r-- 1 wand docker  1649  4月  9 19:52 env
-rw-r--r-- 1 wand docker  1654  4月  9 19:52 printenv
-rw-r--r-- 1 wand docker 77047  4月  9 19:54 set
  • もとの名前を呼び出す
\ls
env  printenv  set
  • 後始末
unalias ls

関数の定義

  • functionはオプショナル
  • {, }の後/前はスペース必須
  • 1行スタイルではセミコロン必須
function echohoge(){ echo 'hoge'; }
echopiyo() { echo 'piyo'; }

echohoge
echopiyo
hoge
piyo
  • これは駄目
echodame() { echo 'dame' }
  • 複数行に分けて書く(対話型)
    • シェルスクでももちろん可能
    • この場合セミコロン不要
echomulline()
> {
> echo 'a'
> echo 'b'
> echo 'c'
> }

echomulline
a
b
c
  • {()と同じ行でもいい
  • セミコロンはあってもいい
mul() {
echo 'a';
}
  • 定義見る
declare -f echohoge
  • 複数行スタイルに展開されている
echohoge () 
{ 
    echo 'hoge'
}
  • けす
    • シェル変数とおなじ
unset echohoge
echohoge
  • 関数一覧みる
declare -F
...
declare -f echopiyo
declare -f hogehoge
...
  • コマンド展開すると定義も見れる
$(declare -F | grep hoge)
echohoge () 
{ 
    echo 'hoge'
}
hogehoge () 
{ 
    echo 'hoge'
}

bashの設定ファイル

ファイル 説明
/etc/profile ログイン時に実行
/etc/bash.bashrc bash起動時に実行される
/etc/bashrc ~/.bashrcから参照
~/.bash_profile ログイン時に実行
~/.bash_login ~/.bash_profileがない場合、ログイン時に実行
~/.profile ~/.bash_profile~/.bash_loginもない場合、ログイン時に実行
~/.bashrc bash起動時に実行
~/.bash_logout ログアウト時に実行
  • /etc/以下のやつは全ユーザーから参照
  • ~/以下のやつは対応するユーザーからのみ参照

/etc/profileファイル, /etc/profile.dディレクトリ以下*.shファイル

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).

if [ "${PS1-}" ]; then
  if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
    # The file bash.bashrc already sets the default PS1.
    # PS1='\h:\w\$ '
    if [ -f /etc/bash.bashrc ]; then
      . /etc/bash.bashrc
    fi
  else
    if [ "`id -u`" -eq 0 ]; then
      PS1='# '
    else
      PS1='$ '
    fi
  fi
fi

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

/etc/bash.bashrcファイル

  • ディストリによっては無いらしい
    • Ubuntu18.04にはあった
  • rc: run commandsの意
  • 全ユーザーから参照

~/.bash_profile, ~/.bash_login, ~/.profileファイル

  • なかった
  • ユーザごとの環境変数の設定等を行うのでしょう
    • PATHとか

~/.bashrcファイル

  • 対話型シェルが起動されるたびに実行される
  • このシェルスクから/etc/bashrcを呼び出す
    • 全ユーザ用設定

~/.bash_logoutファイル

  • ログインシェル終了時に実行
    • -bashのように、頭に-がつく

bash起動時における設定ファイルの実行順序

  • 暇な時に絵を書く

シェルスクリプト

シェルスクリプトの基礎

echo 'echo hoge' > hoge.sh

bash hoge.sh
source hoge.sh
. hoge.sh
hoge
hoge
hoge
  • ファイルパス指定で実行も出来る
    • パスが通っていない場合、カレントにあっても./が必要
    • 実行権を付与してあること
hoge.sh
./hoge.sh

chmod +x hoge.sh
./hoge.sh
hoge.sh: コマンドが見つかりません
bash: ./hoge.sh: 許可がありません

hoge
  • bash: 新しいbashサブシェルが立ち上がる
  • source, ., ファイルパス指定: 元のbashで実行する
  • exec
    • プロセスがすげ変える
  • execしない例
ps

  PID TTY          TIME CMD
19989 pts/1    00:00:00 bash
21693 pts/1    00:00:00 ps

sh
ps

  PID TTY          TIME CMD
19989 pts/1    00:00:00 bash
21726 pts/1    00:00:00 sh
21727 pts/1    00:00:00 ps

exit
  • execする例
exec sh
ps

  PID TTY          TIME CMD
19989 pts/1    00:00:00 sh
21733 pts/1    00:00:00 ps

exec bash  # exitじゃない
  • X Window Systemでウィンドウマネージャを起動するような場合、待機しているシェルのプロセスは不要なのでexecしてXのプロセスにすげ替えるべき

スクリプトに渡す引数

  • $1 ... ${n}
    • シェルスクに渡すパラメータ
  • $#
    • パラメータ数($1 ... ${n}に対するn)
  • $@
    • 全パラメータ(空白区切り)
  • $*
    • 全パラメータ(環境変数IFSで指定されたもの)

実行結果の戻り値

  • $?
    • 終了コード
hoge

echo $?
echo $?
Command 'hoge' not found

127
0
  • コマンドが見つからない: exit 127
  • echo 127: exit 0

ファイルのチェック

  • testコマンド
  • []記法
if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi
  • if test -f ~/.bash_aliases ; thenと同義

制御構造

条件分岐

  • if-then-elif-else-fi

case文による条件分岐

  • case-in-esac

month.sh

case $1 in
    1) echo 'Jan' ;;
    2) echo 'Feb' ;;
    *) echo 'others' ;;
esac
. month.sh 1
. month.sh 2
. month.sh 3
Jan
Feb
others

for文による繰り返し処理

for.sh

for i in $(seq 1 10)
do
    echo $i
done
. for.sh
1
2
3
4
5
6
7
8
9
10

while文による繰り返し処理

i=1
while test $i -le 10
do
    echo $i
    let i=i+1
done

readコマンド

  • 標準入力からの入力を受け付ける

list

hoge
piyo
fuga

echoes.sh

while read INPUT
do
    echo $INPUT
done
. echoes.sh < list
hoge
piyo
fuga
  • こういう書き方もできる
while read INPUT
do
    echo $INPUT
done < $1
  • この場合、使い方はこう
. echoes.sh list

シェルスクリプトの実行環境

  • シバン
#!/bin/bash
  • bash特有の機能を使っているのに#!/bin/shとかかいちゃだめ
  • CRLF改行に気をつける
    • /bin/bash^Mになって死ぬ
    • windows環境でdockerを使うとよくある
  • シェルスクの中でexportしても、シェルスク呼び出し元のシェルに環境変数は持ち出されない
  • 実行したユーザの権限で動作する
    • SUID, SGIDはバイナリにしか効かない。スクリプトファイルにつけても無視される
      • shとかplとか
      • セキュリティ上の理由らしい
-rwsr-xr-x 1 root root 11  49 21:42 root.sh
echo $USER
sudo ./root.sh
./root.sh
  • SUIDが無視される
root
wand