LPM: Local Package Manager

Want to install software without root?

どんなツールですか

自分のホームディレクトリ以下にパッケージ(tar ball)をインストールする人のためのパッケージ管理ツールです。

どんなツールではありませんか

rpm や deb パッケージをそのまま使って自分のホームディレクトリ以下にインストールするツールではありません。tar ball ならいけます。

yum とか apt とか何が違うんですか

最終的な目的はあんまり違わないんですけど、root 権限が無いと yum とか apt とか基本的に使えないですよね。

たとえば CentOS に libboost 1.33.1 が付いてくるけれども自分は libboost 1.41.0 を使いたいんだー、とかいうときに、 root 権限がないと rpm ではどうしようもない。

たとえ root 権限があったとしても自分で spec ファイル書かなきゃならないし、CentOS に入っている古いバージョンと自分の 入れたい新しいバージョンが衝突したりすると、ホームディレクトリ以下に入れて他のユーザーには干渉させないから勘弁してよ!と 言いたくなります。

tar ball を使ってホームディレクトリ以下にインストールすれば?

tar ball を自分でダウンロードして、./configure --prefix=$HOME/local && make && make install すれば確かに問題はだいたい解決するんですが、 面倒なことがいろいろありまして

  • ソフト名で google 検索して最新版のホームページを探し、tar ball をダウンロードしてくる作業が面倒。 5台も6台もマシンを使っていると URL をメモしておきたいですよね。
  • tar ball をダウンロードする先のディレクトリもたいてい決まっているので、ブラウザのダイアログでいちいち指定するのも面倒。
  • configure するときに --prefix をたまに付け忘れて悲しいことになり面倒。
  • make install した後に PATH とか MAN_PATH とか LD_LIBRARY_PATH とか設定し忘れて、絶対PATH指定しないと動かなかったり man が出てこなかったりいろいろ面倒。
  • .bash_profile に記述したら tcsh を使ったときに読み込まれなくて残念。
  • アンインストールしたいときに面倒。GNU automake で作ったパッケージなら make uninstall で行けるんですけど、.bash_profile の PATH の指定とか MAN_PATH の指定とか消えません。 GNU式の configure を使っていない場合にはソフト自体のアンインストールも面倒。 porg とか使えばいいんですけど、porg のインストールも面倒だし、使い方を思い出すのも面倒。環境変数は消してくれないし。
  • Perl とか Python のモジュールをホームディレクトリ以下にインストールしたい時とか、tar ball だとかなり面倒。
  • 実験で一時的に違うバージョンのライブラリをインストールした状態で自分のソフトをテストし、テストが終わったら元に戻したい、などというときに面倒。

結局何をするツールなんですか

上で説明した状況で役に立つツールです。使い方を見た方がわかりやすいです。

使い方

インストール方法

まず、Perl は入っているものと仮定します。gcc 等のコンパイラもあるものとします。無いと動きません。

ダウンロードし実行権限を立てて lpm initlocaldir と実行して下さい。

$ wget https://lpm.bio/lpm (wgetが無ければブラウザなどでダウンロードしてください)
$ chmod +x ./lpm
$ ./lpm initlocaldir
$ rm ./lpm (インストール終わったら消してもOK)

インストールすると何が走るか

Sourceforge に porg というパッケージ管理ソフトがあるのですが、 こいつの最新版をダウンロードして ~/lcl 以下にインストールします。 porg を使うとたいていのソフトのアンインストールが自動化できますが、 lpm は porg の機能を使っています。

.bash_profile や .bashrc (tcsh や zsh を使っている人は同等のファイル) に ~/lcl/.bash_profile や ~/lcl/.bashrc も参照するように source 命令を書き加えます。 bash/csh/tcsh/zsh 以外のシェルのことは考えていません。

~/lcl 以下の .bashrc などのスタートアップファイルに、 ~/lcl/bin に PATH を通したり /lcl/lib に LD_LIBRARY_PATH を通したり、 ~/lcl/man に MAN_PATH を通したりする設定を書き込みます。 次回ログイン時にはこのへんの設定が読み込まれます。

porg と lpm 自身を ~/lcl 以下にインストールします。

パッケージのインストール方法

デフォルトリポジトリに入っているソフトの場合(例: ttyrec)

$ lpm install ttyrec

lpmスクリプトが存在するソフトの場合(架空の例: foo)

$ lpm install foo.lpm (foo.lpm がカレントにある場合)

tar ball しかないソフトの場合

$ lpm install http://www.example.com/foo.tar.bz2 (ローカルファイルの場合には単にファイルのパスを書けばOK)

インストールしたパッケージのリスト取得

lpm list

パッケージのアンインストール

lpm uninstall パッケージ名

パッケージのアップデート

lpm update パッケージ名

lpm update コマンドは lpm freeze/lpm uninstall/lpm install を立て続けに実行します。lpm update コマンドはパッケージのアップデートがあろうがなかろうがアップデートを試みます。一部のパッケージではバージョン番号の取得が不可能でありアップデートの有無を自動で判別することが不可能であるためにこのような仕様になっています。

最後の install に失敗した場合にはパッケージが無くなってしまいますが、lpm thaw コマンドで元に戻すことができます。

パッケージの冷凍

lpm freeze パッケージ名

LPM はインストールされたファイルを追跡しています。 追跡しているファイルをすべて tar ball に保存することで、あるパッケージのあるバージョンをバイナリで保存することができます。 ~/lcl/lib/lpm 以下に tar ball が作られます。

バージョンアップが失敗した場合に、ここで冷凍したパッケージから以前の状態を復元することができます。

また、OSのバージョンやアカウント名等が同一である場合には、この冷凍パッケージをマシン間でコピーして解凍することでバイナリをそのまま動かせるかもしれません(実際に動作するかどうかはパッケージの性質に依ります)。

冷凍されたパッケージの一覧取得

lpm fridge

冷凍されたパッケージの一覧を表示します。引数を追加して、正規表現によるサーチを行うこともできます。

冷凍されたパッケージの解凍

lpm thaw パッケージ名

冷凍したパッケージを解凍します。これから解凍するパッケージと同じ名前のパッケージが既にインストールされているとエラーとなります。

指定したパッケージについて複数バージョンが冷凍されている場合には、曖昧性を排除するために、パッケージ名だけではなくバージョンも追加してください(例: lpm thaw ttyrec-1.7.0)

Perl のパッケージインストール

前準備として lpm initcpan する。Perl の CPAN は元々使える人が操作することを前提としている。

後はお好きに普通にモジュールをインストール。lpm installcpan モジュール名 でもインストール可能。

Python のパッケージインストール

lpm install virtualenv をどうぞ。

あとはお好きに普通にモジュールをインストールできる。元々 Python のモジュールインストール方法を知っていることが前提。

パッケージの一覧

lpm listrepos コマンドでリポジトリ中のパッケージリストを閲覧できる。

サーチは grep でもなんでも使ってください。

ファイアーウォールが sourceforge へのアクセスをブロックしていて 'lpm initlocaldir' が動作しません。どうしたらよいですか?

最新版(である必要は必ずしもないが)の porg (詳しくは porg のウェブページを参照)をダウンロードして, '--porgbase' オプションを 'lpm initlocaldir' に与えて下さい.

例: lpm initlocaldir --porgbase=/tmp/porg-0.1.tar.gz

質問してほしい質問

lpm スクリプトの仕様は?

下のコーナーを見て。

~/lclって何?私は~/○○○を使いたい。

~/hogehoge がよければ --local=hogehoge を lpm に付けて下さい。'lpm initlocaldir --local=hogehoge' といった要領。initlocaldir コマンドが動作した際に lpm 自身を書き換えてデフォルトを --local=hogehoge に変更するので2回目以降に同じオプションを付ける必要はありません。

リポジトリに○○○が入っていない。

趣味で作ったソフトなので作者が必要だったプログラムしかパッケージ化していません。

パッケージをメンテしてくれる人が増えると楽なので是非プロジェクトに加わって下さい。メンテするパッケージは1つでもいいです。

長期的にメンテするのはイヤです。

長期的にやる気が無くても lpm ファイルを送ってくれればとりあえずデフォルトリポジトリに入れておきます。何も無いよりはマシだと考えましょう。

使えないので lpm 自体をアンインストールしたい。

lpm removelocaldir すると何も無かったかのごとく消え去ります。

.bashrc 等のスタートアップスクリプトにコメントのゴミとかが多少残るかも。

lpm ssconfig コマンドでバックアップファイルがどんどん増えるのは困る.

安全のためにデフォルトではバックアップを作る設定になっています。lpm のソースコードを編集して、"use constant DEFAULT_BACK_UP => 1;" と書かれた行の 1 を 0 に変更するとバックアップファイルを作らなくなります。lpm updatelpm した場合にもこの設定はコピーされますのでご安心を。

lpm スクリプトの書き方

基本

# で始まる行はコメントです。空行は無視されます。

GNUスタイルのtar ball (./configure && make && make install でインストールできる tar ball) の場合

下記の source のところを埋めて下さい。

# 以下の「1行説明」は無くても良いが、スクリプトをアップロードした場合にはこの行が説明として使われる.
# Description: netcat
#
# 以下の行も無くて良いが、スクリプトをアップロードした場合に表示される.
# Tested: CentOS 6.4
#
# 依存するパッケージがあればここに書く。機械処理はされないので自由に書いて良いが、
# 慣例として LPM パッケージがあればその名前を書く.依存パッケージが無ければ省略可能.
# Depends:
#
# 長い説明は(# で始まるコメント中で) note タグの中に書く. 公式リポジトリにアップロードする場合には英語で書いて貰えると嬉しいが日本語で書いて貰っても誰かが英訳する.
# <note>
# It depends on almost nothing.
# Should be easy to install.
# </note>
#
# source URL. ダウンロード元URLを指定する.
source=http://internap.dl.sourceforge.net/sourceforge/netcat/netcat-0.7.1.tar.bz2
# URL. スクリプトをアップロードした場合にはここへリンクが張られる.
url=http://netcat.sourceforge.net/
# パッケージをダウンロードする.
download
# ファイルを解凍する.
extract
# configure する.
configure
# make する.
make
# make install する.
makeinstall

source として指定する URL は原則として tarball の URL で、基本的には http://, ftp:// などをここには指定します。

source には git や mercurial, subversion リポジトリを指定することもできます。リポジトリの種類は URL から自動的に判定されますが、http や https を用いる場合などは頭にリポジトリ名とカンマを付けて source=git,http://foo.example.com/reponame のように指定し、曖昧性を取り除いてください。 リポジトリからダウンロードした場合には extract コマンドは不要になります。

url=を書くと公開リポジトリに登録したときにパッケージリストのページからリンクが張られますので lpm スクリプトを他人と共有するときには役に立ちます。

私はLPMスクリプトの開発者です。商用アプリ等ライセンスの関係でLPMから自動ダウンロードさせることはできないのですが。

まずは download の代わりに manualdownload と LPM スクリプトの中で指定してください。このコマンドはダウンロードを行わず、指定のフォルダ(デフォルトでは ~/lcl/archive) にパッケージがあるかどうかだけを検査します

ファイルが存在しない場合には url= で指定された URL を表示してユーザーにダウンロードを促します。ライセンス名が分かっている場合には manualdownload の引数に名前を渡して下さい。ユーザーに表示されます。

manualdownload を指定した場合には source= の行で完全な URL ではなくファイル名だけを指定してください。

私はLPMの単なるユーザーです。商用アプリ等ライセンスの関係でLPMから自動ダウンロードはできないのですが、共有ディレクトリを持っていないマシンがたくさんあり、ファイルをいちいちコピーするのが面倒です。時間を節約できませんか?

できます。~/lcl/.lpmlocalrepo (ディレクトリ名は適宜読み替えてください。)に自分だけがアクセスできるリモートのディレクトリ名を記述してください。

もしパッケージがローカルの指定されたディレクトリ(e.g., ~/lcl/archive)に存在しないときには .lpmlocalrepo で指定されたディレクトリから scp で当該ファイルをコピーすることを試みます。

ファイルのコピーには scp コマンドを用いているので scp コマンドに渡せるオプションも同時に記述することができます。

# コメントを書けます。scp の書き方にならって書いて下さい。詳しくは'man scp'で表示されるマニュアルで。 username@ssh.example.com:/home/username/secretdir # 必要な場合は scp のオプションを記述することもできます。 -l username -I /home/myuser/.ssh/id_rsa_lpm ssh.example.com:/home/username/secretdir

Java アプリ等で make の必要はないんだけど

makeの行を外して下さい。

ソフト名やバージョン番号の認識が変です。

GNU style でないアーカイブ名を使った場合や、URL から推測できない(LPMは単純な正規表現で推測しています)ソフト名・バージョン番号の場合には lpm スクリプト内で記述してください (e.g., boost_1_49_0 はダメですが、boost-1.49.0 なら OKです。).

source=http://example.com/really-difficult-to-read-SoftwareName0.1.bin2.22fc.example.ver.zip
name=SoftwareName
ver=0.1.bin2.22fc

また、バージョン番号は download コマンドを実行した直後にリポジトリのバージョン番号に書き換えられますので、必要な場合には download コマンドの後に ver コマンドを追加してください。

アーカイブ内のトップディレクトリが GNU 標準に従ってないので make && ./configure に失敗します。

hogehoge version 1.2.3 なら hogehoge-1.2.3.tar.gz (あるいは.tar.bz2)という tar ball のファイル名で、トップディレクトリ(アーカイブ中の最上位に含まれるディレクトリ)は hogehoge-1.2.3 でなくてはなりません。

それ以外の場合には手動で設定してください。

topdirname=SoftwareName_0.1.bin2.22fc

make install ではインストールできないんだけど

custominstall から EOC までの行でシェルスクリプトを書いて下さい。 custominstall の次の行では、カレントディレクトリはトップディレクトリになっています。

# install
custominstall
cd FastQC
cp -r uk $LIB_DIR/java
mkdir $SHARE_DIR/FastQC
cp -r *.txt *.ico *.bat Help $SHARE_DIR/FastQC
EOC

シェルスクリプト内で使える環境変数は、ローカルディレクトリを ~/lcl (--local オプションで設定できます)として、hogehoge-1.3.2.tar.gz をインストール中だとすると、

環境変数値の例
$LOCAL_DIR~/lcl
$ARCHIVE_DIR~/lcl/archive
$BIN_DIR~/lcl/bin
$LIB_DIR~/lcl/lib
$VAR_DIR~/lcl/var
$OPT_DIR~/lcl/var
$SHARE_DIR~/lcl/share
$MAN_DIR~/lcl/man
$BUILD_DIR~/lcl/build
$INCLUDE_DIR~/lcl/include
$LPMLIB_DIR~/lcl/lib/lpm
$PACKAGE_NAMEhogehoge
$PACKAGE_VER1.3.2
$ARCHIVE_FILE~/lcl/archive/hogehoge-1.3.2.tar.gz
$OSlinux または darwin
$ARCHx86_64 または x86
$RAW_ARCHx86_64, i386, i686, ...
$DIST_TYPE'rhel' は Cent OS, RedHat Enterprise Linux, Fedora Linux, Scientific Linux の何れかを表し, 'suse' は SuSE Linux を, 'ubuntu' は Ubuntu を表します. Mac 上では 'mac' となります。
$DIST_DESCディストリビューションに依存する文字列が返ります. 例えば RHEL 6.4 では 'Red Hat Enterprise Linux Server release 6.4 (Santiago)' となります.
です。--local=foo として LPM のローカルディレクトリを初期化した場合にはそれぞれ ~/foo/archive, ~/foo/bin, ... となります。

例では普通に cp コマンドを用いてファイルをインストールしていますが、 全てのファイル生成は porg を用いて追跡されているので、どんなやり方でファイルを生成しても ちゃんとアンインストールできます。 例外としては Java VM のように static compile されたソフトからファイルを生成する場合ですが、 インストーラーで Java はまぁ、使わないので普通は問題ないでしょう。

バイナリ配布のソフトはどう指定すれば良い?

バイナリ配布のソフトは上の「make installではインストールできない」ソフトにならってインストール方法を記述してください。(要は自分でバイナリをコピーしてください。)

環境によってダウンロードするバイナリを変更したい場合には以下のように記述してください。

# Use this URL for Linux
if{$osname eq 'linux'} source=linux_binary.tar.gz
# Use this URL for Mac
if{$osname eq 'darwin'} source=macos_binary.tar.gz
# Use this URL for 64bit (Intel/AMD x86_64)
if{$btype eq 'x86_64'} source=binary.x86_64.tar.gz
# Use this URL for 32bit (Intel/AMD x86)
if{$btype eq 'x86'} source=binary.x86.tar.gz
# Use this URL for Linux 64bit (Intel/AMD x86_64)
if{$btype eq 'x86_64' && $osname eq 'linux'} source=linux_binary.x86_64.tar.gz
# Use this URL for Mac 64bit (Intel x86_64)
if{$btype eq 'x86_64' && $osname eq 'darwin'} source=macos_binary.x86_64.tar.gz

”{}” の内側が Perl の式として評価されます。括弧の種類が Perl とは異なり、() ではなく {} であることに注意してください。$btype と $osname は LPM が事前に定義した値です。また、コードブロックは使えません(if の効力はその行のみ。1行ifしか使えない。)。

以下に、よく使われる変数名のリストを載せます。

変数名説明
$osnameLinux の場合には 'linux' を, MacOSX の場合には 'darwin' となります.
$btype64bit OS では 'x86_64', 32bit OS では 'x86' をとります.
$dist_info->{type}'rhel' は Cent OS, RedHat Enterprise Linux, Fedora Linux, Scientific Linux の何れかを表し, 'suse' は SuSE Linux を, 'ubuntu' は Ubuntu を表します. Mac 上では 'mac' となります。
$dist_info->{description}ディストリビューションに依存する文字列が返ります. 例えば RHEL 6.4 では 'Red Hat Enterprise Linux Server release 6.4 (Santiago)' となります.

最初に porg を取ってくるみたいに Sourceforge で最新版を取ってきたい

getlatest=package URL

URL にはダウンロードページを書いておいて下さい。 packageにはパッケージ名を書いて下さい。HTMLを解析して最もバージョン番号が高いものをダウンロードします。 source, name, ver は自動でセットされますが、GNU style でないファイル命名規則の場合には動かない場合もあります。

configure にオプションを付けたいです。

configure の後ろにはオプションが付けられます。

configure --disable=lib-foo

make の代わりに任意のシェルスクリプトを実行したいです。

shell と EOC で囲まれたスクリプトを実行できます。custominstall コマンドとほとんど同じですが、porg によるファイル追跡を行わないのが shell コマンドの特徴です。

shell の次の行では常にトップディレクトリがカレントディレクトリです。shell ブロック内で cd しても次の shell/custominstall ブロックではカレントディレクトリはトップディレクトリに戻っています。

環境変数のセットアップを行いたいです。

ログインシェルに作用させたい場合

loadstartup
setlogin
export FOO=abc
...
EOC
savestartup

tcsh/csh 系のために、'export FOO=' を 'setenv FOO ' に自動で置き換えてくれますのでスクリプトは bash 用にだけ用意すればOKです。また、’export FOO=$FOO:bar’ のような追加表現も(かなり面倒になりますが) csh 用の同等表現に置き換えられます。

全てのシェルに作用させたい場合

loadstartup
setini
シェル起動時に実行したいスクリプト
EOC
savestartup

ダウンロードしたパッケージが壊れていないかチェックしたいです。

md5 か sha256 が使えます。

md5 9fcbe4fbb11f9168c675a9ab05879e7a
sha256 5baf33b4232d267acb1e1ef8c0606b0bad5866473837a3fd22f714fca29efcbf

インストールしたファイルの一部分をちょっと書き換えたいです。

ありますよねぇ。Makefile をちょっとだけいじりたいとか。

replaceregexp
ファイル名
サーチ正規表現
置き換え正規表現

このコマンドは4行を消費します。横に並べる仕様でも良かったのですが、スペースをサーチしたい場合を考えるとエスケープが面倒になりすぎでやめました。

ファイル名は解凍したアーカイブからの相対パスです。上からファイルを走査して、「サーチ正規表現」にヒットする行まで移動し、その行で「置き換え正規表現」を適用します。

使い方がピンとこないって?以下の例では Makefile の中から CFLAGS を設定している行をサーチし、-fPIC オプションを追加します。

replaceregexp
Makefile
/CFLAGS/
s/CFLAGS=/CFLAGS=-fPIC /

並列 make したいんだけど

make に -j オプションを渡す方法もありますが、一般的には環境変数 LPM_MAKE_OPTION を使ってください。

後者だとユーザーの環境にCPUコアがいくつあるかによってユーザーが使用する CPU コア数を変更することができてより柔軟です。

export LPM_MAKE_OPTION=-j8
lpm install hogehoge

lpm をバージョンアップしたい

updateself コマンドでどうぞ

lpm updateself

updatelpmdevel コマンドで開発版(不安定)へのアップデートもできます

httpsでダウンロードが出来ない

一部のサイトでは Agent を見て変なソフトウェアだと弾く設定になっていることがあります。

LPM に --wgetオプションを付けて wget によるダウンロードを試してみて下さい。

複数のローカルディレクトリを使い分けたい

例えばいくつかのソフトについて、gcc と Intel C でスピードを測りたい、という状況を考えます。

まず、gcc をコンパイラとして用いる状態で ~/gcc 以下にソフトを入れます。

$ export CC=gcc
$ lpm initlocaldir --local=gcc
$ exec $SHELL -l
$ export CC=gcc (上のコマンドで再ログインしたので CC は消えているかもしれないので)
$ lpm install targetsoft1 --local=gcc
$ lpm install targetsoft2 --local=gcc
$ lpm install targetsoft3 --local=gcc

ソフトを入れ終わったら ~/gcc ディレクトリは非アクティブにしてしまいましょう。

lpm ssconfig gcc off

非アクティブになったことを確認します。

lpm ssconfig

設定ファイル類を読み直して環境変数を正しい状態にするために一回再ログインします。

つぎに、icc (Intel C compiler)をコンパイラとして用いる状態で ~/icc 以下にソフトを入れます。

$ export CC=icc
$ lpm initlocaldir --local=icc
$ exec $SHELL -l
$ export CC=icc (上のコマンドで再ログインしたので CC は消えているかもしれないのを思い出して下さい)
$ lpm install targetsoft1 --local=icc
$ lpm install targetsoft2 --local=icc
$ lpm install targetsoft3 --local=icc

この状態で targetsoft1,2,3 のベンチマークを取ります。終わったら今度は gcc を有効にします。

lpm ssconfig icc off
lpm ssconfig gcc on

再ログインして下さい。今度は gcc で作った targetsoft1,2,3 が実行できるようになっています。

wget で証明書の検証ができないと言われダウンロードができない。

証明書の検証ができない場合にはダウンロードしないのが本来は正解ですが、セキュリティ上の問題があることは承知のうえでどうしてもダウンロードした場合には --wnocert オプションを付けて下さい。

R のパッケージのように、LPM の管理外でインストールされるファイルがある場合にはどうすればよいですか?

LPM スクリプトの中で、そのようなファイルが設置されるディレクトリに .lpm_save_under_this_dir というファイルを作ってください。

lpm freeze コマンドがそのディレクトリの下にあるファイルも冷凍の対象にします。このディレクトリは uninstall の対象とはならないため気をつけて下さい。