Hatena::ブログ(Diary)

Magical Diary このページをアンテナに追加 RSSフィード

2011年08月18日

Titanium Mobileでスクレイピング

Titanium Mobileウェブサイトスクレイピングする方法を考えてみた。ターゲットとなるサイトは (XMLではない) 普通HTMLエンコードShift_JIS

  1. Titanium.Network.HTTPClient + Titanium.XML.DOMDocument → 整形式なXMLかつUTF-8じゃないとダメ。多分。
  2. NSXMLDocument を呼び出すモジュールを作成する → Macプロトタイプを作ってXCodeに持っていったらエラーiPhoneではNSXMLParser (SAX) しかサポートしないようだ。orz モジュール作成勉強になったからよしとする。
  3. libxml2 → iPhoneアプリではよく使われているようなので、多分問題無い。JavaScript, Objective C, C のコードが混在するのが気持ち悪い。(cf. Using libxml2 for XML parsing and XPath queries in Cocoa)
  4. webView + evalJS → 今回やって上手く動いた。外部モジュールやライブラリを使わずに動くので、一番楽かもしれない。

コード

var url = "http://www.akaneshinsha.co.jp/online/comics-shinkan/shinkan-top.htm";
var webView = Titanium.UI.createWebView({url: url});
webView.addEventListener("load", function(p) {
  this.evalJS('alert("あずにゃんペロペロ");');
  var title = this.evalJS('document.evaluate("//title", document, null, XPathResult.STRING_TYPE, null).stringValue');
  Titanium.API.info("title = " + title);
  var count = this.evalJS('document.evaluate("count(//body/div[6]/table//tr)", document, null, XPathResult.NUMBER_TYPE, null).numberValue');
  Titanium.API.info("count = " + count);
  for(var i = 3; i < count - 1; i++) {
    var td = this.evalJS('document.evaluate("//body/div[6]/table//tr[' + (i + 1) + ']/td[3]//font/text()", document, null, XPathResult.STRING_TYPE, null).stringValue');
    Titanium.API.info("[" + i + "] = " + td);
  }
});

win1.add(webView);

/*
// 本番ではwebViewを隠す方が良いかも?
var blind = Titanium.UI.createWindow({  
  title:'aaa',
  backgroundColor:'#fff'
});
webView.add(blind);
*/

実行結果

[INFO] title = 茜新社 単行本 コミックス 今月の新刊
[INFO] count = 13
[INFO] [3] = COMIC 天魔 2011年9月号
[INFO] [4] = COMIC RIN 2011年9月号
[INFO] [5] = 熟女ものがたり 2011年10月号
[INFO] [6] = COMIC LO 2011年10月号
[INFO] [7] = comic Sigma vol.60
[INFO] [8] =  ただし二次元に限る
[INFO] [9] =  のらシス
[INFO] [10] =  TAKAMICHI SUMMER WORKS
[INFO] [11] =  OPERA vol.28 - Kiss-

そろそろLOの発売日か…

追記

Yahoo! Query Language (YQL) を使えば簡単に取り出せそうだ。

YQL - Yahoo Developer Network

(はてなブックマークより。thanks to: id:tittea)

2011年02月13日

(新人向け) Unixオペレーションの注意点

主に新人向けとして、Unixサーバで作業をする際の注意点を書いておく。

ここに書いてある内容は絶対的なものではないし、会社や現場ごとにルールがあるので、適宜ルールに合わせて実践すれば良い。

ログを取れ

何をやったか、何をやらなかったか、というエビデンスのためにログは必ず残しておく。SSHクライアントによっては毎回自動的にログ取得する設定が可能なので、設定しておくと良いだろう。

f:id:hirata_yasuyuki:20110213210741p:image

作業後に問題が発生した場合に作業内容を確認するためにも使うため、必ずログは取得しておくこと。

(追記) 当たり前だが、コマンドとその出力をペアで取ることに意味がある。

set -x (set verbose) しろ

ログを取得しても、コマンドライン編集した際には以下のように非常に見づらいものとなってしまう。(がんばれば解析することは出来るが…)

ESC[0mESC[27mESC[24mESC[JESC[1myasu@kiki:~%ESC[0m cat /etc/ESC[Kpa^M
ESC[1mCompleting fileESC[0m
ESC[Jpam.dESC[27m/ESC[27m  ESC[27m  ESC[27mESC[JpasswdESC[27m  ESC[27m  ESC[27m
ESC[JpathsESC[27m   ESC[27m  ESC[27mESC[Jpaths.dESC[27m/ESC[27mESC[JESC[AESC[A
ESC[0mESC[27mESC[24mESC[0mESC[27mESC[24m^MESC[13Ccat /etc/paESC[KESC[0mESC[27m
ESC[24msswd^M
ESC[J##

set -x (bsh系)、set verbose (csh系) を実行することで、コマンド実行時には以下のように出力されるため、作業内容を確実に記録することが出来る。ただし、ワイルドカードの展開結果がそのまま表示されるため、実際に入力したコマンドそのものではない点には注意。

 +zsh:2> cat /etc/passwd

最初にやること

hostname

対象のホストであるか確認する。対象のサーバを間違えることは無いだろうと思いがちだが、ホスト間違いのオペレーションミスは意外に多い。特に本番機・検証機の両方にアクセス可能場合や、ホスト名が類似している場合 (ペアになっていて、www01, www02など) には要注意。

ifconfig | grep inet

少々特種な事例だが、同一ホスト名で他のサーバ (IPアドレス) に移転した (またはする可能性がある) 場合には、旧サーバで作業しているつもりで新サーバを変更してしま可能性がある。IPアドレスも確認することでこのようなミスを避けられる。

date

確認と言うよりは作業開始時刻を記録する目的ログを確認する場合にも役立つので、ログアウト直後にも打っておくと良い。

都度確認すること

pwd

破壊的な作業かつ相対パスで指定する場合など、作業ディレクトリ重要場合には、必ずカレントディレクトリを確認する。

date; command...; date

時間かかるコマンドの前後でdateを打っておくとログから実績時間が分かるため、後々役立つこともある。

バックアップを取れ

何かしらの変更をする際には、必ずバックアップを取得してから行う。

ファイル場合:

cp -p named.conf named.conf.20110101
ls -ltr named.conf*

crontabの場合:

crontab -l > crontab.20110101

会社や現場によってはバージョン管理システムを利用するなどのルールがあると思うので、その場合はそれに従えば良い。

diffを取れ

編集した内容はdiffを取り、意図した編集けが行われているか確認する。ログ上に変更点を明示的に残す目的もある。

例:

diff -u named.conf.20110101 named.conf

バージョン管理システムを利用している場合は、rcsdiff, svn diffなど適当な手段を使うこと。

同一性を確認しろ

データを他から移動する際には、破損の可能性を考慮して同一性を確認する。(FTPでうっかりASCIIモード転送してしまうというのは良くあることだ。)

md5 (md5sum), sha1 (sha1sum), sha256 (sha256sum) などの高度なハッシュ値を求めるコマンドが利用できればそれを使えば良いが、無ければcksumでも構わない。(オペレーションミスを防ぐレベルなら十分。) なお、cksumはその名前に反して単純なチェックサムではなくCRC値を求める。

右クリックペーストするな

TeraTermPuTTYなど、Windows用のSSHクライアントでは右クリックペーストすることが出来るが、この機能は避けた方が良い。右クリックをする際に誤ってマウスを動かしてしまうと、思わぬところをコピーペーストしてしまからだ。

右クリックによるペースト機能は向こうにしておいて、Shift+Insペーストするのが一番安全だ。

f:id:hirata_yasuyuki:20110213210742p:image

万全を期すなら、クリップブックでクリップボードの内容を常時表示させておくと良い。クリップブックは Win+R → clipbrd で起動することが出来る。

追記

右クリック

以前はTeraTerm右クリックしたままマウスを動かすと、そのときに選択された領域がコピーペーストされて大惨事… だったが、今は "Select only by L button" がデフォルトなので以前ほどの危険ではないようだ。(それでも、右クリックを避けた方が良いのには変わらないが。)

"hostname" or "uname -n"

ブックマークでも指摘を頂いた通り、一般ユーザならどちらでも良いが、rootなら "uname -n" の方が安全。"hostname" コマンドだと、オペレーションミスホスト名を変更してしま可能性がある。

クリップブック

Vista以降には無いらしい。適当なフリーソフト探すしかないのか… (thanks id:migimigi, id:nomber3)

ブックマークに反応

(id:pratto) hostname,date,whoamiはプロンプトに出していても、オペレータには作業前に打たせてる。打たせて、出力した文言を確認させてる。そこまでが手順。奴ら、プロンプトなど見ないし、そういう意味なことすら理解できないし。

pwd を打たせるのはこれと同様で、意識して確認するという動作が重要から。指差し確認・声に出すのも効果あり。

(id:dekaino) history知らないのかな? GNU screenも知らないんだろうな

こういう的外れなことを言われても困るのだが、historyで間に合うような用途ならそれを使えばいいし、GNU screenインストールして良いならそうすれば良い。まずはもう一度、最初段落を読んで欲しい。(想像出来ないかも知れないが、世の中にはGNU screenが入っていないシステムも、インストールが許されないシステムもあるのだ。)

2011年01月04日

シェルスクリプト中で連番を得る

先日、IRCNet #ruby:*.jp で話題になったのでメモ

シェルスクリプト中で連番や複数回の繰り返しが必要になった場合BSD系 (4.2BSD以降・Mac含む) では jotGNU系では seq を使うことが多い。が、普通は片方しか入っていないし、互換性も全く無いというやっかいな代物。

jot 回数

jot 回数 開始

jot 回数 開始 終了

jot 回数 開始 終了 増加

seq 終了

seq 開始 終了

seq 開始 増加 終了

awk

awk を使って出力すればどうかということになるが、以下の書き方ではSolarisでは標準入力オープンしてしまうため期待通りに動作しないらしい。*1

% awk 'BEGIN { for(i = 0; i < 10; i++) { print i } }'

この場合、/dev/null を読ませるようにしてこのようにすればSolarisでも動作するようだ。*2

% awk 'BEGIN { for(i = 0; i < 10; i++) { print i } }' /dev/null

expr

もしくは、expr でがんばる?

getseq()
{
  i=$1
  END=$2
  while [ "$i" -lt "$END" ]; do
    echo $i
    i=`expr "$i" + 1`
  done
}

POSIX shellだと、exprの代わりに$((expr)) を利用出来るようだ。かなり古いFreeBSD/bin/shでも利用出来たし、もう移植性のある方法と言って差し支えないのかもしれない。

でも…

もうPerlでいいような気もしてきた。大抵どこにでもあるし。

% perl -e 'print "@{[0..9]}\n"'

*1http://ya.maya.st/d/200611b.html#s20061116_2

*2:手元に環境がないので試していない。

2011年01月03日

OpenVZ/Virtuozzo (DTI VPSなど) の利用者向け便利情報

DTIのServersMan@VPSなど、OpenVZ/VirtuozzoのVE (仮想環境) を利用している場合に便利な情報を書いてみる。

OpenVZ/Virtuozzoの仕組み

一言で言えば、FreeBSD Jailと類似している。(かなり高機能だが。)

OpenVZ/Virtuozzoは HWN (hardware node; ホストOS) とVE (virtual environment; ゲストOS) がカーネルファイルシステムプロセス空間を共用しているため、以下のような制限がある。

  • kernel周りの入れ替えは出来ない。
  • sysctl -wや/proc/sys以下への書き込みによるカーネル設定の変更は出来ない。
  • 時刻を設定することが出来ない。(HWN側で設定する)
  • スワップを設定することが出来ない。
  • その他もろもろ

リソース

プロセス数やメモリ使用量やその制限状況は/proc/user_beancountersを読み出すことで確認することが出来る。(rootのみ読み取り可能。) ちなみに "bean counter" は経理担当者会計士という意味*1

# cat /proc/user_beancounters

ここで、heldは現在の値、maxheldは直近に集計した時点の最大値、barrierとlimitは制限値や保証*2、failcntがリソース割り当てに失敗した回数を表す。

VPSでfailしやすいリソースは、プロセス数 (numproc)、メモリ (vmguarpages=保証値、privvmpages=最大値)、TCPソケットの同時接続数 (numtcpsock) なので、この値を注意して見ておくと良い。保証値を超えた分はOOM killerで停止される可能性があるため、安定して運用するためにはこの範囲内で動作させる必要がある。

なお、商用版のVirtuozzo*3ではPPP (Parallels Power Panel) やVZPP (Virtuozzo Power Panel) からResource Alertを確認する事ができるように設定してあることが多い。

ネットワークインターフェイス

ネットワークインターフェイス名はethではなくvenetとなるため、ethのMACアドレス (HWaddr) をチェックしているソフトが動作しない。(技術的な理由と言うよりは、ライセンス確認のために行っていることが多い。)

プロバイダ操作を制限出来るか

プロバイダVPS内を操作することが出来ないような設定は出来ない。たとえhosts.allow/hosts.denyでsshアクセス制限をした場合でも、HWN側からvzctlコマンドでVE側にログインすることや、コマンドを直接実行することが出来る。

VE内の全プロセスはHWNからは全て操作可能のため、直接停止などのシグナルを送信することも可能。(HWNからvzps*4などを利用するとVE内のプロセスを見やすく表示することが出来る。)

ファイルシステムはHWNの /vz/root/$VEID 以下にそのまま展開されているため、HWN側から直接そのまま操作することが可能。

情報源

とりあえず OpenVZ Wiki 見ておけばいいと思う。

http://wiki.openvz.org/

*1:あまり好意的な使い方ではないようだ。

*2:barrierとlimitの意味リソースによって異なる

*3DTIでは採用していない。

*4:OpenVZには無い。

2011年01月01日

DTI VPSの大部分がオープンプロキシになっていた件について

Twitterで断片的につぶやいた (http://twilog.org/hirayasu/date-101230) 内容をもう少し詳しくまとめておく。

概要

先日、DTIのServersMan@VPS*1メンテナンス (機能追加) http://www.dti.co.jp/release/101216.html でAirDisplay@VPS*2インストールが行われたが、設定ミスがありほぼ全てのVPSオープンプロキシ (アクセス制限が行われず誰でも利用出来るプロキシサーバ) となっている状態だった。

12/27メンテナンス作業後

まず、27日のメンテナンス時点で /etc/httpd/conf.d/proxy_ajaxterm.conf にはイカのように記載されていた。これは localhost:8022 で動作する AjaxTerm に対するリバースプロキシ設定だが、本来不要な記載をしているためにセキュリティ上の問題があった。

<IfModule mod_proxy.c>
ProxyRequests On

<Proxy *>
        Order deny,allow
        Deny from all
        Allow from all
</Proxy>
ProxyPass /airdisplay/ http://localhost:8022/
ProxyPassReverse /airdisplay/ http://localhost:8022/

ProxyRequests On を設定することによりApacheHTTP Proxyサーバとして動作するが、ProxyPass, ProxyPassReverse を利用する場合にはこの設定を有効にする必要は全く無い。これは、Apacheマニュアルにもイカのように記載されている。

The ProxyRequests directive should usually be set off when using ProxyPass. (http://httpd.apache.org/docs/2.2/en/mod/mod_proxy.html#proxypass)

さらに、このプロキシ機能に対して Allow from all (制限無しにアクセス可能) を設定したため、無制限にプロキシ機能を提供するオープンプロキシの状態となっていた。

12/30緊急メンテナンス作業後

ProxyRequests On の設定は12月30日の緊急メンテナンスコメントアウトされたようだが、Proxy * に対するアクセス制限が allow from all のままとなっているため、元々HTTP Proxyサーバとして動作させている場合にはそのアクセス制限にかかわらず、allow from allで上書きされる可能性がある。

ServersMan@VPSサービス 緊急メンテナンスのお知らせ

http://info.dti.ne.jp/announce/docs/20101230_01.html

CentOS/RHELパッケージで導入されたApache場合、/etc/httpd/conf/httpd.conf に

include conf.d/*.conf

という記載があり、途中で設定が読み込まれる。この読み込まれる順番は文字コード順となる。

proxy_ajaxterm.conf が読み込まれる前にHTTP Proxyの設定が記載されていた場合、たとえば192.0.2.0/24 からのみアクセス可能とするためにproxy.confというファイル名 (読み込み順はproxy_ajaxterm.confより先となる) で以下の設定を行っている場合でも、アクセス制限は上書きされてオープンプロキシとなる。

ProxyRequests On
<Proxy *>
  Order deny,allow
  deny from all
  allow from 192.0.2.0/24
</Proxy>

HTTP Proxyサーバとして利用している例は多くはないだろうが、メンテナンスでは既存環境に極力影響を与えないように行うべきだと思う。

推奨する設定変更

AjaxTermを無効化、AjaxTermに対するリバースプロキシ設定を削除することをおすすめする。

service ajaxterm stop
chkconfig ajaxterm off
rm /etc/httpd/conf.d/proxy_ajaxterm.conf
service httpd restart

また、各種ブラックリストに登録されていないか確認しておく方が良いだろう。

*1http://dream.jp/vps/

*2:AjaxTermを利用したウェブ経由のシェルアクセス