こんなかんじすかね?
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)