インターフェース
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 を合わせる。
-
サーバに名前がついてると意思疎通しやすい
-
ハイフンで名前空間を作るようにすると機械的に扱いやすい
コマンドを作る
第一引数をサブコマンドとして解釈する。
以降の引数はサブコマンドへ移譲する。
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
実装
対象のホストへ向けてリモート実行をする。
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 ブランチとの差分を出力します。
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 での利用例
{
"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
}
<?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.
実装
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
をリモート実行します。
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
によりサーバ用の鍵ファイル
を用意する手間が省ける - ちょっとしたドキュメント代わりに使えるかも
- 例: スニペッツを吐き出すサブコマンドを用意する