4
3

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 5 years have passed since last update.

組織名の汎用コマンドを作ってスクリプトを共用する

Last updated at Posted at 2017-03-08
1 / 21

インターフェース

my-company という自作コマンドを例に挙げていきます。

$ my-company
usage: my-company <command> [<args>]

commands:
  hosts                     サーバのホスト名一覧を表示
  git-log-remote [<hosts>]  デプロイされていない差分コミットがあれば表示
  env-diff [<hosts>]        環境変数の設定漏れを表示
  check-update [<hosts>]    yum パッケージの更新を表示
  self-upgrade              my-company コマンドを更新
  update [<hosts>]          yum パッケージを更新

よくある風景

  • Chat bot は環境構築が面倒(言語・ツール等の巨大な依存があったり・・・)

  • 運用ツールのコマンドをコピペ中心に運用している

運用で使うコマンドを管理する話です


各自インストールして使う汎用コマンドの話をします


汎用コマンドの構成

各自 git clone した後に bin/ へパスを通しておく

|- bin/my-company  # パスを通しておく実行ファイル
|- lib/            # Bash,Perl,PHP,Ruby,Python などのスクリプト
`- README.md

主な依存は SSH

チームで ssh config の Host を合わせる。

  • サーバに名前がついてると意思疎通しやすい

  • ハイフンで名前空間を作るようにすると機械的に扱いやすい


コマンドを作る

第一引数をサブコマンドとして解釈する。

以降の引数はサブコマンドへ移譲する。

bin/my-company
set +e
subcmd=${1:-help}
shift
set -e

if type "my-company-${subcmd}" >/dev/null 2>&1 ; then
  my-company-${subcmd} "$@"
else
  echo "'${subcmd}' is not a my-company command."
fi

準備おわり


サブコマンドを作る

あると便利なサブコマンドを my-company へ実装していきます。

$ my-company
usage: my-company <command> [<args>]

commands:
  hosts                     サーバのホスト名一覧を表示
  git-log-remote [<hosts>]  デプロイされていない差分コミットがあれば表示
  env-diff [<hosts>]        環境変数の設定漏れを表示
  check-update [<hosts>]    yum パッケージの更新を表示
  self-upgrade              my-company コマンドを更新
  update [<hosts>]          yum パッケージを更新

記事内では引数処理やループ処理などのボイラープレートは省いてあります。


hosts - サーバのホスト名一覧を表示する

$HOME/.ssh/config から Host を抽出する。 peco などと組み合わせると便利。

$ my-company hosts
my-company-vpn
my-company-service-prod-bastion
my-company-service-prod-web-1
my-company-service-prod-admin
my-company-service-prod-api

実装

ホスト名をチーム内で合わせると活きる

my-company-hosts() {
  cat ${HOME}/.ssh/config | grep 'Host my-company-' | grep -v '*' | awk '{print $2}'
}

check-update - yum パッケージの更新を表示

$ my-company check-update
# my-company-service-stg-web
        Loaded plugins: priorities, update-motd, upgrade-helper
        Security: kernel-4.4.41-36.55.amzn1.x86_64 is an installed security update
        Security: kernel-4.4.19-29.55.amzn1.x86_64 is the currently running version

実装

対象のホストへ向けてリモート実行をする。

ssh -A $host yum check-update

update - yum パッケージを更新する

$ my-company update
# my-company-service-stg-web
Loaded plugins: priorities, update-motd, upgrade-helper
No packages marked for update

実装

対象のホストへ向けてリモート実行をする。

bin/my-company
function my-company-update {
    ssh -A $host sudo yum -y update
}

git-log-remote - デプロイされていないコミットがあれば表示する

本番・ステージングのリリースついでに全環境のデプロイ漏れを確認する癖がつく

$ my-company git-log-remote                                                                                         
# my-company-service-prod-web

# my-company-service-stg-web
        > 0123abcde キャッシュさせない

実装

対象のホストで git log を実行して master ブランチとの差分を出力します。

my-company
function my-company-git-log-remote() {
  ssh -A "$host" 2>/dev/null <<'EOT'
    cd /var/www/html && \
    git fetch && \
    git log --oneline --left-right HEAD..origin/master | perl -pe 's/^/\t/g'
EOT
}

phan-filter - phan のログからノイズを除去します

Lint の出力に含まれるノイズをフィルタリングする。

$ phan -ophan-orig.log; cat phan-orig.log \
    | my-company phan-filter > phan-filtered.log

Composer scripts での利用例

composer.json
{
    "scripts": {
        "lint": "phan --progress-bar -oapp/tmp/phan-original.log ; cat app/tmp/phan-original.log | my-company phan-filter > app/tmp/phan-filtered.log"
    }
}

実装

参考: Phan静的解析がもたらす大PHP型検査時代 - pixiv inside

my-company-phan-filter() {
  cd "$(dirname $0)/../"
  php lib/phan-filter.php < /dev/stdin
}
lib/phan-filter.php
<?php

$const = [
    'undeclared type \ComponentCollection',
    'undeclared class \MissingViewException',
    'undeclared type \Model',
    'undeclared type \View',
    'PhanRedefineClass Class \AppHelper defined',
];

while ($line = fgets(STDIN)) {
    foreach ($const as $c) {
        if (strpos($line, $c) !== false) {
            goto next;
        }
    }

    echo $line;
next:
}

self-upgrade - my-company コマンドを更新

$ my-company self-upgrade
Already up-to-date.

実装

bin/my-company
my-company-self-upgrade() {
  cd "$(dirname $0)/../"
  git pull
}

env-diff - 設定漏れの環境変数を出力する

Git 管理下にあるテンプレートGit 管理下にない設定ファイル の差分を検出します

$ my-company env-diff my-company-service-stg-web
# my-company-service-prod-web

# my-company-service-stg-web
array(3) {
  [0]=>
  string(13) "some_var_name"
}

実装

対象ホストで lib/env-diff.php をリモート実行します。

bin/my-company
function my-company-env-diff() {
  php_cmd=$(cat lib/check_env.php | sed -e 's/<?php//' | sed -e 's/\$/\\$/g')
  echo "# $host"
  echo "test \"\$(whereis php)\" != \"php:\" && php -r \"$php_cmd\"" | ssh $host || true
}

便利

$ my-company
usage: my-company <command> [<args>]

commands:
  hosts                     サーバのホスト名一覧を表示
  git-log-remote [<hosts>]  デプロイされていない差分コミットがあれば表示
  env-diff [<hosts>]        環境変数の設定漏れを表示
  check-update [<hosts>]    yum パッケージの更新を表示
  self-upgrade              my-company コマンドを更新
  update [<hosts>]          yum パッケージを更新

汎用コマンドの所感

  • 実行環境が統一されていると汎用化しやすい
  • Chat bot を整備しきれていない環境では汎用コマンドの方が楽なこともある
    • 例: Chat bot 化する前段階として導入する
  • サーバの管理台数が少なければ ssh -A のリモート実行でだいたい何とかなる
  • 踏み台を用意しておくと ssh -A により サーバ用の鍵ファイル を用意する手間が省ける
  • ちょっとしたドキュメント代わりに使えるかも
    • 例: スニペッツを吐き出すサブコマンドを用意する
4
3
0

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
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?