背景
- ラズパイやりたい
- よくエラーが出る。出た場合に、スマートに原因確認したい
- 人口少ないのでググっても解決されないこと多々ある
- シェル読めばいいのでは?
- 雰囲気でしか読めない
- シェルの知識を一回洗いたい
- ということで改めて雰囲気でやってたところお勉強
注意
筆者はターミナルでzsh使ってますが、クウォーティングがbashと異なるせいか、ターミナルで思ったように動かないことが多発しました。そんなときはきちんとファイルにして、shebangで/bin/bash
を設定して遊んで見ましょう。zshなんか個人の問題だしシェルスクリプトをzshで書くのはやめようね。色々困るので
そもそも入力されたコマンドってどうなってるの?
雰囲気というか、全く勉強したことなかった笑
どうやらLinuxでは以下の順番でシステムコールというものが実行されています、
- fork = プロセスをコピーして子プロセスを作成する
- exec = コマンドを実行する
- wait = 親プロセスが子プロセスを監視する
- exit = 実行結果を返す
- forkによって現在のコマンドラインのプロセス(以降,X)から子プロセス(以降,x)をコピーして作成
- Xはwaitによって、子プロセスを監視
- x上でexecによってコマンドが実行され、exitで結果が返される
- waitが感知してコマンドを終了する
shebang
シェルスクリプト先頭にあるこういう表現。
#!/bin/bash
#!/bin/sh
ただのコメントやん。と思ってしまいますが、実はコメントではないので、なんでも書いていいわけではないようです。
実は、先ほど書いたexec
システムコールに関係します
execシステムコールは、バイナリ形式のファイルを読み込む仕組みです
しかし、ファイルの先頭が#!
となっている場合のみ、#!
から改行までをコマンド、それ以降は、そのコマンドにファイルが引数として渡されているとして扱われます。
なので、例えば
#!/usr/bin/env php
<?php
echo "Hello,world";
?>
これを、こうすると動くんです
$ ./sample_php.sh
便利やんと思う反面、shebangを扱う上で弱点があるようです。
ファイルに必ず実行権限がないと実行できないようです
$ chmod -x sample.sh
$ ./sample.sh
zsh: permission denied: ./sample.sh
$ chmod +x sample.sh
$ ./sample.sh
Hello,world
この問題は、直接shebangをコマンドラインで指定すると解決されます。
$ chmod -x sample.sh
$ /bin/bash sample.sh
Hello,world
環境構築しているときに、たまにこういう場面きますよね、こういう理由だったみたいです。
sourceコマンド
よく、.bashrc
を修正した後、その修正を反映させるにはsource ~/.bashrc
をしろっていうのをみますね、
これに使われるsource
コマンドですが実はスクリプトファイルを1行ずつ読んでいっているだけなんです。これを聞くと普通のshと同じようです。唯一違う点は、sourceは子プロセスで実行しないんです。なので変数などの設定が現在のプロセスに全て引き継がれます。だから追加したばかりのaliasが使えたりするんですね、
ブレース展開
パス名展開(*.sh
とかsample.[ch]
とかのパス名を展開する機能)はみなさん知っていると思いますが、ブレース展開というものもあります
めっちゃ便利そうです。
mkdir {src,test} // srcディレクトリ,testディレクトリを作成
mkdir dir_{1..100} //ディレクトリを`dir_1`から`dir_100`まで作成
mkdir sample-{a..d} // sample-aからsample-dまで作成
mkdir sample-{4..11..2} //4から2ずつ増えて11まで展開する。従って `4,6,8,10`として展開され作成
やばい、めっちゃ便利。
パラメータ展開
${変数:-値}
たまにみますよねこの表現、変数
に値が設定されていない場合は値
を使うみたいです。
コマンドの引数が設定されていない場合のデフォルト値を設定する際によく使われてます
#!/bin/bash
echo ${1:-デフォルトパラメータだよ}
$ ./myecho.sh
デフォルトパラメータだよ
$ ./myecho.sh 引数1
引数1
これと似た表現で、以下のようなものもありますね、
${変数:=値}
これはどうやら変数
が空文字または未定義だった場合に値
を代入して展開します
さらに似たような表現で
${変数:?値}
もちょくちょく見ます。
これは、変数
が未定義だった場合は標準エラーに値
を出力します。
$ echo ${file:?Please set file}
zsh: file: Please set file
使いどころありすぎてイイ!
if文
以下のように[]
があったりなかったりと3パターン存在しているのがすごい気になってた。
if コマンド; then
:
fi
if [条件っぽいもの]; then
:
fi
if [[条件っぽいもの]]; then
:
fi
ちなみに、:
はヌルコマンドといって、文字どおり何も実行しない。しかしこれを書かないとなんか処理しろやゴルァと言われるので書いている
まず一つ目if コマンド; then ...
コマンドの実行結果は,正常終了なら0,それ以外なら0以外を返す。
if {コマンド}; then ....
の場合は、そのコマンドの実行結果が0である場合に条件に合致するということだ
if cd ~/sample; then
echo 'Dir exists.'
else
echo 'Not exists.' >&2
fi
この場合、cd ~/sample
で、sampleディレクトリが存在している場合は条件内に入る。
echo 'Not exists.' >&2
は、標準出力を標準エラー出力ヘリダイレクトしている。エラーを手っ取り早く表示するにはこの方法がいいらしい
次にif [条件っぽいもの]; then ...
独特の記法がされている。これはtestコマンドのエイリアスらしい。
testコマンドとは、引数に独自の演算子を渡すと、文字列のチェックやファイルの権限確認などを行なってくれる
演算子 | 0(true)を返す場合 |
---|---|
-a x | xが存在する場合 |
-e x | xが存在する場合 |
-d x | xがディレクトリの場合 |
-f x | xがファイルの場合 |
-L x | xがシンボリックリンクの場合 |
-h x | xがシンボリックリンクの場合 |
-z x | xが空文字列の場合 |
-n x | xが空文字列ではない場合 |
x === y | xとyが等しい場合(数値でも文字列でも可能) |
x == y | xとyが等しい場合(数値でも文字列でも可能) |
x != y | xとyが等しくない場合(数値でも文字列でも可能) |
x < y | xがyよりも辞書順で前である場合(数値でも文字列でも可能) |
x > y | xがyよりも辞書順で後ろである場合(数値でも文字列でも可能) |
$ test 0 == 1
$ echo $?
1 // falseとして1が返る
$ [ 0 == 1 ]
$ echo $?
0 // trueとして0が返る
$ [ 'hoge' \< 'fuga' ] // クウォーティング必須。 '<'でも可
$ echo $?
1 // falseとして1が返る
ちなみに、$?
は直前のコマンドの実行結果を取得するコマンド。
また、これらを複雑に条件づけるために、以下の演算子も存在する
演算子 | 処理 |
---|---|
式a -a 式b | aかつb。よくある(a&b) |
式a -o 式b | aまたはb。よくある(a |
最後にif [[条件っぽいもの]]; then ...
これは、testコマンドをさらに拡張したものみたいです
簡単にいうと、先ほどの-a
や大なり小なりのクウォーティングが不要になるんです。
testコマンド時▼
[[]]
時▼
$ [ 'hoge' < 'fuga' && 1 == 0]
$ echo $?
1
後者の方がわかりやすいですねえ。こんな書き方ができるのは、[[]]
がコマンドではないためらしいです。
しかも、[[]]
の場合には、&&
の前者で1(false)だった場合は後者の処理は行わないので使いやすいですね。なので先ほどの処理では実は1 == 0
の処理は行われていないんです!
まとめ
- まだ半分ぐらいしか読んだこと書いていないけどこれでだいたい内部のシェル読める気がする(読めるとは言っていない)
- 残り半分は気が向いたら書く
- 参考資料
- 続きがきになる方はこちらからどうぞ▼
- https://www.amazon.co.jp/%E6%96%B0%E3%81%97%E3%81%84%E3%82%B7%E3%82%A7%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E4%B8%89%E5%AE%85-%E8%8B%B1%E6%98%8E/dp/4797393106
- https://www.amazon.co.jp/%E6%94%B9%E8%A8%82%E7%AC%AC3%E7%89%88-%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E5%9F%BA%E6%9C%AC%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-sh%E3%81%A7%E3%80%81%E3%81%93%E3%81%93%E3%81%BE%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B-PRESS-plus/dp/4774186945/ref=pd_lpo_sbs_14_t_1?_encoding=UTF8&psc=1&refRID=T19XWWZ1EM0HA1RAPMYX
- 続きがきになる方はこちらからどうぞ▼