4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

シェルスクリプトを書く時に気を付けていること

Last updated at Posted at 2022-12-21

株式会社サムザップで SRE をしているれおすけです。サムザップ AdventCalendar 2022 の22日目の記事です。
昨日の記事は @shintsu_takamasa さんの「Unity開発アプリでのGooglePlayConsole NativeDebugSymbols登録について」でした。

概要

ふと昔の同僚と飲みながら6日目に投稿した記事について話していた時に、シェルスクリプト書く時にシバンに何を書くかという話題になりました。「いやいやいや、シバンって何?」、「お前のシバン意味が分からん」など盛り上がって楽しかったのですが... 自分の考えを知ってもらうのは大事だなと改めて思いました。
POSIX準拠に対する考え方、可読性と効率のバランス、シェルで作る意義は?など、盛り上がった話題の中からいくつか本記事にまとめてみました。冬の寒い日に効率よく寝られる記事の一つになりそうなので、ゆっくりと読み進めてもらえればと思います。

考えていること

シバンは汎用性を高めて書く

シバン(shebang)は hash bang の略で、インタプリタを指定するためのものです。# は縦2本、横2本切り刻むイメージのハッシュ(ハッシュドポテトのハッシュ)と!マークで銃声のバン!と教わりました。本当かどうか定かではないし、シェバンと呼ぶ派もいます。他にも諸説あり、参考文献にまとめられていた記事を載せたので興味がある人は読んでください。

さて、シバンが #!/bin/sh で始まるシェルスクリプトを見る機会が多いのではないでしょうか?
実際に中身を見てみると Bash固有の機能が使われていたり(一部のOSやOSの特定バージョンで /bin/sh/bin/bash へのリンクなので問題なく動く場合がある)、/bin/配下に bash がなかったりして、特定の環境限定なら動くけどクロスプラットフォームで動かないこともあります。
ゲーム業界では Unity でクライアント側を実装することもあり、iOS端末向けに MacOS でアプリケーションをビルドしなくてはなりません。サウンド系を Windows でビルドする人もいます。

bashがどのようにインストールされ、どのバージョンが使用しているかなど気にしたらキリがないのですが、ツールはどこで使われてるか分からないのでできるだけ多くの環境をカバーしたいので、その度に書き換えるのは大変ですよね。
そこで、毎回シェルスクリプトを書く際はシバンを #!/usr/bin/env bash にしています。そして堂々と固有の機能である配列変数や [[ ]]による便利な比較を使います。

効率と可読性のバランスを判断する基準を決めておく

シェルスクリプトは効率的に書こうとすると読みにくくなるなと個人的に思っています。USP研究所の方々が広めたユニケージ開発は、一時期、私のメインタスクでした(今の会社ではありません)。ユニケージ開発で成果物となるシェルスクリプトは、ワンプログラムワンフローの原則を守り、関数化も基本的に禁止されています。改修依頼が来るたびにスクリプトを実行しながら、一個一個地道に確認していました(隣には見ただけで内容を全て理解するプロフェッショナルがいたので、私の能力が低かっただけかもしれません)。

共有するツールの場合はやはりきちんと判断基準を決めておくのが大事だと思います。
私が考える時に判断基準になるのは、以下の3点です。

  1. どう使われるのか(時間制約やパフォーマンス重視なのか、モック的に最速で実装したいのか)
  2. 誰が使うのか(ユニケージ開発チームだけか、社内でツールとして共有するのか)
  3. どこで実行されるのか(特定の環境だけなのか、他でも実行されるのか、流用される可能性があるか)

短所を考えた上で使う

コマンドを列挙するだけのように思われるシェルスクリプトですが、意外と弱点というか短所が多いです。数分で考えただけでも、以下の3点がありました。

  1. シバンで指定できるのはインタプリタのみ(細かいバージョンや環境はシェルスクリプト内で分岐なり、処理をする必要がある)
  2. マルチプラットフォームの互換性を担保しようとすると苦労する(シェルのバージョンは小さな違いなことが多いが、呼び出している外部コマンドのオプションやバージョンの違いがある場合もある)
  3. ループ内でパイプを多用すると実行が遅くなる(パイプを使用するとフォークしてサブシェルが作られるので遅くなる。)

まとめと感想

今まで書いたことを3行でまとめるとこんな感じです。

  • 異なる環境で実行されるかもしれない場合、汎用性を高めたシバンを使おう!
  • 効率を重視した自分だけが使うツールではない限り、使う側に合わせた(可読性を少し高めたり、効率を優先したりした)書き方を心がけよう。
  • 短所を把握した上でシェルを選択して書こう。

なんとなくシバンを書いていた人もいるのではないでしょうか? 6日目の記事でモック的なツールを提供した記事を投稿しましたが、その裏でいろいろと考えて作成しています。
まだまだ、学ぶことも多く、奥深いシェルスクリプト。これから真面目に取り組もうとする人、寒くてなかなか寝られない人の手助けになれば嬉しいです。
Advent Calendar もあとわずかですね。寂しいようなホッとしたようなそんな気分です。

参考文献

  1. 「#!」 (SheBang)の語源を徹底追求 「切り刻んでビックリ」
  2. POSIX準拠 とは本当はどういうことなのか?「POSIXで規定されたものだけを使う」ではありません
  3. シェルスクリプト リファクタリング ~遅いシェルスクリプトが供養されてたので蘇生して256倍に高速化させました~
4
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?