ssh-copy-id というsshの公開鍵をリモートサーバーに登録する ちょっと便利なコマンドがあるんですが、macでbrewでインストールできなかったので、メモです。 下記のふぁいるを、/usr/local/binなどに作成します。
$ vi /usr/local/bin/ssh-copy-id
#=> 下記のファイルを貼付け
$ chmod +x /usr/local/bin/ssh-copy-id
$ ssh-copy-id -i ~/.ssh/id_rsa.pub user@host #=> ~/.ssh/id_rsa.pub を指定したサーバーに設定
(ssh-copy-id)
#!/bin/sh
# Shell script to install your identity.pub on a remote machine
# Takes the remote machine name as an argument.
# Obviously, the remote machine must accept password authentication,
# or one of the other keys in your ssh-agent, for this to work.
ID_FILE="${HOME}/.ssh/id_rsa.pub"
if [ "-i" = "$1" ]; then
shift
# check if we have 2 parameters left, if so the first is the new ID file
if [ -n "$2" ]; then
if expr "$1" : ".*\.pub" ; then
ID_FILE="$1"
else
ID_FILE="$1.pub"
fi
shift # and this should leave $1 as the target name
fi
else
if [ x$SSH_AUTH_SOCK != x ] ; then
GET_ID="$GET_ID ssh-add -L"
fi
fi
if [ -z "`eval $GET_ID`" ] && [ -r "${ID_FILE}" ] ; then
GET_ID="cat ${ID_FILE}"
fi
if [ -z "`eval $GET_ID`" ]; then
echo "$0: ERROR: No identities found" >&2
exit 1
fi
if [ "$#" -lt 1 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
echo "Usage: $0 [-i [identity_file]] [user@]machine" >&2
exit 1
fi
{ eval "$GET_ID" ; } | ssh $1 "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys" || exit 1
cat
sporkを走らせようとしたが、なぜかrequire ‘spork’ができずこまった。rspec/railsもロードされていないし。 もう少し調べてみると、どうもGemfileのdevelop & test groupにいれたgemがロードできない。 なんじゃこりゃ〜
サーバ側でbundle installした時に下記のコードで実行した。
bundle install --without development test
これ自体は問題はない。が、 ここから誰かがサーバ側で作業して、リポジトリにpushした。それを自分がpullした。 そうすると、.bundle/configというファイルが勝手にできていて、下記のようになっている。
1 ---
2 BUNDLE_WITHOUT: development:test
これによって、developmentとtestのgroup中のgemは無視されるらしい。。。
上記の2行目を消す事は当然で、 予防策として、.hgignoreで必ず.bundleを無視しておく必要があると思う。 vim .hgignore
+ ^\.bundle
一応ここらへんに書いてあったが、もっとわかりやすくしておいてくれ〜 http://gembundler.com/groups.html
いまさらこんなレガシーなのを使っているのは、よろしくないが、 現実は3系にあげられないでいる。 そうすると、似たような問題を検索しても引っかかってこない。
何かしらのオブジェクトに対して、ネストしたパラメータがあると、以前は行けたのに、アップ後はエラーとなる。
2.3.9 -> OK
>> r = Reservation.new
>> r.attributes = {:start_attributes=>{:id=>’1005’}}
=> {:start_attributes=>{:id=>”1005”}}
>> r.start (=>オブジェクトが表示される。)
2.3.14 -> error
>> r = Reservation.new
>> r.attributes = {:start_attributes=>{:id=>’1004’}}
ActiveRecord::RecordNotFound: Couldn’t find Place with ID=1004 for Reservation with ID=
以前のバージョンでは、start_attributesのidからオブジェクトを取得しているようだが、アップ後はエラーを出している。
2.3.9 L288
elsif attributes[‘id’]
existing_record = self.class.reflect_on_association(association_name).klass.find(attributes[‘id’])
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
self.send(association_name.to_s+’=’, existing_record)
2.3.14 L288
elsif attributes[‘id’]
raise_nested_attributes_record_not_found(association_name, attributes[‘id’])
https://github.com/rails/rails/blob/v2.3.9/activerecord/lib/active_record/nested_attributes.rb
https://github.com/rails/rails/blob/v2.3.14/activerecord/lib/active_record/nested_attributes.rb
おそらく、なんらかの理由があって、変更しているのだろうが、 これを使っている箇所全体を新しい書き方に変更するのはかなりのコストなので、 以前の書き方に戻すようにパッチを当てることにした。
config/initializers/active_record.rbとか適当にファイルを作成して
module ActiveRecord
module NestedAttributes #:nodoc:
def assign_nested_attributes_for_one_to_one_association(association_name, attributes)
options = nested_attributes_options[association_name]
attributes = attributes.with_indifferent_access
check_existing_record = (options[:update_only] || !attributes['id'].blank?)
if check_existing_record && (record = send(association_name)) &&
(options[:update_only] || record.id.to_s == attributes['id'].to_s)
assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy])
elsif attributes['id']
existing_record = self.class.reflect_on_association(association_name).klass.find(attributes['id'])
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
self.send(association_name.to_s+'=', existing_record)
elsif !reject_new_record?(association_name, attributes)
method = "build_#{association_name}"
if respond_to?(method)
send(method, attributes.except(*UNASSIGNABLE_KEYS))
else
raise ArgumentError, "Cannot build association #{association_name}. Are you trying to build a polymorphic one-to-one association?"
end
end
end
end
end
続けて、HTTPのサイトをtelnetで見ることになったので同じようなネタでもう一つ
HTTPSと同じように、hogehoge.com:80をにアクセスしようとするとこんな感じです。 まずは、Basic認証がない場合から、
$ telnet hogehoge.com 80
> GET /index.html HTTP/1.1
> Host: hogehoge.com
> [returnを2回]
で、さらに、Basic認証がかかっているばあいは、
$ telnet hogehoge.com 80
> GET /index.html HTTP/1.1
> Host: hogehoge.com
> Authorization: Basic aG9nZWhvZ2U6aG9nZWhvZ2U=
> [returnを2回]
と、Authorizationも含めておくってあげればOKです。 Basicの後の文字列は、Basic認証なので、”ID:PW”をbase64化したものを送ればOKです。
$ echo -n ‘hogehoge:hogehoge’ | openssl enc -e -base64 #=> aG9nZWhvZ2U6aG9nZWhvZ2U=
上記は、IDとPWがhogehogeの場合です。
最初は、SafariやらChromeでやっていたのですが、面倒になったのでTerminalでやってみました。 ちょっとググったらあったのでメモしておきます。
例として、hogehoge.com の /index.html を調べることにします。
まずは、以下のコマンドで、接続します。
$ openssl s_client -connect hogehoge.com:443
この際、SSLの情報も見れます。 つづけて、
GET /index.html HTTP/1.1
Host: hogehoge.com
[さらにreturn]
と打ちましょう。returnを2回打たないといけないので注意です。 これで、気軽にレスポンスヘッダとSSLの情報がみれました。
WWDCで個人的に一番気になったのが、passbookでした。 passbookは、iOS6から乗るクーポンや映画チケットなどの管理アプリってところです。 NFCへの布石にもなっていそうな本アプリ。 web serverとどうやって連動するのか調べておこうという趣旨で、ざっとSDKを見てみました。
ということで、盛り上がってくればなかなか面白いサービスなんじゃないかなと。 また、オリジナルのクープン等も発行できそうなので、状況を見てサービスに取り込んでいければなと思いました。
メモ的に書いておきます。
console.log req.url
console.log new Date()
console.log req.headers['x-forwarded-for'] || req.connection.remoteAddress #=>
console.log req.headers.referer
console.log req.headers["user-agent"]
console.log req.headers.cookie
以上。
backbone.jsのrouterを使用して、開かれたURLによって、実行するjsを切り替えていた。
Android2系までは対応していたのに、3系以降対応しなくなったらしい。
http://d.hatena.ne.jp/zentoo/touch/20111130/1322667152
ちなみにこのサイト(http://fmbip.com/)で対応しているかどうかチェックできる。
で、backboneではpushStateに対応していないと、URLのパス部分をfragmentとして、
hashタグに変換して、リダイレクトする仕様になっているが、
そのあたりでどうも無限ループに陥っていた。
Backbone.Historyの引数とかnavigateでなんとか設定できないか探してみたが、わからなかったので、外部からstartの関数を書き換えることにした。
今回の制約事項として、スマホのみ。なのでIEの行は不要
// Start the hash change handling, returning `true` if the current URL matches
// an existing route, and `false` otherwise.
Backbone.History.prototype.start = function(options) {
if (Backbone.History.started) throw new Error("Backbone.history has already been started");
Backbone.History.started = true;
// Figure out the initial configuration. Do we need an iframe?
// Is pushState desired ... is it available?
this.options = _.extend({}, {root: '/'}, this.options, options);
this._wantsHashChange = this.options.hashChange !== false;
this._wantsPushState = !!this.options.pushState;
// 20120603 mod for Android4.0
//this._hasPushState = !!(this.options.pushState && window.history && window.history.pushState);
this._hasPushState = !!(this.options.pushState && window.history);
var fragment = this.getFragment();
var docMode = document.documentMode;
//var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode ').hide().appendTo('body')[0].contentWindow;
//this.navigate(fragment);
//}
// Depending on whether we're using pushState or hashes, and whether
// 'onhashchange' is supported, determine how we check the URL state.
if (this._hasPushState) {
$(window).bind('popstate', this.checkUrl);
} else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {
$(window).bind('hashchange', this.checkUrl);
} else if (this._wantsHashChange) {
this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
}
// Determine if we need to change the base url, for a pushState link
// opened by a non-pushState browser.
this.fragment = fragment;
var loc = window.location;
var atRoot = loc.pathname == this.options.root;
// If we've started off with a route from a `pushState`-enabled browser,
// but we're currently in a browser that doesn't support it...
//if (this._wantsHashChange && this._wantsPushState && !this._hasPushState && !atRoot) {
//this.fragment = this.getFragment(null, true);
//window.location.replace(this.options.root + '#' + this.fragment);
//// Return immediately as browser will do redirect to new url
//return true;
//// Or if we've started out with a hash-based route, but we're currently
//// in a browser where it could be `pushState`-based instead...
//} else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {
//this.fragment = this.getHash().replace(routeStripper, '');
//window.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment);
//}
if (!this.options.silent) {
return this.loadUrl();
}
}
そもそも、pushStateが使えなくても動くような、別なプラグインを入れるべきかもしれない。
スマホでアプリっぽいWebシステムを作ろうとした時の設計について書いておきます。
AndroidでシェアがそれなりにあるOpera miniは画面が崩れまくって、 リンクがおかしくなって、対応に相当かかるのでとりあえず対応から外した。
Fluentd: Log Everything in JSON -
Fluentd is a log collector daemon written in Ruby. Fluentd receives log as JSON streams, buffers them, and storeds or forwards to other systems like MongoDB, or even other instances of Fluentd.