RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

新人エンジニアの読めそうで読めなかったシェルの話

はじめに

はじめまして。新卒1年目のtuq376sです。
気付けば入社してから季節は4つ目。毎日新しい壁にぶつかりながら、それでも随分とわかることが増えたなぁと思うくらいには成長できている気がします。
今回はそんな壁の中から、初めてシェルスクリプトを業務で触った時のことをまとめてみようかと思います。

読めそうで読めなかったシェル

シェルスクリプトに関するタスクを割り振ってもらったのは、少しずつ業務に携わり始めて、普段使っているJavaの至極簡単な修正であれば1人でも頑張れるようになり始めたころ。
今まで触れたことがなかったとはいえ、シェルスクリプトの概要は研修でも学んだし、改修する内容も既存に合わせて分岐を1つ増やすだけだったのでなんとかできそうだと思っていました。
一応新卒1年目とはいえエンジニアの端くれ、実際コードを見てどこをどうすればいいのかはすぐわかったのです。……けれど同時に、読めているのは雰囲気だけだなということにも気づきました。
いくら簡単なタスクとはいえ流石にそんな中途半端ができるわけもなく。ものの30分もしないうちに、まずは基礎の基礎を知ろうと思ったのでした。

学んだこと

特殊パラメータ

シェルスクリプトを見てまず思ったのは$が多いということ。眺めていれば${hghg}は変数で、$1${10}はこのプログラムへの引数だろうというのは見当がつきました。
けれどいくつか記号と組み合わさっているものについてはわからず、真っ先に調べることに。
どうやら特殊パラメータと呼ばれるもののようで、調べた中から自分でもぱっと理解して使えそうなものから覚えることにしました。

特殊パラメータ 内容
$@渡された引数全て。区切り文字は空白
$#渡された引数の個数
$$シェルのプロセスID
$?フォアグラウンドで最後に終了したコマンドステータスの値
$!バックグラウンドで最後に終了したコマンドプロセスのID

よく見る$HOME$PATHのように予約された変数ということですね。
流石に記号だとどのような意味かは見ただけで推測できないので、わからなくなったら自分でここを見返そうかと思います。

if文の条件式

次にif文。これは雰囲気でも読めてしまうので書き方が違うだけだな……と思っていたのですが。

if [ ${a} -ne ${b} ]; then
    処理
fi

条件式の中にコマンドのオプションらしきものを見て、これもわからないとなったわけです。
調べるとどうやらif文の条件式は本来testコマンドを使うようで、[条件式] はtestコマンドの書き方の1つだとか。
testコマンドについても最低限しか知らなかったため、再度おさらいをすることになりました。

testコマンド

条件を判定し、真偽を返すコマンドです。

test 条件

または

[ 条件 ]

と表記します。

条件に使用するオプションは数多くありますが、一般的な数値処理と論理処理に関するものは以下になります。

オプション 意味
-eq== (equal)
-ne!= (not equal)
-lt< (less than)
-le<= (less than or equal)
-gt> (greater than)
-ge>= (greater than or equal)
-a&& (and)
-o|| (or)

こちらは英語の省略系なので、わかっていれば毎度調べなおすこともなさそうですね。

リダイレクト

さてもう1つ、読んでいて全然知らない……となったのはリダイレクトを行っている部分でした。

`コマンド` > ファイル名 2>&1

上記のような表記になじみがなかったのですが、これはファイルディスクリプタを利用して、標準出力と標準エラー出力を同じファイルに書き込んでいるらしい。
まずファイルディスクリプタとはなんだったっけ……ということでこれもまたおさらいしました。

ファイルディスクリプタ

ファイルディスクリプタとはOSがファイルを識別するために割り当てる管理番号のことで、各ファイルの名前や属性などが参照できるように結び付けられています。
普段ユーザがこの番号を意識することはありませんが、予約されている番号に関しては時々見かけることがあるようです。

番号 内容
0標準入力
1標準出力
2標準エラー出力

内容を見ると、ああそれかとはなるのですが、普段見かけていないとすぐ忘れてしまいますね……。

これを踏まえてさっきの記述を解釈すると、

`コマンド` > ファイル名 2>&1
  1. コマンドが実行され、標準出力をファイルにリダイレクト
    (標準出力をするときのディスクリプタ番号は省略可)
  2. 標準エラー出力を標準出力へリダイレクト
  3. 標準出力はファイルにリダイレクトされているため、標準エラー出力もファイルへ書き出される

ということのようです。もちろん上書きではなく追記を行う>>についても同じように使うことができます。

さいごに

というわけで基本的な最低限を調べた私は、なんとかコードをきちんと理解したうえでタスクをこなすことができたのでした。
今回記事にまとめるにあたって、その時に調べたことをもう一度きちんと調べたのですが、そのおかげで
「読めるようで読めなかったシェル」も「読めないようでちょっとだけ読めるシェル」くらいには親しくなれたような気がしています。
これからも業務で触る機会はそこそこにありそうなので、少しずつ「読める!」と断言できるようになっていきたいなと思います。

そして、動作確認前に改めてコードを読み直してみたら思った以上に改修の必要な範囲が広くて顔を青くしたのはまた別のお話……。

Copyright © RAKUS Co., Ltd. All rights reserved.