Browse Month: December 2015

Homebrew cask の仕様がすこし変わった話

OS X 使いの皆さん定番の homebrew-cask ですが、おそらくクリスマス頃に仕様が少し変わったようです。

詳細のチケットは、こちらですが、要約すると、次のような感じになります。

  • 今まで ~/Applications へはすべてリンクだったが、移動するようになった
  • アプリケーションディレクトリは、すべて ~/Applications ではなく、/Applications になる
  • :target はしばらく動作するが、そのうち link に変更になる
  • Caskroom は、デフォルトで /opt/homebrew-cask/Caskroom となる
  • 上記のような理由で Caskroom 以下のバージョン番号のディレクトリは存在しなくなる

これはとても嬉しい変更です、例えば Google Chrome を homebrew-cask 経由でインストールした場合、今までだと 1Password が symlink のため動作しなかった問題があったので、これを根本的に解決できることになります。今までは、個人的にはまだ boxen を使っているので自動的に移動させるようなマニフェストを書いていましたが、これをしなくても済みます。

また、こちらのチケットにあるとおり、tap コマンドを使ったもののみに変更するようです。今までは、brew-cask というパッケージが必要でこれを更新するようになっていましたが、これから brew update コマンドのみで homebrew + homebrew-cask どちらもまとめて更新できるようになります。これはうれいしですね。

新しいシステムに切り替えるには、次のコマンドを実行するだけです。


$ brew uninstall --force brew-cask; brew update

簡単ですね、少し既存のもので試してみましたが、例えば google-chome をみると、次のようになっていますね。


$ brew cask info google-chrome
google-chrome: latest
Google Chrome
https://www.google.com/chrome/
/opt/boxen/homebrew-cask/Caskroom/google-chrome/latest (208 files, 184M)
https://github.com/caskroom/homebrew-cask/blob/master/Casks/google-chrome.rb
==> Contents
Google Chrome.app (app)
==> Caveats
The Mac App Store version of 1Password won't work with a Homebrew-Cask-linked Google Chrome. To bypass this limitation, you need to either:

+ Move Google Chrome to your /Applications directory (the app itself, not a symlink).
+ Install 1Password from outside the Mac App Store (licenses should transfer automatically, but you should contact AgileBits about it).

すべて同じようになっているのかなと思い、他のアプリでも確認してみましたが、なっていないようですね。


$ brew cask info flux
flux: 36-5
f.lux
https://justgetflux.com/
/opt/boxen/homebrew-cask/Caskroom/flux/36-5 (105 files, 2.7M)
https://github.com/caskroom/homebrew-cask/blob/master/Casks/flux.rb
==> Contents
Flux.app (app)

おそらく、順次変更しているのか、いつか内部的にまとめて切り替えるのかもしれません。

 

homebrew-cask を使っている人は、この機会に新しいアップデートに対応してみてはいかがでしょうか?

CentOS 7 で起動時と終了時にそれぞれ1回だけ実行するスクリプトを作成する

CentOS 7 で起動時と終了時にそれぞれ1回だけ実行するスクリプトを作成する方法を紹介したと思います。
次のような systemd スクリプトを作成します。


cat << EOF > /usr/lib/systemd/system/my-oneshot.service

[Unit]
Description=my-oneshot
After=network.service
Before=shutdown.target
Requires=network.service

[Service]
Type=oneshot
ExecStart=/bin/bash -v ‘/usr/local/bin/my-up.sh’
ExecStop=/bin/bash -v ‘/usr/local/bin/my-down.sh’
RemainAfterExit=true

[Install]
WantedBy=multi-user.target
EOF

次に systemd をリロードして、サービスを有効・開始します。


$ sudo systemctl daemon-reload
$ sudo systemctl enable my-oneshot
$ sudo systemctl start my-oneshot

これで、起動時には /usr/local/bin/my-up.sh が実行されて、終了時には /usr/local/bin/my-down.sh が実行されます。
もちろん、EC2 上でも利用可能ので、AutoScaling 時などに起動あるいは終了時に実行したいコマンドがあるときに設定すると便利ですよね。

CircleCI 上で、最初から定義されている環境変数について

CircleCI 便利ですが、CircleCI 上の EC2 ホスト上で、いくつか CircleCI 上の環境変数が定義されているので、一部まとめておきます。
公式ドキュメントは、こちらですね。

  • CI: 値 true、CI かどうか
  • CIRLECI: 値 true、CircleCI かどうか
  • CIRCLE_ARTIFACTS: 値 /tmp/circle-artifacts.XXXX
  • CIRCLE_BRANCH: 値 ブランチ名、対象のブランチ名
  • CIRCLE_BUILD_NUM: 値 整数、CircleCI 上でのビルド回数番号です
  • CIRCLE_COMPARE_URL: 値 URL、前回のビルドからの差分をあらわす URL、GitHub の場合 https://github.com/[project]/compare/xxx…yyy となります
  • CIRCLE_NODE_INDEX: 値 整数、CircleCI で並列で使っている場合 0 から始まるインデックス番号です
  • CIRCLE_NODE_TOTAL: 値 整数、CircleCI で並列で使っている場合合計のコンテナの数です
  • CIRCLE_PREVIOUS_BUILD_NUM: 値 整数、前回のビルド回数番号です、CIRCLE_BUILD_NUM -1 になります
  • CIRCLE_PROJECT_REPONAME: 値 リポジトリ名、対象のリポジトリ名です
  • CIRCLE_PROJECT_USENAME: 値 ユーザ名、対象のリポジトリを操作しているユーザ名です、GitHub の場合関連づけたオーガニゼーション名となるようです
  • CIRCLE_SHA1: 値 SHA1、コミットをあらわすハッシュ値です
  • CIRCLE_USERNAME: 値 ユーザ名、GitHub の場合自身の GitHub ユーザ名です
  • CI_TEST_REPOSTS: 値 パス、Junit のレポートパス名です
  • CI_PULL_REQUEST: プルリクエストです
  • CI_PULL_REQUESTS: プリクエストの URL です

これらの環境変数をうまく使い分けることで、CI の操作ができて便利です。
特に、個人的に CIRCLECI、CIRCLE_NODE_INDEX、CIRCLE_NODE_TOTAL、あたりはインフラ CI で駆使して使っていますので、別の機会に紹介したいと思います。

Fluentd s3 + ローカルファイルに出力する設定の紹介

このエントリは、Fluentd Advent Calendar 2015 – Qiita の 4 日目のエントリです。当日、勝手にエントリしています。

今日は、最近実施した非常によくある構成 Fluend 経由で s3 + ローカルファイルに出力する設定を本番環境(※ただし、正式本番稼働前)で設定したので、どこにもある情報ですが、一緒に設定された設定ファイルの例がなかなかなかったので紹介してみます。

OS は、CentOS 7 になります。td-agent は、公式の方でインストール します。

やりたいことしては、S3 のバケット上に、「YYYY/MM/DD/HH/タグ1_タグ2」ファイルとして出力して、ローカルファイルにも同じディレクトリ構成のファイルで、同時出力することになります。

まず、設定ファイルですが、次のようになりました。

<source>
  type forward
  bind 127.0.0.1
  port 24224
</source>

<match hoge.**>
  type copy

  <store>
    type forest
    subtype s3
    <template>
      id hoge-s3-${tag_parts[1]}
      path ${tag_parts[1]}/

      aws_key_id <AWS_ACCESS_KEY_ID>
      aws_sec_key <AWS_SECRET_ACCESS_KEY>
      s3_bucket hoge-bucket
      s3_region <AWS_DEFAULT_REGION>
      format json
      s3_object_key_format %{path}%{time_slice}_%{index}.log
      store_as json

      time_slice_format %Y/%m/%d/%H/${tag_parts[1]}_%Y%m%d%H%M_${tag_parts[2]}
      flush_interval 60s
      flush_at_shutdown true

      buffer_type file
      buffer_path /var/log/td-agent/.s3-${tag_parts[1]}_%Y%m%d%H%M_${tag_parts[2]}.log
      buffer_chunk_limit 64m
      buffer_queue_limit 32

      num_threads 1
    </template>
  </store>

  <store>
    type forest
    subtype file_alternative
    <template>
      id hoge-file-${tag_parts[1]}
      path /var/log/td-agent/${tag_parts[1]}/%Y/%m/%d/%H/${tag_parts[1]}_%Y%m%d%H%M_${tag_parts[2]}.log
      symlink_path /var/log/td-agent.log
      dir_mode 0750

      time_slice_format %Y%m%d%H%M
      flush_interval 0s
      flush_at_shutdown true

      buffer_type file
      buffer_path /var/log/td-agent/.${tag_parts[1]}_%Y%m%d%H%M_${tag_parts[2]}.log
      buffer_chunk_limit 64m
      buffer_queue_limit 32

      num_threads 1
    </template>
  </store>
</match>

プラグインは、設定ファイルから分かるとおり、fluentd-plugin-forestfluent-plugin-file-alternative、が必要なので、td-agent-gem 経由でインストールしておきます。


$ sudo /opt/td-agent/usr/sbin/td-agent-gem install --no-ri --no-rdoc fluentd-plugin-forest fluent-plugin-file-alternative

ここでちょっとハマったのは、ローカルファイルへ出力する file_alternative の実際の出力ファイルが「/var/log/td-agent/.YYYY/MM/DD/HH/ファイル名」となってしまって、/var/log/td-agent 以下とみるとドットディレクトリとしてしまったところでした。上の設定で、正しくファイルが出力されています。

これから、この環境で本番稼働前のベンチマークを実施して、buffer まわりのパラメータ、thread の調整などを行ってみるつもりです。

今回、監視まわりは Datadog を使っているので、別のエントリーで紹介したいと思います。