tarボールソースからインストールしたソフトを管理する「Graft」を使ってみる

ソースインストールした物を管理するツール「Graft」をインストールして使ってみたので、記録として残しておきます。

インストールと言っても簡単で、配布元サイトのドキュメント通りに実行すれば問題ありません。
配布元サイト
graft.html – peters

$ wget -O graft-2.4.tar.gz "http://peters.gormand.com.au/Home/tools/graft/graft-2.4.tar.gz?attredirects=0"
$ tar zxvf graft-2.4.tar.gz
$ cd graft-2.4
## ここでエラーがでます。
$ make -f Makefile.dist
######################################################
#                                                    #
#       You'll now need to modify the Makefile       #
#      variables to suit your local conditions.      #
#                                                    #
######################################################
make: *** [Makefile] Error 1
## エラーが出るので、Makefileを編集する必要があるようです。

Makefile

このPACKAGEDIRがパッケージ管理用のディレクトリになり、ここにソースからインストールします。
PACKAGEDIR	= /pkgs
TARGETDIRは、通常インストールしたい場所、つまり/usr/localなどを指定します。
# TARGETDIR	= /pkgs
TARGETDIR	= /usr/local
Perlコマンドの場所を指定します。/pkgs/bin/perl となっていますが、ほとんどの場合、/usr/bin/perl に設置されていると思いますので変更します。
# PERL		= /pkgs/bin/perl
PERL		= /usr/bin/perl

あらためてビルドします。

$ make clean
$ make
# sudo make install
## graftがインストール出来ていることを確認。
$ ls /pkgs
graft-2.4
## graft自身を/usr/local/bin配下にインストール
# /pkgs/graft-2.4/bin/graft -i graft-2.4
## シンボリックリンクされていることがわかる
$ ls -l /usr/local/bin
lrwxrwxrwx  1 root root 25 7月 30日 09:23 /usr/local/bin/graft -> /pkgs/graft-2.4/bin/graft

これでインストールは無事に完了しましたので、さっそく使ってみます。
今回は、試しにrubyをインストールしてみました。

$ wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p299.tar.gz
$ tar zxvf ruby-1.8.7-p299.tar.gz
$ cd ruby-1.8.7-p299
$ ./configure --prefix=/pkgs/ruby-1.8.7-p299 && make
# make install
## 無事にインストール出来たことを確認
$ ls /pkgs
graft-2.4  ruby-1.8.7-p299
## graftコマンドでインストール
# graft -i ruby-1.8.7-p299
$ ls -l /usr/local/bin
lrwxrwxrwx  1 root root 30 7月 30日 09:27 /usr/local/bin/ruby -> /pkgs/ruby-1.8.7-p299/bin/ruby

rubyをアンインストールしてみる。

# graft -d ruby-1.8.7-p299
EMPTY        /usr/local/lib/ruby/1.8/bigdecimal/ is now empty. Delete manually if necessary.
EMPTY        /usr/local/lib/ruby/1.8/cgi/session/ is now empty. Delete manually if necessary.
...

一部ディレクトリが残ってしまっていますが、-Dオプションで実行することで、空のディレクトリも削除してくれるようです。

アップデートを想定して、ruby1.9系を入れてみることにしました。
アンインストール後に、インストールしても問題ないかと思いますが、今回はPruneという機能を使ってみます。これは既存のファイル群との衝突を回避するために、末尾に.prunedを付けたファイル名にリネームしてくれるものです。

## まず1.8.7をインストール
# graft -i ruby-1.8.7-p299
$ /usr/local/bin/ruby -v
ruby 1.8.7 (2010-06-23 patchlevel 299) [i686-linux]
## 1.9.1をダウンロード、インストール
$ wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p429.tar.gz
$ tar zxvf ruby-1.9.1-p429.tar.gz
$ cd ruby-1.9.1-p429
$ ./configure --prefix=/pkgs/ruby-1.9.1-p429 && make
# make install
## graftコマンドでrubyを1.8.7から1.9.1にアップデートします
## アンインストール前に新しいバージョンの物をインストールしようとすると、衝突としてエラーが表示されます
# graft -i ruby-1.9.1-p429
CONFLICT     /usr/local/bin/erb is linked to something other than /pkgs/ruby-1.9.1-p429/bin/erb (/usr/local/bin/erb -> /pkgs/ruby-1.8.7-p299/bin/erb)
# graftコマンドを-pオプションで実行してみると、ファイル名の後ろに.prunedとリネームされているのがわかる
# graft -p ruby-1.8.7-p299
$ ls -l /usr/local/bin
lrwxrwxrwx  1 root root 30 7月 30日 09:39 /usr/local/bin/ruby.pruned -> /pkgs/ruby-1.8.7-p299/bin/ruby
# あらためてインストール
$ graft -i ruby-1.9.1-p429
## 1.9.1がインストールできていることを確認
$ ls -l /usr/local/bin
lrwxrwxrwx  1 root root 30 7月 30日 10:02 /usr/local/bin/ruby -> /pkgs/ruby-1.9.1-p429/bin/ruby

いくつか気になった点がありました。

  • 衝突回避のためにリネームされた.prunedファイルを消せない。

 (-pオプションで実行させる度に、上書きされるようなので問題なし?)

  • 設定ファイルも一緒に上書きされそうなので、.graft-exclude

や.graft-includeなどを使って、必要なものだけインストールするように調整する必要があるかもしれません。(未検証)

非常にシンプルに出来ていて簡単に使うことが出来るので、ごちゃごちゃとした余計な機能はいらない、という人にとってはオススメです。
あとは、ソースからインストールしたものが/pkgsに溜まっていくので、前のバージョンにすぐに切り替えたりといった事もできます。

tarボールからインストールしたものを管理

最近はほとんどのものがパッケージで提供されており、ソースからわざわざインストールする機会もずいぶん減った気がします。
しかし、中にはソースからインストールしないといけない場合もあるかと思います。
自分はApachePHPなど主要なソフトは、ソースからインストールする事が多いです。

今までは、バージョンアップさせる度にバカの一つ覚えと言わんばかりに、make && make installをひたすら叩きまくっていたわけです。
バージョアップしたはいいけど、おかしくなったらすぐ戻せる環境がベストだと思い、ちょっと色々調べてみました。

僕が理想とする機能は、

  • ソースから入れたファイル群を管理できる
  • バージョン毎にインストールしたものが管理できる
  • 前のバージョンに戻せる
  • コマンドから削除ができる

paco

まず最初に見つけたのがpacoです。
これはほぼ理想通りで、欲しい機能がほとんど揃っていました。なにより、使っている人が多くて、実績という点でも安心できそうです。
一つ気になった点は、前のバージョンに戻すような履歴管理が簡単ではなかった点です。
軽く調べた感じだと、pacoballというコマンドで、今のバージョンをtarボール化し、新しいバージョンの物を入れるという感じになりそうです。

インストール

## -Dオプションでカレントディレクトをパッケージ名として利用します
# paco -D make install
## -pオプションでパッケージ名の指定が可能
# paco -p "app-1.4.1" make install

アンインストール

# paco -r app-1.4.1

その他

## インストール済みソフトの一覧表示
# paco -a
## 共有ファイルの表示
# paco -fc app
app-1.4.1:
/usr/local/app/conf/local.conf
## インストールした日を表示
# paco -dd app
01-Sep-2008 18:46  app-1.4.1
## configureオプションの表示
# paco -o app
--disable-hoge --enable-extension
## 現在のバージョンをtarボール化
# pacoball -b app-1.4.1
app-1.4.1.paco.tar.bz2
## tarボール化したものに戻す
# tar jtvf app-1.4.1.paco.tar.bz2

参考
Pacoでソースからインストールした物を管理する – WapBox
paco – a source code pacKAGE oRGANIZER for Unix/Linux
pacoでソースから導入したパッケージを管理する | Glide Note – グライドノート

Graft

次に見つけたのがこのGraftです。
pacoより機能面では劣るものの、ずいぶん昔から存在していたようです。
しかし、使ってる人の情報がほとんどない・・・。非常にシンプルが故に簡単に使うことができます。
衝突回避のためのPruneという機能がユニークです。

インストール

# graft -i app-1.4.1

アンインストール

# graft -d app-1.4.1

その他

## 衝突回避のためのPrune機能。既存ファイルが.pruned拡張子にリネームされる
# graft -p app-1.4.1

Graftの詳細記事はこちら
tarボールソースからインストールしたソフトを管理する「Graft」を使ってみる – フタなしカンヅメ

Stow

次は、Stow(すとーんと読むのかな?)です。
これもけっこう有名な物のようで、色々なサイトで紹介されていました。
モデルとしてはGraftと似ているようですが、Graftより機能が少ないようです。
たぶんこっちのStowのほうが古い。

インストール

# stow -t /usr/local/bin app-1.4.1

アンインストール

# stow -D app-1.4.1

その他

## 既存のファイルを更新した時の再処理(再読込)
# stow -R app-1.4.1

調べてみた感じだと、paco >> Graft >> Stowという印象です。後発であるpocoは機能面で優れており、色々便利な機能がたくさんあるので、新しく使うならpocoが良さそうです。
シンプルで最小限の機能だけで十分ということであれば、Graftがよさそうです。

RPMのDBがぶっ壊れた

いつものようにyumでパッケージを更新しようとしたらハングしてしまう。

# yum update
Loaded plugins: fastestmirror ## ここで止まってしまう

再起動して、またアップデートを実行してみたら、今度は次のようなエラーが表示された。

# yum update
error: rpmdb: damaged header #1304 retrieved -- skipping.
エラー: rpmdbNextIterator: スキップします。 h#    1304 タグ[60]: 異常です。tag 33281 type 4 offset 42564 count 1

またyumのキャッシュがおかしくなったのかと思い、yum clean allを実行してみたが同様にハングしてしまう。調べてみた所、RPMのDBが壊れているようで、DBを再構築することで対応できました。

# rpm --rebuilddb
zsh: segmentation fault  rpm --rebuilddb ## 一度目はこんなエラーがだた。
## /var/lib/rpm/ 以下のファイルをバックアップして、削除後にもう一度実行。
# rm /var/lib/rpm/*
# rpm --rebuilddb

参考サイト
RPM DB リビルド – まーのすけRoom
404 Not Found | Web、スマートフォンのオフショア開発 バイタリフィ

iptablesのセッション管理テーブルの上限を上げる

下記のようなログが出るようになったので、調べてみるとiptablesのセッション管理テーブルを使い果たすと出てくるエラーみたいです。

Jul 24 19:25:44 www-02 kernel: printk: 39 messages suppressed.
Jul 24 19:25:44 www-02 kernel: ip_conntrack: table full, dropping packet.

下記のURLを参考にnet.ipv4.ip_conntrack_maxの上限を上げてみたところ、エラーは出なくなった。とりあえず、これで様子見。

処理するセッション数が増えると、突然通信できなくなる(又は検査できなくなる。)(ip_conntrack数の変更) – 覚え書き Plus!

fon2405EルータにDD-WRTを入れる

iPadを買った時にfonという無線ルータをもらいました。どうせなので、色々いじってみたいと思い、改造ファームウェアを入れてみることにしました。

ファームウェアを書き換えるには、シリアルケーブルで接続する必要があるようで、fonの基盤に直接ケーブルをハンダ付けします。
SSHやtelnetなどの接続も試みましたが、このfonでは無理なようでした。
下記サイトを参考にしました。
unix is mine oyster, which I with code will open!: FON2405Eの中身
FONルータ復旧大作戦 | このいえ
DD-WRT – FoNまとめwiki
[FON] –  
Hot Tuna Labs

今回用意したのは、9-KEというシリアルケーブルと、fon本体のみです。9-KEは、ネット通販で送料込み数百円くらいでした。
ちなみにハンダ付けは今回が初めてで、以前から電子工作に興味があったので、これを機会にやってみようと思ったわけです。

なんとか取り付けることができ、シリアル経由でコンソールに繋いでみた所、起動ログがちゃんと流れてきました。ちょっと感動。

こんなログが流れてきました。

U-Boot 1.1.3 (Jan  6 2010 - 07:10:30)
Board: Fonera
DRAM:  32 MB
relocate_code Pointer at: 81fac000
spi_wait_nsec: 3e
spi deice id: c2 20 15 c2 20 (2015c220)
find flash: mx25l1605d
raspi_read: from:41030000 len:1000
Using default environment
##### The CPU freq = 320 MHZ ####
SDRAM bus set to 16 bit
SDRAM size =32 Mbytes
Please choose the operation:
1: Boot system code via Flash (default).
2: Load system code then write to Flash via TFTP.
3: Entr boot command line interface.
booting from flash
## Booting image at bf020000 ...
raspi_read: from:20000 len:40
Image Name:   MIPS OpenWrt Linux-2.6.21
Created:      2010-02-11   8:09:34 UTC
Image Type:   MIPS Linux Kernel Image (lzma compressed)
Data Size:    613723 Bytes = 599.3 kB
Load Address: 80000000
Entry Point:  80000000
raspi_read: from:20040 len:95d5b
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80000000) ...
## Giving linux memsize in MB, 32
Starting kernel ...
LINUX started...
THIS IS ASIC
Linux version 2.6.21 (blogic@blap4) (gcc version 4.1.2) #143 Thu Feb 11 09:09:18 CET 2010
The CPU feqenuce set to 320 MHz
CPU revision is: 0001964c
Determined physical RAM map:
memory: 02000000 @ 00000000 (usable)
Built 1 zonelists.  Total pages: 8128
Kernel command line: console=ttyS1,57600n8 root=/dev/mtdblock4 init=/sbin/preinit
Primary instruction cache 32kB, physically tagged, 4-way, linesize 32 bytes.
Primary data cache 16kB, 4-way, linesize 32 bytes.
Synthesized TLB refill handler (20 instructions).
Synthesized TLB load handler fastpath (32 instructions).
Synthesized TLB store handler fastpath (32 instructions).
Synthesized TLB modify handler fastpath (31 instructions).
Cache parity protection disabled
cause = 80800000, status = 1100ff00
PID hash table entries: 128 (order: 7, 512 bytes)
calculating r4koff... 0030d400(3200000)
CPU frequency 320.00 MHz
Using 160.000 MHz high precision timer.
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 30416k/32768k available (1689k kernel code, 2352k reserved, 186k data, 100k init, 0k highmem)
Mount-cache hash table entries: 512
NET: Registered protocol family 16
Generic PHY: Registered new driver
NET: Registered protocol family 2
Time: MIPS clocksource has been installed.
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 1, 8192 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
was not able to assign mahjor 200 to button chardev
ramips_gpio: done
squashfs: version 3.2-r2 (2007/01/15) Phillip Lougher
squashfs: LZMA suppport for slax.org by jro
io scheduler noop registered
io scheduler deadline registered (default)
ramips_wdt: loaded
Serial: 8250/16550 driver $Revision: 1.3 $ 2 ports, IRQ sharing disabled
serial8250: ttyS0 at I/O 0xb0000500 (irq = 37) is a 16550A
serial8250: ttyS1 at I/O 0xb0000c00 (irq = 12) is a 16550A
PPP generic driver version 2.4.2
NET: Registered protocol family 24
tun: Universal TUN/TAP device driver, 1.6
tun: (C) 1999-2004 Max Krasnyansky <[email protected]>
deice id : c2 20 15 c2 20 (2015c220)
mx25l3205d(c2 20160000) (4096 Kbytes)
mtd .name = raspi, .size = 0x00400000 (4M) .erasesize = 0x00010000 (64K) .numeraseregions = 0
ramips_mtd: kernel size is 613787
padded kernel is 00096000
Creating 6 MTD partitions on "raspi":
0x00000000-0x00010000 : "uboot"
0x00010000-0x00020000 : "boardconfig"
0x00020000-0x00200000 : "image"
0x00020000-0x000b6000 : "linux"
mtd: partition "linux" doesn't end on an erase block -- force read-only
0x000b6000-0x001f0000 : "rootfs"
mtd: partition "rootfs" doesn't start on an erase block boundary -- force read-only
mtd: partition "rootfs" set to be root filesystem
0x001f0000-0x00200000 : "uci_overlay"
Registered led device: power
Registered led device: wps
Registered led device: wlan
nf_conntrack version 0.5.0 (256 buckets, 2048 max)
IPv4 over IPv4 tunneling driver
ip_tables: (C) 2000-2006 Netfilter Core Team, Type=Linux
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
802.1Q VLAN Support v1.8 Ben Greear <[email protected]>
All bugs added by David S. Miller <[email protected]>
ramips: ethernet loaded
ramips_eth: loaded
VFS: Mounted root (squashfs filesystem) readonly.
Freeing unused kernel memory: 100k freed
Warning: unable to open an initial console.
Preinit complete, spawning microd
found uci_overlay -> /dev/mtd5
i found OPENWRT_UCI_OVERLAY inside /dev/mtd5
loading file zepttho 275
loading file wireless 696
loading file user 70
loading file system 72
loading file reg 16
loading file network 473
loading file led 342
loading file lang 33
loading file form 4768
loading file fonsmcd 290
loading file fon 4Algorithmics/MIPS FPU Emulator v1.5
07
loading file firewall 907
loading file passwd 149
loading file chilli.conf 566
loading fon config
Spawning syslogd
registering led wps -> /sys/class/leds/wps/
registering led wlan -> /sys/class/leds/wlan/
registering led power -> /sys/class/leds/power/
loading base firewall ...iptables: Chain already exists
done
adding zone wannet
adding zone lan
adding zone wan
adding zone hotspotwifi
adding zone hotspot
adding forwarding lan->wan
adding forwarding hotspot->wan
interface loopback
proto = static
ipaddr = 127.0.0.1
netmask = 255.0.0.0
ifname = lo
interface lan
proto = static
ipaddr = 192.168.10.1
netmask = 255.255.255.0
ifname = eth0.1
type = bridge
interface wan
proto = dhcp
ifname = eth0.2
interface hotspot
ifname = tun0
interface hotspotwifi
proto = none
ifname = ra1
net event up loopback ...bringing up lo
done
net event up lan ...bringing ueth0.1: dev_set_promiscuity(master, 1)
p eth0.1
device eth0 entered promiscuous mode
device eth0.1 entered promiscuous mode
br-lan: port 1(eth0.1) entering learning state
adding br-lan to zone lan
done
net event up wan ...bringing up eth0.2
Spawning udhcpc for eth0.2
udhcpc (v0.9.9-pre) started
Trying to connect...
sending -> "udhcpc|deconfig|eth0.2|"
adding eth0.2 to zone wan
Sending discover...
done
wifi device rt305x
type = rt305x
channel = 11
mode = 9
wifi interface public
ifname = ra1
ssid = FON_FREE_INTERNET
encryption = none
network = hotspotwifi
device = rt305x
isolate = 1
auto = 1
wifi interface private
ifname = ra0
ssid = MyPlace
encryption = wpa-wpa2
key = 4141414141
password = ueriehaeph
wpa_crypto = mixed
network = lan
device = rt305x
channel = 0
mode = bgn
txpower = 100
br-lan: topology change detected, propagating
br-lan: port 1(eth0.1) entering forwarding state
rt2860v2_ap: module license 'unspecified' taints kernel.
Sending discover...
WSending discover...
0x1300 = 00064380
bringing up rt30device ra0 entered promiscuous mode
5x ...done
br-lan: port 2(ra0) entering learning state
Terminate the task(RtmpCmdQTask) with pid(202)!
Terminate the task(RtmpWscTask) with pid(203)!
br-lan: port 2(ra0) entering disabled state

しかし、入力を一切受け付けてくれません。どうやら制限が入っているようで、こちらの操作を受け付けないようになっているようです。
これではファームウェアの更新はできません…。色々試してみたものの、結局解決には至りませんでした。残念。

f:id:happytar0:20100719003100j:image

配線を4本ハンダ付けしてしまったり、他の線と干渉?しちゃったりで、電子工作はやっぱりたいへんだなという感じでしたが、面白かったのでこれからもいじっていきたいです。

mixiアプリでRESTful APIを使う

今さらながらmixiアプリでRESTful APIが使えることに気づいたわけで、早速試してみました。

mixiデベロッパー向けサイトに、サンプルコードも付いて詳しく説明されているので、これを参考にして書いていけば問題なさそうです。

実際のリクエストには、「Consumer Key」と「Consumer Secret」を使い、2-legged OAuthによって適切に署名をする必要があります。
「Consumer Key」と「Consumer Secret」は、アプリごとに割り当てられており、mixiアプリ設定画面より、確認することができます。

注意する点は「xoauth_requestor_id」をリクエストに付加する必要があるということです。公式サイトから引用です。

RESTful APIにアクセスする際に、xoauth_requestor_idパラメータによって、誰の権限でアクセスを行うかを指定することが必要になります。パラメータ値は、対象ユーザのIDとなります。このユーザIDについて、「一定時間内にWebブラウザで対象のmixiアプリを起動したユーザ」のIDのみ指定することが可能です。

対象ユーザが対象のmixiアプリを起動していない、もしくは起動から一定時間が経過した後にRESTful APIにアクセスを行った際には、HTTPレスポンスコードとして「401 Unauthorized」が返却されます。

対象ユーザのID、すなわちコンテナから送られてくる「opensocial_viewer_id」を指定することになります。

下記のようなコードで動かすことが出来ました。署名にはoauthライブラリを使います。

  require 'oauth'
consumer = OAuth::Consumer.new(「アプリのConsumer Key」,
「アプリのConsumer Secret」,
{:site => 'http://api.mixi-platform.com'})
end_point = 'http://api.mixi-platform.com/os/0.8'
req = consumer.request(:get, end_point + '/people/@me/@self' + '?xoauth_requestor_id=' + opensocial_viewer_id)
JSON.parse(req.body) # JSONデータをオブジェクト化

公式にはRubyのコードがなかったようなので載せておきます。