コンテンツにスキップ

シェル@ユーティリティ

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. シェルとは

仕組み

標準入力からの入力を解釈し、Linuxカーネルを操作する。

また、Linuxカーネルの処理結果を解釈し、標準出力/標準エラー出力に出力する。

基本的には、いずれのシェルも同じ仕組みである。

shell


01-02. 起動方法の種類

ログインシェル

▼ ログインシェルとは

認証情報を必要とし、認証後に最初に起動するシェルのこと。

パスワードは、/etc/passwdファイルに設定されている。

▼ su -

特定のユーザーで認証し、シェルを起動する。

# ハイフンオプション有り
$ su - <ユーザー名>

▼ bash --login

現在のユーザーで認証し、シェルを起動する。

# --loginオプション有り
$ bash --login

▼ ssh

SSH公開鍵認証で認証し、シェルを起動する。

$ ssh


インタラクティブシェル

▼ インタラクティブシェルとは

認証情報を必要とせず、最初に起動するシェルのこと。

▼ su <ユーザー名>

特定のユーザーで、認証なしでシェルを起動する。

# ハイフンオプション無し
$ su <ユーザー名>

▼ bash

現在のユーザーで、認証なしでシェルを起動する。

# --loginオプション無し
$ bash


非インタラクティブシェル

▼ 非インタラクティブシェルとは

シェルスクリプトを指定して実行するシェルのこと。

▼ bash -c

$ bash -c foo.sh


確認方法

現在の起動方法の種類は、変数の『$0』に格納されたシェルスクリプトのファイル名から確認できる。

$ echo $0

sh # インタラクティブシェル

# ログインシェルを起動する。ハイフンオプションがあることに注意する。
$ sudo su -
Last login: Mon Jun 20 13:36:40 JST 2022 on pts/0

[root@<IPアドレス> bin] $ echo $0

-bash # ログインシェルの場合、シェルの前にハイフンが付く。

補足として、もしシェルスクリプト内でこれを実行した場合は、これのファイル名を取得できる。

#!/bin/sh
# foo.shファイル

echo $0 # foo.sh


シェルの種類

▼ 系譜

shell_history

▼ 設定ファイル

シェルを起動するとき、各種設定ファイルが読み込まれる。

ファイルが存在しなければ、自身で作成する。

bashの場合 zshの場合 読み込まれるタイミング
なし ~/.zshenvファイル ログインシェル、インタラクティブシェルの起動時
~/.bash_profileファイル ~/.zprofileファイル ログインシェルの起動時
~/.bashrcファイル ~/.zshrcファイル ログインシェルの起動時。ただし、zshではインタラクティブシェルの起動時も含む。
~/.bash_loginファイル ~/.zloginファイル ログインシェルの起動時。profileファイルと機能が重複するため、個人的には使用しない。
~/.bash_logoutファイル ~/.zlogoutファイル exitコマンド時

▼ 確認方法

現在使用しているシェルを確認する。

$ echo $SHELL

/bin/zsh


変数

▼ 変数スコープと親子プロセス

シェルでは、変数のスコープがプロセスの親子関係によって決まる。

shell_variable_scope

▼ シェル変数

現在実行中のプロセスのみで有効な変数のこと。

そのため、sourceコマンド以外の方法で実行されたシェルスクリプトでは、親プロセスで定義されたシェル変数を使用できない。

#!/bin/bash
# foo.shファイル
echo "${FOO}"
$ FOO=foo # シェル変数を定義する。

$ bash foo.sh
# 出力されない

補足として、標準出力に対する出力をシェル変数に代入することもできる。

FOO=$(echo "foo")

▼ 環境変数

現在実行中のプロセスと、その子プロセスでも有効な変数のこと。

そのため、シェルスクリプトの実行コマンドに限らず使用できる。

#!/bin/bash

# foo.shファイル
echo "${FOO}"
$ export FOO=foo # 環境変数を定義する。

$ bash foo.sh

foo # 出力される

▼ 置換してから出力する

変数内の文字列を置換してから出力できる。

$ VERSION=1.0.0 # シェル変数を定義する。

# 文字列内の全てのドットをハイフンに置換する
echo "${VERSION//\./-}"


02. セットアップ

インストール

▼ apkリポジトリから

ほとんどのOSで、bashコマンドはプリインストールされているが、Alpine Linuxではシェル以外を別途インストールが必要である。

$ apk add bash


03. 終了ステータス

終了ステータスとは

プロセスは別の新しいプロセスを作成できる。

子プロセスの終了時に、親プロセスに終了ステータス (0255) が返却される。


終了ステータスの種類

意味 エラーの原因 発生例
0 正常な完了 - -
1 一般的なエラー 構文エラーではないが、ロジックが誤っている可能性がある。 $ let "var 1 = 1 / 0"
2 シェルビルトインな機能の誤用 シェルの構文や権限が誤っている可能性がある。 $ empty_function(){}
126 呼び出したコマンドが実行できなかった時 権限やその他の理由でコマンドを実行できてない可能性がある。 $ /dev/null
127 コマンドが見つからない時 バイナリファイルの$PATHの未設定や、コマンドのタイポの可能性がある。 $ illegal_command
128 exitコマンドに不正な引数を渡した時 exitコマンドに0〜255以外の整数を渡している可能性がある。 $ exit 3.14159
128 + n シグナル nで致命的なエラー killがシグナルnで実行された可能性がある。 $ kill -9 $PPID
(128 + 9 = 137で終了)
128 + 2 スクリプトが Ctrl+Cで終了 Ctrl+Cはシグナル2で終了するため、Ctrl+Cが実行された可能性がある。 (128 + 2 = 130) Ctrl+C
255 範囲外の終了ステータス exitコマンドに0〜255以外の整数を渡している可能性がある。 $ exit -1


trueコマンド

trueコマンドを使用することにより、処理が途中で成功するか失敗するか (終了コードが00以外か) にかかわらず、処理を続行できる。

これは、複数の同じような処理を実行したい場合に役立つ。 (例:静的解析ツールに、異なるバージョンのパラメーターを渡して、同じ処理を連続的に実行する)

#!/bin/bash

# ここで失敗すると、終了コードが0以外でシェルスクリプトの処理を中断する
echo foo

echo bar
#!/bin/bash

# ここで失敗しても、終了コードが0になり、シェルスクリプトの処理は続行される
echo foo || true

echo bar


$?

コマンドの終了コードを出力する

$ echo "" ; echo $?

0 # 終了コードが 0 である


04. コマンドの実行タイミング

順次実行

▼ 終了ステータスがいずれであっても

連結したコマンドを順次実行する。

前のコマンドがいずれかの終了ステータスで完了しない限り、後ろのコマンドを実行しない。

$ echo foo; echo bar; echo baz

▼ 終了ステータスが0の場合のみ

連結したコマンドを順次実行する。

前のコマンドが終了ステータスが0で完了しない限り、後ろのコマンドを実行しない。

$ echo foo && echo bar && echo baz

▼ 終了ステータスが0以外の場合のみ

連結したコマンドを順次実行する。

前のコマンドが終了ステータスが0以外で完了しない限り、後ろのコマンドを実行しない。

$ echo foo || echo bar || echo baz


並列実行

連結したコマンドを並列実行する。

前のコマンドが完了しない限り、後ろのコマンドを実行しない。

$ echo foo & echo bar & echo baz