will and way

ただの自分用メモを人に伝える形式で書くことでわかりやすくまとめてるはずのブログ

Google App Scriptから直接Slackに通知

割と本気で家庭用Slack Botを作ってみた - 八発白中 がかなり、あついですね。

VPSはおもちゃ箱なんだなあと、ゆめがあるなあと感じます。

とはいえ、お金をかからない方法をとるという強かなスタンスもまた、アリです!

またまたやってみました。Google App Scriptの定期実行。

今回はヤマトからの未読メールかつ、不在通知メールがあれば、notificationチャンネルにメール内容を投稿し、さらにメールを既読にするGoogle App Script。

gist.github.com

これをGoogle App Scriptのcron機能で1時間毎とかに実行する

フックをDocsやらCalendarの更新などにすれば使いみちはいくらでもあるので、テンプレとして今後使えそう。

blog.matsuokah.jp

以前、Spread Sheetの情報をマスタとしてゴミの日の前日にSlackに翌日がなんのゴミの日かを通知cronを実装した時の話を書きましたが

IFTTTを介さずともslackに通知できるし今後はIF GAS Then Slackスキームで行こうと思う。

fluentd(td-agent)でGoogle Cloud Storageにログをためる

初めてrubyを書いた。mixinとかいろいろ省略してかけるとかaliasをメソッドに貼るとか便利だなーというのが感想。

gemの公開もbundleコマンドでさくさく出来たのでこれは開発者にとってかなり魅力的なのでは。エコシステム?が素晴らしい。

さて、本題ですが、今、開発中のfluentdのoutputプラグインの使い方をメモ。Fluentd(td-agent)からGoogle Cloud Storageにログのファイルを直接置くという役割。

ルビー書き始めて2日なのでまだまだクソース&開発中です。まさかりまってます

gem

fluent-plugin-google-cloud-storage-out | RubyGems.org | your community gem host

github

github.com

モチベーション

Google Cloud Storage (以下、GCS)にとりあえずログを置く

GCSに置いとけばあとからBigQueryにインポートできるので、生ログをとりあえずここにためて置くと良さそう。

BigQueryにストリーミングインサートするとお金がかかるし、安定してなかった?という話もあったので、直接GCSに置くことに。

とはいえ、各ホストからログのアグリゲーションをするのもめんどくさそう。いっそ各々でtd-agentが動いてるのでそこから送っちゃおうという魂胆

さらには、オンプレミスで減価償却するよりもクラウドの値段が下がるほうが速いんじゃないのかな。GCSはとてもやすい。

一応既存のものはあったが

fluent-plugin-google-cloud-storage | RubyGems.org | your community gem host

というgemがすでにあったが、最新のGoogle Client APIや認証の形式についていっていないようだし、gem公開をしたかったのでw

使い方

インストール

よしなにgemで

Service Accountを登録し、認証情報(.json)をよしなに配置

GCSのAPI状態がEnableか確認して、鍵を作成。

td-agent.confを編集

<match *.log>
  type google_cloud_storage_out
  service_account_json_key_path /etc/td-agent/client_secrets.json
  bucket_id log-hangar
  path activity/%Y_%m_%d/${hostname}_%H%M_${unique}
  unique_strategy timestamp
  unique_format %S
  format json
  compress gzip

  buffer_type memory
  buffer_chunk_limit 100m
</match>
  • service_account_json_key_path 名の通り、jsonキーのパス
  • bucket_id => bucketは現状は作成済みでなければならない
  • path => GCS上のファイルパス。unique_strategyを設定する場合、${unique}をパスに含まなければならない。含まない場合はローテートされるまえにバッファのフラッシュが2回起きると上書きされてしまう
  • unique_strategy => [increment, timestamp, chunk_id]から選択。${unique}をどう置換するかの実装を選ぶ。
    • increment => 0, 1, 2, ...とカウンタが使われる
    • timestamp => フォーマットに従って、バッファフラッシュ時のタイムスタンプに置換
    • chunk_id => バッファのchunkのユニークIDに置換する
  • unique_format => timestampの場合に使われる。
  • format => デフォルトのfileアウトと同じ実装

再起動

よしなに.テスト時はバッファのmemory容量を10kとか低い値にするとテストしやすかった

参考にしたもの

展望

  • ドキュメント
  • ユニットテスト
  • ストレステスト
  • エラーハンドリング
  • コードスタイルに合わせる
  • 英語を良くする

まとめ

fluentdがプラガブルなので、素人でもとりあえず動くプラグインはかけた。fluentdすごい

slackと仲良くなる

まず、公式ドキュメントよめ

get.slack.help

公式読まない人は何をやっても使いこなせないでしょう。と自分にいいきかせ読んでみたら、とても良かったので使えそうなやつをカテゴリ別にメモしていきます。

Hipchat → Slack移行なう

もともとHipchatを使っていて、先月くらいから移行中。複数のチームを共存できるのイイ。個人(家用)と会社用でつかっています。

個人のアカウントはIFTTT連携して、Google App Scriptから前日に翌日は「なんのゴミの日なのか?」をSlackに通知するために使ったり。

本格的につかうならショートカットとスニペットは覚えなくては

Hipchat使ってた時には⌘ + t⌘ + [, ⌘ + ]くらいしか使ってなかったのですが、公式に載ってるショートカットがなさすぎる。

それに対し、slackはチャンネル切り替えなどの基本動作だけで15個。スバラ!

設定

Display Options

✅ show times with 24-hour clock → 24時間表記(個人的にこっちがすきなので)

Advanced Options

✅ Whtn typing code with ```, Enter should not send the message → コードを入力しようとした時はEnterでメッセージを送らない。(対となる```で閉じたあとにEnterで送信は有効化される)
✅ List public and privte channels separately → 公開と非公開のチャンネルのリストを分ける

ショートカット

Slack keyboard shortcuts

Chromeとショートカットが同じ or 似ていて覚えやすいショートカット

コンテキストスイッチが少ないのでありがたい。

Chrome Shortcut Slack
拡大/縮小/元の縮尺 ⌘ + +
⌘ + -
⌘ + 0
拡大
縮小
元の縮尺
ブラウザフォワード/バック ⌘ + ]
⌘ + [
1つ先/前に見ていたチャンネル
カレントタブのリロード ⌘ + R カレントアカウントのリロード
N番目のタブを開く ⌘ + [1-9] N番目のチームを開く
次/前のタブを開く ⌘ + shift + ]
⌘ + shift + [
次/前のチームを開く
形式に合わせてペースト ⌘ + shift + v スニペットペースト
設定を開く ⌘ + , 設定を開く

あまり使わないショートカットがあるにせよ、これだけで覚えやすい。

⌘ + ,に限っては当然のごとく。

その他に積極的に使うショートカット

Shortcut 動作
Alt + ↑
Alt + ↓
上/下のチャンネルを開く
Shift + Alt + ↑
Shift + Alt + ↓
未読がある上/下のチャンネルを開く
Esc 開いているチャンネルを既読にする
⌘ + f 開いてるチャンネルをターゲットに検索する
⌘ + / ショートカットチートシート表示
Alt + messageをクリック そこから未読扱いにする。
後で読む的な使い方
⌘ + Shift + m 自分へのメンションのリストを開く

/コマンド

Using slash commands

コマンド 動作
/leave チャンネルから退出
/keys ショートカットチートシート表示
/who チャンネルにいる人をリスト表示
/search query 検索

searchのクエリについて

Searching in Slack

どこのだれからか
  • in:[channel|user]
  • from:[user|me]
メッセージに含む
  • has:[link|star|:絵文字:]
いつ
  • befor:
  • after:
  • on:
  • during:

時間指定に使えるのは

  • today
  • yesterday
  • week
  • month
  • year
  • YYYY-MM-DD

ここは少し、わかっていないところ。

まとめると覚えるのでよい。

Vagrant公式ドキュメントを見るときに気をつけたい

VagrantのprovisionerにAnsible

Vagrantにはprovisionerが幾つか、用意されています。

メジャーなのはchef-clientchef-soloかと思います。vagrant-omunibusというプラグインがあるので、実行環境を整えやすいですし。

また、簡単なプロビジョニングであればshellで済みます。

一方で、自分はよくAnsibleを使っています。最近Ansible熱があるというだけです笑

OSXの環境を整えるのもAnsibleでやったりしています。

話は戻りまして、Vagrant上にDockerのプロビジョニング環境を作るときにもprovisionerにAnsibleを使いました。

blog.matsuokah.jp

この時、公式ドキュメントを見ていて、設定項目がすくなくないか?と思ったのですがVagrantにはAnsibleとAnsible localの2種類があるため、共通のオプションは別ページとのこと。

Optionのリストだけを見ていて、説明をすっ飛ばしたので気づかなかった。。。

Ansibleの共通オプションはCommon Ansible Options - Provisioning | Vagrant by HashiCorpを見るべし。また、気をつけたいのがこのページはprovisionerのカラムからは直接飛べないので、一度Ansibleのページを開き、OPTIONSの説明の

This section lists the specific options for the Ansible (remote) provisioner. In addition to the options listed below, this provisioner supports the common options for both Ansible provisioners.

この部分のリンクを開かねばなりません。

副産物

説明がないものと思い込み、Vagrantgithubのソースを読んでおりました。

github.com

この部分を読めば、オプションが書いてあります。また、他のprovisionerも同様です。

DocsへはPRできる模様

VagrantのDocsの右下にEdit this pageというリンクが有り、クリックするとgithub上で対応するページのドキュメントのソースに飛びます。きっと、PRを受け入れてくれるのでしょう。

https://github.com/mitchellh/vagrant/tree/master/website/docs

個人的にこういうスタンスになっている事自体が、すごいな〜と思いました。

壁美人をつかったという話

C++初心者ならビルドはBazelでラクしちゃいましょうの主役となったBazelや100円でオフィスのデスクをスッキリさせたという報告。でまな板たて使うというアイディアを教えてくれた、会社の先輩に年末に

「壁美人いいよ。特に賃貸だったら」

と言われ、我が家でも導入してみた。

壁美人とは

一言で言うと、画鋲や釘など大きな穴を開けずに壁にフックをつけたり、テレビを設置したりできるというもの。

画鋲でも穴がひどいと、壁紙張り替えになって敷金なくなっちゃう場合があるので。。。

パッケージがこれ

f:id:matsuokah:20160102161355j:plain

ホチキスでとめる

まさかのホチキス。家にあるので、工具も特別なものが不要なところがとてもありがたい。

試しにつけてみる

f:id:matsuokah:20160102163751p:plain

拡大してみる

f:id:matsuokah:20160102163749p:plain

比較用に画鋲も刺してみたけど、画鋲のあなは目立つ

ホチキス針は専用針

完全に憶測なのですが、ホチキスの芯はステンレス。なぜなら、文房具屋で売ってるものは鉄なのでさびやすいです。

サビで壁が赤くならないようになってるんですね〜

見た目が不格好じゃない?

自分もそう思いましたが、隠せました!

f:id:matsuokah:20160102164849p:plain

もっとリース飾りたいと言われたので、追加購入します

Mac OSXの設定をAnsibleで9割以上自動化する

f:id:matsuokah:20160102014950p:plain 自分のMBPRetinaは3年前のモデルでアップデートする度に、スリープからの復帰画面がおかしくなったりしたのでOSのクリーンインストールも兼ねました。データはほとんどクラウド化されてるので残るは設定ファイルのみ。0から設定するのだるい。

今後、0スタートするときも苦労したくない!ポチポチクリックしたくない!ということで

mawatari.jp

この記事にインスパイアされて、自分もやったので、ハマりどころとかプラスで対応したところをメモ。 9割はこれで行ける、残り1割はアプリにログインした時にクラウド同期してくれる系(Chromeとか).

githubにdotfilesやらshellにするよりも比較的容易にprogramaticallyにできたのでやってよかった。

github.com

対応したこと

  • ansibleのインストール
  • brewのインストール
  • brewによるアプリのインストール
  • brew-caskによるアプリのインストール
  • defaultsコマンドによるMacの設定自動化
  • zshの設定
  • vimの設定
  • gitの設定
  • sshの設定
  • xcodeプラグインパッケージマネージャのインストール

xcodeインストールして利用規約に許諾したあとに cd /path/to/repository-top && makeでプロビジョニングが終わるようになっています。

ディレクトリ構成

provisioning ❯❯❯ tree -L 1
.
├── Context.sh
├── InstallAnsible.sh
├── Makefile
├── PlayAnsible.sh
├── README.md
└── provisioning/
  • Context.sh ... 実行環境のコンテキスト
  • InstallAnsible.sh ... pipがなければインストール、ansibleがなければインストール
  • Makefile ... InstallAnsible, PlayAnsible.shのフック
  • PlayAnsible.sh ... Ansibleの実行
  • provisioning ... Ansibleの設定集

brewのインストール

はじめに紹介したリンクではbrewでansibleをインストールしており、brewがある前提でansibleが組まれています。

もっと自動化したかったのでansibleを先にインストールし、brewのroleのタスク内でインストールするようい順番を変えました。

Ansibleのインストール

InstallAnsible.sh
which pip >/dev/null 2>&1
if [ $? -ne 0 ];
then
  echo "not found command pip"
  echo "install pip"
  sudo easy_install pip
fi

which ansible >/dev/null 2>&1
if [ $? -ne 0 ];
then
  echo "not found command ansible"
  echo "install ansible"
  sudo pip install ansible
fi

easy_installでpipをインストールし、pipでansibleをインストールしています。自分の環境ではsudoを付ける必要がありました。

改めてbrewのインストール

roles/brew/tasks/main.ymlの一部抜粋
- name: update brew
  register: result
  ignore_errors: True
  command: >
    brew update

- name: get brew installer
  get_url: url=https://raw.githubusercontent.com/Homebrew/install/master/install dest=/tmp/brew_install
  when: result|failed

- name: proceed brew installer
  command: >
    ruby /tmp/brew_install
  when: result|failed

brewのアップデートに失敗すればコマンドがないという前提のもと、なければbrewをインストールしています。

brewや後述するXcodeのAlcatraz、VimのNeoBundleのようにインストールスクリプトが準備されていると、楽ですね〜。

あとは、インストールするアプリを列挙するのみ

github.com

上記がbrew-caskでインストールできるアプリのリストですが、cloneしないと、全アプリのリストを確認できません。面倒な場合は、リポジトリ内検索でしらべるとヒットしてくれたりします。

defaultsコマンドによる設定値の変更

http://docs.ansible.com/ansible/osx_defaults_module.htmlによると

- osx_defaults:
  domain=NSGlobalDomain
  key=AppleMeasurementUnits
  type=string value=Centimeters
  state=present

osx_defaultsモジュールがある!Ansible先生有能すぎ!

ただし、Ansible2.0系以上で使えるのですがまだrc版で、2016年1月時点ではpip install ansibleでインストールされるstableなバージョンは1.9.4です。

したがって、実行するとモジュールがないと怒られてしまいます。

ansible --versionで取れるバージョンのメジャーバージョンが1ならcommand、Ansibleが2.0系ならosx_defaultsによる実行するタスクを用意しroleを分け、playbook_defaults.ymlとplaybook_defaults_v1.ymlを呼び分けるようにしました。

defaults内のmain.ymlは共有したいのでシンボリックリンクで対応。

本当は1つのroleにして、ansible_version.majorで取得した値でtaskのincludeを切り替えようと思ったのですが、includeされた設定はすべて構文チェックをされるらしくだめでした。

また、ansible_versionという変数があること自体は公式ドキュメントに記載されておらず、このissueで知りました。2系でundefinedになってしまうとのことだが、修正されているようです。

defaultsの設定

roles/defaults/defaults/main.ymlの一部を抜粋
#
# see also https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/defaults.1.html 
# 

mac_defaults_settings:
  - {
    domain: com.apple.ImageCapture,
    key: disableHotPlug,
    type: bool,
    value: false,
  }

mac_global_domain_defaults_settings:
  - {
    key: InitialKeyRepeat,
    type: int,
    value: 13,
  }
  - {
    key: KeyRepeat,
    type: int,
    value: 3,
  }

設定が増えてきたらドメイン別にファイルを分けて、includeするといいかも。

global_domainの設定に関してはドメイン指定が不要なので別リストとして持っています。あとは、これらをループして設定するタスクを書けばOK

defaults_v1/tasks/main.yml
- name: 
  command: >
    defaults write {{ item.domain }} {{ item.key }} -{{ item.type }} {{ item.value }}
  with_items: mac_defaults_settings
  when: mac_defaults_settings

- name: 
  command: >
    defaults write -g {{ item.key }} -{{ item.type }} {{ item.value }}
  with_items: mac_global_domain_defaults_settings
  when: mac_global_domain_defaults_settings

一部抜粋でしたのが設定できる値はいろいろあるので、こちらも参照ください

blog.matsuokah.jp

zshのインストールと設定

roles/zshではzshプラグインマネージャantigenpreztoのインストールを行っています。

ここはハマりました。antigenの設定ファイルと読み込むようにして、ログインシェルとしてzshを設定したあとでもantigenコマンドがnot foundに。

したがって少し強引にantigenコマンドを呼んでいます

- name: append source antigen
  shell: >
    echo "{{source_antigen}}" >> ~/.zshrc
  when: grep_command.rc != 0

- name: install prezto through antigen
  shell: >
    source ~/.zshrc && antigen bundle sorin-ionescu/prezto
    executable={{which_zsh.stdout}}
  ignore_errors: True
zshをログインシェルに設定

以下の設定ではログインシェルにzshを設定しており、 このときにパスワードの入力が必要です。パスワードの入力に失敗しても3回までリトライするようにしています。

- name: change login shell
  shell: >
    chpass -s {{which_zsh.stdout}}
  register: result
  until: result.rc == 0
  retries: 3

パスワードはタスクの序盤で入力が要求されるのでの直前に

osascript -e 'display notification "Prease input password in terminal" with title "osx-provisioning"'

を実行してあげると

f:id:matsuokah:20160102003827p:plain

こんな感じで、notiをしてくれます。

sayコマンドで喋ってもらうのもいいですね(笑)

xcodeプラグインパッケージマネージャ(Alcatraz)のインストール

これはダウンロードしてシェルを実行するだけでした。

sshの設定

鍵をリポジトリに含むわけにも行かないので、ここはほぼ手作業。.sshで~/sshシンボリックリンクを貼るようにしました。

sshディレクトリにプライベートリポジトリを配置すれば良いかなと。submoduleにしなかったのはpublicリポジトリからprivateリポジトリに依存するのは微妙だなと思ったので。

設定ファイルのImport

ほとんどのアプリでは設定のexportとimport機能がついています。例えば、karabenerは設定ファイルをshellとしてexportしてくれるので、exportしておいてkarabenerをインストール後にshell実行すれば設定を復元することができます。

こんな感じ

$ /Applications/Karabiner.app/Contents/Library/bin/karabiner export
#!/bin/sh

cli=/Applications/Karabiner.app/Contents/Library/bin/karabiner

$cli set remap.doublepresscommandQ 1
/bin/echo -n .

今回、自分はこの設定たちをexportする前にSSDのクリーンをしてしまったので後悔。これから作っていく予定。

まとめ

これでPC買い替えも、会社のPCの環境構築も、クリーンインストールも怖くない!!そして、まだまだdefaultsの設定が足りてないのでやらねば!

参考

ブログなど

公式docks

please fork me!

github.com

追記

blog.matsuokah.jp

brew caskでインストールしていたアプリを幾つか、AppStore経由でインストールできるように改修した。

OSXのコマンドラインからすると捗った設定リスト

mobilelaby.com

上記で紹介されていたiPhoneを接続した時に写真アプリの自動起動を防ぐターミナルでのコマンド

defaults write com.apple.ImageCapture disableHotPlug -bool NO

これ便利。実は他にもある。さらに、コマンドライン経由から設定することで、設定アプリではUI上不可能な値も設定できるので設定してまとめてみた。

フォーマット

まずはdefaultsコマンドのフォーマットから

一般的なフォーマット

サードパーティ製のアプリも含め、Dockの設定などがこちら。

書き込み
defaults write DOMAIN KEY -TYPE VALUE
読み込み
defaults read DOMAIN

グローバルドメイン

グローバルドメインと呼ばれる領域がある。これはジェネラルな内容、キーボードのキーリピート設定やマウスのカーソル移動速度などが設定される領域。

書き込み
defaults write -g KEY -TYPE VALUE
読み込み
defaults read -g

設定できるドメインを調べる

man defaultsしましょう。マニュアルを読もう。

defaults domains

↑を実行すると設定可能なドメインのリストの取得ができます。

~/ ❯❯❯ defaults domains                                                        
2BUA8C4S2C.com.agilebits.onepassword4-helper, MobileMeAccounts, com.agilebits.onepassword4, com.alfredapp.Alfred, com.apple.AddressBook, com.apple.AppleMultitouchMouse, com.apple.AppleMultitouchTrackpad, com.apple.BezelServices, com.apple.CalendarAgent, com.apple.CallHistorySyncHelper, com.apple.CharacterPicker, com.apple.CloudPhotosConfiguration, com.apple.CommCenter.counts, com.apple.CoreGraphics, com.apple.Dictionary, com.apple.FolderActionsDispatcher, com.apple.GEO,
.
.
.

したがって、defaults read domainして設定したいアプリのドメインを調べて目的のキーのバリューを変更すればいいことになります。

全部の設定値をダンプするワンライナー
echo $(defaults domains) | tr -s ',' '\n' | while read domain; do; defaults read $domain; done;

設定を反映する

Finderなどは設定がキャッシュされていて、プロセスを再起動しないと反映されません。

基本的にはkillall APPLICATION_NAMEでいけます。Finderならkillall Finder

また、KeyboardのKeyrepeat設定は再起動不要、Trackpadはプロセスを見つけられず再ログインで対処しています。

Trackpad周り

タップでクリックを許可

defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -int 1

カーソルの移動速度を変える

defaults write -g com.apple.trackpad.scaling -float 1

遅 0 ~ N 速

隠しファイルをFinder上で可視化する

defaults write com.apple.finder AppleShowAllFiles true

すべての拡張子を表示する

defaults write NSGlobalDomain AppleShowAllExtensions -bool true

Dock

Dockの表示位置

defaults write com.apple.dock orientation -string "left"

left, bottom, rightが設定可能

オンマウスでのアイコンサイズズーム

defaults write com.apple.dock magnification -bool true

Dockを自動的に隠す

defaults write com.apple.dock autohide -bool true

アイコンサイズの変更

defaults write com.apple.dock tilesize -int 50

KeyRepeat

InitialKeyRepeat

defaults write -g InitialKeyRepeat -int 13

速 0 ~ N 遅

KeyRepeatが始まるまでのディレイ。設定アプリではmost fastで15までしか設定できないです。

KeyRepeat

defaults write -g InitialKeyRepeat -int 3

速 0 ~ N 遅

KeyRepeat中のディレイ。設定アプリでは2->6と設定値が飛んでしまうので1単位で設定できないです。

参照

www.defaults-write.com

ここを参照すればいろいろ便利に設定してるし、設定の説明をしてくれてる方々がいるのでおすすめ〜

応用

こんな感じでコマンドライン化することによって設定を定義して置けるようになるのが副産物。

Ansible化したのがこちら

blog.matsuokah.jp

追記

どこのことだろう?> "ここを参照すればいろいろ便利に設定してるし、設定の説明をしてくれてる方々がいる"

参照先を間違っていたので、修正しました。ご指摘ありがとうございます〜!