July 08(Wed), 2009
ブログを移転しました。
新しいアドレスはこちらです。
http://d.hatena.ne.jp/Naruhodius/
はてなIDを変更しましたので、今後こちらのブログは更新されません。
フィードを購読しているかたは変更をお願いします。
June 15(Mon), 2009
Mac OS X Leopardをクリーンインストールして環境構築して使えるようになるまで(2009年6月版)
MacBook ProにLeopardをクリーンインストールして環境構築をした。この手の記事はよく見かけるし自分も以前に書いたのだが、もうだいぶ古くなってきた上に情報も散在しているので、あらためてまとめた。
システムのインストール
Mac OS X LeopardをDVDからインストールする。このとき、オプションで各言語環境とプリンタドライバは外してしまうのが良い。ほとんどの場合必要とならないし、どうしても必要になった場合は後から追加インストールできる。言語とプリンタドライバをすべて外すことで、OS自体のサイズを大幅に削減し、後述するTimeMachineでのバックアップ量も減らすことができる。
セキュリティ
とりあえず最低限のセキュリティ対策をしないと話にならない。
FileVault
暗号ファイルシステム。ファイルが増えてからだと暗号化に時間がかかるため、必ず最初にオンにしておく。
ファイアウォール
必須サービスのみ許可する。Apacheを使うならWeb共有、SSHを使うならリモートログインなどを有効にする。
ソフトウェアアップデート
必ず設定する。なお、実際にアップデートをおこなう際は、事前に必ずTimeMachineでバックアップする。
パスワード
管理者アカウントにパスワードを付与し、スリープやスクリーンセーバを解除するときにパスワードを要求する設定にする。
Open Firmware Password
LeopardのインストールDVDの /Applications/Utilities に入っているので、ターミナル等でデスクトップにコピーしてインストールをおこなう。Open Firmware PasswordによってEFIにパスワードを付与し、外部ディスクでのブートを回避できる。
rootパスワード
ターミナルからrootにパスワードを設定する。
sudo passwd root
管理者アカウント
別に管理者アカウントを作成して、ふだん利用するアカウントを一般ユーザーに降格させる。
SSHのセキュリティ設定
/etc/sshd_config を編集しパスワードログインを不可にする。これを設定しないと外に持ち出したときに総当たり攻撃を食らってしまう。なお、外部からSSHログインしたい場合はそのマシンの ~/.ssh/id_rsa.pub を ~/.ssh/authorized_keys に登録してやれば良い。この作業は面倒なのでシェルスクリプトなどで一元的におこなうのがおすすめ。
PermitRootLogin no PasswordAuthentication no
アプリケーションのインストール
インストールするアプリケーションは厳選して必要最低限のものにする。
- XCode (LeopardのインストールDVDから追加インストールする)
- Quick Silver http://www.blacktree.com/
- The Unarchiver http://wakaba.c3.cx/s/apps/unarchiver.html
- KeyRemap4MacBook http://www.pqrs.org/tekezo/macosx/keyremap4macbook/index.html.ja
- Firefox http://mozilla.jp/firefox/
- Thunderbird http://mozilla.jp/thunderbird/
- Skype http://www.skype.com/intl/ja/download/skype/macosx/beta/
- Adium http://adium.im/
- LimeChat http://limechat.net/mac/index_ja.html
- iTerm http://iterm.sourceforge.net/
- Carbon Emacs http://homepage.mac.com/zenitani/emacs-j.html
- TrueCrypt (暗号ファイルシステム) http://www.truecrypt.org/
- Safari 4 http://www.apple.com/jp/safari/
- SIMBL http://www.culater.net/software/SIMBL/SIMBL.php
- GreaseKit http://8-p.info/greasekit/
- Glims for Safari (Safari拡張) http://www.machangout.com/
- MacPorts http://www.macports.org/
- macfuse/sshfs http://code.google.com/p/macfuse/
- Growl http://growl.info/
- Picasa http://picasa.google.com/mac/
- Seashore http://seashore.sourceforge.net/
- SWF & FLV Player http://www.swf-mac.com/swfplayer.html
- VLC media player http://www.videolan.org/vlc/
- NeoOffice http://www.neooffice.org/neojava/ja/index.php
- ClamAV (アンチウイルス) http://www.clamxav.com/
- OnyX (システムメンテナンス) http://www.titanium.free.fr/pgs2/english/onyx_leopard.html
- iStats (システム状態監視) http://islayer.com/apps/
- Brightness Control (輝度調整) http://www.splasm.com/
- LockTight (スクリーンロック) http://www.gkoya.com/2006/11/23/locktight-for-mac-os-x-intel/
- StartupSound (起動音調整) http://www5e.biglobe.ne.jp/~arcana/StartupSound/BETA/
- Remote Desktop Connection Client for Mac http://www.microsoft.com/japan/mac/collaboration/rdc/default.mspx
- Dropbox http://www.getdropbox.com/
- VMware Fusion
- イー・モバイル関係
- 地デジ関係
スクリーンのロック
上記のLockTightをインストールすることでショートカット一発でロックできる。外出時などは重宝する。
nmblookupを使えなくする
Macはネットワークのタイムアウトが発生するとシステム全体のレスポンス低下を招くことが多いようだ。そこで、Sambaサーバーを利用しないのであれば、nmblookupを使えなくしておくとプチフリーズの頻度を低下させることができる。
sudo chmod -x /usr/bin/nmblookup
本当はもっと良い方法があるのかもしれないが、ひとまずこれで問題なくMacを利用することができている。
他のMacからのデータ移行
Firefox、Thunderbird、Adium、GreaseKit等は ~/Library/Application Support の下をコピーすれば他のMacからそのまま環境を持ってくることができる。
LimeChatの透過設定
以前はソースコードを変更する必要があったが、現在のバージョンのLimeChatではメニューから普通に設定することができるので不要。
イー・モバイルの設定
ユーティリティ無しでイー・モバイルに接続する設定が役に立つ。
フォルダ名を英語化する
「ダウンロード」「ライブラリ」を「Downloads」「Library」にする。それぞれのディレクトリの下にある.localizedファイルを削除する。
rm ~/Downloads/.localized rm ~/Library/.localized
ネットワーク接続時に .DS_Store ファイルの作成を抑制する
ターミナルから以下のコマンドを投入して再起動すれば反映される。
defaults write com.apple.desktopservices DSDontWriteNetworkStores true
開発環境を構築する
MacPortsでほとんどの環境がそろう。シェルスクリプトを用意してまとめてインストールするのが良い。
sudo port -d selfupdate sudo port -d install libiconv +enable_cp932fix sudo port -d install coreutils sudo port -d install findutils sudo port -d install wget sudo port -d install curl sudo port -d install nkf sudo port -d install screen sudo port -d install ruby sudo port -d install zlib sudo port -d install openssl sudo port -d install rb-rubygems sudo port -d install subversion sudo port -d install git-core sudo port -d install -f svk sudo port -d install lv sudo port -d install chasen sudo port -d install sqlite3 sudo port -d install libxml sudo port -d install libxml2 sudo port -d install expat sudo port -d install p7zip sudo port -d install bzip2 sudo port -d install ctags sudo port -d install ncurses sudo port -d install vim sudo port -d install smartmontools # Python sudo port -d install python25 sudo ln -s /opt/local/bin/python2.5 /usr/local/bin/python sudo port -d install py25-hashlib sudo port -d install py25-zlib sudo port -d install py25-readline sudo port -d install py25-mysql sudo port -d install py25-twisted sudo port -d install py25-pgsql sudo port -d install py25-mechanize sudo port -d install py25-openssl sudo port -d install py25-paste sudo port -d install py25-pastedeploy sudo port -d install py25-simplejson sudo port -d install py25-nose sudo port -d install py25-sqlalchemy sudo port -d install py25-sqlalchemy-migrate sudo port -d install py25-turbogears sudo port -d install py25-memcached sudo port -d install py25-yaml TARGET_PATH=`python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` wget http://peak.telecommunity.com/dist/ez_setup.py sudo python ez_setup.py -U setuptools sudo cp ez_setup.py $TARGET_PATH/ez_setup.py rm ez_setup.py sudo ln -s /opt/local/bin/easy_install-2.5 /usr/local/bin/easy_install sudo easy_install ipython sudo ln -s /opt/local/bin/ipython2.5 /usr/local/bin/ipython svn co http://code.djangoproject.com/svn/django/trunk/ cd trunk sudo python setup.py install cd .. rm -rf trunk/ # Ruby export RUBYOPT=rubygems sudo gem update --system sudo gem update sudo gem install mongrel sudo gem install mongrel_cluster sudo gem install mechanize sudo gem install Selenium sudo gem install vim-ruby sudo gem install postgres-pr sudo gem install BlueCloth sudo gem install RedCloth sudo gem install net-ssh sudo gem install net-sftp sudo gem install coverage sudo gem install zentest sudo gem install capistrano sudo gem install magic_multi_connections sudo gem install redgreen sudo gem install rspec sudo gem install rspec-rails sudo gem install cucumber sudo gem install rails sudo gem cleanup
TimeMachineで環境をバックアップする
ここまで完了したら、TimeMachineを利用して初期環境構築直後の状態をバックアップする。TimeMachineはゲームをセーブするようなもので、今後なにか問題が発生しても現在の状態までシステムを戻すことができるので非常に便利なバックアップツールである。なお、パーティションを別にしたりデータフォルダを対象外にするなどして、システムの中核だけをバックアップすると容量も20〜40GB程度で済むのでおすすめである。TimeMachineはシステムの状態保存に利用して、データはファイルサーバーやNASに置いて別途バックアップするのが良いだろう。現在ではHDDも非常に安価だし、必要ならネットワークを経由してGNU/Linux環境にバックアップを取得することもできる。
ソフトウェアアップデートや大掛かりなシステム変更の前に必ずTimeMachineバックアップをおこなうのはもちろんのこと、他にもさまざまな活用方法が考えられる。たとえば同機種であれば別のマシンにも復元できるので、初期不良や故障等でやむを得ず別のマシンへ交換した場合でもすぐに環境を取り戻せる。また内蔵HDDの換装時にもTimeMachineで環境をそのまま移すことができる。自宅と仕事場で同じ機種を利用するなら片方で環境構築すればもう片方はTimeMachineから復元するだけで済む。まだTimeMachineを利用していないのであれば、今すぐ現在の環境をバックアップするのが良いだろう。
June 10(Wed), 2009
新しいMacBook Proを買った。
銀座アップルストアに立ち寄って、そのまま購入した。
13inch 1280×800 2.53GHz Intel Core 2 Duo 250GB 5400rpm SATA HDD 4GB 1066MHz DDR3 SDRAM (MAX 8GB) NVIDIA GeForce 9400M 内蔵リチウムポリマーバッテリー(58Wh) 最大7時間 重量 2.04kg ¥168,800
さっそく開封。
液晶の品質がMacBook Proシリーズのグレードになっている。
つい先日iMacを買ったばかりだが、同世代のMacBook Proも購入。これでマシン台数が19台になった。
June 08(Mon), 2009
Xfce4のインターフェイスのテーマをカスタマイズする。
GNOMEやKDEと並んで人気の軽量デスクトップ環境であるXfceでは、豊富にインターフェイスのテーマが用意されている。このテーマは /usr/share/themes/テーマ名/gtk-2.0/gtkrc を編集することで、細部をカスタマイズすることができる。
ふだんは Xfce4-dusk テーマを利用しているのだが、インターフェイスの細かい部分に不満を感じていた。たとえばテキストの基本色に #fcfcfc という中途半端な白色が指定されているので、背景に白系統の色が指定されたウェブサイトなどで極端に文字の視認性が低下したり、背景色黒と文字色緑という統一性を欠いたりするためだ。
そこで /usr/share/themes/Xfce-dusk/gtk-2.0/gtkrc で以下のように編集してみた。
style "default" { GtkEntry::cursor_color = "#00ff00" GtkEntry::secondary_cursor_color = "#00ff00" GtkTextView::cursor_color = "#00ff00" GtkTextView::secondary_cursor_color = "#00ff00" fg[NORMAL] = "#00ff00" fg[PRELIGHT] = "#00ff00" fg[SELECTED] = "#00ff00" text[ACTIVE] = "#00ff00" text[INSENSITIVE] = "#00ff00" text[NORMAL] = "#00ff00" text[PRELIGHT] = "#00ff00" text[SELECTED] = "#00ff00" }
結果として、このように表示されるすべての文字色を統一できた。
文字色が常に緑なので、背景が黒でも白でも読み取ることができる。
インターフェイスももちろん全部緑。
UIも黒背景に緑文字。
これで、Emacsやターミナルのカラーと足並みを揃えることができた。
気軽に細部を編集できるXfceは、生産性とリッチさを兼ね備えた、すばらしいデスクトップ環境だ。
Ubuntu 8.04 LTS および Debian GNU/Linux 5.0 lenny の Xfce 4.4.2 で動作を確認した。
http://packages.ubuntu.com/hardy/xfce4
http://packages.debian.org/lenny/xfce4
参考
Xfceを使う。
May 29(Fri), 2009
UbuntuでモバイルPCの起動速度が遅い問題を対処する。
ネットブックに、Ubuntuなどに代表されるDebian系ディストリビューションを入れて使用するという例が増えてきつつある。モバイルでUbuntuなどを利用していると、起動がやたら遅くなるケースがまれにある。このようなトラブルに備え、設定しておいたほうが良い箇所がいくつかある。
スプラッシュスクリーンを除去して起動時のメッセージを確認する。
Ubuntuでは起動時に派手なスプラッシュスクリーンが表示され、起動時のメッセージが隠蔽されている。これはこれで確かに見栄えは良いのだが、起動時のネットワークやディスクまわりのエラーメッセージを検知しにくいという欠点がある。特にモバイルで利用することがある場合では外しておいた方が良いだろう。
/boot/grub/menu.lst を編集する。以下は Ubuntu 8.04 LTS での例。
title Ubuntu 8.04.2, kernel 2.6.24-24-generic root (hd0,4) kernel /vmlinuz-2.6.24-24-generic root=UUID=b088f146-118b-4f91-bd16-d83c096f67a5 ro locale=ja_JP # 上記の文字列から、末尾の quiet splash を除去する initrd /initrd.img-2.6.24-24-generic
さらに、同ファイルのコメント内にある defoptions の文字列を変更しておけば、カーネルが新しく更新された場合も初期値として反映される。そこで defoptions からもquiet splashを除去する。
# defoptions=locale=ja_JP
イー・モバイル端末利用時は不要なネットワーク接続を起動しない。
LAN接続時にIPアドレスをDHCPから取得するようにしていると、LANに接続しない状態でOSを起動したときに、DHCPクライアントが起動してIPアドレスを取得しようとして長い時間がかかっていることに気づく。モバイルで起動がやたら遅いことがあれば、たいてい原因はこのDHCPによるIPアドレス取得であることが多い。そこで、イー・モバイル端末を接続した状態でOSを起動したときは、不要なネットワーク接続を起動しないようにしておく。
/etc/init.d/networking を編集する。
case "$1" in start) test -c /dev/ttyUSB0 && exit 0 # イー・モバイル端末が接続されていたらそのまま終了 log_action_begin_msg "Configuring network interfaces" ...
あらかじめイー・モバイル端末のデバイスファイル名を調べておく。たいていは /dev/ttyUSB0 になるケースが多いようだ。OSが起動するときに /etc/init.d/networking start コマンドが発行されているので、このとき /dev/ttyUSB0 が存在していればそのまま戻り値0で終了するようにする。
ログイン時に自動的にイー・モバイル端末でネットワーク接続する。
OS起動時にイー・モバイル端末が接続されていたら pon コマンドを発行してネットワークへ接続する。これは /etc/rc.local で設定する。
test -c /dev/ttyUSB0 && pon em
May 19(Tue), 2009
EmacsのキーバインドをVimライクにし、さらにLispをバイトコンパイルして高速化する。
Emacsは強力な編集機能と拡張性を持つが、ファイルの編集に関してはVimのように閲覧と編集のモードを分けてメリハリのある操作ができたほうが良い。そこでEmacs Lispをあれこれ書いた。なお、動作確認は GNU/Linux の GNU Emacs 23.0.60.1 及び Mac OS X の Carbon Emacs でおこなっている。
;; .emacsは2行だけ (byte-recompile-directory "~/.emacs.d/elisp") (load "~/.emacs.d/elisp/startup")
;; startup.elでロードパスなどの設定をしてautoload.elを呼ぶ (load "autoloads")
rubikitchさんのエントリで紹介されていた key-chord.el を利用。これは主に2つのキー同時押しでEmacs Lispの関数を呼び出す目的に利用するもので、これを導入するとEmacsの使用感は革命的に変化すると言っても良い。なお同時押しキーと対応する機能の定義は key-chord-define-global 関数でおこなう。
;; autoloads.elでは様々なファイルをロードするがここで一緒にrequireする (require 'key-chord) (setq key-chord-two-keys-delay 0.04) (key-chord-mode 1)
;; autoloads.elの最後でconfigs.elを呼び環境設定する ;; キーバインド設定 (load "global-set-key") ;; view-modeキーバインド設定 (load "view-mode-key") ;; key-chord.el専用キーバインド設定 (load "key-chord-define-global")
キーバインドは、全体的なキーバインド設定(global-set-key.el)と、Viewモードで閲覧するためのキーバインド設定(view-mode-key)、key-chord.elによる同時押し専用のキーバインド設定に分割しておく。分割することで、どの設定がどのファイルに依存するのかわかりやすくする狙いがある。
Viewモード専用のキーバインド設定を抜粋。以下の記事を参考にした。
http://d.hatena.ne.jp/rubikitch/20081104/1225745862
http://d.hatena.ne.jp/yaotti/20081104/1225809687
(setq view-read-only t) (defvar pager-keybind `( ;; vi-like ("h" . backward-word) ("l" . forward-word) ("j" . next-line) ("k" . previous-line) ("J" . next-window-line) ("K" . previous-window-line) ("b" . scroll-down) ("f" . scroll-up) (" " . scroll-up) ("w" . forward-word) ("e" . backward-word) ("n" . ,(lambda () (interactive) (scroll-up 1))) ("p" . ,(lambda () (interactive) (scroll-down 1))) ("[" . forward-sexp) ("]" . backward-sexp) ("." anything-c-moccur-occur-by-moccur) ("c" . scroll-other-window-down) ("v" . scroll-other-window) )) (defun define-many-keys (keymap key-table &optional includes) (let (key cmd) (dolist (key-cmd key-table) (setq key (car key-cmd) cmd (cdr key-cmd)) (if (or (not includes) (member key includes)) (define-key keymap key cmd)))) keymap) (defun view-mode-hook0 () (define-many-keys view-mode-map pager-keybind) (hl-line-mode 1) (define-key view-mode-map " " 'scroll-up)) (add-hook 'view-mode-hook 'view-mode-hook0) (do-not-exit-view-mode-unless-writable-advice view-mode-exit) (do-not-exit-view-mode-unless-writable-advice view-mode-disable) (provide 'view-support)
Viewモードではファイルにテキストを入力しないはずなので、このようにhjklなどVimライクなカーソル移動にキーバインドを割り振っている。Vimではファイルを開くとき、最初はコマンドモードとなり、実際にテキストに変更を加えるときにインサートモードに推移して編集をおこなう。それと同じ操作感をEmacsでも実現するために、EmacsでもViewモードと通常モードを切り替えて編集作業をおこなうようにする。まずは configs.el で find-file-hooks をフックして、Emacsでファイルを開くときは必ず読み取り専用でオープンするようにしておく。
;; ファイルオープン直後は読み取り専用 (add-hook 'find-file-hooks (lambda () (cond (view-mode) (t (view-mode)))))
これで find-file や引数渡しでファイルを開いても find-file-read-only で開くのと変わらなくなる。次に、Viewモードと通常モードのトグル切り替えのための操作が必要なので global-set-key.el で定義する。
;; C-x C-j または C-x j で view-mode を切り替える (defun toggle-view-mode () (interactive) (cond (view-mode (view-mode nil) (setq hl-line-mode nil)) (t (view-mode)))) (define-key global-map "\C-x\C-j" 'toggle-view-mode) (define-key global-map "\C-x\ j" 'toggle-view-mode) (define-key global-map [C-backspace] 'toggle-view-mode)
これでC-x jで閲覧と編集の切り替えが可能、GUIではC-backspaceも有効。ここまでは以前も書いたが、さらにkey-chord.el専用キーバインドでも同時押しによる切り替えを定義しておく。
;; jk で view-mode を切り替える (key-chord-define-global "jk" 'toggle-view-mode)
せっかくなので、key-chord.el専用のキーバインドを紹介。よく使用する機能を同時押しで実現できるようにしておくと大変べんりである。バッファリストやファイルオープン、画面移動などは隣り合う2つのキーを同時押しでできるように設定しておく。
;; yu で auto-complete-modeの有効/無効を切り替える (key-chord-define-global "yu" 'auto-complete-mode) ;; 分割したウィンドウを移動(上下左右) (key-chord-define-global "io" 'windmove-up) (key-chord-define-global ",." 'windmove-down) (key-chord-define-global "hj" 'windmove-left) (key-chord-define-global "l;" 'windmove-right) ;; fg で keyboard-escape-quit する (key-chord-define-global "fg" 'keyboard-escape-quit) ;; jk で view-mode を切り替える (key-chord-define-global "jk" 'toggle-view-mode) ;; バッファ切り替え (key-chord-define-global "m," 'previous-buffer) (key-chord-define-global "ui" 'backward-buffer) ;; バッファリスト (key-chord-define-global "kl" 'electric-buffer-list) ;; バッファ先頭/末尾へのカーソル移動 (key-chord-define-global "rt" 'beginning-of-buffer) (key-chord-define-global "vb" 'end-of-buffer) ;; アンドゥ/リドゥ (key-chord-define-global "as" 'undo) (key-chord-define-global "sd" 'redo) ;; ファイルを開く (key-chord-define-global "df" 'find-file) ;; スクロール (key-chord-define-global "er" 'scroll-down) (key-chord-define-global "cv" 'scroll-up)
さて、Emacs Lispが複雑、巨大化してくるとLispインタプリタの遅さが気になってくる。そこで事前にバイトコンパイルすることにより高速化を図る。Emacs Lispをインストールするためのシェルスクリプトを用意し、その中でバイトコンパイルするようにしておく。
#!/bin/sh setup_dotemacs() { test -d ~/.emacs.d && rm -rf ~/.emacs.d/ test -f ~/.emacs && rm -f ~/.emacs cp $OPTIONS $SCRIPTS/dot_files/dot_emacs $HOME/.emacs test -d $TARGET || mkdir -p $TARGET cp $OPTIONS $SCRIPTS/dot_files/dot_emacs.d/* $TARGET/ } batch_byte_compile() { cd ~/.emacs.d/elisp/3rd-party emacs --batch --eval '(byte-compile-file "js2.el")' emacs --batch --eval '(byte-compile-file "redo.el")' emacs --batch --eval '(byte-compile-file "ruby-block.el")' emacs --batch --eval '(byte-compile-file "auto-complete.el")' emacs --batch --eval '(byte-compile-file "key-chord.el")' emacs --batch --eval '(byte-compile-file "twitter1-mode.el")' emacs --batch --eval '(byte-compile-file "twitter2-mode.el")' emacs --batch --eval '(byte-compile-file "twitter3-mode.el")' emacs --batch --eval '(byte-compile-file "twitter4-mode.el")' cd ~/.emacs.d/elisp emacs --batch --eval '(byte-compile-file "delete-empty-file.el")' emacs --batch --eval '(byte-compile-file "emacs-w3m.el")' emacs --batch --eval '(byte-compile-file "global-set-key.el")' emacs --batch --eval '(byte-compile-file "key-chord-define-global.el")' emacs --batch --eval '(byte-compile-file "kill-all-buffers.el")' emacs --batch --eval '(byte-compile-file "new-file-p.el")' emacs --batch --eval '(byte-compile-file "persistent-scratch.el")' emacs --batch --eval '(byte-compile-file "physical-line.el")' emacs --batch --eval '(byte-compile-file "proxy.el")' emacs --batch --eval '(byte-compile-file "startup.el")' emacs --batch --eval '(byte-compile-file "tab4.el")' emacs --batch --eval '(byte-compile-file "twitter-key.el")' emacs --batch --eval '(byte-compile-file "unix-defaults.el")' emacs --batch --eval '(byte-compile-file "utils.el")' emacs --batch --eval '(byte-compile-file "view-mode-key.el")' } test -d $SCRIPTS/dot_files/dot_emacs.d || exit 1 TARGET=$HOME/.emacs.d case $OSTYPE in *darwin*) OPTIONS=-Rv ;; *) OPTIONS=-Rvd ;; esac setup_dotemacs batch_byte_compile
autoloads.el や configs.el のように他のファイルをロードするものはコンパイルの対象外とするが、単体で機能できるものについてはすべて事前にバイトコンパイルしておく。同じ要領で、rubyに付属のEmacs Lispもバイトコンパイルしておく。まず、以下のシェルスクリプトでrubyのソースコードをリポジトリからチェックアウトしてビルド。ソースコードのmiscディレクトリにruby用のEmacs Lispが付属している。
install_branch() { test -d /usr/local/src/ruby/branches || sudo mkdir -p /usr/local/src/ruby/branches cd /usr/local/src/ruby/branches sudo svn co http://svn.ruby-lang.org/repos/ruby/branches/$1/ $1 cd $1 sudo autoconf sudo ./configure sudo make sudo make install test -x $SCRIPTS/installer/install_emacs_ruby.sh && $SCRIPTS/installer/install_emacs_ruby.sh /usr/local/src/ruby/branches/$1/misc } install_branch ruby_1_8_7
これをEmacsのロードパスである /usr/local/share/emacs/site-lisp にシンボリックリンクして、バイトコンパイルする。
install_emacs_ruby() { test -L $1/ruby-mode.el && sudo rm $1/ruby-mode.el sudo ln -s $2/ruby-mode.el $1/ruby-mode.el test -L $1/ruby-style.el && sudo rm $1/ruby-style.el sudo ln -s $2/ruby-style.el $1/ruby-style.el test -L $1/ruby-electric.el && sudo rm $1/ruby-electric.el sudo ln -s $2/ruby-electric.el $1/ruby-electric.el test -L $1/inf-ruby.el && sudo rm $1/inf-ruby.el sudo ln -s $2/inf-ruby.el $1/inf-ruby.el test -L $1/rubydb2x.el && sudo rm $1/rubydb2x.el sudo ln -s $2/rubydb2x.el $1/rubydb2x.el test -L $1/rubydb3x.el && sudo rm $1/rubydb3x.el sudo ln -s $2/rubydb3x.el $1/rubydb3x.el cd $1 test -f ruby-mode.elc && sudo rm ruby-mode.elc sudo emacs --batch --eval '(byte-compile-file "ruby-mode.el")' test -f ruby-style.elc && sudo rm ruby-style.elc sudo emacs --batch --eval '(byte-compile-file "ruby-style.el")' test -f ruby-electric.elc && sudo rm ruby-electric.elc sudo emacs --batch --eval '(byte-compile-file "ruby-electric.el")' test -f inf-ruby.elc && sudo rm inf-ruby.elc sudo emacs --batch --eval '(byte-compile-file "inf-ruby.el")' test -f rubydb2x.elc && sudo rm rubydb2x.elc sudo emacs --batch --eval '(byte-compile-file "rubydb2x.el")' test -f rubydb3x.elc && sudo rm rubydb3x.elc sudo emacs --batch --eval '(byte-compile-file "rubydb3x.el")' } install_emacs_ruby /usr/local/share/emacs/site-lisp $1
Lispはインタプリタで動作するが、事前にバイトコンパイルしておくと特にEmacsの起動時間が高速化する。JavaScriptの編集に活躍するjs2-mode.elのようにバイトコンパイルを必須とするものもあるので、Emacs Lispはできるだけ事前にバイトコンパイルすると良いだろう。
May 01(Fri), 2009
Railsアプリ開発のために書いたEmacs Lispあれこれ。
Ruby on RailsによるアプリをEmacsで編集しながら、同時にいろいろEmacs Lispを書くなどしたのでまとめ。
バッファ破棄/再読み込み
Railsアプリのソースコードを一度に開くと大量のバッファが作成されるので、一度に破棄したり再読み込みしたりする機能が欲しくなってくる。そこでいくつかの関数を定義。
;; 開いているすべてのバッファをkillする (defun kill-all-buffers () (interactive) (dolist (buf (buffer-list)) (kill-buffer buf))) ;; バッファ再読み込み (defun revert-current-buffer () (interactive) (revert-buffer t t)) (defun revert-all-buffers () (interactive) (let ((cbuf (current-buffer))) (dolist (buf (buffer-list)) (if (not (buffer-file-name buf)) nil (switch-to-buffer buf) (revert-buffer t t))) (switch-to-buffer cbuf) )) (define-key global-map "\C-c\C-c\C-p" 'revert-current-buffer) (define-key global-map "\C-c\C-c\ p" 'revert-all-buffers) (define-key global-map "\C-c\C-c\ 0" 'kill-all-buffers)
参考
http://q.hatena.ne.jp/1134532052
ちなみにrevert-bufferだとundoできない。Meadow/Emacsメモによるとelispで独自に実装する手もあるようだ。
http://www.bookshelf.jp/soft/meadow_24.html#SEC254
ただこの方法だとバッファ再読み込み後に編集せず閉じたときの挙動が気に入らなかったので、結局revert-bufferを素直に使うことにした。
空ファイル削除
編集して0バイトになったファイルをファイルシステム上から除去できるようにする。選択肢で残すことも可能にする。
(if (not (memq 'delete-file-if-no-contents after-save-hook)) (setq after-save-hook (cons 'delete-file-if-no-contents after-save-hook))) (defun delete-file-if-no-contents () (when (and (buffer-file-name (current-buffer)) (= (point-min) (point-max))) (when (y-or-n-p "Delete file and kill buffer?") (delete-file (buffer-file-name (current-buffer))) (kill-buffer (current-buffer)))))
参考
http://www.bookshelf.jp/soft/meadow_24.html#SEC264
行末スペース除去
行末にスペースが付いていたりすると気になる性格なのでこれも関数を定義して対処する。
(defun trim-buffer () "Delete excess white space." (interactive) (save-excursion (goto-char (point-min)) (while (re-search-forward "[ \t]+$" nil t) (replace-match "" nil nil)) (goto-char (point-max)) (delete-blank-lines) (mark-whole-buffer) (tabify (region-beginning) (region-end))))
Rinari
従来はemacs-railsが使われたが、現在ではRinariが熱いらしい。標準だとrhtml(erb)のシンタックスハイライトが無かったりするのでこのあたりも必須。そこでまとめて追加する。
まずはRinariとrhtml-modeを一次配布元のgithubからチェックアウトして、Emacsのロードパスにシンボリックリンクする。ruby-mode.elはRubyのソースコードのmiscディレクトリに付属しているので、これも同じくシンボリックリンクする。
#!/bin/sh setup_rhtml() { if [ -d ~/local/github/rhtml ]; then cd ~/local/github/rhtml git pull else cd ~/local/github git clone git://github.com/eschulte/rhtml.git cd ~/local/github/rhtml fi # rhtml-modeへのリンクを作成 ln -s ~/local/github/rhtml ~/.emacs.d/elisp/3rd-party } setup_rinari() { if [ -d ~/local/github/rinari ]; then cd ~/local/github/rinari git pull else cd ~/local/github git clone git://github.com/eschulte/rinari.git cd ~/local/github/rinari fi # チェックアウト後に必要 git submodule init git submodule update # Rinariへのリンクを作成 ln -s ~/local/github/rinari ~/.emacs.d/elisp/3rd-party } setup_rhtml setup_rinari install_emacs_ruby() { test -L $1/ruby-mode.el && sudo rm $1/ruby-mode.el sudo ln -s $2/ruby-mode.el $1/ruby-mode.el test -L $1/ruby-style.el && sudo rm $1/ruby-style.el sudo ln -s $2/ruby-style.el $1/ruby-style.el test -L $1/ruby-electric.el && sudo rm $1/ruby-electric.el sudo ln -s $2/ruby-electric.el $1/ruby-electric.el test -L $1/inf-ruby.el && sudo rm $1/inf-ruby.el sudo ln -s $2/inf-ruby.el $1/inf-ruby.el test -L $1/rubydb2x.el && sudo rm $1/rubydb2x.el sudo ln -s $2/rubydb2x.el $1/rubydb2x.el test -L $1/rubydb3x.el && sudo rm $1/rubydb3x.el sudo ln -s $2/rubydb3x.el $1/rubydb3x.el } # Rubyのソースコード(svnからチェックアウト)に付属のEmacs LispへのシンボリックリンクをEmacsロードパスに作成する install_emacs_ruby /usr/local/share/emacs/site-lisp /usr/local/src/ruby/branches/ruby_1_8_7/misc
次にEmacsのロードパスを正しく設定しておく。
(defvar default-load-path load-path "*Base of `load-path'. It is used as a default value of target path to search file or subdirectory under load-path.") (setq my-load-path (list "/usr/local/share/emacs/site-lisp" (expand-file-name "~/.emacs.d/elisp") (expand-file-name "~/.emacs.d/elisp/3rd-party") (expand-file-name "~/.emacs.d/elisp/3rd-party/rhtml") (expand-file-name "~/.emacs.d/elisp/3rd-party/rinari"))) (setq load-path (append my-load-path default-load-path))
これらを利用するためRubyに関する一連のEmacs Lispを書く。
;; ruby-mode (when (autoload-p 'ruby-mode "ruby-mode" "Ruby" 'interactive) (setq auto-mode-alist (cons '("\\.rb$" . ruby-mode) auto-mode-alist)) (setq interpreter-mode-alist (cons '("ruby" . ruby-mode) interpreter-mode-alist)) ;; inf-ruby (autoload 'run-ruby "inf-ruby" "Run an inferior Ruby process") (autoload 'inf-ruby-keys "inf-ruby" "Set local key defs for inf-ruby in ruby-mode") (add-hook 'ruby-mode-hook '(lambda () (inf-ruby-keys))) ;; ruby-electric.el (require 'ruby-electric) (add-hook 'ruby-mode-hook '(lambda () (ruby-electric-mode t))) ;; rubydbnx.el (autoload 'rubydb "rubydb2x" "run rubydb on program file in buffer *gud-file*. the directory containing file becomes the initial working directory and source-file directory for your debugger." t) ;; ruby-block.el (require 'ruby-block) (ruby-block-mode t) (setq ruby-block-highlight-toggle t)) ;; Rinari (require 'rinari) ;; rhtml-mode (require 'rhtml-mode) (setq auto-mode-alist (cons '("\\.erb$" . rhtml-mode) auto-mode-alist)) (setq auto-mode-alist (cons '("\\.rhtml$" . rhtml-mode) auto-mode-alist)) (add-hook 'rhtml-mode-hook (lambda () (rinari-launch)))
参考
http://d.hatena.ne.jp/willnet/20090110/1231595231
これで、だいぶEmacsが快適になってきた。
April 24(Fri), 2009
カレントバッファの強制再読み込みをおこなう。
ログファイルをEmacsで開いているときや、IDEなど他のエディタを併用しているとき、カレントバッファの内容を再読み込みしたくなる。そこでelispを書いた。
(defun revert-buffer-force () (interactive) (revert-buffer t t)) (define-key global-map "\C-c\C-x\C-j" 'revert-buffer-force) (define-key global-map "\C-c\C-x\ j" 'revert-buffer-force) (define-key global-map "\C-x\C-j" 'revert-buffer) (define-key global-map "\C-x\ j" 'revert-buffer)
C-x j なら確認の上再読み込みをし、確認が不要な場合は C-c C-x j で強制再読み込みをする。こまめにセーブする性格でないと編集内容を失いかねないので少し複雑なキー・バインドに割り当てた。
April 17(Fri), 2009
Emacsの終了時に確認するようにする。
C-x C-c の両方とも頻繁に入力するキーなので、誤って大量に開いたバッファを失うことが多く、これを対策する。
(defun confirm-save-buffers-kill-emacs () (interactive) (if (y-or-n-p "quit emacs? ") (save-buffers-kill-emacs))) (global-set-key "\C-x\C-c" 'confirm-save-buffers-kill-emacs)
いたって簡単な話だった。
参考
March 31(Tue), 2009
iMacを買った
24inch 1920×1200 2.66GHz Intel Core 2 Duo 640GB 7200rpm SATA HDD 4GB 1066MHz DDR3 SDRAM (MAX 8GB) テンキーレス Apple Keyboard
いわゆるiMac竹(2009年3月モデル)、ヤマダ電機で買うのが一番安くてポイントを含めると実質12万円台で買えた。
現在の作業環境はこんな感じ。これでサーバーだけでなくデスクトップも充実してきた。
中央にiMac。
右手はDebian GNU/Linux用コンソール(2台切替使用)。
左手はモバイル用ノートPC置き場(MacBook/ThinkPad/AspireOne)。
iMacの24インチモニタは大きくて快適。となりのMacBookが小さく見える。
March 21(Sat), 2009
Debian sid から Xubuntu 8.10 に移行した。
Debian sid を最新化したところ、イー・モバイルの接続が不安定になった。起動時に D02HW を接続していないと起動後に接続してもイー・モバイルにつながらなかったり、接続状態で起動しても pon コマンドでダイアルアップできなかったりする。ThinkPad と AspireOne の両方で同じ状態なのでハードウェアの問題では無さそう。/dev/ttyUSB0 は見えているので、デバイスの認識はできていると思うのだが原因がはっきりしない。このままでは不便を感じるので Debian sid 環境を捨て Ubuntu 8.10 に移行することにした。
1. Ubuntu の Server Edition から CUI 環境をインストールする。
手元に Ubuntu 7.10 Server の CD があったのでそこからシェルのみの環境をインストールした。サーバー版では Debian の昔ながらのインストーラーが採用されており、暗号化された LVM を導入したり、tasksel で LAMP 環境をまるごとインストールしたりできる。こうすることで Ubuntu でも小さな環境から必要なものだけを入れて小回りの利いた環境構築をしていくことができる。
2. 長期安定版にアップグレードし、環境を構築する。
sudo vim /etc/apt/sources.list # gutsyからhardyに変更 sudo aptitude update && sudo aptitude -y dist-upgrade
各種プログラム言語とライブラリ、フレームワーク、RDBMSも一通りそろえる。この時点で、すでにメインのサーバー環境として稼働中の Ubuntu 8.04 LTS Server と同じ環境になった。これでサーバーにデプロイする機能を手元で試験的に動作させる環境が出来上がる。さらに加えて、イー・モバイルや無線LANの接続設定をおこなう。
3. カーネルをサーバー版からデスクトップ版に入れ替える。
カーネルの入れ替えは apt だけでできる。
sudo aptitude install linux-image-2.6.24-23-generic sudo shutdown -r 0 sudo aptitude purge linux-image-2.6.24-23-server
4. デスクトップ環境をインストールする。
sudo aptitude install xubuntu-desktop
5. 開発環境の動作確認をする。
GUI で動作する管理ツール等をこの段階でインストールする。デスクトップのテーマやキー・バインド設定もおこなう。
[参考] Xfceを使う。
http://d.hatena.ne.jp/Ubuntu/20080717/install_xfce
6. Intrepid にアップグレードする。
この時点で環境構築は完成なのだが、現在稼働中の Hardy の環境もいずれはアップグレードするだろうし、将来の移行を見据えた試験も兼ねて手元の環境は最新版にすることにした。Ctrl-Alt-F1 で tty1 へ切り替えてコマンドでアップグレードをする。
sudo vim /etc/apt/sources.list # hardyからintrepidに変更 sudo apt-get update && sudo apt-get dist-upgrade
7. キー・マップの再配置をする。
Intrepid ではキー・コードが Hardy から大幅に変更になっている。そこで xev で調べつつ、新しく xmodmap 用の定義ファイルを書き直した。
keycode 66 = Control_L keycode 37 = Control_L keycode 105 = Control_L clear lock add lock = Caps_Lock clear control add control = Control_L Control_R keycode 49 = Zenkaku_Hankaku Kanji keycode 9 = Escape keycode 102 = Escape keycode 100 = Return keycode 101 = Down keycode 151 = Up keycode 117 = Up keycode 133 = Up keycode 111 = Up keycode 116 = Down keycode 112 = Prior keycode 117 = Next keycode 97 = backslash underscore keycode 98 = Up keycode 36 = Return
8. GNU Screen の問題を対処する。
ターミナルを起動しようとしたら起動できない。tty1 のシェルで確認したところ screen を起動する際になぜか /var/run/screen が無いので起動失敗していた。こちらもすぐに原因がつかめていなかったので、とりあえずスタートアップ時に実行されるスクリプト /etc/rc.local に以下の通り記述して暫定的に対処した。
test -d /var/run/screen || mkdir -p /var/run/screen chmod 775 /var/run/screen chown root:utmp /var/run/screen
所持しているマシンのうちメインのモバイルマシンである ThinkPad X60 はこうして Debian sid から Xubuntu 8.10 に移行した。もう1台の Debian sid マシンである AspireOne は再インストール中にいきなり起動ができなくなってあせった。原因は BIOS の突然死だったのでこちらの方法で BIOS をアップデートしたら無事に復旧した。AspireOne には Debian lenny を再インストールすることにした。
[参考資料] 第48回東京エリアDebian勉強会資料
http://hackerscafe.g.hatena.ne.jp/Ubuntu/20090118/1232279226
March 18(Wed), 2009
/etc/modprobe.d/ 配下のファイルについて大量の警告が出力される現象の対処
Debian squeeze/sid を使っていて、3月に入ってからフルアップグレードしたところ、システムのブート時に以下のような大量の警告が表示されるようになった。
WARNING: All config files need .conf: /etc/modprobe.d/aliases, it will be ignored in a future release. WARNING: All config files need .conf: /etc/modprobe.d/arch-aliases, it will be ignored in a future release. WARNING: All config files need .conf: /etc/modprobe.d/blacklist, it will be ignored in a future release. ...
これは module-init-tools パッケージで仕様変更がおこなわれ /etc/modprobe.d/ 配下のファイル名称については .conf というサフィックスを付与されるものと決定したのが原因だ。なお、この件についてはメーリングリストに情報がある。
lenny の module-init-tools 3.4-1 では /etc/modprobe.d/aliases だったコンフィギュレーションファイルは squeeze/sid (3/17現在) の 3.7-pre9-1 では /etc/modprobe.d/aliases.conf となる。現時点では旧ファイル名称でも有効だが、将来のリリースではやがて完全に移行することになるので、今のうちに変更しておいたほうが良いだろう。
#!/bin/sh change_modprobe() { sudo mv /etc/modprobe.d/$1 /etc/modprobe.d/$1.conf } change_modprobe aliases change_modprobe arch-aliases change_modprobe blacklist change_modprobe display_class change_modprobe madwifi change_modprobe pnp-hotplug
来月リリースが予定されている Ubuntu 9.04 Jaunty では、元々が lenny/sid 時代の Debian なので、ファイル名称も古いままである。予定では Ubuntu 9.10 Karmic から squeeze/sid ベースになるので、おそらく 9.04 → 9.10 のアップグレードの際に、これと同じファイル名称の変更が必要になるだろう。
(3/18 19:56追記)
Jaunty で 3.7-pre9-1 が採用されているので 8.10 → 9.04 で変更になるのが正解。
February 28(Sat), 2009
Happy Hacking Keyboard Professional JP用のキーマップを書いた。
Happy Hacking Keyboard Professional JP 墨 (PD-KB420B)を購入した。HHKLite2もコストパフォーマンスの割に使い勝手は非常に良いが、やはりProfessionalは定価2万5千円もするだけあって別格の使い心地だ。なお例によってスペースの左右にESCとEnterを配置するため日本語配列をチョイス。GNU/Linuxでしか使用しないのでXmodmapの設定でキーバインドを変更する。さっそく書いてみた。
keycode 66 = Control_L keycode 37 = Control_L clear lock add lock = Caps_Lock clear control add control = Control_L Control_R keycode 49 = Alt_L keycode 9 = Zenkaku_Hankaku Kanji keycode 131 = Escape keycode 129 = Return keycode 208 = Down keycode 117 = Alt_L keycode 116 = Alt_L keycode 115 = Alt_L keycode 113 = Up keycode 98 = backslash underscore keycode 211 = Up keycode 36 = Return
このキーマップのポイントは右Shiftのすぐ左にbackslash/underscoreを配置し、カーソルをその左へとシフトしている点。HHKProJPはこの右Shift配列が変態的なので工夫が必要。ディップスイッチ4番をONにすればカーソルとShiftが反転するようだが、あえて211番のキーと入れ替えをしてみた。
さらに左側はFnキーとESC(スペースの左)の中間にあるキーすべてをAlt_Lに変更。Enter(スペースの右)の右側にDownとUpを配置してThinkPadのキーバインドと統一した。アバウトな感覚でEmacsのメタキーを使えるので満足。
February 22(Sun), 2009
PythonでTwitterのタイムラインを監視する
自分がfollowしているユーザーの発言をcronで定期的に収集する。テキストで取得できるので、メールにしてGmailなどに送ったりログファイルとして蓄積するなどいろいろ使い道がある。
#!/usr/bin/python import os, sys import urllib2 from xml.dom.minidom import parse import re import time import pynotify password = 'xxxxxxxx' timeline_url ='http://twitter.com/statuses/friends_timeline.xml' last_id = 0 def notify(username, tmpfile, ban_file): auth_handler = urllib2.HTTPBasicAuthHandler() auth_handler.add_password( 'Twitter API', 'http://twitter.com/', username, password) opener = urllib2.build_opener(auth_handler) urllib2.install_opener(opener) tagText = lambda node, tagName: \ node.getElementsByTagName(tagName)[0].firstChild.nodeValue print >>sys.stderr, time.strftime("[%H:%M:%S] "), "checking update" global last_id f = open(tmpfile,'r') last_id = int(f.read()) f.close ban_list = open(ban_file,'r') banlist = [] for ban in ban_list: banlist.append(ban.rstrip()) ban_list.close() r = urllib2.Request(timeline_url) r.add_data("since_id="+str(last_id)) e = parse(file=urllib2.urlopen(r)) print >>sys.stdout, time.strftime("[%Y-%m-%d %H:%M:%S] "), username, "friends timeline" for s in reversed(e.getElementsByTagName("status")): if int(tagText(s, "id")) > last_id: screen_name = tagText(s, "screen_name") text = tagText(s, "text") try: banlist.index(screen_name) except ValueError: print >>sys.stdout, "%s: %s" % (screen_name, text) else: pass last_id = int(tagText(s, "id")) print >>sys.stderr, time.strftime("[%H:%M:%S] "), "last_id is", last_id f = open(tmpfile,'w') f.write(str(last_id)) f.close() if __name__ == '__main__': from optparse import OptionParser usage = "usage: %prog [options]" parser = OptionParser(usage) parser.add_option("-u", "--username", dest="username", help="your username") parser.add_option("-t", "--tmpfile", dest="tmpfile", help="temporary file") parser.add_option("-b", "--banfile", dest="banfile", help="banlist") (options, args) = parser.parse_args() pynotify.init("TwitterNotifier") if options.username and options.tmpfile: notify(options.username, options.tmpfile, options.banfile) else: parser.error("Incorrect options, Add -h option for help.")
これをtwitter-client.pyとして名前をつけて保存し、以下のようにシェルスクリプトを用意してcronで定期的に実行する。ユーザー名や一時ファイルは引数で与え、パスワードはスクリプト内に直接記述する方式をとっている。なお引数 -b で指定するファイルには、followしているのだけど除外したいアカウントを記述しておく。この機能は円滑な人間関係を維持するのに一役買うだろう。
#!/bin/sh JOBLOG=/var/log/twitter-update.log TWITTER_LOG=/var/log/twitter.log test -x /home/hoge/bin/twitter-client.py && /home/hoge/bin/twitter-client.py -u xxxxxxxx -b /home/hoge/etc/banlist -t /home/hoge/tmp/last_id>$JOBLOG cat $JOBLOG>>$TWITTER_LOG # ADMIN_MAIL_ADDRESS=xxxxxx@gmail.com case "$ADMIN_MAIL_ADDRESS" in *@*) cat $JOBLOG | mail -s "[cron-log][`/bin/hostname`] Twitter Logger" $ADMIN_MAIL_ADDRESS ;; esac
数分ごとに発言を収集してGmailに送ってみた。こんな感じでTwitterのタイムラインを時系列に蓄積することができる。
TwitterNotifierのソースコードを参考にして実装しました。
February 20(Fri), 2009
Emacs起動後に4つのTwitterアカウント用バッファを同時起動する
id:hayamiz さんの twittering-mode.el を、単純に名前空間を分離して使っている。
毎回個別に起動するのが面倒なので Emacs 起動後にキー1発で4つのアカウントを縦に並べるようにしてみた。
;; Twitter (defun switch-to-twitter1-mode () (interactive) (twitter1-mode)) (defun switch-to-twitter2-mode () (interactive) (twitter2-mode)) (defun switch-to-twitter3-mode () (interactive) (twitter3-mode)) (defun switch-to-twitter4-mode () (interactive) (twitter4-mode)) (defun switch-to-twitter-all-mode () (interactive) (split-one-window-p) (split-window-vertically) (twitter1-mode) (split-window-vertically) (windmove-down) (twitter2-mode) (windmove-down) (twitter3-mode) (split-window-vertically) (windmove-down) (twitter4-mode)) (define-key global-map "\C-c\C-c\ 1" 'switch-to-twitter1-mode) (define-key global-map "\C-c\C-c\ 2" 'switch-to-twitter2-mode) (define-key global-map "\C-c\C-c\ 3" 'switch-to-twitter3-mode) (define-key global-map "\C-c\C-c\ 4" 'switch-to-twitter4-mode) (define-key global-map "\C-c\C-c\ 5" 'switch-to-twitter-all-mode)
4つのバッファが左側に縦4段で表示されるのでもう半分で別な作業ができる。
ThinkPadの1024x768の画面でも広々と使える。だいぶ快適になった。
February 19(Thu), 2009
Python 2.6をインストールする。
Python本体をビルドする
現時点での 2.6 系の最新は 2.6.1。
make_and_install() { cd Python-$1 test -n "$2" || ./configure test -n "$2" && ./configure --prefix $2 make test -n "$2" || sudo make install test -n "$2" && make install cd .. } get_python() { mkdir install_python cd install_python wget http://www.python.org/ftp/python/$1/Python-$1.tar.bz2 test -f Python-$1.tar.bz2 || exit 1 tar xjvf Python-$1.tar.bz2 test "$2" = "sourceonly" || make_and_install $1 $2 test -d /usr/local/src/python || sudo mkdir -p /usr/local/src/python sudo cp $OPTIONS Python-$1 /usr/local/src/python cd .. rm -rf install_python } case $OSTYPE in *darwin*) OPTIONS=-pR ;; *) OPTIONS=-a ;; esac test -n "$1" || exit 1 get_python $1 $2 case $OSTYPE in *darwin*) sudo chown -R root:wheel /usr/local/src/python ;; *) sudo chown -R root:root /usr/local/src/python ;; esac python -V
上記のスクリプトを install_python.sh として保存し install_python 2.6.1 と打てば良い。
EasyInstallをセットアップする
これが無いと easy_install コマンドが使えないので入れる。
TARGET_PATH=`python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` wget http://peak.telecommunity.com/dist/ez_setup.py sudo python ez_setup.py -U setuptools sudo cp ez_setup.py $TARGET_PATH/ez_setup.py rm ez_setup.py
EasyInstallを利用してライブラリをインストールする
sudo easy_install ipython
sudo easy_install mechanize
sudo easy_install nose
sudo easy_install -Z SQLAlchemy
sudo easy_install migrate
特に ipython は必須とも言える。
その他のパッケージをインストールする
EasyInstallで入らないものなどはソースから入れる。たとえば MySQL-python など。
install_python_packages() { sudo aptitude install libmysqlclient15-dev mkdir install_python_packages cd install_python_packages wget "http://downloads.sourceforge.net/mysql-python/MySQL-python-1.2.2.tar.gz" tar xzvf MySQL-python-1.2.2.tar.gz cd MySQL-python-1.2.2 python setup.py build sudo python setup.py install cd .. test -d /usr/local/src/python/packages || sudo mkdir -p /usr/local/src/python/packages sudo cp $OPTIONS MySQL-python-1.2.2 /usr/local/src/python/packages/ cd .. sudo rm -rf install_python_packages } case $OSTYPE in *darwin*) OPTIONS=-R ;; *) OPTIONS=-a ;; esac install_python_packages case $OSTYPE in *darwin*) sudo chown -R root:wheel /usr/local/src/python/packages ;; *) sudo chown -R root:root /usr/local/src/python/packages ;; esac
Djangoフレームワークをインストールする
以下の内容がそのまま使える。現段階での Django の最新は 1.0.2。
http://d.hatena.ne.jp/Ubuntu/20080908/django
TurboGearsフレームワークをインストールする
現時点の安定版 1.0 は Python 2.5系 までしか対応していない。
2.6 で動かしたければベータバージョンをインストールする。
TARGET_PATH=`python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` wget http://www.turbogears.org/download/tgsetup-betaversion.py sudo python tgsetup.py sudo cp tgsetup.py $TARGET_PATH/tgsetup.py rm tgsetup.py
動かしてみる
setsモジュールが 2.6 から非推奨になったため、警告メッセージが表示される。(無視して良い)
$ ipython /usr/local/lib/python2.6/site-packages/ipython-0.9.1-py2.6.egg/IPython/Magic.py:38: DeprecationWarning: the sets module is deprecated from sets import Set Python 2.6.1 (r261:67515, Feb 14 2009, 09:43:26) Type "copyright", "credits" or "license" for more information. IPython 0.9.1 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython's features. %quickref -> Quick reference. help -> Python's own help system. object? -> Details about 'object'. ?object also works, ?? prints more. In [1]: import sys In [2]: sys.version_info Out[2]: (2, 6, 1, 'final', 0) In [3]: import django In [4]: django.VERSION Out[4]: (1, 0, 2, 'final', 0) In [5]: import MySQLdb In [6]: MySQLdb.version_info Out[6]: (1, 2, 2, 'final', 0) In [7]: import mechanize In [8]: mechanize.__version__ Out[8]: (0, 1, 11, None, None) In [9]: import sqlalchemy In [10]: sqlalchemy.__version__ Out[10]: '0.5.2' In [11]: turbogears.__version__ Out[11]: '1.1b3'
January 21(Wed), 2009
Emacsで画面が分割されていなければ縦に二分割する。
単純にone-window-pで判定しているので、かなり手抜き。
;; ウィンドウが1つしかない場合は縦に分割する関数をあらかじめ定義しておく (defun split-one-window-p () (if (one-window-p) (split-window-horizontally))) (defun split-one-window () (interactive) (split-one-window-p)) ;; C-c C-c j で縦に二分割する (define-key global-map "\C-c\C-c\C-j" 'split-one-window) (define-key global-map "\C-c\C-c\ j" 'split-one-window) ;; twittering-mode.elを開始時に縦分割する (defun switch-to-twitter1-mode () (interactive) (split-one-window-p) (twitter1-mode)) (defun switch-to-twitter2-mode () (interactive) (split-one-window-p) (twitter2-mode)) (defun switch-to-twitter3-mode () (interactive) (split-one-window-p) (twitter3-mode)) (defun switch-to-twitter4-mode () (interactive) (split-one-window-p) (twitter4-mode)) (define-key global-map "\C-c\C-c\ 1" 'switch-to-twitter1-mode) (define-key global-map "\C-c\C-c\ 2" 'switch-to-twitter2-mode) (define-key global-map "\C-c\C-c\ 3" 'switch-to-twitter3-mode) (define-key global-map "\C-c\C-c\ 4" 'switch-to-twitter4-mode) ;; Navi2chを開始時に縦分割する (defun switch-to-navi2ch() (interactive) (split-one-window-p) (navi2ch)) (define-key global-map "\C-c\C-c\C-i" 'switch-to-navi2ch) (define-key global-map "\C-c\C-c\ i" 'switch-to-navi2ch)
January 19(Mon), 2009
Dynamically changing window title of zsh/screen.
I wanted to change the window title of GNU screen dynamically by this feeling.
I wrote .zshrc as follows.
show_window_title() { if [ "$TERM" = "screen" ]; then chpwd() { echo -n "^[_`dirs`^[\\" } preexec() { emulate -L zsh local -a cmd; cmd=(${(z)2}) case $cmd[1] in fg) if (( $#cmd == 1 )); then cmd=(builtin jobs -l %+) else cmd=(builtin jobs -l $cmd[2]) fi ;; %*) cmd=(builtin jobs -l $cmd[1]) ;; cd) if (( $#cmd == 2 )); then cmd[1]=$cmd[2] fi ;; ls|clear) echo -n "^[k$ZSH_NAME^[\\" return ;; screen|pwd) return ;; *) echo -n "^[k$cmd[1]:t^[\\" return ;; esac local -A jt; jt=(${(kv)jobtexts}) $cmd >>(read num rest cmd=(${(z)${(e):-\$jt$num}}) echo -n "^[k$cmd[1]:t^[\\") 2>/dev/null } chpwd fi } show_window_title
January 15(Thu), 2009
MadWifiで無線LANを利用する。
MadWifiはGNU/Linuxにおける優れた無線LANドライバのひとつであり、ath5kやath9kのような公式にサポートされていない無線LANカードのサポートを主眼において開発が進められている。AspireOneやEeePC901等に幅広く搭載されているAtheros AR5007チップで無線LAN接続するときにも有効だ。
MadWifiの最新のソースコードを取得してビルドする方法。
#!/bin/sh set_network_permission() { case $OSTYPE in *darwin*) sudo chown -R root:wheel /usr/local/src/network ;; *) sudo chown -R root:root /usr/local/src/network ;; esac } install_trunk() { test -d /usr/local/src/network/madwifi || sudo mkdir -p /usr/local/src/network/madwifi cd /usr/local/src/network/madwifi sudo svn co http://svn.madwifi-project.org/madwifi/trunk cd trunk sudo make sudo make install sudo modinfo ath_pci sudo vim /etc/modules # add line "ath_pci" } install_trunk set_network_permission
Debianの場合、ソースからビルドする代わりにmodule-assistantを利用してインストールしても良い。
sudo aptitude install build-essential module-assistant madwifi-source sudo m-a prepare sudo m-a auto-install madwifi
インストールすれば、あとはドライバさえ読み込めば無線LANが使用可能になるはず。
たとえば Debian/UbuntuでWEP接続するなら /etc/network/interfaces に以下のように設定する。
auto ath0 iface ath0 inet dhcp wireless-key s:xxxxxxxxxxxxx wireless-essid XXXXXXXXXX
(1/16)追記
ドライバを読み込まないと有効にならない。
方法はディストリビューションによるがDebian/Ubuntuなら /etc/modules に以下の一行を追加する。
ath_pci
January 07(Wed), 2009
さまざまなバージョンのRailsを併用する。
Railsの日々の進歩は目覚ましいものがある。Rails3ではmerbと統合され下位互換性が切り捨てられるという話があったり、そうでなくてもRails2.2では謎なメソッドが追加されたりMySQLドライバが標準でなくなったりと、思い切った変更が多く見受けられる。さらに今月リリースされる予定のRails2.3でも大幅な変更が加えられることになっている。
このような特徴は企業などで長期的に取り扱うソフトウェアを開発するツールとしては不向きとなることもある。また、ここしばらくの1.2→2.0→2.1という流れの中で開発したRailsアプリの資産の数もそろそろ増えてきている頃だろう。アプリケーションの保守や追加開発をするにあたり、手元で複数のバージョンのRailsを同時に使用したいこともある。
gemでバージョンを指定してインストールするには以下のようにする。
sudo gem install rails -v 2.1.2 gem list --local
gem list --localすると該当バージョンのRailsが存在することがわかる。
これ以外にローカルにスタンドアロンなパッケージがあると試験や納品の際になにかと便利なので、install_rails.shという名前でスクリプトを書いた。LinuxまたはMac OS Xで動作する。
#!/bin/sh set_rails_permission() { case $OSTYPE in *darwin*) sudo chown -R root:wheel /usr/local/src/rails ;; *) sudo chown -R root:root /usr/local/src/rails ;; esac } extract_rails_zip() { test -d $1 && sudo rm -rf $1 sudo mkdir $1 cd $1 sudo unzip ../$1.zip sudo rm ../$1.zip set_rails_permission } wget_rails_zip() { sudo wget http://rubyforge.org/frs/download.php/$2/rails-$1.zip } select_rails_package() { case "$1" in 222) RAILS_VER=2.2.2 wget_rails_zip $RAILS_VER 47183 ;; 212) RAILS_VER=2.1.2 wget_rails_zip $RAILS_VER 45625 ;; 210) RAILS_VER=2.1.0 wget_rails_zip $RAILS_VER 37770 ;; 205) RAILS_VER=2.0.5 wget_rails_zip $RAILS_VER 45369 ;; 202) RAILS_VER=2.0.2 wget_rails_zip $RAILS_VER 29361 ;; 126) RAILS_VER=1.2.6 wget_rails_zip $RAILS_VER 28340 ;; 116) RAILS_VER=1.1.6 wget_rails_zip $RAILS_VER 12324 ;; esac extract_rails_zip rails-$RAILS_VER sudo gem install rails -v $RAILS_VER } install_rails_standalone() { test -d /usr/local/src/rails || sudo mkdir -p /usr/local/src/rails cd /usr/local/src/rails select_rails_package $1 } install_rails_gem() { sudo gem install -v rails } export RUBYOPT=rubygems case "$1" in *[0-9]*) install_rails_standalone $1 ;; *) install_rails_gem ;; esac gem list --local
使い方としては、以下のように利用したいRailsのバージョンを引数に指定する。これにより該当のgemとスタンドアロンパッケージが両方インストールされる。
install_rails.sh 212 install_rails.sh 210 install_rails.sh 205
/usr/local/src/rails/rails-x.x.x/rails/vendor/rails をアプリケーションのvendor/railsに対してシンボリックリンクするか、実ファイルをコピーなどすると良い。これによりrubyさえあればgem不要で動作する(rubygemsは必要)ので運用環境でも役立つだろう。引数無しの場合は単純に最新のRailsをインストールする。
関連
Rubyをインストールする。
December 26(Fri), 2008
Emacsで編集と閲覧を切り替える
view-mode専用のキーバインドとしては以下のものが完成度が高い。
http://d.hatena.ne.jp/rubikitch/20081104/1225745862
元記事では2つのキーの同時押しでview-modeを切り替えているが、タイミングがずれると誤入力が発生しがちなので、素直にC-x C-yで編集と閲覧を切り替えるようにした。
;; C-x C-y または C-x y で view-mode を切り替える (defun toggle-view-mode () (interactive) (cond (view-mode (view-mode nil) (setq hl-line-mode nil)) (t (view-mode)))) (define-key global-map "\C-x\C-y" 'toggle-view-mode) (define-key global-map "\C-x\ y" 'toggle-view-mode)
やはりC-x C-yのような操作のほうがEmacsらしくて愛着が持てる。
ちなみにview-mode-key.elは元記事のまま利用し、単純にロードしておく。
(load "view-mode-key")
hl-line-modeの有無により、編集と閲覧の切り替えを直感的に把握できるのが良い感じだ。
12/28追記 hl-line-modeの切り替えはid:znzさんのやり方が良さそう。
December 25(Thu), 2008
Emacsで細かい誤操作をふせぐ
Escを押して離した直後にC-gを押してしまうとエラーになり、これが煩わしいので以下のようにふせぐ。
(global-set-key "\C-\M-g" 'keyboard-escape-quit)
EmacsでC-x kをするときに左手小指がキーボードから離れずC-x C-kとしてしまうことが多いので、これもkill-bufferにしてしまう。
(define-key global-map "\C-x\C-k" 'kill-buffer)
なお以下はVimで同様の操作をする設定。
nmap <C-H><C-H> :bdelete<CR> nmap <C-X><C-H> :bdelete!<CR> nmap <C-X><C-K> :close<CR>
VimではC-x C-hでバッファを閉じ、C-x C-kは分割したウィンドウを消すのに使う。
Emacsで、Escを押して離した直後に上書き保存を押してエラーになることが多いので対策する。
;; C-x C-wを上書き保存にする(別名保存はC-x w) (define-key global-map "\C-x\C-w" 'save-buffer) (define-key global-map "\C-x\ w" 'write-file) ;; C-M-x C-wでも上書き保存する (global-set-key "\C-\M-x\C-w" 'save-buffer)
Vimでは以下のようにして操作を共通化する。
nmap <C-W><C-W> :w<CR> nmap <C-X><C-W> :w!<CR>
細かい操作だけど、いずれもよく使うので快適さに大きく影響する。
December 11(Thu), 2008
Anthyでことえり風にカタカナ変換する
Anthyの変換は全体的にEmacs風のキーが割り当てられており地味に使いやすい。しかしカタカナ変換したいときなどにファンクションキーを押すことになりイラッとする。そこで、ことえり風のカタカナ変換を割り当て。
確定からSKK風のC-jを除去し、変換開始にC-nとC-pを追加する。
ことえり風に。ついでにC-:も追加。
まぁ、SKKを使えば済む話ではある。
December 09(Tue), 2008
システムのアップグレードを自動化する
この記事を読んだ。
http://d.hatena.ne.jp/hijouguchi/20081209/1228823713
自動でaptしたい、それならcron-aptというパッケージがある。
http://packages.ubuntu.com/ja/hardy/cron-apt
http://packages.debian.org/ja/etch/cron-apt
セキュリティパッチのみを自動適用したりなど、きめ細やかな運用が可能だ。
特別なパッケージを使わなくても、cronとシェルスクリプトでシステムを自動更新するのは非常にシンプルで古典的な方法だ。以下のスクリプトをauto-upgradeという名前でcronに登録し定期的に実行すれば良い。ちなみに利用しているUbuntuまたはDebian GNU/Linuxの該当のaptitudeのコメントアウトを削除し、ADMIN_MAIL_ADDRESSに自分のメールアドレスを記入して利用すること。
JOBLOG=/var/log/auto-upgrade.log echo -n "*** $0: Job start at `/bin/hostname` on ">>$JOBLOG 2>&1 date "+%Y/%m/%d %T">>$JOBLOG 2>&1 # Debian unstable (simulate only) #aptitude update >> $JOBLOG 2>&1 && aptitude -s -v -y full-upgrade >> $JOBLOG 2>&1 # Debian stable/testing #aptitude update >> $JOBLOG 2>&1 && aptitude -y safe-upgrade >> $JOBLOG 2>&1 && aptitude autoclean >> $JOBLOG 2>&1 # Ubuntu Server #aptitude update >> $JOBLOG 2>&1 && aptitude -y safe-upgrade >> $JOBLOG 2>&1 && aptitude -y install linux-image-server linux-server gnupg >> $JOBLOG 2>&1 && aptitude autoclean >> $JOBLOG 2>&1 # Ubuntu Desktop #aptitude update >> $JOBLOG 2>&1 && aptitude -y safe-upgrade >> $JOBLOG 2>&1 && aptitude -y install linux-image-generic linux-generic linux-restricted-modules-generic linux-headers linux-headers-generic gnupg >> $JOBLOG 2>&1 && aptitude autoclean >> $JOBLOG 2>&1 # AntiVirus Database freshclam >> $JOBLOG 2>&1 echo -n "*** $0: End of Job at `/bin/hostname` on ">>$JOBLOG 2>&1 date "+%Y/%m/%d %T">>$JOBLOG 2>&1 echo>>$JOBLOG 2>&1 # ADMIN_MAIL_ADDRESS=xxxxxx@gmail.com case "$ADMIN_MAIL_ADDRESS" in *@*) cat $JOBLOG | mail -s "[cron-log][`/bin/hostname`] APT Upgrade Log" $ADMIN_MAIL_ADDRESS ;; esac
Ubuntuのデスクトップ/サーバー版ならカーネルのアップグレードも自動でやってくれる。Debian GNU/Linuxの場合、stable/testingなら単純にsafe-upgradeを、sidの場合はfull-upgradeのシミュレーションのみをおこなう。その後、古いパッケージのキャッシュをクリアするためaptitude autocleanを実行。それからウイルススキャンソフトのClamAVを使っているならfreshclamコマンドでパターンファイルも更新。最後にADMIN_MAIL_ADDRESSに記載した自分のメールアドレスへログを送信する。ログをlogrotateで循環させるのも忘れないように。
さすがにsidを自動更新というのはあまりにも無茶すぎるので、ログを見て安全であることを確認してから手動でaptitude full-upgradeするのが良いだろう。他はこのスクリプトを仕掛けてあとはログを確認するだけでも大丈夫。
December 06(Sat), 2008
MacBookでGNU/Linuxを利用するときのキー・バインド
MacBookで、キー・バインドを三籟の布陣に設定しており、なおかつVMware FusionでGNU/Linuxを起動して使用する場合のxmodmaprcを記述した。
keycode 66 = Control_L keycode 37 = Control_L clear lock add lock = Caps_Lock clear control add control = Control_L Control_R keycode 49 = Zenkaku_Hankaku Kanji keycode 9 = Escape keycode 131 = Escape keycode 129 = Return keycode 208 = Down keycode 227 = Up keycode 37 = Alt_L keycode 117 = Up keycode 116 = Alt_L keycode 115 = Zenkaku_Hankaku Kanji keycode 211 = backslash underscore keycode 234 = underscore keycode 233 = asciitilde keycode 36 = Return
December 04(Thu), 2008
Debian sid(不安定版)を常用する
Debian sidを常用環境として利用しているので、利用に関するあれこれを記してみた。
すべて独自の経験から導かれたノウハウを記したものであり独学なので信憑性は必ずしも高くない。正誤の指摘やより良い改善があれば歓迎したい。
Debian GNU/Linuxの種類
Debian GNU/Linuxには主に3つのリリースがある。
- 安定版(stable) ...現在はetch、次期はlenny
- テスト版(testing) ...現在はlenny、次期はsqueeze
- 不安定版(unstable) ...永遠にsidのまま
サーバー用途には環境の変化を伴わない安定版、ローカル環境には常に最新化される不安定版が特に適している。テスト版というのは次期安定版のことであり、アップロードから一定期間を経てRCバグの出なかったパッケージが自動的に組み込まれる。不安定版というのは名前からするとなにやら物騒に聞こえるが、早い話が「安定版では無い」という意味であり不安定なわけではない。適切に扱えば常に新しいパッケージが利用できるので大変便利である。
ローカル開発環境としてDebianを選択する
公式には安定版こそがDebian GNU/Linuxのリリース版なわけだが、安定版のリリースは非常に遅くパッケージも古い。たとえば現安定版であるetchのブラウザとメーラーはFirefox 2.0/Thunderbird 1.5相当のパッケージである。これはデスクトップで利用するにはあまりにも古い。かといって外からあれこれパッケージを持ってきたのではせっかくの安定版の意味が薄れる。サーバーとしての利用であれば安定版が適切だが、ローカルの開発環境としてDebian GNU/Linuxを利用するならおのずとテスト/不安定版を選択することになるだろう。公式にセキュリティサポートが提供されるのは安定版のみだが、限定的ながらテスト版にもセキュリティサポートが存在する。また不安定版は最新のパッケージが常に提供されるので、結果的に見るとセキュリティの問題が真っ先に解決されるケースが多い。
サーバーとしてDebianを選択する
サーバーとしてはDebianの安定版、またはUbuntu LTSのServer版を利用するのが良いだろう。DebianとUbuntuでは比較記事はいろいろあるし、nonfreeなソフトウェアの扱い、商用サポートの有無、実績の長さなど違いを挙げればキリが無いが、システムの根幹をなすコンポーネントは細かいバージョンの差異こそあれ基本的に一緒である。
乱暴に特徴を表現するならこうだろう。
- Debian ...期日より品質重視
- Ubuntu ...品質より期日重視
Debian GNU/Linuxはリリース品質を重視するがそのためいつ次期安定版がリリースされるかわからない。リリースが予定日から当たり前のようにずるずると遅れる。2008年9月リリース予定のlennyがいまだテスト版のままなことからもうかがえる。またDebianの品質がUbuntuより本当に高いかというと、BTSを見る限り一概にそうとも言い難い面がある。
Ubuntuは期日が来たら原則として必ずリリースする。そのため非常につまらないバグが埋め込まれることもある。しかしながらその後のアップグレードでいずれ解消されることが多い。Ubuntu LTSのServer版は5年サポートされる。Debian GNU/Linuxはより新しいバージョンがリリースされてから原則として1年サポートされる。長期サポートをおこなう案も一応あるようだが、それにしても1年では短いと言わざるを得ない。このように考えると、5年サポートを掲げ計画的なライフサイクルを持つUbuntu LTS Serverに優位性があるように思える。ただUbuntu自体が2004年後半に登場したものであり、15年の歴史を持つDebian GNU/Linuxのほうが実績面で信頼できるのは確かである。
結論としては、どれを選択しても結局は使い方次第なので大きな差は無い。したがって好きなものを使えば良い。
sidを選択する理由
ではなぜローカルにsidを使っているかという話だが、開発環境として利用しているので常に最新版のパッケージが欲しいというのが個人的には大きな理由である。たとえば例を挙げると今日(12/4)の時点でVimは7.2.49、MySQLは5.0.67である。lennyのVimは7.1.314、MySQLは5.0.51aだから最新の機能を使いたいのであれば迷わずsidを選ぶだろう。
また、日々最新に更新し続けたほうが、Ubuntuのように半年に一度大きな更新をかけるより、影響が小さく変更箇所が特定しやすい。絶え間なく変化するので安定しないわけだが、例えばMacやWindowsで使っているソフトの最新版が公開されたらすぐ入れて試すという性格(気の早い開発者にありがち)の場合、それを簡単にやってくれるsidが適しているというわけだ。
sidをインストールする
sidをインストールするには主に2種類の方法が存在する。
- テスト版のDebianを元にsources.listをsidに書き換えてaptitude full-upgradeする。
- 最小サイズの最新ビルドイメージを利用してエキスパートモードでネットワークインストールをおこなう。
すでに構築済みで運用中のDebianテスト版があるなら、環境を最新状態に更新した上で前者の方法を採ると環境をそのままアップグレードできる。しかしおすすめは後者で、どうせなら最初から不安定版を入れたほうがトラブルが少なくて済む。なおnetinst.isoではなくbusinesscard.isoでないとエキスパートモードでも不安定版をインストールできないので間違えないこと。
sidをアップグレードする
安定版であれば適当にaptitude safe-upgradeしていれば良く、cronで自動アップグレードして後からログを検査してもまず問題無い。安定版でのaptitude full-upgradeはメジャーバージョンアップ時を除いて実施しない。これに対してリスキーな変化を伴う不安定版ではアップグレード前に注意が必要となる。基本的に不安定版ではaptitude full-upgradeのみをおこなう。
- アップグレード前に仮想環境のsidを最新化し事前検証してから実機のsidを最新化する
- aptitude --simulateオプションを利用する
一番確実なのは、VMwareなど仮想環境のゲストOSとして同じ構成のsidを用意しておいて、そちらを先にアップグレードする方法である。何か問題があればOSイメージを破棄して以前のものに戻せば良いし、実機は問題解決までアップグレードをしばらく控えれば良い。それとは別におすすめなのがaptitude -v -y -s(--simulateオプション)を定期的に実行する方法で、これは実際にパッケージの更新はしないが更新予定のパッケージの詳細を表示することができる。したがってこのログを見て既存パッケージの依存関係に影響を及ぼさないと判断してから実際にaptitude full-upgradeすればトラブルを事前に回避できる。こうして日々こまめにシステムを更新していけば、リリースの遅れなどに関係なく常に最新版のDebianを利用することができる。
特定のバージョンを利用する
開発環境としてDebianを利用する場合、基本的に最新のパッケージを利用すれば良いのだが、場合によっては(バージョンを運用環境とあわせる等の理由で)特定のバージョンのパッケージを利用したり、あるいはDebianに無いフレームワークやライブラリを利用することがあるだろう。
このようなときにはやむなくソースからビルドしたり、あるいはRubyやPython、Perlにあるパッケージマネージャを利用している。Rubyにはgem、PythonにはEasyInstall、PerlにはCPANなどがあり、LL系のWebアプリケーションフレームワーク等を利用していると、これらをフル活用するのが常である。
仮にRuby on Railsで開発をするとして、手元のDebianでgem listしてみた。
$ gem list --local *** LOCAL GEMS *** actionmailer (2.2.2) actionpack (2.2.2) activerecord (2.2.2) activeresource (2.2.2) activesupport (2.2.2) BlueCloth (1.0.0) capistrano (2.5.2) cgi_multipart_eof_fix (2.5.0) coverage (0.3) daemons (1.0.10) fastthread (1.0.1) gem_plugin (0.2.3) highline (1.5.0) hpricot (0.6.164) magic_multi_connections (1.2.1) mechanize (0.8.5) mongrel (1.1.5) mongrel_cluster (1.0.5) net-scp (1.0.1) net-sftp (2.0.1) net-ssh (2.0.4) net-ssh-gateway (1.0.0) passenger (2.0.4) postgres-pr (0.4.0) rack (0.4.0) rails (2.2.2) rake (0.8.3) RedCloth (4.1.1) redgreen (1.2.2) rspec (1.1.11) Selenium (1.1.14) vim-ruby (2007.05.07)
gemパッケージだけでもこれだけ利用しており、これらのライブラリ類は /usr/local/lib/ruby/gems/1.8/gems に存在し当然Debianのパッケージマネージャの管轄外である。またRuby自体も、まだDebianにはない1.8.7-p73に独自のコンパイルオプションを付与してビルドしている。(sidではp72だが、諸事情によりp73が必要)
今日の"Debian Meeting" with Coffeeで少し話題に挙がったので、こんなときに自前でビルドインストールしていると話したところ眉をひそめられたように思う。だが、開発環境を構築するにあたりDebianのパッケージシステムだけでは現実的には厳しいのではないかというのが実感だ。せいぜいmake installする前にcheckinstallするくらいだが、ここまで来ればもう意味ないと考え普通にインストールしている。このあたり、せめてローカルインストールしたファイルの追跡と削除くらいできればと思うのだが、何か良い方法があるのであれば知りたいところである。
(12/4 16:00追記) シンプルなインストールであればpacoで追跡/削除できることを確認した。
http://d.hatena.ne.jp/rx7/20081011/p2
(2009/6/16 追記) とはいえ自分はその後実機でsidを使うのを結局やめました。ご利用は自己責任でどうぞ。
December 02(Tue), 2008
配列への要素追加と環境変数の参照
非常にシンプルな命題。環境変数SCRIPTSで指定されたパス、もしくはスクリプトの存在するパスにある、libという名称のサブディレクトリに自作のライブラリを置いていたとする。これを呼び出すためロードパスに追加するのにPythonとRubyでどう書くかを比較した。
まずPythonの場合。
#!/usr/bin/env python import sys, os p = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib') if not p in sys.path: sys.path.append(p) try: p = os.path.join(os.environ['SCRIPTS'], 'lib') if not p in sys.path: sys.path.append(p) except KeyError: pass print sys.path
実行結果。先頭はカレントディレクトリ。
['/home/hoge/local/github/scripts', '/usr/lib/python2.5/site-packages/SQLAlchemy-0.5.0rc2-py2.5.egg', '/usr/lib/python2.5/site-packages/simplejson-2.0.3-py2.5-linux-i686.egg', '/usr/lib/python2.5/site-packages/python_twitter-0.5-py2.5.egg', '/usr/lib/python2.5', '/usr/lib/python2.5/plat-linux2', '/usr/lib/python2.5/lib-tk', '/usr/lib/python2.5/lib-dynload', '/usr/local/lib/python2.5/site-packages', '/usr/lib/python2.5/site-packages', '/usr/lib/python2.5/site-packages/Numeric', '/usr/lib/python2.5/site-packages/PIL', '/usr/lib/python2.5/site-packages/gst-0.10', '/var/lib/python-support/python2.5', '/usr/lib/python2.5/site-packages/gtk-2.0', '/var/lib/python-support/python2.5/gtk-2.0', '/home/hoge/local/github/scripts/lib', '/home/hoge/scripts/lib']
次にRubyの場合。配列の末尾に追加するのならpushなのだろうけど、カレントディレクトリが末尾なのでなんとなく逆に。
#!/usr/bin/env ruby $:.unshift File.join(ENV['SCRIPTS'], 'lib') unless ENV['SCRIPTS'] == nil $:.unshift File.join(File.dirname(__FILE__), 'lib') p $:
実行結果。
["./lib", "/home/hoge/scripts/lib", "/usr/local/lib/ruby/site_ruby/1.8", "/usr/local/lib/ruby/site_ruby/1.8/i686-linux", "/usr/local/lib/ruby/site_ruby", "/usr/local/lib/ruby/vendor_ruby/1.8", "/usr/local/lib/ruby/vendor_ruby/1.8/i686-linux", "/usr/local/lib/ruby/vendor_ruby", "/usr/local/lib/ruby/1.8", "/usr/local/lib/ruby/1.8/i686-linux", "."]
もしSCRIPTSが指定されてなくても、例外が返らずに黙ってnilになる。
December 01(Mon), 2008
Python公式ドキュメントのグローバルモジュールインデックスがなぜか空だった件。
Python公式ドキュメント翻訳の2.5対応が完了したという知らせを受けて、ここから html-2.5.tar.bz2 をダウンロードしてイントラ内のサーバーに配備した。確か11月前半だったと思う。
その後11月末頃になってイントラ内のPythonドキュメントを参照しようとしたら、一番重要なページであるはずのグローバルモジュールインデックスがなぜか空だった。いまtarボールを落として展開してみたらちゃんと modindex.html の中身が書かれている。あらためてディレクトリのタイムスタンプを確認したら 2008-11-14 になっているから、配布当初になにかミスでもあったのだろうか。
とりあえず面倒なのでHTMLを直接落として上書きした。
wget http://www.python.jp/doc/2.5/modindex.html sudo cp modindex.html /var/www/Python-Docs-2.5/ rm modindex.html