mysqldumpで欲しいレコードだけ抽出する
DATABASE.TABLEの特定のレコードだけをdumpで抜きたいとき。
mysqldump -uroot --where="id=100" DATABASE TABLE
とか
mysqldump -uroot --where="id in (100, 101, 102)" DATABASE TABLE
とか。--whereが使える。
例えばディレクトリの作成にinstallコマンドを使う
こんなことしたいとしますよね。
mkdir -p /path/to/dir chown 2gou /path/to/dir chgrp oretachino /path/to/dir chmod 700 /path/to/dir
chown 2gou.oretachino /path/to/dir
でもいいけど行数稼ぐために分けた。
同じことをするには、意外と知られてないけどinstall
使うと1コマンドでイナフ。
install -o 2gou -g oretachi -m 700 -d /path/to/dir
installのmanを見てみると
This install program copies files (often just compiled) into destination locations you choose. If you want to download and install a ready-to-use package on a GNU/Linux system, you should instead be using a package manager like yum(1) or apt-get(1).
とあります。このコマンドに気付いたのはrpmを作成しているときにspecファイルに書いてあったからで、specファイルを読むとinstallコマンドによるファイルコピー方法も分かります。
# Install systemd service files mkdir -p $RPM_BUILD_ROOT%{_unitdir} for s in httpd htcacheclean; do install -p -m 644 $RPM_SOURCE_DIR/${s}.service \ $RPM_BUILD_ROOT%{_unitdir}/${s}.service done
例えばCentOS7のhttpdパッケージ内%install
セクションですが、systemd用のファイルをコピーする時にはこんな感じで書いていたり。
コピーの部分に関しては以下の便利オプションがあるので
-p
: コピー元のタイムスタンプはそのまま-b
: ファイル内容に差異があればコピー先のバックアップを取得してからコピー
別ディレクトリに取ってあるバックアップ元のファイルを元の場所に戻したりするときにも便利かなあと思ったのだけれども
-m
を忘れるとデフォルトの755になってしまう- あらかじめコピー元のファイルのパーミッションを知ってないといけなくて面倒
- 再起コピーがないのでバックアップ元が複数階層あってもと同じ階層を再現出来ない
ので、日常だと最初に書いた空ディレクトリの作成が一番重宝するかなと思います。リストアは普通にcp -a
とかrsync
でやればよさそう。
CloudFront+S3の画像配信にリサイズ機能を追加する
CloudFront+S3の画像配信システムに、サムネイルとかに使う画像のリサイズ機能を追加してみる。
要するにオリジナル画像がこのURLだとすると、
http://xxx.cloudfront.net/sample.jpg
こういうURLで100×100にリサイズできるようにする。
http://xxx.cloudfront.net/resize/100x100/sample.jpg
システム構成
元の構成はこういうのを想定。
画像はS3に保存され、アクセスは全てCloudFront経由。
これをパスが/resize/で始まる場合は、画像変換サーバを通してリサイズするようにする。
画像変換サーバはEC2で、ちゃんとELBを使って冗長化もする。
既にELB+EC2でAPPサーバを運用しているなら、流用して追加コスト0で実現できるかも。
画像変換サーバの設定
今回はnginxのimage_filterモジュールを使う。
もちろんsmall_lightを使ってもいいし、自前で開発してもいい。
インストールはAmazonLinuxであれば、ただyum install nginxするだけ。
それ以外の場合ではたぶん、--with-http_image_filter_moduleをつけてnginxをコンパイルしないといけない。
※EPELのnginxは流石にバージョンが古すぎる。
image_filterもその1つなんだけど、AmazonLinuxの標準レポジトリのnginxは、公式rpmには含まれないいくつかのモジュールが追加されているので、確認してみると面白いかも。
# nginx -V ... configure arguments: ... --with-http_image_filter_module ...
サイズを完全に自由指定できるようにするには、こんな感じで設定する。
server { listen 80 default_server; server_name _; root /var/nginx_root; location ~ ^/resize/(\d+)x(\d+)/(.*)$ { set $width $1; set $height $2; set $path $3; image_filter resize $width $height; image_filter_jpeg_quality 90; rewrite ^ /$path break; } }
これでドキュメントルート配下の画像のリサイズが確認できるはず。
※画像が無い時に404にするには『error_page 415 =404 /404.html;』を追加する。
ただ開発環境はいいけど、本番環境にこの設定を入れるとDOS攻撃が怖い。
例えば幅を1ずつ増やしてDOS攻撃されると、
for i in {1..10000};do curl http://xxx.cloudfront.net/resize/${i}x1000/sample.jpg;done
画像変換サーバのCPUや、前段にキャッシュ用Proxyがある場合はそのメモリを使いきってしまうかもしれない。
これを防ぐ方法の1つは、cookpadのtofuのようにURLに予測不可能なハッシュ値を含めること。
http://img.cpcdn.com/cms_articles/3453/100x100c/cdcf6aff4c78c6619b67372f129bdef2.jpg?u=9769263&p=1418093860
しかしその場合はハッシュ関数とSEEDが漏れたらURLを変更しないといけなくなるかもしれない。まぁ直リン禁止なら問題ないけど。
もう1つの方法は、本番系は特定のサイズ指定のみ許可すること。
今回はこっち。
server { listen 80 default_server; server_name _; root /var/nginx_root; location ~ ^/resize/(100x100|200x200)/(.*)$ { set $type $1; set $path $2; if ($type = 100x100) { set $width 100; set $height 100; } if ($type = 200x200) { set $width 200; set $height 200; } image_filter resize $width $height; image_filter_jpeg_quality 90; rewrite ^ /$path break; } location ~ ^/resize/ { return 404; } }
運用がちょっと面倒で応用も効きづらいけど、そのぶん実装は簡単。
設定が冗長になるのはchefとかで動的に作ればそんなに面倒じゃないはず。
CloudFront設定&画像変換サーバのProxy設定
事前にELBを作成して画像変換サーバをその配下に入れておく。
そしてManagementConsoleのCloudFront設定で、/resize/で始まる場合はS3でなくELBに渡すよう設定する。
- 『Origins』でELBをOriginとして追加
- 『Behaviors』でPath Patternを『resize/*』、OriginをELBにしたBehaviorを追加
あとはnginxでCloudFrontにProxyするように設定する。
ここで1つ注意があって、CloudFrontから来たアクセスを同じCloudFrontにProxyする場合、1回目通った時にループ検出のために付与されるViaヘッダをクリアしないとアクセスが拒否されてしまう。
というわけでnginxのlocationに追加する設定は以下の2行。
proxy_set_header Via ""; proxy_pass http://d2sloa042uzrzo.cloudfront.net;
これで作業は完了。
http://d2sloa042uzrzo.cloudfront.net/kuma.jpg http://d2sloa042uzrzo.cloudfront.net/resize/100x100/kuma.jpg
まとめ
いろいろめんどくさいから、CloudFront自体に画像のリサイズ機能つかないかな。
Macでお手軽にリモートマシンからのコマンド終了通知
実行時間の長いコマンドの終了を通知できるようにGrowlや通知センターを使って工夫している人はそれなりにいらっしゃると思います。
- 実行時間の長いコマンドの終了をGrowlやメール通知するRubyスクリプト
- Macで時間のかかるコマンドが終わったら、自動で通知するzsh設定 - Qiita
- zshでエラーや時間のかかる処理後に通知センターで通知するようにする - 僕の車輪の再発明
ただ、これを ssh でログインしたリモートサーバでやろうと思うとけっこうめんどい。
ということで、自分がやっているお手軽な方法の紹介
必要なもの
設定方法
iTerm > Preferences > Profilers > Advanced > Triggers Edit
- ボタンを押して Trigger を作る。Finale, Show Alert, Finale としてみた。
使い方
これで
$ echo Finale
とするとポップアップが表示されるようになる。
あとは、
$ 重い処理; echo Finale
とかすれば良い。リモートサーバで実行しても iTerm2 上にその文字が出てくれば反応するので関係ない。
ちなみに、なぜ Finish じゃなくて Finale (フィナーレ) にしているのかというと、Finish だと普通にコマンド実行結果に含まれていることがあって、ノイズになることがあったため。
catで複数行の文字を入力してファイルへ出力
$ cat <<'EOF' >> /tmp/cat_test.txt heredoc> cat heredoc> test heredoc> text heredoc> EOF $ $ cat /tmp/cat_test.txt cat test text
たまに使う
Travis CIでMongoDB 2.6系を使う設定
あるクエリがローカルやサーバでは動くのにTravisCIのテストでコケる現象があって、よくよく見ると2.4系では無い機能を使っていた。 で、TravisCI側をどうすれば良いのかなーとググっていたら
Using MongoDB 2.6 with TravisCI Builds
というズバリのブログを見つけてそのコピペです。
before_install: - "sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10" - "echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list" - "sudo apt-get update" - "sudo apt-get install mongodb-org-server”
を.travis.yamlに書きましょうという話ですね。いつ頃2.6系対応されるかは対応自体は検討されているようなので、
MongoDB 2.6.x · Issue #2246 · travis-ci/travis-ci · GitHub
そのうち寝ていたら来ることでしょう。
おしまい。
Ruby の Object Data Dumper
プリントデバッグが大好きだ!!!何はなくともとりあえず標準出力に吐いてデバグ!!!!!!!!!っていうようなことはみなさんにおかれましても少なからずあるのではないでしょうか。
プリントデバッグを行う場合、単純に変数に何が入っているかというよりも、オブジェクトの状態とかを見たいことが多いかと思う。
そういうときのためのライブラリとして、Ruby だと、p
, pp
は組み込み、ap
はもう定番化しててみんな使ってると思う。
で、ddp
ってのもある。http://hisaichi5518.hatenablog.jp/entry/2014/11/05/154949
適当なクラスをでっち上げてそれぞれに食わせてみる
こんなクラスがあったとする。
インスタンスを作って、インスタンス自体、インスタンス変数、インスタンスメソッドをそれぞれのライブラリに食わせてみて、どんな感じに表示されるか見てみませう。
class Ore end class Oretachi < Ore attr_accessor :data def initialize @data = [ { name: '1号', entry_count: 4, bookmark_count: 26 }, { name: '2号', entry_count: 3, bookmark_count: 7 }, { name: '3号', entry_count: 3, bookmark_count: 16 }, { name: '4号', entry_count: 2, bookmark_count: 24 }, { name: '5号', entry_count: 2, bookmark_count: 21 }, { name: '6号', entry_count: 2, bookmark_count: 182 }, { name: '7号', entry_count: 2, bookmark_count: 218 }, ] end def [](name) @data.select { |ore| ore[:name] == name }.first end end
インスタンス自体
内包するインスタンス変数をキレイに見たい場合だと pp
に軍配が上がる感じがします。でもなんかインデントとか微妙だしイマイチ。
で、ddp
はインスタンスのクラスの継承関係と、include されているモジュールの一覧まで見られるのでそういう用途においては他のライブラリの出番がなさそう。
require 'pp' require 'ap' require 'ddp' oretachi = Oretachi.new #### p p oretachi #=> #<Oretachi:0x007fef240a13b8 @data=[{:name=>"1号", :entry_count=>4, :bookmark_count=>26}, {:name=>"2号", :entry_count=>3, :bookmark_count=>7}, {:name=>"3号", :entry_count=>3, :bookmark_count=>16}, {:name=>"4号", :entry_count=>2, :bookmark_count=>24}, {:name=>"5号", :entry_count=>2, :bookmark_count=>21}, {:name=>"6号", :entry_count=>2, :bookmark_count=>182}, {:name=>"7号", :entry_count=>2, :bookmark_count=>218}]> #### pp pp oretachi #=> #<Oretachi:0x007fef240a13b8 @data= [{:name=>"1号", :entry_count=>4, :bookmark_count=>26}, {:name=>"2号", :entry_count=>3, :bookmark_count=>7}, {:name=>"3号", :entry_count=>3, :bookmark_count=>16}, {:name=>"4号", :entry_count=>2, :bookmark_count=>24}, {:name=>"5号", :entry_count=>2, :bookmark_count=>21}, {:name=>"6号", :entry_count=>2, :bookmark_count=>182}, {:name=>"7号", :entry_count=>2, :bookmark_count=>218}]> #### ap ap oretachi #=> #<Oretachi:0x007fef240a13b8 @data=[{:name=>"1号", :entry_count=>4, :bookmark_count=>26}, {:name=>"2号", :entry_count=>3, :bookmark_count=>7}, {:name=>"3号", :entry_count=>3, :bookmark_count=>16}, {:name=>"4号", :entry_count=>2, :bookmark_count=>24}, {:name=>"5号", :entry_count=>2, :bookmark_count=>21}, {:name=>"6号", :entry_count=>2, :bookmark_count=>182}, {:name=>"7号", :entry_count=>2, :bookmark_count=>218}]> #### ddp Ddp.p oretachi #=> Oretachi < Ore < Object < BasicObject { included_modules: PP::ObjectMixin Kernel inspect: #<Oretachi:0x007fef240a13b8 @data=[{:name=>"1号", :entry_count=>4, :bookmark_count=>26}, {:name=>"2号", :entry_count=>3, :bookmark_count=>7}, {:name=>"3号", :entry_count=>3, :bookmark_count=>16}, {:name=>"4号", :entry_count=>2, :bookmark_count=>24}, {:name=>"5号", :entry_count=>2, :bookmark_count=>21}, {:name=>"6号", :entry_count=>2, :bookmark_count=>182}, {:name=>"7号", :entry_count=>2, :bookmark_count=>218}]> }
インスタンス変数
オブジェクトの構造を確認したい場合においては、優勝 ap
, 次点 pp
という感じでしょうか。
でもなんか ap
もインデントとかキレイじゃなくてちょっと微妙な気がしてます。もうすこし階層の深いオブジェクトだとちょい見づらいことがあるのだよなー。
require 'pp' require 'ap' require 'ddp' oretachi = Oretachi.new #### p p oretachi.data #=> [{:name=>"1号", :entry_count=>4, :bookmark_count=>26}, {:name=>"2号", :entry_count=>3, :bookmark_count=>7}, {:name=>"3号", :entry_count=>3, :bookmark_count=>16}, {:name=>"4号", :entry_count=>2, :bookmark_count=>24}, {:name=>"5号", :entry_count=>2, :bookmark_count=>21}, {:name=>"6号", :entry_count=>2, :bookmark_count=>182}, {:name=>"7号", :entry_count=>2, :bookmark_count=>218}] #### pp pp oretachi.data #=> [{:name=>"1号", :entry_count=>4, :bookmark_count=>26}, {:name=>"2号", :entry_count=>3, :bookmark_count=>7}, {:name=>"3号", :entry_count=>3, :bookmark_count=>16}, {:name=>"4号", :entry_count=>2, :bookmark_count=>24}, {:name=>"5号", :entry_count=>2, :bookmark_count=>21}, {:name=>"6号", :entry_count=>2, :bookmark_count=>182}, {:name=>"7号", :entry_count=>2, :bookmark_count=>218}] #### ap ap oretachi.data #=> [ [0] { :name => "1号", :entry_count => 4, :bookmark_count => 26 }, [1] { :name => "2号", :entry_count => 3, :bookmark_count => 7 }, [2] { :name => "3号", :entry_count => 3, :bookmark_count => 16 }, [3] { :name => "4号", :entry_count => 2, :bookmark_count => 24 }, [4] { :name => "5号", :entry_count => 2, :bookmark_count => 21 }, [5] { :name => "6号", :entry_count => 2, :bookmark_count => 182 }, [6] { :name => "7号", :entry_count => 2, :bookmark_count => 218 } ] #### ddp Ddp.p oretachi.data #=> Array < Object < BasicObject { included_modules: Enumerable PP::ObjectMixin Kernel inspect: [{:name=>"1号", :entry_count=>4, :bookmark_count=>26}, {:name=>"2号", :entry_count=>3, :bookmark_count=>7}, {:name=>"3号", :entry_count=>3, :bookmark_count=>16}, {:name=>"4号", :entry_count=>2, :bookmark_count=>24}, {:name=>"5号", :entry_count=>2, :bookmark_count=>21}, {:name=>"6号", :entry_count=>2, :bookmark_count=>182}, {:name=>"7号", :entry_count=>2, :bookmark_count=>218}] }
インスタンスメソッド
ddp
すごい。source_location
という項目で、そのメソッドがどこの何行目に定義されているかわかる。これはクソ便利だ。
require 'pp' require 'ap' require 'ddp' oretachi = Oretachi.new #### p p oretachi.method(:[]) #=> #<Method: Oretachi#[]> #### pp pp oretachi.method(:[]) #=> #<Method: Oretachi#[]> #### ap ap oretachi.method(:[]) #=> Oretachi#[](name) #### ddp Ddp.p oretachi.method(:[]) #=> Method < Object < BasicObject { included_modules: PP::ObjectMixin Kernel inspect: #<Method: Oretachi#[]> source_location: ["-", 19] }
まとめとか
構造をいい感じに表示 | 継承関係がわかる | include されているモジュールがわかる | メソッドの定義場所がわかる | 組み込み | require | |
---|---|---|---|---|---|---|
p | × | × | × | × | ◯ | 不要 |
pp | △ | × | × | × | ◯ | 要 |
ap | ◯ | × | × | × | × | 要 |
ddp | × | ◯ | ◯ | ◯ | × | 要 |
ddp
がすごく便利ddp
がオブジェクトの構造をもっといい感じに表示してくれたら最高Ddp.p
って書くのダルいdp object
みたいに書けるようになったら最高
ap
,ddp
は組み込みではないのでインストールが必要bundle exec
でどうこうしたい場合には一時的にでもGemfile
に書いておくなどしなければならずダルい
ap
は Hash とか Array を直接食わせたらいい感じなのに、インスタンス自体を食わせたときには内包するインスタンス変数の内容の表示が残念なのでもうちっとなんとかならんか