読者です 読者をやめる 読者になる 読者になる

Coro::LWPで/etc/hostsを使う

本番環境と同じドメインでアクセスできるストレージ環境があって、
/etc/hostsのIPアドレスを書き換えて開発のチェックをしてたりします。
で、Coro::LWP使ったscriptでアクセスしてみたら本番の方に行ってしまいハマったのでメモ書き。



まずMacOSXだから/etc/hostsを読んでくれてないのかと思いだいぶハマりました。
Linuxでやっても同じように本番の方に行ってしまったので「あれ?おかしいな」と。
で、試しに/etc/hostsに

127.0.0.1	 www.google.co.jp

と書き、LWP::UserAgent使って

perl -MLWP::UserAgent -e 'warn LWP::UserAgent->new->get("http://www.google.jp")->code'

を実行してみると

403 at -e line 1.

ちゃんとエラーになる。



次にCoro::LWPを使って

perl -MLWP::UserAgent -MCoro::LWP -e 'warn LWP::UserAgent->new->get("http://www.google.jp")->code'

を実行してみると

200 at -e line 1.

200正常が返って来て/etc/hostsを見てくれてないことがわかった。



こっから色々ググって何か方法ないかと探してみたのだけどなかなか見当たらず。
で、Coro::LWPの中を覗いてみて

Coro::Util::inet_aton

ってのが使われてて、Coro::Utilを覗いてみると

AnyEvent::Socket::inet_aton

ってのが使われてて、さらにAnyEvent::Socketを覗いてみると

      require AnyEvent::DNS;

ってなってて、「コレっぽいかな?」と当てを付けてみたのだけど、そこから先に進めず。



「わからないことがあれば#perl-casualで聞くといいよ!」
ってのを色んな発表で聞いていたので良い機会だと思い試しに聞いてみました。

monmon
Coro::LWPについて分かる方いたら教えて欲しいのですが、
monmon
Coro::LWPで/etc/hostsの内容を読んでくれる方法ってありますか?
monmon
例えば、
monmon
[13:50@www5206u]% grep google /etc/hosts                                         [/tmp]127.0.0.1	 www.google.co.jp
monmon
と、hostsに書いておいて、
monmon
普通にLWPを使った場合は
monmon
[13:50@www5206u]% perl -MLWP::UserAgent -e 'warn LWP::UserAgent->new->get("http://www.google.jp")->code'
monmon
403 at -e line 1.
mobitaro
Google [text/html; charset=UTF-8]
monmon
hosts見てくれるのですけど、
monmon
Coro::LWP使うと
monmon
[13:51@www5206u]% perl -MLWP::UserAgent -MCoro::LWP -e 'warn LWP::UserAgent->new->get("http://www.google.jp")->code'
monmon
200 at -e line 1.
mobitaro
Google [text/html; charset=UTF-8]
monmon
DNSを見ちゃう
kazuho
AnyEvent::DNS? なのでそうですね
monmon
Coro::LWPの中で、Coro::Util::inet_atonを使ってて、Coro::Utilが
monmon
あ、そです
tokuhirom4
うん
monmon
AnyEvent::DNS使ってるようなので
monmon
どうにかやる方法がないのかなと
tokuhirom4
AnyEvent::DNS に hosts を見る機能がないから
monmon
思い。
monmon
そうすると/etc/hosts見るようにするには自分でCoro::LWPに似たようなものを作るしかないですかね?
tokuhirom4
自分だったら、どっかをフックして、/etc/hosts をよんでよしなにするけど
kazuho
とりあえずなおせりゃいいなら Coro::Util::inet_aton をフックするのがいいかなと
kazuho
/etc/hosts をちゃんと読むのめんどくさそう
tokuhirom4
そういう CPAN module とか
tokuhirom4
ありそうだけどw
tokuhirom4
つーかまあ
tokuhirom4
シリアスな用途じゃないなら
tokuhirom4
Coro::LWP を use する前に
tokuhirom4
Socket::inet_aton を保存しておいて
tokuhirom4
use Coro::LWP してから restore するとかでも
tokuhirom4
いいとおもうけど。
tokuhirom4
DNS が block するのが問題なければ。
tokuhirom4
カジュアル用途ならそれで十分とおもう。
tokuhirom4
なにかいてるのかしらんけど!
monmon
なるほどなるほど。ドメインを同じにしてあるステージング環境のステータスコードチェックしたいだけなので
monmon
その方法調べてみます。
monmon
ありがとございます

ということで説明する前に理解してもらって速攻で道筋を教えてもらえました。



出来上がったのが以下のような感じ。
Socket::inet_atonを上書きしてみたのだけどCoro::Utilの中でも使っていたので
Coro::Util::inet_atonごと上書きしました。

#!/usr/bin/env perl
use strict;
use warnings;
use LWP::UserAgent;

use Socket;
use Data::Dumper;

BEGIN {
    *inet_aton = \&Socket::inet_aton;
}
use Coro::LWP;

#*Socket::inet_aton = \&inet_aton;
*Coro::Util::inet_aton = \&inet_aton;

my $url = shift || "http://www.google.co.jp";
print LWP::UserAgent->new->get($url)->code;

https://gist.github.com/751157
「上手くいったーやったー。」と思って#perl-casualにありがとうありがとうの報告をしようと見てみたら

mash_
dnsmasqって/etc/hostsを見てくれるDNSサーバをローカルにたてたりしてます

という続きがあったのでそっちもやってみました。


dnsmasqのインストールと設定と起動

homebrewにあったのでそのままinstall

sudo brew install dnsmasq

名前解決で自分を見るように/etc/resolv.confに以下を追加

nameserver 127.0.0.1

あとは起動

/usr/local/sbin/dnsmasq

/etc/hostsを見ているか確認

% nslookup www.google.co.jp
Server:		127.0.0.1
Address:	127.0.0.1#53

Name:	www.google.co.jp
Address: 127.0.0.1

おぉぉ!上手くいってる様子。
超楽だ。これは便利。



IRC使ったことなくて聞くの躊躇してたんだけど今日聞いておいて良かった。
ありがとうありがとう。