Debian Squeeze に TeX Live 2012 を入れた

手元の PC で org-latex-export をしようと思ったら,TeX の処理系が入っていなかった.
TeX 環境の構築というのは本当にうんざりするつまらない作業で,避けて通れるならできるだけやりたくないものという印象があるのだけれど,pTeXTeX Live に取り込まれて以来かなりよい方向に向かいつつあるようで,最近はさくっとパッケージ管理システムで入れれば済んでしまう世界らしい.とはいえ Debianリポジトリは相変わらず古めなので,世界が結構幸せになった TeX Live 2012 を入れようと思うと,Wheezy あたりから借りてこないといけない.とりうる方法は四つぐらい考えられる.

  • TUG 本家からもらってきて /usr/local あたりに放り込む
  • apt-pinning で wheezy から借りてくる
  • wheezy に chroot して,そこに apt で入れる
  • VirtualBoxVMWare などの仮想環境に wheezy を入れてそこに apt で入れる

このうち第一の選択肢は,TeX Live 2012 についてではないが以前試した.手続きが面倒くさかったが,今のところ特に問題は起こっていない.きっと TeX Live 2012 のケースでも,Autotools のバージョンを適当に合わせて,必要なパッケージを手で入れてあげればインストールできるだろう.ただ次に述べる理由によってこれは選びたくない.
第二の選択肢は試したことがない.一見すると apt-pinning は手続き的にもっとも簡単な方法であるような気がするが,せっかく「安定版」パッケージの依存関係を壊さないように慎重に管理されている枠組みを逸脱することになるため,特に長期間安定して運用することを目指すシステムではこれは推奨されない.cf. 第2章 Debian パッケージ管理
ということで,今回は第三の選択肢を選んでみる.TeX くらいだと牛刀の感が否めないが,この方法は必ずしも他のアプリケーションと切り離すことが難しい大きな言語の処理系を複数持ちたいときなどに役に立つ.*1もちろん仮想環境にまるっと OS ごと入れてやることも可能だが,カーネルを巻き込まない程度の話であれば chroot の方がリソースを食わなくてパソコンにやさしい.

chroot する環境を作る

Debian は debootstrap という Perl で書かれた bootstrap の仕組みを持っていて,コマンド一つで最小の Debian を作ることができる.さらに schroot という root 権限を持たない一般ユーザが chroot できる素敵な wrapper が用意されているので,安全にいくつもの環境を散歩することができる.

% sudo aptitude install debootstrap schroot

chroot 環境は /var/chroot 以下に作ることにする.パッケージは sudo は入れておいた方がいいが他はどうでもいいかもしれない.

hoge % sudo mkdir -p /var/chroot/texlive.sid.amd64
hoge % sudo debootstrap --arch amd64 --include=sudo,zsh,locales,less,git,tig,vim sid /var/chroot/texlive.sid.amd64 http://cdn.debian.or.jp/debian
hoge % ls /var/chroot/texlive.sid.amd64
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  selinux  srv  sys  tmp  usr  var

続いてホスト側からユーザ情報をコピーする.chroot した中で閉じるように環境を別途構築する手もあるが,ユーザ情報を丸ごと引き継ぐ方がシームレスな環境になるし,設定も簡単なのでそのようにする.
ちなみにハードリンクにしておいた方がホスト側での変更が直ちに反映されて便利だが,ゲスト側でこれらをうかつに変更できなくなるので,個人的にはコピーの方がよいと思う.

hoge % cd /var/chroot/texlive.sid.amd64/etc/
hoge % for FILE in {hosts,passwd,shadow,group,gshadow}; do sudo mv -v $FILE{,.org}; sudo cp -v -a /etc/$FILE .; done

apt-line もいじっておく.

hoge % cat apt/sources.list
deb http://cdn.debian.or.jp/debian sid main
hoge % sudo vi apt/sources.list
hoge % cat apt/sources.list
deb http://ftp.jp.debian.org/debian/ sid main contrib non-free
deb-src http://ftp.jp.debian.org/debian/ sid main contrib non-free

そしてこれが肝心,/etc/debian_chroot というファイルを作っておく.これを用意しておくと,bash を特に弄らず使っている場合は chroot 環境内外でプロンプトが変化するのでどこにいるのかわからなくなることを防げる.

hoge % cat debian_chroot
cat: debian_chroot: No such file or directory
hoge % echo "TeXLive.sid" | sudo tee debian_chroot
TeXLive.sid
hoge % cat debian_chroot
TeXLive.sid

続いて chroot 内から見えると便利なものを bind で mount する.ただしこの状態で sudo rm -rf /var/chroot/texlive.sid.amd64 とかやるとひどいことになるので注意.

hoge % sudo vi /etc/fstab
hoge % cat /etc/fstab
...
/proc /var/chroot/texlive.sid.amd64/proc  proc  defaults  0 0
/dev  /var/chroot/texlive.sid.amd64/dev none  rbind 0 0
/sys  /var/chroot/texlive.sid.amd64/sys none  rbind 0 0
/tmp  /var/chroot/texlive.sid.amd64/tmp none  bind  0 0
/home /var/chroot/texlive.sid.amd64/home  none  bind  0 0
hoge % sudo mount -a
hoge % mount
...
/proc on /var/chroot/texlive.sid.amd64/proc type proc (rw)
/dev on /var/chroot/texlive.sid.amd64/dev type none (rw,bind)
/sys on /var/chroot/texlive.sid.amd64/sys type none (rw,bind)
/tmp on /var/chroot/texlive.sid.amd64/tmp type none (rw,bind)
/home on /var/chroot/texlive.sid.amd64/home type none (rw,bind)

これで chroot する環境は整った./etc/inittab を編集して tty8 を割り当ててあげるなり,いきなり chroot するなりしてもよいが,前者で X なしに頑張るのも,後者で環境変数の引き継ぎに頭を悩ますのもしんどいだけであまり有益ではないので,schroot を使う.

hoge % sudo vi /etc/schroot/schroot.conf
hoge % cat /etc/schroot/schroot.conf
...
[texlive.sid.amd64]
description=TeX Live 2012 (Debian sid)
directory=/var/chroot/texlive.sid.amd64
users=foo

これでユーザ foo で chroot する準備ができた.やってみる.

hoge % cat /etc/debian_version
6.0.6
hoge % schroot -c texlive.sid.amd64 -p
hoge(TeXLive.sid) % cat /etc/debian_version
wheezy/sid

これは適当に設定した zsh を使っているが,何も弄っていない bash を使うとプロンプトはこんな風になる.

foo@hoge:~$ schroot -c texlive.sid.amd64 -p
(TeXLive.sid)foo@hoge:~$ uname -a
Linux hoge 2.6.32-5-amd64 #1 SMP Sun Sep 23 10:07:46 UTC 2012 x86_64 GNU/Linux

chroot した環境内で最低限の環境を整えておく.

hoge(TeXLive.sid) % sudo dpkg-reconfigure locales
hoge(TeXLive.sid) % sudo dpkg-reconfigure tzdata

一段落したので,chroot 環境をバックアップしておく./var/chroot/texlive.sid.amd64 よりも下位に bind で /home やら何やらをマウントしているので,何も考えずにバックアップをしようとすると大変なことになる.もちろんアンマウントしてからバックアップすればよいのだが,/var/chroot/texlive.sid.amd64 自体を bind でさらに他のところにマウントしてしまうのが簡単でよい.こうすれば chroot 下で走らせているプロセスに気を配る必要がない.

hoge % sudo mkdir /var/chroot/tmp
hoge % sudo mount --bind /var/chroot/texlive.sid.amd64 /var/chroot/tmp
hoge % sudo rsync -az --stats -h /var/chroot/tmp/ /var/chroot/texlive.sid.amd64.bak

Number of files: 16485
Number of files transferred: 13264
Total file size: 461.41M bytes
Total transferred file size: 461.38M bytes
Literal data: 461.38M bytes
Matched data: 0 bytes                                                                                                                                                                 
File list size: 348.93K
File list generation time: 0.001 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 230.07M
Total bytes received: 263.15K

sent 230.07M bytes  received 263.15K bytes  4.75M bytes/sec
total size is 461.41M  speedup is 2.00

git やら vim やらを入れても 500 MB に収まってとてもコンパクト.

TeX Live 2012 のインストール

せっかく Debianリポジトリにあるので,そこから入れる.jsarticle.cls などの jsclasses は Debian では okumura-clsfiles という名前でパッケージ化されているが,それが sid では texlive-lang-cjk に発展的に吸収された模様.

hoge(TeXLive.sid) % sudo aptitude install texlive texlive-lang-cjk
The following NEW packages will be installed:
  ca-certificates{a} cpp{a} cpp-4.7{a} dbus{a} ed{a} file{a} fontconfig-config{a} fonts-droid{a}
  fonts-ipaexfont-gothic{a} fonts-ipaexfont-mincho{a} fonts-ipafont-gothic{a} fonts-ipafont-mincho{a}
  ghostscript{a} gsfonts{a} ko.tex-extra-hlfont{a} latex-beamer{a} latex-cjk-all{a} latex-cjk-chinese{a}
  latex-cjk-chinese-arphic-bkai00mp{a} latex-cjk-chinese-arphic-bsmi00lp{a}
  latex-cjk-chinese-arphic-gbsn00lp{a} latex-cjk-chinese-arphic-gkai00mp{a} latex-cjk-common{a}
  latex-cjk-japanese{a} latex-cjk-japanese-wadalab{a} latex-cjk-korean{a} latex-cjk-thai{a}
  latex-fonts-thai-tlwg{a} latex-xcolor{a} libavahi-client3{a} libavahi-common-data{a} libavahi-common3{a}
  libcups2{a} libcupsimage2{a} libdatrie1{a} libdbus-1-3{a} libdrm-intel1{a} libdrm-nouveau1a{a}
  libdrm-radeon1{a} libdrm2{a} libencode-locale-perl{a} libffi5{a} libfile-basedir-perl{a}
  libfile-desktopentry-perl{a} libfile-listing-perl{a} libfile-mimeinfo-perl{a} libfont-afm-perl{a}
  libfontconfig1{a} libfontenc1{a} libfreetype6{a} libgl1-mesa-dri{a} libgl1-mesa-glx{a} libglapi-mesa{a}
  libglib2.0-0{a} libglib2.0-data{a} libgmp10{a} libgraphite3{a} libgs9{a} libgs9-common{a}
  libhtml-form-perl{a} libhtml-format-perl{a} libhtml-parser-perl{a} libhtml-tagset-perl{a}
  libhtml-tree-perl{a} libhttp-cookies-perl{a} libhttp-daemon-perl{a} libhttp-date-perl{a}
  libhttp-message-perl{a} libhttp-negotiate-perl{a} libice6{a} libijs-0.35{a} libio-socket-ip-perl{a}
  libio-socket-ssl-perl{a} libjasper1{a} libjbig0 libjbig2dec0{a} libjpeg8{a} libkpathsea6{a} liblcms1{a}
  liblcms2-2{a} liblwp-mediatypes-perl{a} liblwp-protocol-https-perl{a} libmagic1{a} libmailtools-perl{a}
  libmpc2{a} libmpfr4{a} libnet-dbus-perl{a} libnet-http-perl{a} libnet-ssleay-perl{a} libopenjpeg2{a}
  libpaper-utils{a} libpaper1{a} libpciaccess0{a} libpcre3{a} libpng12-0{a} libpoppler19{a} libptexenc1{a}
  libruby1.9.1{a} libsm6{a} libsocket-perl{a} libsystemd-login0{a} libtie-ixhash-perl{a} libtiff4{a}
  libtimedate-perl{a} liburi-perl{a} libutempter0{a} libwww-perl{a} libwww-robotrules-perl{a} libx11-6{a}
  libx11-data{a} libx11-protocol-perl{a} libx11-xcb1{a} libxau6{a} libxaw7{a} libxcb-glx0{a} libxcb-shape0{a}
  libxcb1{a} libxcomposite1{a} libxcursor1{a} libxdamage1{a} libxdmcp6{a} libxext6{a} libxfixes3{a}
  libxfont1{a} libxft2{a} libxi6{a} libxinerama1{a} libxml-parser-perl{a} libxml-twig-perl{a}
  libxml-xpathengine-perl{a} libxml2{a} libxmu6{a} libxmuu1{a} libxpm4{a} libxrandr2{a} libxrender1{a}
  libxt6{a} libxtst6{a} libxv1{a} libxxf86dga1{a} libxxf86vm1{a} libyaml-0-2{a} lmodern{a} luatex{a}
  mime-support{a} openssl{a} pgf{a} poppler-data{a} preview-latex-style{a} prosper{a} ps2eps{a} python{a}
  python-minimal{a} python2.7{a} python2.7-minimal{a} ruby{a} ruby1.9.1{a} sgml-base{a} shared-mime-info{a}
  swath{a} tcl8.4{a} tex-common{a} tex-gyre{a} texlive texlive-base{a} texlive-binaries{a} texlive-common{a}
  texlive-doc-base{a} texlive-doc-zh{a} texlive-extra-utils{a} texlive-font-utils{a}
  texlive-fonts-recommended{a} texlive-fonts-recommended-doc{a} texlive-generic-recommended{a} texlive-lang-cjk
  texlive-latex-base{a} texlive-latex-base-doc{a} texlive-latex-extra{a} texlive-latex-extra-doc{a}
  texlive-latex-recommended{a} texlive-latex-recommended-doc{a} texlive-luatex{a} texlive-pictures{a}
  texlive-pictures-doc{a} texlive-pstricks{a} texlive-pstricks-doc{a} thailatex{a} tipa{a} tk8.4{a}
  ttf-dejavu-core{a} ttf-marvosym{a} ucf{a} x11-common{a} x11-utils{a} x11-xserver-utils{a} xbitmaps{a}
  xdg-utils{a} xfonts-encodings{a} xfonts-utils{a} xml-core{a} xterm{a}
0 packages upgraded, 201 newly installed, 0 to remove and 0 not upgraded.
Need to get 808 MB of archives. After unpacking 1,565 MB will be used.
Do you want to continue? [Y/n/?]

現代の TeX の図体のでかさを痛感する瞬間.まあともかく,これで chroot 環境下に TeX 処理系が入った.

hoge(TeXLive.sid) % platex -kanji=utf-8 bar.tex
hoge(TeXLive.sid) % platex -kanji=utf-8 bar.tex
hoge(TeXLive.sid) % dvipdfmx bar.dvi

hoge % schroot -c texlive.sid.amd64 -p -- sh -c "platex -interaction=nonstopmode bar.tex && platex -interaction=nonstopmode bar.tex && dvipdfmx bar.dvi"

などとすることができる.

chroot してタイプセットするスクリプト

しかしタイプセットのたびに毎回 chroot するのは面倒なので,その辺を一気にやってしまうスクリプトをこしらえる.
YaTeX などから呼び出すことを想定するとエラー処理をちゃんとやらないと使い物にならないが,org-latex-export から使う場合インタラクティブにエラーに対処する必要はないので捨ててしまっている.
きっともっと筋のいいやり方があるので,誰か教えてください.

#!/bin/sh

SCHROOT='schroot -c texlive.sid.amd64 -p'
PLATEX='platex -kanji=utf-8 -interaction=nonstopmode'
DVIPDFMX='dvipdfmx'

NOPT=`expr $# - 1`
for i in `seq 1 $NOPT`; do
    OPTS="$OPTS $1"
    shift
done
FILE=$1

if [ ! -e "$FILE" ]; then
    echo "$FILE does not exist" >&2
    exit 1
fi

$SCHROOT -- sh -c "$PLATEX $OPTS $FILE; $PLATEX $OPTS $FILE; $DVIPDFMX ${FILE%tex}dvi"

こんなスクリプトを /usr/local/bin/schrootex などという名前で保存しておいて,

;; TeX process
(setq org-latex-to-pdf-process
      '("/usr/local/bin/schrootex %s"))

などと設定してあげると,Org-mode から C-c C-e p で pdf 出力できるようになる.

*1:たとえば Python で書かれた Web フレームワークである Django の 1.2, 1.4 系を Apache テスト環境もろとも共存させようと思ったりしたときに chroot は無難な選択肢になるだろう.