3章 シェルとスクリプト
用語
ターミナル
- 文字の入出力
- エスケープシーケンス
- バックスベースとか
- 種類
- xterm, rxvt, Gnome terminator
- New: Alacritty, kitty, warp GPUを利用しているらしい
シェル
ターミナル内で動作するプログラム。ストリームによる入出力処理、コマンドの実行をする。対話的/スクリプトでの使用。
user@vm:~$ file -h /bin/sh
/bin/sh: symbolic link to dash
user@vm:~$ echo $0
-bash
user@vm:~$ echo $SHELL
/bin/bash
ストリーム
入力ストリーム(input stream)と出力ストリーム(output stream)がある。2つ合わせて入出力(I/O, Input/Output)という。
シェルはすべてのプロセスに3つのファイルディスクリプタ(FD)をデフォルトで用意している。
stdin
(FD 0): 標準入力stdout
(FD 1): 標準出力stderr
(FD 2): 標準エラー出力
特に指定しない限り、シェルで入力したコマンドはキーボードから入力(stdin)され、画面に出力(stdout)する。エラー発生時も画面に出力する(stderr)。
ストリームはリダイレクト1できる。$FD>
と<$FD
を使用する。$FD
はファイルディスクリプタである。
例えば次の通り。
2>
stderr
ストリームをリダイレクト1>
,>
(同じ意味)stdout
ストリームをリダイレクト&>
stderr
とstdout
の両方をリダイレクト
また、行き先を/dev/null
にするとストリームの出力は破棄される。
シェルは次の特殊文字を解釈する。
- アンパサンド (
&
) コマンドの最後に置くとコマンドをバックグランドで実行する - バックスラッシュ (
\
) 次の行にコマンドを続ける - パイプ (
|
) あるプロセスのstdout
と次のプロセスのstdin
をつなぐ
Info
curl
HTTPリクエストを投げるhead
先頭から数行表示する- ex
$ head -n 10
- ex
tr
stdinから読み込んだ文字を置換するwc
'word count' 文字や行数を数える
変数
2種類ある。unset
で未定義の状態に戻せる。
- 環境変数
- シェル全体の設定
export
を使って作成(bash)
- シェル変数
- 実行中のシェルでのみ有効、子プロセスには継承されない
set
を使って作成もできる
変数にアクセスするためには変数の前に$
をつける。
実例は次のとおり。
$ MY_VAR=42 # シェル変数
$ set | grep "^MY_*"
MY_VAR=42
$ echo MY_VAR
MY_VAR
$ echo $MY_VAR
42
$ export MY_GLB="omg" # 環境変数
$ set | grep "^MY_*"
MY_GLB=omg
MY_VAR=42
$ bash # ここから子プロセスのシェル
$ set | grep "^MY_*"
MY_GLB=omg # <- 環境変数だけ
次のような環境変数もある。シェルや環境によって異なる。
$ echo $? # ? 直前に実行したコマンドの実行ステータス (0が正常, 1-255は失敗)
0
$ echo $$ # $ 現在のプロセスのPID
198
$ echo $0 # 0 現在のプロセスの名前
-bash
$ ps
PID TTY TIME CMD
198 pts/2 00:00:00 bash
253 pts/2 00:00:00 ps
$ echo $_ # _ 直前のコマンド
ps
ビルドインコマンド
シェルにはビルドインコマンドが用意されている。そもそもコマンドにはシェルビルドインだけでなく、/usr/bin
などシェルの外部にインストールやエイリアスのコマンドなど種類がある。
コマンドの種類を調べるためにはtype
が利用できる。
$ type cd
cd is a shell builtin
$ type sh
sh is /usr/bin/sh
$ type ls
ls is aliased to `ls --color=auto'
また、コマンドの実行可能ファイルがある場所は~~which
~~2 command -v
で取得できる。
参考 Qiita - POSIXコマンドは「どの環境にもあるコマンド」ではないよという話
ジョブ制御
フォアグラウンド実行 シェルで通常通りコマンドを実行し、画面とキーボードの制御を受ける
対話的に実行しない場合やサーバのようなプログラムの場合、ジョブ制御とバッググラウンドジョブがある。
- バックグラウンドでプロセスを起動するには最後に & をつける
- フォアグラウンドのプロセスをバッググラウンドに送るには Ctrl + Z を押す
$ watch -n 5 "ls" & # watch コマンドをバッググラウンドで実行
[1] 299
$ jobs # すべてのジョブの一覧を表示
[1]+ Stopped watch -n 5 "ls"
$ fg # あるプロセスをフォアグラウンドで実行
Info
nohup COMMAND &
シェルが閉じた後もコマンドをバックグラウンドで実行するdisown
kill
対象のプロセスにシグナルを送信して終了させる
モダンなコマンド
日常的に使うコマンドをより使いやすくしたコマンドがある。
exa
ディレクトリの内容を出力bat
ファイルの内容を表示(cat
の進化系)rg
ファイルの中身検索(find
とgrep
)jq
JSONデータの処理
シェル作業の効率化
ファイル内容の整理
vi
を使わないテキストの処理も色々ある。
# /tmp/something を作成し一行追加
$ echo "First line" > /tmp/something
# /tmp/something を表示
$ cat /tmp/something
First Line
# /tmp/something の2行目を追記
$ echo "Second Line" >> /tmp/something && \
> cat /tmp/something
First Line
Second Line
# /tmp/something の内容をsedで置換しstdoutへ (-iオプションで上書き)
$ sed 's/Line/LINE/' /tmp/something
First LINE
Second LINE
# ヒアドキュメントでファイルを作成
# https://tldp.org/LDP/abs/html/here-docs.html
$ cat << 'EOF' > /tmp/another
First Line
Second line
Third line
EOF
# ファイルの差分を表示
$ diff -y /tmp/something /tmp/another
First Line First Line
Second Line | Second line
> Third line
長いファイルの参照
less
やbatのようなページャを使用するのが普通だが、他にもいくつか方法がある。
head
ファイルの先頭行を表示- ex.
head -5 [file]
fileの5行目まで表示
- ex.
tail -f
最終行から数行表示するコマンド +-f
ライブアップデート出力- ex.
tail -f [file]
- ex.