シェル@ユーティリティ¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. シェルとは¶
仕組み¶
標準入力からの入力を解釈し、Linuxカーネルを操作する。
また、Linuxカーネルの処理結果を解釈し、標準出力/標準エラー出力に出力する。
基本的には、いずれのシェルも同じ仕組みである。
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
シェルの種類¶
▼ 系譜¶
▼ 設定ファイル¶
シェルを起動するとき、各種設定ファイルが読み込まれる。
ファイルが存在しなければ、自身で作成する。
bashの場合 | zshの場合 | 読み込まれるタイミング |
---|---|---|
なし | ~/.zshenv ファイル |
ログインシェル、インタラクティブシェルの起動時 |
~/.bash_profile ファイル |
~/.zprofile ファイル |
ログインシェルの起動時 |
~/.bashrc ファイル |
~/.zshrc ファイル |
ログインシェルの起動時。ただし、zshではインタラクティブシェルの起動時も含む。 |
~/.bash_login ファイル |
~/.zlogin ファイル |
ログインシェルの起動時。profileファイルと機能が重複するため、個人的には使用しない。 |
~/.bash_logout ファイル |
~/.zlogout ファイル |
exit コマンド時 |
▼ 確認方法¶
現在使用しているシェルを確認する。
$ echo $SHELL
/bin/zsh
変数¶
▼ 変数スコープと親子プロセス¶
シェルでは、変数のスコープがプロセスの親子関係によって決まる。
▼ シェル変数¶
現在実行中のプロセスのみで有効な変数のこと。
そのため、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. 終了ステータス¶
終了ステータスとは¶
プロセスは別の新しいプロセスを作成できる。
子プロセスの終了時に、親プロセスに終了ステータス (0
〜255
) が返却される。
終了ステータスの種類¶
値 | 意味 | エラーの原因 | 発生例 |
---|---|---|---|
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
コマンドを使用することにより、処理が途中で成功するか失敗するか (終了コードが0
か0
以外か) にかかわらず、処理を続行できる。
これは、複数の同じような処理を実行したい場合に役立つ。 (例:静的解析ツールに、異なるバージョンのパラメーターを渡して、同じ処理を連続的に実行する)
#!/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