It's raining cats and dogs.

無駄なことなんてないはず

perlがスクリプトをどのように解釈しているのかを知るためのB::Deparseなるものを知った

僕のperlの先生monmonさんに今日もまた教えてもらった。

perlがどのようにスクリプトを解釈しているのかを事前に知ることのできるB::Deparseというものがあるらしい。

↓のサイトを参考にさせていただいた。
http://www.g-ishihara.com/perl/compiler01.html

B::Deparseってのは、perlスクリプトをコンパイルして、そこから更にソースコードを生成(デコンパイル?)するらしい。なのでperlがどのようにそのスクリプトを解釈しているのかってのがわかるとか。

ちなみにBモジュールってのはperlコンパイラ系のモジュールで、Oモジュールってのはそのモジュールを操作するためのインターフェースみたいなものとのこと。

ではやってみる。

$ perl -MO=Deparse -e 'use constant HOGE => 1;print HOGE;'
use constant ('HOGE', 1);
print 1;
-e syntax OK

HOGEが展開されてprint 1となっている。

↓はmonmonさんに教えてもらった内容。ループの中で何かの計算をして$xに値を入れている。ループのたびに計算して効率の悪そうな感じなのだけど、Deparseすると、コンパイル時点で既に計算されているので、そんなに効率は悪くないことがわかる。

$ perl -MO=Deparse -e 'for my $i (0..100){my $x = 60*60*24;}'
foreach my $i (0 .. 100) {
    my $x = 86400;
}
-e syntax OK

ちなみにこのforはリストコンテキストなので、foreachになっていることもわかった。

あと面白いのが↓

$ perl -MO=Deparse -e 'use constant DEBUG => 1;if(DEBUG){print "debug";} print "done."'
use constant ('DEBUG', 1);
do {
    print 'debug'
};
print 'done.';
-e syntax OK

よくあるデバッグフラグみたいなものを定数に入れていて、if文で判定してデバッグモードだったらほげほげみたいな処理。
これはif文の判定すらなくなっている。

こんな感じでコンパイル具合がわかるので、これからはちょいちょい使ってみたい。

ORA-12154: TNS: 指定された接続識別子を解決できませんでした

sqlplusなどでoracle clientを使ってoracleにアクセスするときによく出るアレ。これがでるとなんだか憂鬱。 たぶんネットに溢れかえっているであろう内容だけど、備忘録。

$ sqlplus <ユーザーID>/<パスワード>@<SID>

SQL*Plus: Release 11.2 Production on 月 9月 30 20:58:17 2013

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

ERROR:
ORA-12154: TNS: 指定された接続識別子を解決できませんでした


ユーザー名を入力してください:

今回は、tnsnames.oraを読み込めていないのが原因だった。oracleはtnsnames.oraはどのパスで見つけに行くのか。

  1. 環境変数 TNS_ADMIN で設定したディレクトリ配下
  2. $ORACLE_HOME/network/admin 配下

とのこと。 今回はtnsnames.oraが

$ORACLE_HOME/lib/network/admin/tnsnames.ora

となっていたのとTNS_ADMINが設定されていなかったのが原因。なぜこのパスになってしまったのかはわからないけど、
とりあえずこのエラーが出た時に少し萎えなくなれた気がする。

httpsでのgit cloneをやめてssh over https portでcloneした話

以前gitのバージョンが1.7.10以下の環境でhttpsを使ってgithubからcloneするエントリを書いた。

http://tadasy.hateblo.jp/entry/20130903/1378209883

基本的にはコレで問題無さそうで、個人の環境をとして使うのであれば特に問題はないのだけれど、共有の環境、例えばステージング環境や本番を作る場合にはちょっと問題になる。というのも

$ git clone https://<githubのユーザーID>@github.com/sampleProject/hoge.git

こんな感じでcloneしてたのだけど、fetchするときなどに<githubのユーザーID>で指定したアカウントのパスワードを入力しなければいけない。↓な感じで。

$ git fetch
Password for 'https://<githubのユーザーID>@github.com':

.git/configを確認しても

$ cat .git/config
....
 [remote "origin"]
         url = https://<githubのユーザーID>@github.com/sampleProject/hoge.git
         fetch = +refs/heads/*:refs/remotes/origin/*
...

とユーザーIDが書かれている。

みんなで使う環境だとこのアカウントのパスワードを知らないとどうにもならない(もしかしたらやり方があるかもしれないけど)
共有のアカウントを作ればいいのかもしれないけど、それはそれでなんだかなぁと。

あと、

https://username:password@github.com/sampleProject/hoge.git

こんな感じでパスワードも指定できるよ的なことを書いたのだけど、たしかにこれでやればパスワードは覚えなくてよいのだけど、これでやると当然.git/configにもパスワードが記載されてしまう。

$ cat .git/config
...
 [remote "origin"]
         url = https://username:password@github.com/sampleProject/hoge.git
         fetch = +refs/heads/*:refs/remotes/origin/*
...

さすがにコレはまずい。

というわけで見つけたのが↓

https://help.github.com/articles/using-ssh-over-the-https-port

記事に書いてあるとおり、まさにそのままなんだけど、要は、githubのほうでhttps上でssh接続ができる環境を用意してくれていて、それを使えばファイアーウォールでssh閉じられててもsshで接続できるよって話。

まずは接続テスト

$ ssh -T -p 443 git@ssh.github.com
Hi <githubのユーザーID>! You've successfully authenticated, but GitHub does not provide shell access.

接続できた風。 あとは ~/.ssh/config に以下を追加すればOK

Host github.com
  Hostname ssh.github.com
  Port 443

で、sshを使ってcloneしたら完了。

$ git clone git@github.com:sampleProject/hoge.git

ちなみにsshでの接続になるので、以前書いた

http://tadasy.hateblo.jp/entry/20130918/1379509506

このへんなんかも必要なくなってしまった。
もっと早く気がついていれば...

perlコマンドの評価順

extlib的なプロジェクトローカルなディレクトリにCPANモジュールを突っ込んでいて、そのライブラリがうまくインストールできているか(動くか)を確かめたかったのでワンライナーで試していたらなんか失敗した。

$ perl -MDateTime -Mlib=extlib/lib/perl5/ -e 'print DateTime->now(time_zone=>"local");'
Can't locate DateTime.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .).
BEGIN failed--compilation aborted.

@INCにextlibを登録していなかったので、-Mlibでextlibを指定したのに...
で、以下のように-MDateTimeと-Mlibの順序を変えてみた。

$ perl -Mlib=extlib/lib/perl5/ -MDateTime -e 'print DateTime->now(time_zone=>"local");'
2013-09-26T20:45:19

無事動きました。
まぁよくよく考えて見れば、-Mlibの評価の前に-MDateTimeでuseしようとしてもそりゃ見つかんないわな。

use DateTime;
use lib 'extlib/lib/perl5';

みたいなもんだ。
perlコマンドの-Mの動きを少し覚えた。

余談

perlコマンドのオプションを調べるにはperlrunというマニュアルのエントリを調べれば良いことを覚えました。
http://perldoc.jp/docs/perl/5.6.1/perlrun.pod

https経由でgit cloneしたら「error: RPC failed; result=18, HTTP code = 200iB」的な怒られ方をした時の話

まえにhttps経由でとあるリポジトリを古い環境にcloneした時のことを書いた。

http://d.hatena.ne.jp/tadasy/20130904/1378299371

この時に確かもう一つハマっていたことがあって、それが表題の件。

$ git clone https://github.com/sampleProject/hoge.git
Cloning into 'hoge'...
Username for 'https://github.com': <ユーザ名>
Password for 'https://<ユーザ名>@github.com': <パスワード>
remote: Counting objects: 51114, done.
remote: Compressing objects: 100% (11818/11818), done.
error: RPC failed; result=18, HTTP code = 200iB | 212 KiB/s
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: recursion detected in die handler

てな感じで

error: RPC failed; result=18, HTTP code = 200iB | 212 KiB/s

みたいなことを言われる。
調べていくと、同じようにはまってる人はいるもので、以下のブログがみつかった。

http://nantonaku-shiawase.hatenablog.com/entry/2013/09/01/111820

なるほどcurlでpostするときのbufferサイズ的なやつがいかんのか。
とりあえずこのブログからたどった先のように

git config --global http.postBuffer 524288000

というようにしたらうまくcloneできた。
新しい環境(SL6.4)ではこの設定をしなくてもcloneできたので、libcurlのバージョンが古かったせいかもしれないが定かではない。
まぁ前にも書いたけど、この開発環境は使わないのだけど。。。

perlの@INCの値を調べる方法

情弱ネタ

perlのinclude path? load path?を調べる時はこれまで

$ perl -e 'print join("\n", @INC);'
/usr/local/lib64/perl5
/usr/local/share/perl5
/usr/lib64/perl5/vendor_perl
/usr/share/perl5/vendor_perl
/usr/lib64/perl5
/usr/share/perl5

みたいな感じで調べていたのですが、もっと簡単に調べる方法がありました。

※一応それっぽいところは日和って、「*」でふせてみました。

$ perl -V
Summary of my perl5 (***********************) configuration:

  Platform:
     ***********************
  Compiler:
     ***********************
  Linker and Libraries:
     ***********************
  Dynamic Linking:
     ***********************


Characteristics of this binary (from libperl):
  ***********************
  Compiled at Mar 26 2013 17:10:09
  %ENV:
    PERL5LIB="****************"
    PERL_CPANM_OPT="--local-lib=****************"
  @INC:
    /usr/local/lib64/perl5
    /usr/local/share/perl5
    /usr/lib64/perl5/vendor_perl
    /usr/share/perl5/vendor_perl
    /usr/lib64/perl5
    /usr/share/perl5
    .

@INC以外も表示されてしまうけど、さくっと見るのには丁度良いのと、%ENVも見れるのでそれはそれで便利でした。