はじめに
- コマンドを入力する
- コマンドの実行結果を出力する
これらを行うためのインターフェースを提供するアプリケーションを 端末エミュレータ という。
端末エミュレータとしてよく知られているアプリケーションには ターミナル がある。
アプリケーションとしての「ターミナル」は、物理的な端末装置(terminal) とは別のものを指している。
端末は CUI(Character User Interface)または CLI(Command Line Interface)の形式で、ユーザーから入力されたコマンドを シェル に渡し、実行結果をシェルから受け取る。端末はユーザとシェルの仲介役に過ぎず、自身でコマンドをかいs実行しているわけではない。
コマンドは端末が解釈しているわけではない
端末
Terminal
キーボードとディスプレイから構成される物理的な「端末装置」のこと。
英訳が terminal なので混乱してしまうが、はソフトウェアのターミナルのことではなく、ハードウェアの端末装置を指す。
計算能力が無く、もともとは接続された大型計算機にデータを送受信するだけの役割を担っていた端末装置は、コンピュータが小型化して普及すると同時に、計算機自体に搭載された、物理的な端末装置を模倣した 端末エミュレータ と呼ばれるソフトウェアに置き換わっていった。
技術の発展により、物理的な端末装置は姿を消した。
端末エミュレータ
terminal emulator
端末装置をソフトウェアによって模倣(emulate)したもの。
具体的には MacOSのターミナル、Linuxの GNOME Terminal、Windowsの コマンドプロンプト や PowerShell などを指す。
各種製品が存在し、動作する環境や特徴が異なる。
端末エミュレータ | 環境 | 特徴 |
---|---|---|
ターミナル | MacOS | MacOS標準搭載 Bash や Zash などのシェルへアクセスできる |
iTerm2 | MacOS | サードパーティ製 タブ分割、複数ペイン表示、ショートカットなどの機能があり、カスタマイズ性が豊富 |
xterm | X Window System | Unix系OS(特にLinux)で利用される カスタマイズ性が低いが軽量で動作が軽く、基本機能に特化 リソースが少ない環境や古いシステムでの使用に適している |
GNOME Terminal | X Window System | GNOMEデスクトップ環境に標準搭載 高度なカスタマイズ機能を持つ |
Windows Terminal | Windows | Windows10から標準搭載 |
コマンドプロンプト / PowerShell | Windows | Windows標準搭載 |
端末エミュレータは、自身が動作する環境のカーネルにアクセスすることもあれば、ネットワーク上の他のコンピュータ(サーバ)のカーネルにアクセスするためにも利用される。
ターミナル
MacOSに標準搭載されている 端末エミュレータ。
文脈によっては、端末エミュレータそのものを指す場合がある。
プロンプト $
/ %
/ #
prompt
端末エミュレータ が提供するCLIにおいて、ユーザーに対して入力を促す文字列や記号。
prompt には「促す」と言う意味がある。
シェルの種類によって特別な意味を持つ場合がある。
プロンプト | 意味 |
---|---|
$ |
一般ユーザとしてログイン中であることを示す |
# |
スーパーユーザ(管理者)としてログイン中であることを示す |
% |
Zsh 等で利用される |
シェル
コマンドを解釈して、カーネルに対するシステムコールを実行するソフトウェア。
GUIを持たず、端末エミュレータ のCLIを介して利用することができる。
Windows の PowerShell のように、シェルが端末エミュレータと一体になっていて、明確に区別できない場合もある。
種類 | 特徴 |
---|---|
Bash | Unix系システムで広く使用される |
Zsh | 高度な機能とカスタマイズ性を持つ |
sh | 古いUnixシェルの一つ |
コマンドライン(cmd.exe ) |
Windowsコンソールホスト上で動作 MS-DOS由来のコマンドが多い |
Power Shell | コマンドラインの後継 GUIを持つため、端末エミュレータでもある オブジェクト指向 |
Bash
Bourne Again SHell
Unix系システムで広く使用されている標準シェル。
POSIX規格に準拠しており、ほとんどのUnix系システムで動作する。
$ bash
シェルとしての Bash を起動するためのコマンド。
新しいシェルセッションが開始される。
$ bash
Zshを起動したターミナルから実行した場合、以下のような状態になる。
$ bash
The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ # ログインシェルがBashに切り替わる
bash-3.2$exit # 起動した Bash を終了する
引数に Bash で記述したスクリプトファイルを指定することで、指定したスクリプトを起動した Bash 上で実行することもできる。
$ bash myscript.sh
Zsh
Z Shell
高度な機能とカスタマイズ性を持つシェル。Bashと同様にPOSIX規格に準拠している。
近年の MacOS のデフォルトシェル。
$ zsh
bash
と同様に、新しいシェルセッションを開始する。
sh
Bourne Shell
古くから存在するUnixシェルの一つで、他の多くのシェル(Bash、Zshなど)の基礎となっている。
「sh」と言う用語は、シェルスクリプトやコマンドを示すための一般的な総称として使われることがあり、Bash、Zsh、sh で記述されたスクリプトファイルの拡張子には .sh
が使用される。
ログイン中のシェルを知る方法
$SHELL
$SHELL
にはユーザがデフォルトでログインするシェルへのパスが格納されている。
$ echo $SHELL
/bin/zsh
$0
$0
には、現在実行中のシェルまたはコマンド名が格納されている。
$ echo $0
-zsh
$ ps
process status
現在実行中のプロセスのIDや、CPUやメモリの使用状況、実行時間、実行されているコマンドの名前などを確認することができる。
単に $ ps
とした場合、現在のシェルで実行されているプロセスの一覧が表示される。
$ ps
PID TTY TIME CMD
5766 ttys000 0:00.04 -zsh
項目 | 意味 |
---|---|
PID |
プロセスID |
TTY |
プロセスが紐づく端末(仮想端末名 |
TIME |
プロセスがCPUを使用した時間 |
CMD |
実行中のシェルもしくはコマンド |
PGID |
プロセスグループ |
POSIX
Portable Operating System Interface
IEEE によって策定される Unix 系OS間での互換性を保つための規格。
開発者目線では、POSIX規格に従って開発することでプログラムが異なるOS間で移植可能になる。また、Windows OS は POSIX には準拠していない(WSL といった技術は提供されている)。
さまざまなサブ規格に分かれている。
カーネル
Kernel
主にプロセス、メモリ、デバイス、ファイルシステムの管理、アクセス制御などを行う OSの中核 部分を担うソフトウェア。
ハードウェアとソフトウェアの橋渡し的な役割を持つ。
通常、アプリケーション(プロセス)は、カーネルから提供されるインターフェースを介してのみ、デバイスへのアクセスが許されている。
この制限によって、デバイスに複数のプロセスが同時にアクセスする場合でも、カーネルが競合するアクセス要求を調停するため、アプリケーション間でリソースの競合が起きない仕組みになっている。
カーネルがアプリケーションに提供するインターフェースや、機能を利用するために呼び出す命令または関数を システムコール 、スーパーバイザコール(SVC:supervisor call)という。このインターフェースは、ハードウェアの仕様の違いに依存しないように抽象化されている。
カーネルモード / ユーザモード
CPUの動作モードには、カーネルモード と ユーザモード がある。
カーネルモードは、その名の通りカーネルや、デバイスドライバなどのプロセスが動作するモードで 特権モード とも呼ばれる。
カーネルモードのCPUは、メモリ、I/Oデバイスなどのハードウェアリソースに、制限なくアクセスを行うことができる。そのため、カーネルモードで不正な操作が行われたりバグが発生すると、メモリが破壊されたりデバイス動作が停止するといった、システム全体に影響が出る。
一方ユーザモードは、通常のアプリケーションプログラムが動作するモードであり、直接ハードウェアにアクセスを行うことができない。ユーザモードで動作するプロセスは、カーネルの提供するシステムコールを介してハードウェアにアクセスする。
システムコール
カーネルから提供される、プロセスがカーネルの特権的な機能を呼び出すためのインターフェース。
ユーザモード で動作中のCPUを、 カーネルモード へ遷移させる手段でもある。
システムコールの実行が終了すると、CPUはカーネルモードから再びユーザモードに戻ってプロセスの実行を継続する。
以下のような種類がある。
- ファイル操作:
open
,read
,write
- プロセス管理:
fork
,exec
,kill
- ネットワーク通信:
socket
,connect
システムコールを呼び出すことができるプログラミング言語は複数ある。
- C言語
- アセンブリ言語
- Rust
- Go
- Python
- C++
- Perl
- Ruby
- AssemblyScript / WebAssembly
C言語やアセンブリ言語は、OSやカーネル開発において主要言語として採用されることが多い。一方、PythonやPerlなどはシステムコールを直接呼び出す用途ではなく、ラッパーやモジュール経由で利用することが多い。
C言語には、glibc
と呼ばれる 標準Cライブラリ が存在し、この中にはシステムコールを内部的に呼び出すラッパー関数が含まれている。アセンブリ言語は直接システムコールを呼び出すことができるものの、アーキテクチャ ごとに存在するシステムコールを環境に応じて呼び分ける必要がある。C言語では glibc
のようなラッパー関数がアーキテクチャごとの違いを吸収するため、呼び出し側はその違いを意識する必要がない。
例外
プロセスがシステムコールを発行すると、CPUにおいて 例外 が発生する。
この例外をトリガーにして、CPUは ユーザモード から カーネルモード へ遷移し、システムコールの処理を行う。
システムコールの処理が終了すると、CPUは再びユーザモードに戻り、プロセスを継続する。
標準Cライブラリ
C言語に標準で付属しているライブラリ。システムコール のラッパー関数が含まれる。
- 入出力操作(例:
printf
,scanf
) - メモリ管理(例:
malloc
,free
) - ファイル操作(例:
fopen
,fread
,fwrite
) - システムコールのラップ(例:
open
,read
,write
)
システムコール | 標準Cライブラリのラッパー関数 | 説明 |
---|---|---|
open |
open |
ファイルを開く |
read |
read |
ファイルやデバイスからデータを読み取る |
write |
write |
ファイルやデバイスにデータを書き込む |
close |
close |
ファイルを閉じる |
コマンド
シェルに対する命令。端末エミュレータ への入力を介して実行する。
コマンドの実体は実行可能ファイルであり、実行可能ファイルにはバイナリ形式とスクリプト形式がある。
コマンドの実体は実行可能ファイル
またその他にも以下の形式のコマンドもある。
実行可能ファイル(バイナリ形式)
ファイルシステム上に配置されたバイナリ形式の実行可能ファイルは、コマンドとして実行することができる。
呼び出したシェルとは別プロセスとして実行される。
例:ls
、grep
、cat
実体はそれぞれ、/bin/ls
、/usr/bin/grep
、/bin/cat
などで、ファイルに拡張子は無い。
Linux ではバイナリ形式の実行可能ファイルに拡張子はつけない
which
コマンドを使用することで、引数に与えたコマンドの実行可能ファイルを知ることができる。
$ which ls
/bin/ls
また、type
コマンドでビルトインコマンドか、実行可能ファイルかがわかる。
$ type ls
ls is /bin/ls
$ type cd
cd is a shell builtin
バイナリ形式の実行可能ファイルは絶対パスで実行することもできるし、ファイル名だけでも実行できる。
$ /bin/ls
$ ls
ファイル名を与えただけでシェルがファイルを探し当てることができるのは、環境変数 $PATH
の存在があるためである。
$ ls
が実行された時、シェルはまず環境変数 $PATH
から ls
ファイルがないかを探している。
もし環境変数 $PATH
に /bin
が設定されていない場合には、シェルは ls
ファイルを見つけることができず、ファイル名だけでコマンドを実行することはできない。
※ 正確には下記の順に検索が行われる
実行可能ファイル(スクリプト形式)
スクリプトファイルは実行権限を付与することで、スクリプト としてシェルから実行することができる。
(コマンドの実体を理解するために、あえてバイナリ形式とスクリプト形に分類していますが、通常はコマンド実行者が「このコマンドはバイナリファイルなのか、スクリプトファイルなのか」などを気にする必要はありません。また、スクリプトファイルが実行権限エラーで実行できないと言う私自身の経験から権限の付与が必要であることを強調していますが、実行権限はバイナリファイルにも必要です。)
ビルトインコマンド
シェルに組み込まれたコマンド。
シェルによって直接実行されるため、呼び出したシェルのプロセス内で実行される。
cd
、pwd
、echo
、alias
、export
など。
$ type cd
cd is a shell builtin
関数
シェルスクリプトで定義した関数はコマンドのように実行することができる。
$ function say_hello { echo "hello world" }
$ say_hello
hello world
エイリアス
既存のコマンドには エイリアス と呼ばれる「別名」をつけて実行することができる。
登録済みエイリアスは $ alias
で表示することができる。
$ alias
新たにエイリアスを定義する際は、次のようにエイリアス名とコマンド名を =
で指定する。
$ alias エイリアス名=コマンド
$ alias hello='echo "hello world"'
$ hello
hello world
セミコロン ;
を使うと、複数のコマンドを集約させることもできる。
$ alias hello='echo "hello";echo "bye"'
$ hello
hello
bye
引数にエイリアス名を指定すると、エイリアスにしたコマンドを表示することができる。
$ alias エイリアス名
$ alias hello
hello='echo "hello world"'
$ alias
コマンドで登録したエイリアスは、現在ログイン中のシェルセッションでのみ有効。永続的なエイリアスを登録したい場合、シェルの 環境設定ファイル に定義を追加する。
Bash を使用している場合 ~/.bashrc
(~
: ホームディレクトリ)という環境設定ファイルがシェル起動時に読み込まれているため、このファイルに以下の1行を追加しておくことで永続的なエイリアスを追加することができる。
alias hello='echo "hello world"'
編集した ~/.bashrc
ファイルは端末エミュレータを再起動するか、source
コマンドを使って、シェルに再読み込みさせることができる(source
と bash
の違い )。
$ source ~/.bashrc
エイリアスを削除する場合、$ unalias
コマンドを使用する。
$ unalias エイリアス名
変数
シェル変数
シェル上で使用できる変数。パスを格納する使い方が多く利用される。
$ 変数名=値
で宣言し、
$ $変数名
で参照することができる。
$ hello=こんにちは
$ echo $hello
こんにちは
文字列中で変数を使用したい場合は、
$ echo "$変数名"
もしくは
$ "${変数名}"
とする。
特に、パスのようにスペースを開けずに変数を使用したい場合は ${変数名}
を使用する。
$ hello=こんにちは
$ echo $hello
こんにちは
$ echo "$hello"
こんにちは
$ echo "$hello world"
こんにちは world
$ echo "$helloworld"
# 変数 helloworld が未定義のため、何も出力されない
$ echo "${hello}world" # 変数に続いてスペースなしで文字列を使用する場合
こんにちはworld
set
コマンドを使用すると、実行中のシェル環境内で定義された全ての変数(シェル変数、ビルトインシェル変数、環境変数)を表示することができる。
$ set
unset
コマンドでシェル変数を削除できる。
$ unset 変数名
ビルトインシェル変数
シェルであらかじめ宣言されている変数。
ビルトインシェル変数 | |
---|---|
$? |
直前の実行コマンドの終了ステータス 成功の場合は 0 、失敗の場合 0 以外の値が格納 |
$0 |
実行中のシェルの名前、もしくはコマンド名 |
$# |
シェルスクリプト内で、スクリプトに渡された引数の数を取得 |
$1 ,$2 ,$3 ... |
シェルスクリプト内もしくは関数内で、渡された引数が順に格納される(1番目は $0 ではなく $1 ) |
$* ,$@
|
シェルスクリプト内で、スクリプトに渡されたすべての引数を取得$* :一つの文字列として格納$@ :文字列の集合として格納 |
$$ |
実行中のシェルのプロセスID |
$! |
最後にバックグラウンドで実行されたコマンドのプロセスID |
$PATH |
実行可能ファイルの検索パス(複数のパスが: で区切られた文字列として格納される) |
$HOME |
ユーザのホームディレクトリのパス~ でも取得可能 |
$PWD |
現在の作業ディレクトリ |
$OLDPWD |
$ cd で移動する前の作業ディレクトリ |
$SHELL |
現在使用されているシェルのパス(/bin/bash 、/bin/zsh など) |
終了ステータス / $?
直前の実行コマンドの終了ステータス。0
~ 255
が使用可能。
- 成功:
0
- 失敗:
0 以外
自作のスクリプトで終了ステータスを呼び出し元に返すには、exit
コマンドを使用する。
exit 0 # 正常終了(成功)
exit 1 # 異常終了(エラーなど)
これを利用して、異常が発生したらスクリプトを終了させることができる。
if [ $? != 0 ]; then
exit 1;
fi
エラー発生後に echo
コマンドで $?
を確認した場合、echo
コマンドの成否が $?
に再代入される点に注意。
$ cd not_exixts_directory
cd: no such file or directory: not_exixts_directory
# $? には cd コマンドの終了ステータスが格納
$ echo $?
1
# $? には echo コマンドの終了ステータスが格納
$ echo $?
0
環境変数
シェルまたはシステム全体で使用される変数。
親プロセスから子プロセスに引き継がれるため、環境変数を介してプログラム間で情報を共有することもできる。
$ export
を使用することで環境変数を設定し、子プロセスに引き継がせる。
$ export 環境変数名=値
$ export PATH="/some/directory:$PATH"
末尾の :$PATH
は、a = 1 + a
という形で既存の $PATH
を上書きしないようにしている。
echo
とリダイレクト演算子 >>
を利用して追加することもできる。
$ echo 'export PATH="/some/directory:$PATH"' >> ~/.bashrc # Bash
$ echo 'export PATH="/some/directory:$PATH"' >> ~/.zshrc # Zsh
$ export PATH="/some/directory:$PATH"
$ printenv
また、$ printenv
で環境変数の一覧を表示する。
$ printenv
特定の環境変数を指定することもできる。
$ printenv 環境変数名
$ env
環境変数を表示したり、一時的な環境変数を設定しながら別のコマンドを実行する。
単に $ env
とした場合、$ printenv
と同様に環境変数の一覧が表示される。
$ env
下記のように記述すると、一時的に環境変数を設定してコマンドを実行することができる。
$ enc 環境変数名=値 コマンド
コマンド置換
コマンドの実行結果を文字列に変換して、別のコマンドの引数に渡す機能。
`$(コマンド)`
もしくは
`コマンド`
とすると、コマンドの実行結果が文字列に置換される(`
はバックコーテーション)。
シングルコーテーションとダブルコーテーションの違いに注意。
$ alias hello="echo こんにちは"
$ echo "$(hello)"
こんにちは
$ echo '$(hello)'
$(hello) ⬅️ コマンド置換されない
スクリプト
- Bash
- Zsh
- Python
- JavaScript
- PHP
- Perl
- Ruby
などの他のソフトウェアの動作を制御するために使用されるプログラミング言語のをスクリプト言語と言う。
スクリプト言語で記述されたプログラムは スクリプト と呼ばれ、以下の拡張子が使用される。
-
.sh
: Bash, Zsh など -
.py
: Python -
.pl
: Perl -
.rb
: Ruby -
.js
: JavaScript
また、OSの動作を制御するための Bash、 Zsh、 sh で記述されたスクリプトを特に シェルスクリプト と言う。Windows では、シェルスクリプトは バッチファイル と呼ばれる。
スクリプトはインタプリタによって逐次解釈・実行されるため、実行前にコンパイルを行う必要がない。スクリプトを実行させる場合、言語に対応するインタプリタを実行環境にインストールする必要があるが、Bash(言語)のようなシェルスクリプトはシェル(Bash)自身が解釈・実行する。
$ source
/ $ .
指定したファイル内にあるシェルスクリプトを現在のシェル環境で実行する。
$ source スクリプトファイル名
環境設定ファイルを編集した際に、シェルを再起動することなく反映させるために使用される。
$ source ~/.bashrc
$ source
コマンドで読み込んだスクリプトは、現在起動しているシェルのプロセス内で実行されるため、環境変数やエイリアスなどを、起動中のシェル環境に適用させることができる。
ドット $ .
もコマンドであり $ source
と同じ機能を持つ。
$ . ファイル名
$ source
と $ bash
との違い
$ source スクリプトファイル名
$ source
は呼び出したシェルプロセス内で実行される。
$ bash コマンド名
一方、bash
は呼び出し元のシェルが新しいシェルプロセスを起動し、引数に渡したコマンドは新たに起動したBashのプロセス上で実行される。
そのため、
$ bash ~/.bashrc
としても、設定の変更や変数の宣言は呼び出し元のシェルプロセスには反映されない。
$ man
manual
コマンドのマニュアルページを表示する。
$ man コマンド名
表示されたマニュアルは Q
キーを押すことで終了する。