Entry: 非root権限でCPANモジュールをインストールする(焼増し)
非root権限でCPANモジュールをインストールする(焼増し)
非root権限でCPANモジュールを使う方法を調べた。Debian lenny(最小限のセットアップ)にて。2006年頃までにすべての情報が出尽くしてるのに何を今さら。
cpanの初期設定をする。設定項目「makepl_arg」はモジュールのインストール先ディレクトリ。PREFIX=~/perlと記載することで~/perl下に配置される。設定ファイルは下記のように書き換える。
$ vi ~/.cpan/CPAN/MyConfig.pm- 'makepl_arg' => q[],
+ 'makepl_arg' => q[PREFIX=~/perl],
依存関係のあるモジュールを芋づる式にインストールするとき、後に入るモジュールのテストスクリプトが、直前の依存モジュールをincludeできなくてつまづく。これを回避するため、ユーザーの環境変数PERL5LIBにパスを設定する。~/.bashrcに下記を追記すれば楽。どうやらものによって下記のような2つのパスにインストールされるらしい。
$ vi ~/.bashrc
export PERL5LIB=~/perl/lib/perl/5.10.0:~/perl/share/perl/5.10.0
最初の「~/perl」は先ほどMyConfigのmakepl_argに追加したパス、それ以降は環境に依存するようなので一度失敗してみてパスを確認して再試行。もっといい方法ないのか。そのためのlocal::libなのかどうなのか、またの機会に調べてみよう。
参考サイト
一般ユーザ環境におけるCPANモジュールの使い方
Using CPAN with a non-root account
Entry: 自作バックアップスクリプトは高速化しなかった
Entry: Perlで差分バックアップスクリプト
Perlで差分バックアップスクリプト
2006年にpdumpfsっぽいPerlスクリプトを書いた。glastreeの存在は知っていたけど、敢えて自分で作ってみた。それ以来、仕事でもプライベートでも重宝していたんだけど、最近問題発生。職場のファイルサーバーには百万越えのファイル数があって、毎日数万の差分が発生し、バックアップに5時間かかっていた。こいつはまずいということで手直しした。結果、取りあえず、自宅では以前の10倍高速になった。
ちなみに、今回はglastreeのソースを追って参考にしてみたらほぼ同じ内容になってしまったんだけど、glasstreeとの違いは下記のとおり。
- バックアップの管理が日付に依存しないので任意の頻度(例えば2時間おきとか)で実行できる
- コピーされたログを残す
- コアモジュール以外に依存しない
- 差分がない場合はバックアップを自動削除
ログが残るってのはなかなか便利です。差分リスト=作業履歴なので。
使い方
perl ddump.pl [バックアップ対象] [保存場所]
ソース
use strict; use warnings; use utf8; use English; use Getopt::Long; use File::stat; use File::Copy; use File::Path; binmode(STDIN, ":utf8"); binmode(STDOUT, ":utf8"); binmode(STDERR, ":utf8"); use open IO => ":utf8"; use vars qw(%QUERY %stat_idx); # 設定 use vars qw($log $copy_count $file_count $symlink_count); # ログ関係変数 use vars qw($tgt_path $newdir $olddir); # ディレクトリ main(); sub main { %stat_idx = ('mode' => 2, 'size' => 7, 'utime' => 9); %QUERY = ('mode' => 1, 'size' => 1, 'utime' => 1); GetOptions(\%QUERY, 'mode=s', 'size=s', 'utime=s'); ### 引数の整備と検証 $ARGV[0] = &fixPath($ARGV[0]); $ARGV[1] = &fixPath($ARGV[1]); -d $ARGV[0] or die "$ARGV[0] not found"; -d $ARGV[1] or die "$ARGV[1] not found"; ### 引数を分離 ($tgt_path, my $tgt_dir) = ($ARGV[0] =~ m!(.*)?/([^/]+)$!); ### 前回バックアップの時刻ディレクトリ名を取得 if (opendir(DIR, "$ARGV[1]")) { my @dirs = sort grep{ -d "$ARGV[1]/$_" && /^[^.]/} readdir( DIR ); close(DIR); $olddir = "$ARGV[1]/". (pop(@dirs) or ''); } ### 時刻ディレクトリの作成 my ($sec, $min, $hour, $mday, $mon, $year) = localtime($BASETIME); my $new_time = sprintf('%04d%02d%02d%02d%02d%02d', $year+1900, $mon+1, $mday, $hour, $min, $sec); $newdir = "$ARGV[1]/$new_time~"; umask 0; mkdir($newdir, 0755) or die "cannnot make $newdir"; ### ログファイル生成 open($log, ">>$newdir/ddumplog.txt") or die "cannnot make log file"; print $log <<EOF; ----------------------------------------------------------------- -- ddump -- $new_time ----------------------------------------------------------------- EOF ### ログ記録用変数 $copy_count = 0; $file_count = 0; $symlink_count = 0; ### バックアップ &backup($tgt_dir); ### ログファイルに結果出力 print $log "$copy_count/$symlink_count/$file_count (Copyed/symlink/Total)\n"; print $log (time() - $BASETIME). "sec passed\n"; close($log); if (! $copy_count) { ### コピーなしならディレクトリ削除 rmtree($newdir); } else { ### ファイル名確定 rename($newdir, substr($newdir, 0 ,length($newdir) - 1)); } } ### -------------------------------------------- ### 再帰的ディレクトリバックアップ ### -------------------------------------------- sub backup { my $cwd = shift; my $tgt_cwd = "$tgt_path/$cwd"; my $old_cwd = "$olddir/$cwd"; my $new_cwd = "$newdir/$cwd"; ### ディレクトリの作成 ©dirstat($tgt_cwd, "/$new_cwd"); ### カレントディレクトリ内の全ファイルを配列に格納 opendir(DIR, $tgt_cwd) or return 0; my @files_and_dirs = readdir(DIR); close(DIR); my @files = grep { -f "$tgt_cwd/$_" or -l "$tgt_cwd/$_" } @files_and_dirs; ### @files_and_dirsのうち、ファイルを処理 foreach my $a_file (@files) { my $old_file = "$old_cwd/$a_file"; my $new_file = "$new_cwd/$a_file"; my $tgt_file = "$tgt_cwd/$a_file"; my $command = 1; # 0: nothing, 1: hard link 2: copy if (-l $tgt_file) { symlink(readlink($tgt_file), $new_file); $symlink_count++; $command = 0; } elsif (-f $old_file) { my $old_stat = stat($old_file); my $crnt_stat = stat($tgt_file); ### 更新ありならコピー foreach my $key (keys %stat_idx) { if ($QUERY{$key} and $old_stat->[$stat_idx{$key}] ne $crnt_stat->[$stat_idx{$key}]) { $command = 2; last; } } } else { ### ファイルがなければコピー $command = 2; } ### コピー if ($command == 2) { copystat($tgt_file, $new_file); $copy_count++; ### ログ出力 utf8::decode($new_file); print $log "$new_file\n"; } ### ハードリンク elsif ($command == 1) { link($old_file, $new_file); } $file_count++; } ### @files_and_dirsのうち、ディレクトリを再帰処理 my @dirs = grep { -d "$tgt_cwd/$_" and not -l "$tgt_cwd/$_" and $_ ne '.' and $_ ne '..' } @files_and_dirs; foreach my $a_dir (@dirs) { &backup("$cwd/$a_dir") or print "Error at $cwd/$a_dir\n"; } return 1; } ### -------------------------------------------- ### 属性丸ごとファイルコピー ### -------------------------------------------- sub copystat { my ($from, $to) = @_; my $stat = stat $from; copy($from, $to); chown($stat->uid, $stat->gid, $to) if $EUID == 0; chmod($stat->mode, $to); utime($stat->mtime, $stat->mtime, $to); } ### -------------------------------------------- ### 属性真似てディレクトリ作成 ### -------------------------------------------- sub copydirstat { my ($from, $to) = @_; my $stat = stat $from; mkdir $to, 0555; chown ($stat->uid, $stat->gid, $to) if $EUID == 0; chmod ($stat->mode, $to); utime ($stat->mtime, $stat->mtime, $to); } ### -------------------------------------------- ### ファイルパスの整備 ### -------------------------------------------- sub fixPath { my $in = $_[0]; $in =~ s!^!\./! unless ($in =~ m!^\.*/!); $in =~ s!/$!!; return $in; }
Entry: OSC行ってきた
OSC行ってきた
OSC行ってきた。朝から晩までセミナー三昧。
一番面白かったのはPostgresqlで全文検索というやつでした。to_tsvectorってのを使うことでlikeでマッチングするより速度が100倍(!)っていうデモをやってました。バージョン8.3からって言ってたかな。
その他にはFirefoxの中の人のセミナーでは、オープンソースの基礎知識的な話題もあって、今さら人には聞けない系の知識を収集できた。Netscapeがブラウザのソースを公開する際に、フリーウェアという名称の代替えとしてオープンソースと呼称したのがOSSの始まりだったとか、GIFのサブマリン特許の話、動画を巡る同様の問題を回避する取り組み->Firefox3.5という流れ。
OpenOffice Baseに関するセミナーも面白かった。まだ、MS Accessの代替にはならないけど、がんばってますって話。なんか、自分には何かできることがあるだろうか、なんて発想が自然と湧いてくるいい内容でした。
最後にAndroidのアプリ開発に関するセミナー。何らかのトラブルでうまく進行してなかったみたいだけど、人が開発してる様子をリアルに眺めるだけでも刺激的。そして、となりの席にリアル兄がいたという偶然。
その他にもサーバー系とネットワーク系のセミナーも受けたけど、全く理解できなくて少し凹んだ。サーバーマシントラブルのほとんどはホコリが原因だという話だけがためになった。
Entry: text-overflow:ellipsis
text-overflow:ellipsis
以前にこんなエントリ書いたり、こんなjQueryプラグイン作ったりしたけど、それってCSSだけでできるんじゃん!
http://www5e.biglobe.ne.jp/~access_r/hp/css/css_text_019.html
text-overflow
テキストがオーバーフロー(領域を超えてしまう事)する際にオーバーフローしたテキストを「...」で省略することが出来ます。
しかも属性名と値などのキーワードも思い描いたまんまじゃん。ただし、省略記号を有効にする指定はtext-overflow: ellipsis;だ。以前にもちゃんとググったつもりだったけど、英語の情報無視してたかなあ。
ただしFirefoxは未対応なので依然としてJavascriptでのハックは必要。また、text-overflowはIEのみの対応のようで、SafariやOperaはそれぞれの拡張属性を併記して対応できる。
a.width-limited {
display:block;
overflow: hidden;
white-space:nowrap;
-webkit-text-overflow: ellipsis; // Safari
-o-text-overflow: ellipsis; // Opera
text-overflow: ellipsis; // IE
}
Entry: ブックマーク
Entry: Javascriptオフ対策、その2
Javascriptオフ対策、その2
検索とタグクラウドもノースクリプトで利用できるようにした。ページナビゲーションはまだない。
JS用に用意した部品のDOMをNoscriptな人に見せないために、最初は<script></script>内に書けばいいのかと思ったら失敗。<script>タグは<noscript>タグのnotでは全然なかったのだ。考えたこともなかったけど、<script>タグ内にはスクリプトしか書いちゃいけない、とのこと。今さらながら。
スクリプト用のDOMはスクリプトで書くしかないのかと思い、document.writeの列挙が頭をよぎったものの、メンテナンス性に配慮してjQueryのappendだのprependだののDOM操作で何とかする。それでも、文字のエスケープの問題もあるし、本来HTMLで書くべきものをJavascriptで書き出すのはやはり手間がかかる。でもまあいいか。
と思っていたのが昨日の話で、今日、あっけない結論に達する。まあ、ここに書くまでもないことかも。
<div class="dom_for_script" style="display:none"></div> <script type="text/javascript"> //<![CDATA[ $(".dom_for_script").show(); //]]> </script>
Entry: Javascriptオフ対策、少しした
Entry: ブックマーク
Entry: ブックマーク
ブックマーク
- Google「ストリートビュー」で素早い移動が可能に
めっちゃ便利。久々にストリートビュー使ってみたら、いつのまにユーザーの写真が掲載されてたのね。 - グーグル、「Google Chrome」のMacとLinux向け開発者プレビュー版をリリース
- 自分の考えたアイデアを内緒にしたがるひと
- ついに出た!最新Perlフレームワーク「Ark」徹底解剖
未だにCatalystすら使ったことなくって、全部自前フレームワーク。そろそろ人の作ったソースを追ってみたい。これはうってつけ。 - 正規表現まとめサイト
プログラミングとか資料作成とかデータ整理とかスケジューリングとかネットサーフィンとか、ありとあらゆる場面で正規表現なしには生きて行けない。Google検索も正規表現に対応してほしいくらいだ。でも、最近XMLを扱う機会が多いのでXPATHを覚えたい。XPATHが扱えるテキストエディタ探し中。 - 日本ファルコム「音楽フリー宣言」を発表
そうなるんだ、これからは。「著作権」は消える。無形の何かに権利を主張できる時代はもう終わるんだ。レコードの時代は終わりライブの時代ふたたび。音楽家も作家も技術者も、継続的にライブな生産をして行くしか生き残る道はない。一旦世に出たらもう人類の共有財産。 - Googleが社内で使っていたWebサイト高速化ツールを一般公開
Subscribe to my RSS feed