ふり返る暇なんて無いね

日々のメモ書きをつらつらと。メインブログに書くほどでもないことを流してます

sudoersにはワイルドカードが使える

デーモン管理はUpstartでやっていて、Webアプリケーションサーバwebapp-${project_name}、ジョブワーカーはjobworker-${project_nameみたいな感じの名前で定義しています。

serviceコマンドはrootじゃないと実行出来ないのですが、デプロイのときなど、大量のサーバにいちいちパスワード打てないので、特定のユーザにNOPASSWORDで実行出来るようにします。 ただ、何も考えず/etc/sudoersに設定していくとサブコマンド毎に指定していかないといけないのでなかなか辛いです。

app ALL=(root) NOPASSWD: /usr/bin/service webapp-project_1 restart
app ALL=(root) NOPASSWD: /usr/bin/service webapp-project_1 reload
app ALL=(root) NOPASSWD: /usr/bin/service webapp-project_1 stop
app ALL=(root) NOPASSWD: /usr/bin/service webapp-project_1 start
app ALL=(root) NOPASSWD: /usr/bin/service webapp-project_2 restart
app ALL=(root) NOPASSWD: /usr/bin/service webapp-project_2 reload
app ALL=(root) NOPASSWD: /usr/bin/service webapp-project_2 stop
app ALL=(root) NOPASSWD: /usr/bin/service webapp-project_2 start
app ALL=(root) NOPASSWD: /usr/bin/service jobworker-project_1 restart
app ALL=(root) NOPASSWD: /usr/bin/service jobworker-project_1 reload
app ALL=(root) NOPASSWD: /usr/bin/service jobworker-project_1 stop
app ALL=(root) NOPASSWD: /usr/bin/service jobworker-project_1 start

かといって、こうしてしまうと、全てのUpstart管理のデーモンをパスワード無しで操作出来てしまうのでかなり危険です。

app ALL=(root) NOPASSWD: /usr/bin/service

なんかうまい方法無いかなとsudoersのmanpageを引いていたらワイルドカードが使えるらしいので、こうしてみました。 これなら権限を絞りつつ、記述も簡潔になって良い感じです。

app ALL=(root) NOPASSWD: /usr/bin/service webapp-* *
app ALL=(root) NOPASSWD: /usr/bin/service jobworker-* *

※ この記述あくまで一例だからこのまま使ってることを意味しないです。念為

fabricで現在実行中のhostを取りたい

A. env.host を使うと良い。

hostによって配るcrontabが違っていて、レポジトリ的には ${HOSTNAME}.crontab みたいな感じでhost名を含むファイル名で置いてあるときに、どうしたらうまく配れるかなと考えた結果 env.host で実行中のhost名が取れるのでそいつを利用した。

from fabric.api import sudo, env
from fabric.decorators import task

@task
def some_task(project):
    src = "/opt/%s/config/crontab/%s.crontab" % (project, env.host)
    dst = "/etc/cron.d/%s" % project
    sudo("if [ -e $src ];then cp %s %s; fi" % (src, dst))

わざわざワークツリーに移動しなくてもgit操作したい

今まで、ワークツリーにいちいち移動してから、gitの操作してたんですが、 --git-dir で指定してあげればその必要も無いという知見を得ました。

今まではこうしてたのを、

cd /path/to/repos/
git log

こうしてあげることで、ディレクトリの移動が必要無くgitの操作ができます。

git --git-dir=/path/to/repos/.git --work-tree=/path/to/repos/ log

古めのgitは上記の方法じゃないとダメなんですが、1.8.5からは -C オプションが使えるようになってるので、こちらを利用した方が良いです。

git -C /path/to/repos/ log

べんり。

GitHubはsvn対応していたらしい

そういうのを昔どっかで聞いて、ネタじゃないの?とか思って居たんですが、ふとさっき思い出して、試してみたら、普通にcheckoutできた。

% svn checkout https://github.com/masasuzu/resume
A    resume/branches
A    resume/trunk
A    resume/trunk/README.md
Checked out revision 5.

commitもできる。

% svn commit -m 'cpan => CPAN'
Authentication realm: <https://github.com:443> GitHub
Password for 'masasuzu':

Committed revision 8.

なるほど。ちゃんと反映されてる

参照

svnだから特定のディレクトリからチェックアウトするということもできるので、使いようによっては便利かも。

CodeDeploy-Agent をUbuntu12.04でもインストールしたい

  • ※そもそも、サポート対象外のディストリビューションのバージョンなので、ちゃんと動くかどうかはまったく保証出来ません。

  • ※前提として、awsコマンドインストール済みで、CodeDeployなどの各種設定済みであること

Ubuntu12.04でaws deploy installしようとするとruby2.0が無いのでインストール失敗します。

E: Unable to locate package ruby2.0
E: Couldn't find any package by regex 'ruby2.0'
Installing the AWS CodeDeploy Agent... ERROR
Command '['apt-get', '-y', 'install', 'ruby2.0']' returned non-zero exit status 100
Install the AWS CodeDeploy Agent on the on-premises instance by following the instructions in "Configure Existing On-Premises Instances by Using AWS CodeDeploy" in the AWS CodeDeploy User Guide.

そこで、brightboxのレポジトリにruby2.0があるので、追加してあげた後にインストールしてあげると、うまくCodeDeploy-Agentがインストールできます。

apt-get install python-software-properties
add-apt-repository ppa:brightbox/ruby-ng
apt-get update
apt-get install ruby2.0


aws deploy install --config-file codedeploy.onpremises.yml --override-config --region ap-northeast-1

ひとまず、動いている模様です。

# service codedeploy-agent status
The AWS CodeDeploy agent is running as PID 18324

# tail -F /var/log/aws/codedeploy-agent/codedeploy-agent.log
2015-11-25 15:50:00 INFO  [codedeploy-agent(18708)]: master 18708: Spawned child 1/1
2015-11-25 15:50:01 INFO  [codedeploy-agent(18708)]: Started master 18708 with 1 children
2015-11-25 15:51:01 INFO  [codedeploy-agent(18712)]: [Aws::CodeDeployCommand::Client 200 61.042376 0 retries] poll_host_command(host_identifier:"arn:aws:iam::1234:user/deploy")

2015-11-25 15:52:03 INFO  [codedeploy-agent(18712)]: [Aws::CodeDeployCommand::Client 200 61.021466 0 retries] poll_host_command(host_identifier:"arn:aws:iam::1234:user/deploy")

AWS CodeDeployをオンプレミスで使うにあたっての料金に関してざっくり計算

https://aws.amazon.com/jp/codedeploy/pricing/

1台に対して1回デプロイする毎に$0.02かかる ざっくりの計算だと、1日あたり20回くらいデプロイがあるとし、各プロジェクトの平均台数が30台とする。 これを計算すると1日当たり$12。

  • (20回) * (30台) * ($0.02) = $12

1ヶ月20営業日換算ですると$240

  • ($12) * (20営業日) = $240

$1 == 120円で計算すると、28800円。

これに追加して、s3などの使用料金がかかかる。 なお、6ヶ月間の無料枠にはAWS CodeDeployは含まれてはいない模様。

http://aws.amazon.com/jp/free/

月あたり約3万円をどう取るか。AWSにあるインスタンスに対してデプロイするときは1台当たりの$0.02というのはかからない。 要はAWS移行しろとのAWSからの思し召しだ。

pyenvでpythonをビルドしたときにいくつかライブラリが足りないと怒られた

Ubuntu12.04な環境です。

2.7.10をビルドしようとすると、いくつかライブラリがないと怒られたのでした。

% pyenv install 2.7.10
Downloading Python-2.7.10.tgz...
-> https://yyuu.github.io/pythons/eda8ce6eec03e74991abb5384170e7c65fcd7522e409b8e83d7e6372add0f12a
Installing Python-2.7.10...
Ignoring potentially dangerous file name ../Python-2.7.10/Lib/site.py
patching file ./Lib/site.py
WARNING: The Python readline extension was not compiled. Missing the GNU readline lib?
WARNING: The Python bz2 extension was not compiled. Missing the bzip2 lib?
Installed Python-2.7.10 to /home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10

dev用のパッケージがいくつかたりないパターンなのでbz2とreadlineをここで入れる。

sudo aptitude update
sudo aptitude install libbz2-dev  libreadline-dev

※今回はすでに入っていて怒られてないけどたぶんlibssl-devも必要かも

再度実行すると、warningが無くなってめでたしめでたし

% pyenv install 2.7.10
pyenv: /home/masashi/.anyenv/envs/pyenv/versions/2.7.10 already exists
continue with installation? (y/N) y
Downloading Python-2.7.10.tgz...
-> https://yyuu.github.io/pythons/eda8ce6eec03e74991abb5384170e7c65fcd7522e409b8e83d7e6372add0f12a
Installing Python-2.7.10...
Ignoring potentially dangerous file name ../Python-2.7.10/Lib/site.py
patching file ./Lib/site.py
Installed Python-2.7.10 to /home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10

pyenvで入れたpythonでUnicodeEncodeErrorと怒られる

easy_installだとちゃんとインストールできる。なんで?

Ubuntu 12.04の環境です。

% pip install fabric
Collecting fabric
Exception:
Traceback (most recent call last):
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/basecommand.py", line 211, in main
    status = self.run(options, args)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/commands/install.py", line 294, in run
    requirement_set.prepare_files(finder)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/req/req_set.py", line 334, in prepare_files
    functools.partial(self._prepare_file, finder))
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/req/req_set.py", line 321, in _walk_req_to_install
    more_reqs = handler(req_to_install)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/req/req_set.py", line 461, in _prepare_file
    req_to_install.populate_link(finder, self.upgrade)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/req/req_install.py", line 250, in populate_link
    self.link = finder.find_requirement(self, upgrade)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/index.py", line 486, in find_requirement
    all_versions = self._find_all_versions(req.name)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/index.py", line 404, in _find_all_versions
    index_locations = self._get_index_urls_locations(project_name)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/index.py", line 378, in _get_index_urls_locations
    page = self._get_page(main_index_url)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/index.py", line 818, in _get_page
    return HTMLPage.get_page(link, session=self.session)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/index.py", line 928, in get_page
    "Cache-Control": "max-age=600",
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/_vendor/requests/sessions.py", line 477, in get
    return self.request('GET', url, **kwargs)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/download.py", line 373, in request
    return super(PipSession, self).request(method, url, *args, **kwargs)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/_vendor/requests/sessions.py", line 465, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/_vendor/requests/sessions.py", line 573, in send
    r = adapter.send(request, **kwargs)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/_vendor/cachecontrol/adapter.py", line 36, in send
    cached_response = self.controller.cached_request(request)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/_vendor/cachecontrol/controller.py", line 102, in cached_request
    resp = self.serializer.loads(request, self.cache.get(cache_url))
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/_vendor/cachecontrol/serialize.py", line 108, in loads
    return getattr(self, "_loads_v{0}".format(ver))(request, data)
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/_vendor/cachecontrol/serialize.py", line 170, in _loads_v2
    cached["response"]["body"]
  File "/home/masasuzu/.anyenv/envs/pyenv/versions/2.7.10/lib/python2.7/site-packages/pip/_vendor/cachecontrol/serialize.py", line 20, in _b64_decode_bytes
    return base64.b64decode(b.encode("ascii"))
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4452: ordinal not in range(128)