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

LPICLinux勉強メモ

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

環境変数とシェル変数

  • 環境変数

    • シェル自身と、そのシェルから起動されるすべてのプロセスに引き継がれる
    • 代表

      • 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': そのようなファイルやディレクトリはありません
  • set

    • シェル変数と環境変数を表示
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起動時における設定ファイルの実行順序

  • 暇な時に絵を書く

シェルスクリプト

  • 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文による繰り返し処理

  • よくあるスクリプト言語のforeachにちかい

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