LPIC Level1 復習ラジオ 17:bashの基本
音声
目次
bashとシェル
シェルは、利用者が入力したコマンドを解釈し、コマンドの実行、変数展開、リダイレクト、パイプ、ジョブ制御などを行うプログラムです。
bashは、GNU Bourne-Again SHellの略で、Linuxで広く使われるシェルの一つです。Bourne Shellの機能を引き継ぎながら、履歴、コマンドライン編集、配列などの機能を備えています。
| 用語 | 役割 |
|---|---|
| ターミナル | 文字を入力し、結果を表示するための画面や端末 |
| シェル | 入力された文字列をコマンドとして解釈するプログラム |
| bash | シェルの実装の一つ |
ターミナルを開いたとき、画面そのものがbashなのではありません。ターミナルの中でbashなどのシェルが動作し、入力を受け取ります。
利用者
↓
ターミナル
↓
bash
↓
組み込みコマンド・外部コマンド
↓
カーネル
Linuxでは、bash以外にもsh、dash、zshなどが利用されます。シェルによって利用できる構文や起動ファイルが異なるため、現在どのシェルを使っているかを確認することが重要です。
bashの起動と確認
bashを引数なしで実行すると、現在のシェルの中から新しいbashを起動できます。
bash
exit
exitを実行すると、そのbashを終了し、一つ前のシェルへ戻ります。シェルを何重にも起動すると、どの階層にいるか分かりにくくなるため注意します。
バージョンと場所
bash --version
command -v bash
type -a bash
bash --version:bashのバージョンを表示するcommand -v bash:現在の実行環境でbashがどのように見つかるかを表示するtype -a bash:同名の候補を含めて表示する
現在動いているシェル
echo "$SHELL"
echo "$0"
ps -p $$ -o pid=,ppid=,comm=,args=
$SHELLは、通常は利用者のログインシェルのパスを表します。今この瞬間に動いているシェルと必ず一致するとは限りません。
$$は現在のシェルのPIDです。現在動いているプロセスを確かめる場合は、ps -p $$が役立ちます。
コマンド文字列とスクリプト
bash -c 'echo "$HOME"'
bash script.sh
bash -n script.sh
-c:続く文字列をコマンドとして実行するbash ファイル:ファイルをbashで読み込んで実行する-n:コマンドを実行せず、構文を確認する
ログインシェルと起動ファイル
bashは、ログインシェルかどうか、対話的に使われているかどうかで、読み込む起動ファイルが変わります。
| 種類 | 代表例 | 主に読むファイル |
|---|---|---|
| 対話的なログインシェル | コンソールログイン、bash --login |
/etc/profileの後、~/.bash_profile、~/.bash_login、~/.profileの最初に見つかった一つ |
| 対話的な非ログインシェル | 端末アプリ内で起動するbash | ~/.bashrc |
| 非対話シェル | シェルスクリプト | 通常は対話用の~/.bashrcを自動では読まない |
ログインシェルでは、次の順に確認されます。
/etc/profile
~/.bash_profile
~/.bash_login
~/.profile
利用者側の三つは全部読むのではなく、最初に見つかった読み取り可能な一つだけを読みます。
対話的な非ログインシェルでは、通常~/.bashrcを読みます。そのため、エイリアスや対話操作向けの設定は~/.bashrcへ書くことが一般的です。
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
ログイン時にも~/.bashrcの設定を使うため、~/.bash_profileなどから上のように読み込む構成がよく使われます。
変更を現在のシェルへ反映する
source ~/.bashrc
. ~/.bashrc
sourceとドットコマンドは、指定したファイルを現在のシェルで読み込みます。別プロセスで実行するのではないため、変数やエイリアスの変更が現在のシェルへ反映されます。
PATH
PATHは、コマンド名だけが入力されたときに、実行ファイルを検索するディレクトリの一覧です。各ディレクトリはコロンで区切られ、左から順に検索されます。
echo "$PATH"
printf '%s\n' "$PATH" | tr ':' '\n'
例えば、次のPATHでは、/usr/local/bin、/usr/bin、/binの順に探します。
/usr/local/bin:/usr/bin:/bin
PATHを使う場合と使わない場合
ls
/usr/bin/ls
./myscript
ls:コマンド名にスラッシュがないため、シェルの組み込みなどを確認した後、必要に応じてPATHを検索する/usr/bin/ls:スラッシュを含むため、指定されたパスを実行する./myscript:現在のディレクトリにあるmyscriptを明示して実行する
通常、現在のディレクトリはPATHへ含まれていません。そのため、カレントディレクトリの実行ファイルは./を付けて指定します。
PATHへディレクトリを追加する
export PATH="$HOME/bin:$PATH"
export PATH="$PATH:/opt/example/bin"
先頭へ追加すると、そのディレクトリが既存のPATHより先に検索されます。末尾へ追加すると、既存のコマンドが優先されます。
PATHへ信頼できないディレクトリやカレントディレクトリを安易に先頭追加すると、同名の不正なコマンドを実行する危険があります。
どのコマンドが実行されるか確認する
command -v python3
type python3
type -a python3
typeは、名前がエイリアス、関数、組み込みコマンド、外部コマンドのどれとして解釈されるかを確認できます。
bashは、見つけた外部コマンドのパスを内部のハッシュ表へ記憶します。コマンドを移動した直後などに古い場所が使われる場合は、次で記憶を消去できます。
hash
hash -r
シェル変数と環境変数
変数は、名前と値の組み合わせです。bashでは、次の形式でシェル変数を作成します。
name=Haruki
message="hello world"
echo "$name"
echo "${message}"
代入の=の前後には空白を入れません。空白を含む値は引用符で囲みます。
name = Haruki
この書き方では、nameというコマンドを実行しようとしてエラーになります。
| 種類 | 主な範囲 | 確認例 |
|---|---|---|
| シェル変数 | 現在のシェル内部 | set、declare -p |
| 環境変数 | 現在のプロセスから起動される子プロセスへ渡される | env、printenv、export -p |
値の参照
file="report"
echo "$file.txt"
echo "${file}.txt"
$file.txtでは、変数名はfileまでと解釈されます。ただし、変数名と後続文字の境界が分かりにくい場合は、${file}のように波括弧を使います。
未設定と空文字
empty=""
unset missing
printf '<%s>\n' "$empty"
printf '<%s>\n' "$missing"
空文字を代入した変数と、未設定の変数は同じではありません。設定を削除する場合はunsetを使います。
親と子の関係
子プロセスは、親プロセスの環境変数のコピーを受け取ります。子プロセス側で値を変更しても、通常は親シェルへ逆向きに反映されません。
export COLOR=blue
bash -c 'echo "$COLOR"; COLOR=red'
echo "$COLOR"
最後の表示は、親シェル側のblueのままです。
export
exportは、シェル変数にexport属性を付け、後から起動するコマンドの環境へ渡せるようにするbashの組み込みコマンドです。
COLOR=blue
export COLOR
代入とexportを一行で行うこともできます。
export COLOR=blue
子プロセスで確認する
local_only=one
export shared=two
bash -c 'echo "local_only=$local_only"; echo "shared=$shared"'
local_onlyは現在のシェルだけの変数なので、子のbashには通常渡りません。sharedはexportされているため渡ります。
export済み変数を確認する
export -p
env
printenv
printenv PATH
export -p:export属性が付いた変数を、再利用できる形式で表示するenv:環境を表示するほか、環境を変更してコマンドを実行できるprintenv:環境変数を表示する
一つのコマンドだけに変数を渡す
LANG=C date
MODE=test ./run.sh
名前=値 コマンドの形式では、そのコマンドの実行環境だけに一時的な値を渡せます。現在のシェルの値を恒久的に変更するわけではありません。
export属性の解除と変数の削除
export -n COLOR
unset COLOR
export -nはexport属性を外しますが、シェル変数自体は残ります。unsetは変数を削除します。
主な変数
シェルや多くのコマンドは、変数の値を参照して動作を変えます。
| 変数 | 主な意味 |
|---|---|
HOME |
利用者のホームディレクトリ |
USER・LOGNAME |
ログイン利用者名 |
SHELL |
通常はログインシェルのパス |
PATH |
実行ファイルを検索するディレクトリ一覧 |
PWD |
現在の作業ディレクトリ |
OLDPWD |
直前の作業ディレクトリ |
LANG |
標準のロケール |
LC_ALL |
個別のロケール設定より優先される全体指定 |
PS1 |
対話シェルの主プロンプト |
HISTFILE |
履歴を保存するファイル |
HISTSIZE |
メモリ上の履歴リストに保持する件数 |
HISTFILESIZE |
履歴ファイルに保持する最大行数 |
echo "$HOME"
echo "$PWD"
cd /tmp
echo "$OLDPWD"
cd -
locale
printf '%s\n' "$PS1"
cd -は、通常OLDPWDへ移動します。
変数を安全に表示する
printf '%s\n' "$PATH"
declare -p HOME PATH SHELL
単純な確認ではechoも使えますが、書式を明示したい場合はprintfが便利です。変数展開は、意図しない単語分割やファイル名展開を避けるため、基本的に二重引用符で囲みます。
alias
aliasは、コマンド行の先頭にある単語を、別の文字列へ置き換えるbashの組み込み機能です。長いオプションの省略や、安全確認用のオプション追加などに使われます。
一覧と作成
alias
alias ll='ls -alF'
alias grep='grep --color=auto'
エイリアス名と置換文字列の間には=を使い、置換文字列は引用符で囲みます。
ll /etc
この例では、bashがllをls -alFへ置き換え、後ろの/etcを引数として続けます。
確認と削除
alias ll
type ll
unalias ll
unalias -a
alias 名前:指定したエイリアスを表示するtype 名前:名前がエイリアスとして解釈されるか確認するunalias 名前:指定したエイリアスを削除するunalias -a:すべてのエイリアスを削除する
一時設定と永続設定
コマンドラインで作ったエイリアスは、通常そのシェルを終了すると消えます。継続して使う場合は、~/.bashrcなどへ記述します。
alias ll='ls -alF'
alias ..='cd ..'
編集後は、新しいシェルを開くか、次で再読み込みします。
source ~/.bashrc
エイリアスより関数が向く場合
エイリアスは単純な文字列置換です。引数を途中へ入れたい場合や、複数処理をまとめたい場合は、シェル関数が向きます。
mkcd() {
mkdir -p -- "$1" && cd -- "$1"
}
非対話シェルでは、標準設定のままではエイリアスが展開されません。スクリプトの処理をエイリアスへ依存させず、関数や通常のコマンドを使う方が分かりやすくなります。
history
historyは、対話的なbashで入力したコマンド履歴を表示・操作する組み込みコマンドです。
表示
history
history 20
history | tail
history | grep ssh
引数に数値を指定すると、末尾から指定件数を表示します。
履歴から再実行する
!!
!42
!ssh
!!:直前のコマンド!42:履歴番号42のコマンド!ssh:sshで始まる直近のコマンド
履歴展開は、実行前に内容を十分確認できない場合があります。削除や上書きを含むコマンドでは、矢印キーやCtrl+Rで呼び出して編集してから実行する方が安全です。
逆方向検索
Ctrl+R
Ctrl+Rを押して文字を入力すると、過去の履歴を後方検索できます。候補を表示した状態で左右キーなどを使うと、実行前に編集できます。
履歴ファイルと件数
echo "$HISTFILE"
echo "$HISTSIZE"
echo "$HISTFILESIZE"
shopt histappend
HISTFILE:履歴ファイル。標準では通常~/.bash_historyHISTSIZE:現在の履歴リストに保持する件数HISTFILESIZE:履歴ファイルに保持する最大行数histappend:終了時に履歴ファイルへ追記するかどうか
履歴ファイルとの読み書き
history -a
history -n
history -w
| オプション | 意味 |
|---|---|
-a |
現在のセッションで新たに入力した履歴を履歴ファイルへ追記する |
-n |
履歴ファイルへ追加された未読の行を現在の履歴へ読み込む |
-w |
現在の履歴リストで履歴ファイルを上書きする |
削除
history -d 42
history -c
history -dは指定項目を削除し、history -cは現在の履歴リストを消去します。履歴リストと履歴ファイルは別に扱われるため、削除したつもりでもファイル側に残っている場合があります。
保存対象の調整
HISTCONTROL=ignoredups:ignorespace
HISTIGNORE='ls:pwd:history*'
HISTCONTROLやHISTIGNOREで保存対象を調整できます。ただし、履歴へ残さない設定は秘密情報を守る完全な仕組みではありません。
実践的な確認手順
bashの設定やコマンド検索で問題が起きた場合は、次の順で確認すると整理しやすくなります。
1. 現在のシェルを確認する
echo "$SHELL"
ps -p $$ -o pid=,ppid=,comm=,args=
bash --version
$SHELLだけで現在のプロセスを断定せず、psも確認します。
2. コマンドの解釈を確認する
type -a コマンド名
command -v コマンド名
alias コマンド名
同じ名前のエイリアス、関数、組み込みコマンド、外部コマンドがないか確認します。
3. PATHを一行ずつ確認する
printf '%s\n' "$PATH" | tr ':' '\n'
必要なディレクトリが含まれているか、順序が正しいか、空の要素や不審なディレクトリがないか確認します。
4. 変数がexportされているか確認する
declare -p 変数名
export -p | grep '変数名'
printenv 変数名
現在のシェルでは見えるのに、起動したプログラムから見えない場合は、exportされていない可能性があります。
5. 起動ファイルを確認する
ls -la ~/.bashrc ~/.bash_profile ~/.bash_login ~/.profile
grep -n 'PATH\|alias\|export' ~/.bashrc ~/.bash_profile ~/.profile 2>/dev/null
同じ変数を複数ファイルで上書きしていないか、構文エラーがないかを確認します。
6. 再読み込み後に確認する
source ~/.bashrc
type -a コマンド名
printenv 変数名
起動ファイルに問題がある場合、現在のシェルへ読み込むと設定が途中まで適用されることがあります。重要な作業中は別のターミナルを残し、新しいターミナルで確認すると安全です。
よくある症状
| 症状 | 主な確認点 |
|---|---|
| command not found | コマンド名、実行権限、PATH、インストール先 |
| 想定と違うコマンドが動く | type -a、エイリアス、関数、PATHの順序、ハッシュ |
| 設定が新しい端末だけに反映される | 起動ファイルとsourceの実行 |
| 子コマンドから変数が見えない | exportの有無 |
| エイリアスがスクリプトで動かない | 非対話シェルでは標準で展開されないこと |
| 履歴が別端末と一致しない | histappend、history -a、history -n |
30秒チェック
- ターミナルとシェルは、どのような役割の違いがあるでしょうか。
$SHELLは、必ず現在動作中のシェルを表すでしょうか。- 対話的な非ログインbashが通常読み込む利用者用ファイルは何でしょうか。
- PATHに複数のディレクトリがある場合、どの順番で検索されるでしょうか。
- シェル変数を子プロセスへ渡すには、どの組み込みコマンドを使うでしょうか。
- エイリアスを削除するコマンドは何でしょうか。
- 直前のコマンドを履歴展開で再実行する表記は何でしょうか。
HISTSIZEとHISTFILESIZEは、それぞれ何を制御するでしょうか。
答えを表示
- ターミナルは入出力の画面や端末、シェルはコマンドを解釈するプログラム
- 必ずではない。通常はログインシェルを表す
~/.bashrc- コロンで区切られたディレクトリを左から順に検索する
exportunalias!!HISTSIZEはメモリ上の履歴件数、HISTFILESIZEは履歴ファイルの最大行数
要約
- シェルはコマンドを解釈するプログラムで、bashは代表的なシェルの一つです。
- ターミナルは入出力の場所であり、ターミナルそのものとbashは別のものです。
$SHELLは通常ログインシェルを表し、現在のプロセス確認にはps -p $$が役立ちます。- 対話的なログインbashは
/etc/profileなどを読み、対話的な非ログインbashは通常~/.bashrcを読みます。 sourceまたはドットコマンドは、設定ファイルを現在のシェルで読み込みます。PATHはコロン区切りで、左側のディレクトリから順に検索されます。type -aは、エイリアス、関数、組み込み、外部コマンドなど、名前の解釈を調べるのに役立ちます。- シェル変数の代入では
=の前後へ空白を入れません。 exportした変数は、後から起動する子プロセスの環境へ渡されます。名前=値 コマンドは、そのコマンドだけへ一時的な環境を渡します。aliasは単純な文字列置換で、複雑な処理や引数操作には関数が向きます。historyは履歴を表示・操作し、Ctrl+Rで検索できます。HISTSIZEは履歴リスト、HISTFILESIZEは履歴ファイルの大きさを制御します。- 秘密情報をコマンド行へ直接書かず、履歴へ残さない設定だけに頼らないことが重要です。
参考資料
- GNU Bash Reference Manual
- GNU Bash Manual:What is Bash?
- GNU Bash Manual:Bash Startup Files
- GNU Bash Manual:Command Search and Execution
- GNU Bash Manual:Shell Parameters
- GNU Bash Manual:Environment
- GNU Bash Manual:Bourne Shell Builtins
- GNU Bash Manual:Bash Builtins
- GNU Bash Manual:Aliases
- GNU Bash Manual:Bash History Facilities
- GNU Bash Manual:Bash History Builtins
- bash(1) — Linux manual page
- environ(7) — Linux manual page
- POSIX.1-2024:Shell Command Language