「ShellCheck」を使って、メンテナンス性の高いシェルスクリプトを実装する
ShellCheckとは
ShellCheckは、シェルスクリプトの静的解析ツールで、マズい書き方をしてると怒ってくれるLinterだ。
たとえば、example.sh
という下記のシェルスクリプトがあるとしよう。
echo $0
これをShellCheckでチェックすると、こんな警告を出してくれる。
In example.sh line 1: echo $0 ^-- SC2148: Tips depend on target shell and yours is unknown. Add a shebang. ^-- SC2086: Double quote to prevent globbing and word splitting.
この例では、「shebangを書け」「変数使うときはダブルクォート使え」的な指摘をしてくれる。
続きを読む「cli-highlight」で無味乾燥なターミナル表示をカラフルに
cli-highlightとは
cli-highlightはターミナルでもエディタのように、シンタックスハイライトをしてくれるツールだ。
無味乾燥なターミナルがとっても見やすくなる。
Before
なんの面白みもない表示。
After
とってもカラフルで見やすい!
続きを読む
GitHubのWikiをマークダウン形式で取得する
背景
ときどき、GitHubのリポジトリで、ツールの使い方などがバージョン管理されたファイルではなく、Wikiに書かれていることがある。
ブラウザから参照することも可能だが、このWikiで書かれたテキストをマークダウンで取得したくなるときがまれによくある。
GitHub API
とりあえず、GitHub APIでなにか提供されていないか調べるのが王道だろう。
で、調べてみたのだが、なんとWikiに関するAPIが一切存在しない。おぉ、マジか。
curl
じゃあ、curlで適当なURL叩いたら取れないかと思い試行錯誤したら取れた。
curl -s https://raw.githubusercontent.com/wiki/<user>/<repo_name>/<title>.md
たとえば、jqコマンドのWikiのページを取得するときはこんな感じ。
curl -s https://raw.githubusercontent.com/wiki/stedolan/jq/Home.md
タイトルに空白が含まれる場合は、ハイフンで置換すればいい。たとえば、Advanced Topicsのページはこうなる。
curl -s https://raw.githubusercontent.com/wiki/stedolan/jq/Advanced-Topics.md
git clone
余談だが、Wikiの内容はgit cloneすることができる。
git clone git@github.com:<user>/<repo_name>.wiki.git
さきほど同様、jqコマンドのWikiを例にするとこんな感じ。
git clone git@github.com:stedolan/jq.wiki.git
どういうときに必要になるのか分からないが、何かのときに使えるかもしれない。
雑にシェルスクリプトのみを一覧取得するコマンド
ファイル名に拡張子 .sh
が付いていれば見つけるのは簡単だが、拡張子なしのファイルも見つけたかったので、試行錯誤をメモ。
最初に結論
$ grep '^#!' -rn . | grep ':1:#!' | cut -d: -f1 | grep -v .git
試行錯誤
shebangで検索
$ grep '^#!' -rl .
行頭が #!
ではじまるファイルを探している。
あんまりこれで困らないと思うが、欠点も存在する。一行目ではなく、ファイルの途中に #!
があっても拾ってしまうのだ。
一行目のみに絞り込む
$ grep '^#!' -rn . | grep ':1:#!' | cut -d: -f1
最初のgrepで行番号も出力している。たとえば、こんな感じで出力される。
$ grep '^#!' -rn . ./install:1:#!/bin/sh ./README.md:33:#!/bin/sh ./hooks/build:1:#!/bin/bash
そして、 :1:#!
でgrepかけて、一行目に含まれているファイル一覧に絞り込む。
$ grep '^#!' -rn . | grep ':1:#!' ./install:1:#!/bin/sh ./hooks/build:1:#!/bin/bash
最後にファイル名だけ取り出す。
$ grep '^#!' -rn . | grep ':1:#!' | cut -d: -f1 ./install ./hooks/build
.gitを除外
$ grep '^#!' -rn . | grep ':1:#!' | cut -d: -f1 | grep -v .git
git 管理してるディレクトリ配下で実行すると .git
ディレクトリ内も検索してしまう。そこで、単純に -v
オプションで .git
ディレクトリ配下を除外する。
おまけ:Makefile内で使う
最初、Makefileで定義するにあたって、普通にshell関数内で実行して、その結果を変数に格納していたが、なぜかshell関数は、実行結果の改行を空白に置換してしまって困った。
仕方ないのでマクロ定義して、それを呼び出すことにした。
define list_shellscript grep '^#!' -rn . | grep ':1:#!' | cut -d: -f1 | grep -v .git endef
で、使うときはこんな感じ。
$(call list_shellscript)
xargsと組み合わせるときも、こんな感じで書ける。
$(call list_shellscript) | xargs -I {} echo {}
ECS初回構築時に自動作成されるIAMロール「AWSServiceRoleForECS」とTerraformでの予期せぬ挙動
AWSServiceRoleForECSとは
ECSを作成すると、勝手に作られるIAMロール。Terraformでaws_ecs_cluster
リソースを作ったときにも自動作成される。Service-Linked Rolesというヤツの一種らしい。
公式ドキュメントから、AWSServiceRoleForECSについての説明を引用する。
Amazon Elastic Container Service では、AWS Identity and Access Management (IAM) の「サービスにリンクされたロール」を使用します。
ほとんどの状況では、サービスにリンクされたロールを手動で作成する必要はありません。たとえば、新しいクラスターを作成する (たとえば、Amazon ECS の初回実行、クラスターの作成ウィザード、AWS CLI または SDK) か、AWS マネジメントコンソールでサービスを作成または更新するときに、存在しない場合は Amazon ECS によりサービスにリンクされたロールが作成されます。
すごくざっくり言えば、このIAMロールは「ECSをいい感じに動かしてくれる君」である。
続きを読む