第10章 データー管理

目次

10.1. 共有とコピーとアーカイブ
10.1.1. アーカイブと圧縮ツール
10.1.2. コピーと同期ツール
10.1.3. アーカイブの慣用句
10.1.4. コピーの慣用句
10.1.5. ファイル選択の慣用句
10.1.6. バックアップと復元
10.1.7. バックアプユーティリティーのスイート
10.1.8. システムバックアップ用スクリプトの例
10.1.9. データーバックアップ用コピースクリプト
10.1.10. リムーバブルストレージデバイス
10.1.11. ネットワーク経由でのデーター共有
10.1.12. アーカイブメディア
10.2. ディスクイメージ
10.2.1. ディスクイメージの作成
10.2.2. ディスクに直接書込み
10.2.3. ディスクイメージファイルをマウント
10.2.4. ディスクイメージのクリーニング
10.2.5. 空のディスクイメージ作成
10.2.6. ISO9660 イメージファイル作成
10.2.7. CD/DVD-R/RW に直接書込み
10.2.8. ISO9660 イメージファイルをマウント
10.3. バイナリーデーター
10.3.1. バイナリーデーターの閲覧と編集
10.3.2. ディスクをマウントせずに操作
10.3.3. データーの冗長性
10.3.4. データーファイルの復元と事故の証拠解析
10.3.5. 大きなファイルを小さなファイルに分割
10.3.6. ファイル内容の消去
10.3.7. ダミーファイル
10.3.8. ハードディスクの全消去
10.3.9. ハードディスク未使用部分の全消去
10.3.10. 削除されたがまだオープン中のファイルの復活法
10.3.11. 全てのハードリンクを検索
10.3.12. 見えないディスクスペースの消費
10.4. データーセキュリティーのインフラ
10.4.1. Gnupg のためのキー管理
10.4.2. GnuPG をファイルに使用
10.4.3. Mutt で GnuPG を使用
10.4.4. Vim で GnuPG を使用
10.4.5. MD5 和
10.5. ソースコードマージツール
10.5.1. ソースファイル間の相違の抽出
10.5.2. ソースファイルに更新をマージ
10.5.3. 3方マージによる更新
10.6. バージョンコントロールシステム
10.6.1. VCS コマンドの比較
10.7. CVS
10.7.1. CVS レポジトリーの設定
10.7.2. CVS へのローカルアクセス
10.7.3. pserver を使った CVS へのリモートアクセス
10.7.4. ssh を使った CVS へのリモートアクセス
10.7.5. 新規ソースを CVS にインポート
10.7.6. CVS レポジトリーのファイルパーミッション
10.7.7. CVS のワークフロー
10.7.8. CVS から最新ファイル
10.7.9. CVS の管理運営
10.7.10. CVS チェックアウトの実行ビット
10.8. Subversion
10.8.1. Subversion レポジトリーの設定
10.8.2. Apach2 サーバーの経由の Subversion アクセス
10.8.3. グループによる Subversion へのローカルアクセス
10.8.4. グループによる Subversion への SSH 経由のリモートアクセス
10.8.5. Subversion ディレクトリー構造
10.8.6. 新規ソースを Subversion にインポート
10.8.7. Subversion のワークフロー
10.9. Git
10.9.1. Git クライアントの設定
10.9.2. Git リファレンス
10.9.3. Git コマンド
10.9.4. Subversion レポジトリー用の Git
10.9.5. 設定履歴記録のための Git

バイナリーとテキストのデーターを Debian システム上で管理するツールとティップを記します。

[警告] 警告

競合状態とならないようにするために、アクティブにアクセスされているデバイスやファイルに複数プロセスから調整なく書き込みアクセスをしてはいけません。flock(1) を使ったファイルロック機構がこの回避に使えます。

10.1. 共有とコピーとアーカイブ

データーのセキュリティーとそのコントロールされた共有はいくつかの側面があります。

  • データーアーカイブの作成
  • 遠隔ストレージアクセス
  • 複製
  • 変更履歴の追跡
  • データー共有のアシスト
  • 不正なファイルへのアクセスの防止
  • 不正なファイルの改変の検出

こういったことは次の組み合わせを使うことで実現できます。

  • アーカイブと圧縮ツール
  • コピーと同期ツール
  • ネットワークファイルシステム
  • リムーバブルストレージメディア
  • セキュアーシェル
  • 認証システム
  • バージョンコントロールシステムツール
  • ハッシュや暗号学的暗号化ツール

10.1.1. アーカイブと圧縮ツール

Debian システム上のアーカイブと圧縮ツールのまとめを以下に記します。

表10.1 アーカイブと圧縮ツールのリスト

パッケージ ポプコン サイズ コマンド 拡張子 コメント
tar * V:61, I:99 2660 tar(1) .tar 標準アーカイバー (デファクト標準)
cpio * V:41, I:99 920 cpio(1) .cpio Unix System V スタイルのアーカイバー、find(1) とともに使用
binutils * V:58, I:74 11996 ar(1) .ar 静的ライブラリー生成用のアーカイバー
fastjar * V:7, I:31 216 fastjar(1) .jar Java 用のアーカイバー (zip 類似)
pax * V:1.5, I:6 172 pax(1) .pax 新規 POSIX 標準アーカイバー、tarcpio の間の妥協点
afio * V:0.3, I:1.7 240 afio(1) .afio ファイル毎の圧縮などの拡張をされた cpio
gzip * V:91, I:99 284 gzip(1), zcat(1), … .gz GNU LZ77 圧縮ユーティリティー (デファクト標準)
bzip2 * V:51, I:79 132 bzip2(1), bzcat(1), … .bz2 gzip(1) より高い圧縮比 (gzip より遅い、類似シンタックス) の Burrows-Wheeler ブロック並び替え圧縮ユーティリティー
lzma * V:8, I:80 172 lzma(1) .lzma gzip(1) より高い圧縮比の LZMA 圧縮ユーティリティー (非推奨)
xz-utils * V:5, I:26 460 xz(1), xzdec(1), … .xz bzip2(1) より高い圧縮比の XZ 圧縮ユーティリティー (gzip より遅いが bzip2 より早い、LZMA 圧縮ユーティリティーの代替)
p7zip * V:2, I:23 1052 7zr(1), p7zip(1) .7z 高い圧縮比をもつ 7-Zip 圧縮ユーティリティー (LZMA 圧縮)
p7zip-full * V:14, I:26 3612 7z(1), 7za(1) .7z 高い圧縮比をもつ 7-Zip 圧縮ユーティリティー (LZMA 圧縮、他)
lzop * V:0.7, I:6 144 lzop(1) .lzo gzip(1) より高い圧縮と解凍の速度 (gzip より低い圧縮比、類似シンタックス) の LZO 圧縮ユーティリティー
zip * V:8, I:52 632 zip(1) .zip InfoZIP: DOS アーカイブと圧縮ツール
unzip * V:24, I:69 408 unzip(1) .zip InfoZIP: DOS アーカイブ解凍と圧縮解凍ツール

[警告] 警告

何が起こるかを理解せずに "$TAPE" 変数を設定してはいけません。設定すると tar(1) の挙動が変わります。

[注記] 注記

gzip 圧縮された tar(1) アーカイブは ".tgz" とか ".tar.gz" といったファイル拡張子を使います。

[注記] 注記

xz 圧縮された tar(1) アーカイブは ".txz" とか ".tar.xz" といったファイル拡張子を使います。

[注記] 注記

tar(1) 等の FOSS ツールでのポピュラーな圧縮方法は次のように変遷しています: gzipbzip2xz

[注記] 注記

cp(1) と scp(1) と tar(1) は特殊ファイルに関して一部制約があるかもしれません。cpio(1) と afio(1) は最も汎用性があります。

[注記] 注記

cpio(1) と afio(1) はfind(1) 等のコマンドとともに使うようにできていて、ファイルの選定部分のスクリプトを独立にテストできるのでバックアップスクリプトを作るのに向いています。

[注記] 注記

afio(1) はアーカイブ中の各ファイルを圧縮できます。この事実ゆえ afiotar とか cpio アーカイブ全体を圧縮するよりファイルの破損に対してずっと安全となり、バックアップスクリプトにとって最良のアーカイブエンジンとなっています。

[注記] 注記

OpenOffice データーファイルの内部データー構造は ".jar" ファイルです。

10.1.2. コピーと同期ツール

Debian システム上の単純なコピーとバックアップツールのまとめを以下に記します。

表10.2 コピーと同期ツールのリスト

パッケージ ポプコン サイズ ツール 機能
coreutils * V:92, I:99 13828 GNU cp ファイルやディレクトリーのローカルコピー ("-a" で再帰的実行)
openssh-client * V:52, I:99 2104 scp ファイルやディレクトリーのリモートコピー (クライアント、"-r" で再帰実行)
openssh-server * V:70, I:83 700 sshd ファイルやディレクトリーのリモートコピー (リモートサーバー)
rsync * V:19, I:52 704 - 単方向リモート同期とバックアップ
unison * V:0.9, I:3 1816 - 双方向リモート同期とバックアップ

rsync(8) を使ってのファイルのコピーには他の方法より豊かな機能があります。

  • 転送元のファイルと転送先の既存ファイル間の相違のみを送信する差分転送アルゴリズム
  • サイズか最終変更時間に変更があったファイルのみを探す (デフォルトで採用される) 急速確認アルゴリズム
  • tar(1) 類似の "--exclude" や "--exclude-from" オプション
  • 転送先に追加ディレクトリレベルを作成しなくする「転送元ディレクトリ後スラシュ (/) 付加」文法
[ティップ] ティップ

「データーバックアップ用コピースクリプト」 に記された bkup スクリプトを "-gl" オプションとともに cron(8) の下で実行すると静的なデーターアーカイブに関して Plan9 の dumpfs と非常に似た機能を実現できます。

[ティップ] ティップ

表10.16「バージョンコントロールシステムツールのリスト」に記されたバージョンコントロールシステム (VCS) ツールは多方向のコピーと同期のツールとして機能します。

10.1.3. アーカイブの慣用句

"./source" ディレクトリー中の全内容を異なるツールを用いてアーカイブしアーカイブ解凍するいくつかの方法を以下に記します。

GNU tar(1):

$ tar cvzf archive.tar.gz ./source
$ tar xvzf archive.tar.gz

cpio(1):

$ find ./source -xdev -print0 | cpio -ov --null > archive.cpio; gzip archive.cpio
$ zcat archive.cpio.gz | cpio -i

afio(1):

$ find ./source -xdev -print0 | afio -ovZ0 archive.afio
$ afio -ivZ archive.afio

10.1.4. コピーの慣用句

"./source" ディレクトリー中の全内容を異なるツールを用いてコピーするいくつかの方法を以下に記します。

  • ローカルコピー: "./source" ディレクトリー → "/dest" ディレクトリー
  • リモートコピー: ローカルホストの "./source" ディレクトリー → "user@host.dom" ホストの "/dest" ディレクトリー

rsync(8):

# cd ./source; rsync -av . /dest
# cd ./source; rsync -av . user@host.dom:/dest

「転送元ディレクトリ後スラシュ付加」文法を上記の代わりに使えます。

# rsync -av ./source/ /dest
# rsync -av ./source/ user@host.dom:/dest

GNU cp(1) と openSSH scp(1):

# cd ./source; cp -a . /dest
# cd ./source; scp -pr . user@host.dom:/dest

GNU tar(1):

# (cd ./source && tar cf - . ) | (cd /dest && tar xvfp - )
# (cd ./source && tar cf - . ) | ssh user@host.dom '(cd /dest && tar xvfp - )'

cpio(1):

# cd ./source; find . -print0 | cpio -pvdm --null --sparse /dest

afio(1):

# cd ./source; find . -print0 | afio -pv0a /dest

"." を含むすべての例で "." は"foo" で代替でき、ファイルを "./source/foo" ディレクトリから "/dest/foo" ディレクトリにコピーできます。

"." を含むすべての例で "." を絶対パスの "/path/to/source/foo" で代替でき、"cd ./source;" を削除することができます。これらは使うツール次第で異なる場所にファイルをコピーします。

  • "/dest/foo": rsync(8)、GNU cp(1)、scp(1)
  • "/dest/path/to/source/foo": GNU tar(1)、cpio(1)、afio(1)
[ティップ] ティップ

rsync(8) や GNU cp(1) には転送先のファイルが新しい場合にスキップする "-u" オプションがあります。

10.1.5. ファイル選択の慣用句

アーカイブやコピーコマンド (「アーカイブの慣用句」「コピーの慣用句」参照) のためや xargs(1) (「ファイルに関してループしながらコマンドを反復実行」参照) のためにファイルを選択するのに find(1) が使われます。これの操作は find(1) のコマンド引数を使うことで強化できます。

find(1) の基本シンタックスは次のようにまとめられます。

  • 条件の引数は左から右へと評価されます。
  • 結果が決まった時点で評価は終了します。
  • "論理 OR" (条件間に "-o" で指定) は、"論理 AND" (条件間に "-a" または何もなしで指定) より低い優先順位です。
  • "論理 NOT" (条件前に "!" で指定) は、"論理 AND" より高い優先順位です。
  • "-prune" は常に論理真 (TRUE) を返し、ディレクトリーの場合にはこの点以降のファイル探索を停止します。
  • "-name" はシェルのグロブ (「シェルグロブ」参照) を使ってファイル名のベースにマッチし、さらに "*" and "?" 等のメタ文字で最初の "." ともマッチします。(新規の POSIX 機能)
  • "-regex" はデフォールトでは emacs スタイルの BRE (「正規表現」参照) を用いてフルパスをマッチします。
  • "-size" はファイルサイズ ("+" が前に付いた値はより大きい、"-" が前に付いた値はより小さい) に基づいてファイルをマッチします。
  • "-newer" はその引数に指定されたファイルより新しいファイルとマッチします。
  • "-print0" は常に論理真 (TRUE) を返し、フルファイル名を (null 終端処理して) 標準出力へプリントします。

find(1) はしばしば慣用的なスタイルで使われます。

# find /path/to \
    -xdev -regextype posix-extended \
    -type f -regex ".*\.afio|.*~" -prune -o \
    -type d -regex ".*/\.git" -prune -o \
    -type f -size +99M -prune -o \
    -type f -newer /path/to/timestamp -print0

これは次のアクションをすることを意味します。

  1. "/path/to" からはじまる全ファイルを探索
  2. 探索開始したファイルシステムに探索を全体的に制約し、デフォールトの代わりに ERE (「正規表現」参照) を使用
  3. 正規表現 ".*\.afio" か ".*~" にマッチするファイルを処理停止をすることで探索から除外
  4. 正規表現 ".*/\.git" にマッチするディレクトリーを処理停止をすることで探索から除外
  5. 9MiB(1048576バイトの単位) より大きいファイルを処理停止をすることで探索から除外
  6. 上記の探索条件に合致し "/path/to/timestamp" より新しいファイル名をプリントします

上記例中でファイルを検索から除外するときの "-prune -o" の慣用的な使い方に注目して下さい。

[注記] 注記

非 Debian のUnix 的システムでは、一部のオプションは find(1) によってサポートされていないかもしれません。そのような場合には、マッチング方法を調整したり "-print0" を"-print" で置き換えることを考慮します。これに関連するコマンドも調整する必要があるかもしれません。

10.1.6. バックアップと復元

コンピューターはいつか壊れるとか、人間によるエラーがシステムやデーターをへの損害を及ぼすことは皆知っています。バックアップと復元の操作は正しいシステム管理の必須構成要素です。考えうる全ての故障モードはいつかの日にやって来ます。

[ティップ] ティップ

バックアップのシステムは簡単にしておき、システムのバックアップは頻繁にします。バックアップデーターが存在することは、あなたのバックアップ方法が技術的に如何に良いかよりも重要です。

実際のバックアップと復元の方針を決める上で3つの要素があります。

  1. 何をバックアップし復元するかを知っていること

    • あなた自身が作成したデーターファイル: "~/" 中のデーター
    • あなた自身が使用したアプリケーションが作成したデーターファイル: "/var/" ("/var/cache/" と "/var/run/" と "/var/tmp/" は除外) 中のデーター
    • システム設定ファイル: "/etc/" 中のデーター
    • ローカルデーター: "/usr/local/" とか "/opt/" 中のデーター
    • システムインストール情報: 要点 (パーティション、…) をプレーンテキストで書いたメモ
    • 実証済みのデーターセット: 事前に実験的復元操作をして確認済み
  2. バックアップと復元の方法を知っていること

    • セキュアーなデーターのストレージ: 上書きやシステム障害の防止
    • 頻繁なバックアップ: スケジュールされたバックアップ
    • 冗長なバックアップ: データーのミラーリング
    • フルプルーフなプロセス: 簡単な単一コマンドバックアップ
  3. 関わっているリスクと費用の評価

    • データーがなくなった際の価値
    • バックアップに必要なリソース: 人的、ハードウエアー、ソフトウエアー、…
    • 故障モードとその確率

データーのセキュアーなストレージとして、好ましくはファイルシステム破壊に耐えるように異なるディスクや機器上に、少なくとも異なるディスクパーティション上に、データーはあるべきです。重要データーは上書き事故を防ぐために CD/DVD-R のような1回書込みメディアに貯蔵するのが好ましいです。(シェルコマンドラインからストレージメディアにどうして書き込むかについては「バイナリーデーター」を参照下さい。GNOME デスクトップの GUI 環境ではメニュー: "Places→CD/DVD Creator" で簡単に書込みできます。)

[注記] 注記

データーをバックアップする際には MTA (「メールトランスポートエージェント (MTA)」参照) 等のアプリケーションデーモンを停止するのも一計です。

[注記] 注記

"/etc/ssh/ssh_host_dsa_key" や "/etc/ssh/ssh_host_rsa_key" や "~/.gnupg/*" や "~/.ssh/*" や "/etc/passwd" や "/etc/shadow" や "/etc/fetchmailrc" や "popularity-contest.conf" や "/etc/ppp/pap-secrets" や "/etc/exim4/passwd.client" 等のアイデンティティ関連のデーターファイルのバックアップと修復には特に注意が必要です。これらのデーターの一部はシステムに同様な入力をしても再生成できません。

[注記] 注記

ユーザープロセスで cron ジョブを実行している際には、"/var/spool/cron/crontabs" ディレクトリー中のファイルを回復し cron(8) を再スタートしなければいけません。cron(8) と crontab(1) に関しては「タスク定期実行のスケジュール」を参照下さい。

10.1.7. バックアプユーティリティーのスイート

Debian システム上の目に止まったバックアップユーティリティーのスイートから選んだリストを記します。

表10.3 バックアップスイートのユーティリティーのリスト

パッケージ ポプコン サイズ 説明
rdiff-backup * V:1.4, I:3 804 (リモート) 増分バックアップ
dump * V:0.4, I:1.5 716 ext2/ext3 ファイルシステム用の 4.4 BSD 由来の dump(8) と restore(8)
xfsdump * V:0.3, I:1.9 628 GNU/Linux と IRIX 上の XFS ファイルシステム用の xfsdump(8) と xfsrestore(8) を使う dump と restore
backupninja * V:0.5, I:0.6 452 軽量で拡張可のメタバックアップシステム
mondo * V:0.11, I:0.5 1168 Mondo Rescue: 災害復元バックアップスイート
sbackup * V:0.05, I:0.16 488 GNOME デスクトップ用の簡単なバックアップのスイート
keep * V:0.13, I:0.3 1232 KDE 用のバックアップシステム
bacula-common * V:1.3, I:2 1404 Bacula: ネットワークバックアップ、復元および検証 - 共通のサポートファイル
bacula-client * I:0.9 84 Bacula: ネットワークバックアップ、復元および検証 - クライアントメタパッケージ
bacula-console * V:0.3, I:1.2 184 Bacula: ネットワークバックアップ、復元および検証 - テキストコンソール
bacula-server * I:0.5 84 Bacula: ネットワークバックアップ、復元および検証 - サーバーメタパッケージ
amanda-common * V:0.4, I:0.8 6924 Amanda: Advanced Maryland Automatic Network Disk Archiver (ライブラリー)
amanda-client * V:0.4, I:0.8 748 Amanda: Advanced Maryland Automatic Network Disk Archiver (クライアント)
amanda-server * V:0.11, I:0.3 916 Amanda: Advanced Maryland Automatic Network Disk Archiver (サーバー)
backuppc * V:0.8, I:1.0 2460 BackupPC は高性能でエンタープライズ級の、PC をバックアップするためのシステム (ディスクベース)
backup-manager * V:0.4, I:0.6 672 コマンドラインのバックアップツール
backup2l * V:0.2, I:0.3 152 マウントできるメディアのための低メンテナンスのバックアップ/復旧ツール (ディスクベース)

バックアップツールにはそれぞれの特別な狙いがあります。

  • Mondo Rescue を使うと、通常のインストールプロセスを経ずにバックアップ CD/DVD 等から完全なシステムを迅速に復旧できます。
  • sbackupkeep パッケージは、デスクトップユーザーがユーザーデーターの定期的バックアップをする簡単な GUI のフロントエンドを提供します。同様の機能は簡単なスクリプト (「システムバックアップ用スクリプトの例」) と cron(8) で実現できます。
  • BaculaAmandaBackupPC は、ネットワーク越しの定期的バックアップに焦点のあるフル機能のバックアップスイートです。

「アーカイブと圧縮ツール」「コピーと同期ツール」に記された基本的なツールを使うとカスタムスクリプト経由のシステムバックアップができます。そのようなスクリプトは次を使うと強化できます。

  • rdiff-backup パッケージは (リモートの) 増分バックアップを可能にします。
  • dump パッケージは全ファイルシステムの効率的かつ増分のバックアップと復旧を補助します。
[ティップ] ティップ

dump パッケージに関して学ぶには、"/usr/share/doc/dump/" の中のファイルと "Is dump really deprecated?" を参照下さい。

10.1.8. システムバックアップ用スクリプトの例

個人の Debian の unstable (非安定) スイートを実行するデスクトップシステムでは、個人的だったりクリティカルなデーターのみを保護する必要しかありません。いずれにせよ1年に1回はシステムを再インストールします。だから全システムをバックアップする理由もありませんし、フル機能のバックアップユーティリティーをインストールする理由もありません。

簡単なスクリプトでバックアップ用アーカイブを作成し、GUI を使って CD/DVD にそれを焼きます。次のこのスクリプトの例を示します。

#!/bin/sh -e
# Copyright (C) 2007-2008 Osamu Aoki <osamu@debian.org>, Public Domain
BUUID=1000; USER=osamu # UID and name of a user who accesses backup files
BUDIR="/var/backups"
XDIR0=".+/Mail|.+/Desktop"
XDIR1=".+/\.thumbnails|.+/\.?Trash|.+/\.?[cC]ache|.+/\.gvfs|.+/sessions"
XDIR2=".+/CVS|.+/\.git|.+/\.svn|.+/Downloads|.+/Archive|.+/Checkout|.+/tmp"
XSFX=".+\.iso|.+\.tgz|.+\.tar\.gz|.+\.tar\.bz2|.+\.afio|.+\.tmp|.+\.swp|.+~"
SIZE="+99M"
DATE=$(date --utc +"%Y%m%d-%H%M")
[ -d "$BUDIR" ] || mkdir -p "BUDIR"
umask 077
dpkg --get-selections \* > /var/lib/dpkg/dpkg-selections.list
debconf-get-selections > /var/cache/debconf/debconf-selections

{
find /etc /usr/local /opt /var/lib/dpkg/dpkg-selections.list \
     /var/cache/debconf/debconf-selections -xdev -print0
find /home/$USER /root -xdev -regextype posix-extended \
  -type d -regex "$XDIR0|$XDIR1" -prune -o -type f -regex "$XSFX" -prune -o \
  -type f -size  "$SIZE" -prune -o -print0
find /home/$USER/Mail/Inbox /home/$USER/Mail/Outbox -print0
find /home/$USER/Desktop  -xdev -regextype posix-extended \
  -type d -regex "$XDIR2" -prune -o -type f -regex "$XSFX" -prune -o \
  -type f -size  "$SIZE" -prune -o -print0
} | cpio -ov --null -O $BUDIR/BU$DATE.cpio
chown $BUUID $BUDIR/BU$DATE.cpio
touch $BUDIR/backup.stamp

root から実行されるスクリプト断片の例と言う位置づけです。

著者はこれをあなたが次のように変更し実行する事を期待します。

  • このスクリプトを編集して全てのあなたの重要なデーターをカバーしましょう (「ファイル選択の慣用句」「バックアップと復元」参照)。
  • 増分バックアップをするには、"find … -print0" を、"find … -newer $BUDIR/backup.stamp -print0" で置き換えます。
  • scp(1) か rsync(1) を使ってリモートホストにバックアップファイルを転送したり、それらを更なるデーターセキュリティーのために CD/DVD に焼きます。(私は CD/DVD に焼くのに GNOME デスクトップの GUI を使っています。更なる冗長性に関しては「zenity を使うシェルスクリプト例」を参照下さい。)

簡潔にしましょう!

[ティップ] ティップ

debconf の設定データーは "debconf-set-selections debconf-selections" で、dpkg の選択データーは "dpkg --set-selection <dpkg-selections.list" で復元できます。

10.1.9. データーバックアップ用コピースクリプト

ディレクトリーツリーの下のデーターセットは、"cp -a" としてコピーすると通常のバックアップができます。

"/var/cache/apt/packages/" ディレクトリーの下のデーターのようなディレクトリーの下の大きな上書きされない静的なデーターセットは、"cp -al" を利用するハードリンクを使うと通常のバックアップに代わるディスク空間を効率的に利用するバックアップができます。

私が bkup と名付けたデーターバックアップのためのコピースクリプトを次に示します。このスクリプトは現ディレクトリーの下の全ての (非 VCS) ファイルを親ディレクトリーかリモートホストの日付入りディレクトリーにコピーします。

#!/bin/sh -e
# Copyright (C) 2007-2008 Osamu Aoki <osamu@debian.org>, Public Domain
fdot(){ find . -type d \( -iname ".?*" -o -iname "CVS" \) -prune -o -print0;}
fall(){ find . -print0;}
mkdircd(){ mkdir -p "$1";chmod 700 "$1";cd "$1">/dev/null;}
FIND="fdot";OPT="-a";MODE="CPIOP";HOST="localhost";EXTP="$(hostname -f)"
BKUP="$(basename $(pwd)).bkup";TIME="$(date  +%Y%m%d-%H%M%S)";BU="$BKUP/$TIME"
while getopts gcCsStrlLaAxe:h:T f; do case $f in
g)  MODE="GNUCP";; # cp (GNU)
c)  MODE="CPIOP";; # cpio -p
C)  MODE="CPIOI";; # cpio -i
s)  MODE="CPIOSSH";; # cpio/ssh
S)  MODE="AFIOSSH";; # afio/ssh
t)  MODE="TARSSH";; # tar/ssh
r)  MODE="RSYNCSSH";; # rsync/ssh
l)  OPT="-alv";; # hardlink (GNU cp)
L)  OPT="-av";;  # copy (GNU cp)
a)  FIND="fall";; # find all
A)  FIND="fdot";; # find non CVS/ .???/
x)  set -x;; # trace
e)  EXTP="${OPTARG}";; # hostname -f
h)  HOST="${OPTARG}";; # user@remotehost.example.com
T)  MODE="TEST";; # test find mode
\?) echo "use -x for trace."
esac; done
shift $(expr $OPTIND - 1)
if [ $# -gt 0 ]; then
  for x in $@; do cp $OPT $x $x.$TIME; done
elif [ $MODE = GNUCP ]; then
  mkdir -p "../$BU";chmod 700 "../$BU";cp $OPT . "../$BU/"
elif [ $MODE = CPIOP ]; then
  mkdir -p "../$BU";chmod 700 "../$BU"
  $FIND|cpio --null --sparse -pvd ../$BU
elif [ $MODE = CPIOI ]; then
  $FIND|cpio -ov --null | ( mkdircd "../$BU"&&cpio -i )
elif [ $MODE = CPIOSSH ]; then
  $FIND|cpio -ov --null|ssh -C $HOST "( mkdircd \"$EXTP/$BU\"&&cpio -i )"
elif [ $MODE = AFIOSSH ]; then
  $FIND|afio -ov -0 -|ssh -C $HOST "( mkdircd \"$EXTP/$BU\"&&afio -i - )"
elif [ $MODE = TARSSH ]; then
  (tar cvf - . )|ssh -C $HOST "( mkdircd \"$EXTP/$BU\"&& tar xvfp - )"
elif [ $MODE = RSYNCSSH ]; then
  rsync -rlpt ./ "${HOST}:${EXTP}-${BKUP}-${TIME}"
else
  echo "Any other idea to backup?"
  $FIND |xargs -0 -n 1 echo
fi

これはコマンド例の位置付けです。スクリプトを読んで自分自身で編集してからご使用下さい。

[ティップ] ティップ

私はこの bkup を私の "/usr/local/bin/" ディレクトリーに置いています。わたしは一時的スナップショットのバックアップが必要な時に、作業ディレクトリー中で引数無しにこの bkup コマンドを実行します。

[ティップ] ティップ

ソースファイルツリーや設定ファイルツリーのスナップショットの履歴を作成するには、git(7) を使うのが簡単でスペースの効率も良ろしいです (「設定履歴記録のための Git」参照)。

10.1.10. リムーバブルストレージデバイス

リムーバブルストレージデバイスは次の何れも指します。

  • ハードディスク
  • フラッシュメモリーのすべてのフォーマット
  • USBIEEE 1394 / FirewirePC Card 等経由でつながれたデジタルカメラ

このようなリムーバブルストレージは、gnome-mount(1) を使い GNOME 等の現代的なデスクトップ環境では自動的にユーザーとしてマウントできます。

  • GNOME の下のマウント点は次のようにしてカスタマイズ可能な "/media/<disk_label>" と選ばれます。

    • FAT ファイルシステムでは、mlabel(1) を使います。
    • ISO9660 ファイルシステムでは、genisoimage(1) を"-V" オプションとともに使います。
    • ext2/ext3 ファイルシステムでは、tune2fs(1) を"-L" オプションとともに使います。
  • 符号化方式 (エンコーディング) の選択をマウントオプションとして与える必要があるかもしれません (「ファイル名の符号化方式」参照)。
  • マウントされたファイルシステムのオーナーシップはノーマルユーザーが使えるように調整する必要があるかもしれません。
[注記] 注記

"/etc/fstab" にリムーバブルメディアデバイスの記載が無い時のみ、現代的なデスクトップ環境下での自動マウントは起こります。

[ティップ] ティップ

間違ったマウントオプションにより問題が発生した時には、gconf-editor(1) を使って "/system/storage/" の下の対応する設定を消去します。

表10.4 "/etc/fstab" エントリーにマッチが無いリムーバブルデバイスをノーマルユーザーにマウントする事を許すパッケージのリスト

パッケージ ポプコン サイズ 説明
gnome-mount * V:15, I:28 NOT_FOUND ストレージデバイスを (アン)マウントやイジェクトするためのラッパー (GNOME が使用)
pmount * V:4, I:19 548 ノーマルユーザーとしてリムーバブルデバイスをマウントする (KDE が使用)
cryptmount * V:0.2, I:0.5 360 暗号化されたファイルシステムの管理とユーザーモードでのマウント
usbmount * V:0.4, I:1.4 112 USB ストレージデバイスを自動的にマウントやアンマウント

リムーバブルストレージデバイスを使ってデーターを共有する際には、両方のシステムにサポートされた共通のファイルシステムでそれをフォーマットするべきです。ファイルシステム選択のリストを次に示します。

表10.5 典型的な使用シナリオに合わせたリムーバブルストレージデバイスのファイルシステムの選択肢のリスト

ファイルシステム 典型的使用シナリオの説明
FAT12 フロッピーディスク上のクロスプラットフォームのデーター共有 (<32MiB)
FAT16 小さなハードディスク類似のデバイス上のクロスプラットフォームのデーター共有 (<2GiB)
FAT32 大きなハードディスク類似のデバイス上のクロスプラットフォームのデーター共有 (<8TiB, MS Windows95 OSR2 以降でサポート有り)
NTFS 大きなハードディスク類似のデバイス上のクロスプラットフォームのデーター共有 (MS Windows NT 以降でネイティブにサポート、Linux 上では FUSE 経由の NTFS-3G でサポート)
ISO9660 CD-R and DVD+/-R 上の静的データーのクロスプラットフォームの共有
UDF CD-R や DVD+/-R 上への増分データーの書込み (新規)
MINIX ファイルシステム フロッピーディスク上へのスペース効率の良い unix ファイルデーターのストレージ
ext2 ファイルシステム 古い Linux システムとハードディスク類似デバイス上のデーターを共有
ext3 ファイルシステム 現行の Linux システムとハードディスク類似デバイス上のデーターを共有 (ジャーナリングファイルシステム)

[ティップ] ティップ

デバイスレベルの暗号化を使ったクロスプラットフォームのデーター共有に関しては、「dm-crypt/LUKS を使ったリムーバブルディスクの暗号化」を参照下さい。

FAT ファイルシステムはほとんど全ての現代的なオペレーティングシステムでサポートされていて、ハードディスク類似のメディア経由でのデーター交換目的に非常に有用です。

クロスプラットフォームの FAT ファイルシステムを使ったデーター共有にリムーバブルハードディスク類似デバイスをフォーマットする時の安全な選択肢は次です。

  • fdisk(8) か cfdisk(8) か parted(8) (「ディスクパーティション設定」参照) を使ってそれを単一のプライマリパーティションにパーティションしそれを次のようにマークします。

    • 2GB より小さなメディアには FAT16 となるように "6" とタイプします
    • 大きなメディアには FAT32 (LBA) となるように "c" とタイプします
  • 第1パーティションを mkfs.vfat(8) を使って次のようにフォーマットします。

    • FAT16 となるように "/dev/sda1" 等とそのデバイス名だけを使います
    • FAT32 となるように "-F 32 /dev/sda1" 等と明示的なオプション指定とそのデバイス名を使います

FAT とか ISO9660 ファイルシステムを使ってデーターを共有する際の安全への配慮を次に記します。

  • tar(1) や cpio(1) や afio(1) を使ってアーカイブファイルに最初にファイルをアーカイブすることで長いファイル名やシンボリックリンクやオリジナルの Unix ファイルパーミッションとオーナー情報を保持します。
  • split(1) コマンドを使ってアーカイブファイルを 2GiB 以下の塊に分割してファイルサイズの制約から保護します。
  • アーカイブファイルを暗号化してその内容を不正アクセスから保護します。
[注記] 注記

FAT ファイルシステムはその設計上最大ファイルサイズは (2^32 - 1) bytes = (4GiB - 1 byte) です。古い 32 ビット OS 上の一部アプリケーションは、最大ファイルサイズはさらに小さく (2^31 - 1) bytes = (2GiB - 1 byte) です。Debian は後者の問題に苦しむことはありません。

[注記] 注記

Microsoft 自身も 200MB を越すドライブやパーティションに FAT を使うことを勧めていません。マイクロソフトは、彼らの "Overview of FAT, HPFS, and NTFS File Systems" で非効率的なディスク領域の使用等の欠点をハイライトしています。もちろん私たちは Linux では通常 ext3 ファイルシステムを使うべきです。

[ティップ] ティップ

ファイルシステムとファイルシステムのアクセスに関しての詳細は、"Filesystems HOWTO" を参照下さい。

10.1.11. ネットワーク経由でのデーター共有

データーをネットワーク経由で他のシステムと共有するときには、共通のサービスを使うべきです。次に一部のヒントを記します。

表10.6 典型的使用シナリオの場合のネットワークサービスの選択のリスト

ネットワークサービス 典型的使用シナリオの説明
Samba を使う SMB/CIFS ネットワーク経由マウントファイルシステム "Microsoft Windows Network" 経由でのファイル共有、smb.conf(5) と The Official Samba 3.2.x HOWTO and Reference Guidesamba-doc パッケージ参照
Linux カーネルを使う NFS ネットワークマウントファイルシステム "Unix/Linux Network" 経由のファイル共有、exports(5) と Linux NFS-HOWTO 参照。
HTTP サービス ウェッブサーバー/クライアント間のファイル共有
HTTPS サービス 暗号化されたセキュアーソケットレイヤー (SSL) もしくは Transport Layer Security (TLS) を使ったウェッブサーバー/クライアント間のファイル共有
FTP サービス FTP サーバー/クライアント間のファイル共有

このようなネットワーク経由でマウントされたファイルシステムやネットワーク経由のファイル転送法はデーター共有のために非常に便利ですが、インセキュアーかもしれませんこれらのネットワーク接続は次に記すようにしてセキュアーにされなければいけません。

  • SSL/TLS を使い暗号化
  • SSH 経由でそれをトンネル
  • VPN 経由でそれをトンネル
  • セキュアーファイアウォールの背後に限定

さらに「他のネットワークアプリケーションサーバー」「他のネットワークアプリケーションクライアント」を参照下さい。

10.1.12. アーカイブメディア

重要なデーターアーカイブのためのコンピューターデーターストレージメディアを選ぶ時にはそれらの限界について注意を払うべきです。小さな個人的なバックアップのためには、著者としては名前が知られている会社の CD-R と DVD-R を使い、クールで日陰の乾燥した埃の無い環境に保存しています。(プロ用途ではテープアーカイブメディアに人気があるようです。)

[注記] 注記

耐火金庫は紙の文書のためのものです。ほとんどのコンピューターデーターストレージメディアは紙よりも耐熱性がありません。著者は通常複数の安全な場所に保管された複数のセキュアーな暗号化されたコピーに頼っています。

ネット上に散見するアーカイブメディアの楽観的なストレージ寿命 (ほとんどベンダー情報由来)。

  • 100+年: インクと中性紙
  • 100年: オプティカルストレージ (CD/DVD、CD/DVD-R)
  • 30年: 磁気ストレージ (テープ、フロッピー)
  • 20年: 相変化オプティカルストレージ (CD-RW)

これらは取扱いによる機械的故障等は考慮していません。

ネット上に散見するアーカイブメディアの楽観的な書込み回数 (ほとんどベンダー情報由来)。

  • 250,000+回: ハードディスク
  • 10,000+回: フラッシュメモリー
  • 1,000回: CD/DVD-RW
  • 1回: CD/DVD-R、紙
[注意] 注意

ここにあるストレージ寿命や書込み回数の数字はクリチカルなデーターストレージに関する決定に使うべきではありません。製造者によって提供される特定の製品情報を参照下さい。

[ティップ] ティップ

CD/DVD-R や紙は1回しか書けないので、本質的に重ね書きで間違ってデーターを消すことを防げます。これは、利点です!

[ティップ] ティップ

もし高速で頻繁な大量のデーターのバックアップをする必要がある場合、高速のネットワーク接続でつながっているリモートホスト上のハードディスクが唯一の現実的なオプションかもしれません。

10.2. ディスクイメージ

次に、ディスクイメージの操作を論じます。「データー保存のティップ」も参照下さい。

10.2.1. ディスクイメージの作成

例えば2番目の SCSI ドライブ "/dev/sdb" というアンマウントされたドライブのディスクイメージファイル "disk.img" はcp(1) か dd(1) を用いれば次のようにして作れます。

# cp /dev/sdb disk.img
# dd if=/dev/sdb of=disk.img

プライマリ IDE ディスクの最初のセクターにある伝統的 PC のマスターブートレコード (MBR) (「ディスクパーティション設定」参照) のディスクイメージは、dd(1) を用いれば次のようにして作れます。

# dd if=/dev/hda of=mbr.img bs=512 count=1
# dd if=/dev/hda of=mbr-nopart.img bs=446 count=1
# dd if=/dev/hda of=mbr-part.img skip=446 bs=1 count=66
  • "mbr.img": パーティションテーブル付きの MBR
  • "mbr-nopart.img": パーティションテーブル抜きの MBR。
  • "part.img": MBR のパーティションテーブルのみ。

ブートディスクとして SCSI ドライブ (最近のシリアル ATA ドライブを含む) が使われている場合、"/dev/hda" を"/dev/sda" に置き換えて下さい。

オリジナルディスクのパーティションのイメージを作る場合には、"/dev/hda" を"/dev/hda1" 等で置き換えます。

10.2.2. ディスクに直接書込み

ディスクイメージファイル "disk.img" はdd(1) を使ってサイズがマッチする例えば "/dev/sdb" という2番目の SCSI ドライブに次のようにして書き込むことができます。

# dd if=disk.img of=/dev/sdb

同様にディスクパーティションイメージファイル "partition.img" はサイズがマッチする例えば "/dev/sdb1" という2番目の SCSI ドライブの1番目のパーティションに次のようにして書き込むことができます。

# dd if=partition.img of=/dev/sdb1

10.2.3. ディスクイメージファイルをマウント

単一パーティションイメージを含むディスクイメージ "partition.img" は次のように loop デバイスを使いマウントしアンマウントできます。

# losetup -v -f partition.img
Loop device is /dev/loop0
# mkdir -p /mnt/loop0
# mount -t auto /dev/loop0 /mnt/loop0
...hack...hack...hack
# umount /dev/loop0
# losetup -d /dev/loop0

これは以下のように簡略化出来ます。

# mkdir -p /mnt/loop0
# mount -t auto -o loop partition.img /mnt/loop0
...hack...hack...hack
# umount partition.img

複数のパーティションを含むディスクイメージ "disk.img" の各パーティションは loop デバイスを使ってマウント出来ます。loop デバイスはパーティションをデフォルトでは管理しないので、次のようにそれをリセットする必要があります。

# modinfo -p loop # verify kernel capability
max_part:Maximum number of partitions per loop device
max_loop:Maximum number of loop devices
# losetup -a # verify nothing using the loop device
# rmmod loop
# modprobe loop max_part=16

これで、loop デバイスは16パーティションまで管理出来ます。

# losetup -v -f disk.img
Loop device is /dev/loop0
# fdisk -l /dev/loop0

Disk /dev/loop0: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x452b6464

      Device Boot      Start         End      Blocks   Id  System
/dev/loop0p1               1         600     4819468+  83  Linux
/dev/loop0p2             601         652      417690   83  Linux
# mkdir -p /mnt/loop0p1
# mount -t ext3 /dev/loop0p1 /mnt/loop0p1
# mkdir -p /mnt/loop0p2
# mount -t ext3 /dev/loop0p2 /mnt/loop0p2
...hack...hack...hack
# umount /dev/loop0p1
# umount /dev/loop0p2
# losetup -d /dev/loop0

この他、同様の効果は kpartx パッケージの kpartx(8) により作られるデバイスマッパーデバイスを用いて次のようにして実現も出来ます。

# kpartx -a -v disk.img
...
# mkdir -p /mnt/loop0p2
# mount -t ext3 /dev/mapper/loop0p2 /mnt/loop0p2
...
...hack...hack...hack
# umount /dev/mapper/loop0p2
...
# kpartx -d /mnt/loop0
[注記] 注記

MBR 等をスキップするオフセットを使った loop デバイスによっても、このようなディスクイメージの単一パーティションをマウント出来ます。しかしこれは失敗しがちです。

10.2.4. ディスクイメージのクリーニング

ディスクイメージファイル "disk.img" は消去済みのファイルを綺麗に無くした綺麗なスパースイメージ "new.img" に次のようにしてできます。

# mkdir old; mkdir new
# mount -t auto -o loop disk.img old
# dd bs=1 count=0 if=/dev/zero of=new.img seek=5G
# mount -t auto -o loop new.img new
# cd old
# cp -a --sparse=always ./ ../new/
# cd ..
# umount new.img
# umount disk.img

もし "disk.img" が ext2 か ext3 の場合には、zerofree パッケージの zerofree(8) を使うことも出来ます。

# losetup -f -v disk.img
Loop device is /dev/loop3
# zerofree /dev/loop3
# cp --sparse=always disk.img new.img

10.2.5. 空のディスクイメージ作成

5GiB まで成長可能な空のディスクイメージファイル "disk.img" はdd(1) と mke2fs(8) を使って次のようにして作成できます。

$ dd bs=1 count=0 if=/dev/zero of=disk.img seek=5G

loop デバイスを使ってこのディスクイメージ "disk.img" 上に ext3 ファイルシステムを作成できます。

# losetup -f -v disk.img
Loop device is /dev/loop1
# mkfs.ext3 /dev/loop1
...hack...hack...hack
# losetup -d /dev/loop1
$ du  --apparent-size -h disk.img
5.0G  disk.img
$ du -h disk.img
83M disk.img

"sparse" に関して、そのファイルサイズは 5.0GiB でその実ディスク使用はたったの 83MiB です。この相違は ext2fsスパースファイルを保持できるから可能となっています。

[ティップ] ティップ

スパースファイルによる実際のディスク使用はそこに書かれるデーターとともに成長します。

「ディスクイメージファイルをマウント」にあるように loop デバイスまたはデバイスマッパーデバイスによりデバイスに同様の操作をすることで、このディスクイメージ "disk.img" をparted(8) または fdisk(8) を使ってパーティションし mkfs.ext3(8) や mkswap(8) 等を使ってファイルシステムを作れます。

10.2.6. ISO9660 イメージファイル作成

"source_directory" のソースディレクトリーツリーから作られる ISO9660 イメージファイル"cd.iso" はcdrkit が提供する genisoimage(1) を使って次のようにして作成できます。

#  genisoimage -r -J -T -V volume_id -o cd.iso source_directory

同様に、ブート可能な ISO9660 イメージファイル "cdboot.iso" は、debian-installer のような "source_directory" にあるディレクトリーツリーから次のようにして作成できます。

#  genisoimage -r -o cdboot.iso -V volume_id \
   -b isolinux/isolinux.bin -c isolinux/boot.cat \
   -no-emul-boot -boot-load-size 4 -boot-info-table source_directory

上記では、Isolinux ブートローダー (「2段目: ブートローダー」参照) がブートに使われています。

次のようにすると CD-ROM デバイスから直接 md5sum 値を計算し ISO9660 イメージを作成できます。

$ isoinfo -d -i /dev/cdrom
CD-ROM is in ISO 9660 format
...
Logical block size is: 2048
Volume size is: 23150592
...
# dd if=/dev/cdrom bs=2048 count=23150592 conv=notrunc,noerror | md5sum
# dd if=/dev/cdrom bs=2048 count=23150592 conv=notrunc,noerror > cd.iso
[警告] 警告

正しい結果を得るために上記のように Linux の ISO9660 ファイルシステム先読みバグを注意深く避けなければいけません。

10.2.7. CD/DVD-R/RW に直接書込み

[ティップ] ティップ

DVD は、cdrkit が提供する wodim(1) にとっては単に大きな CD です。

使えるデバイスは次のようにするとみつかります。

# wodim --devices

そしてブランクの CD-R をドライブに挿入して、例えば "/dev/hda" というこのデバイスに ISO9660 イメージファイル "cd.iso" にwodim(1) を使って次のようにして書込みます。

# wodim -v -eject dev=/dev/hda cd.iso

もし CD-R ではなく CD-RW が使われている場合には、次を代わりに実行して下さい。

# wodim -v -eject blank=fast dev=/dev/hda cd.iso
[ティップ] ティップ

もしあなたのデスクトップシステムが CD を自動的にマウントする場合、wodim(1) を使う前に "sudo unmount /dev/hda" として CD をアンマウントします。

10.2.8. ISO9660 イメージファイルをマウント

もし "cd.iso" の内容が ISO9660 イメージの場合、次のようにするとそれを "/cdrom" に手動でマウントできます。

# mount -t iso9660 -o ro,loop cd.iso /cdrom
[ティップ] ティップ

現代的なデスクトップシステムではリムーバブルメディアを自動的にマウントします (「リムーバブルストレージデバイス」参照)。

10.3. バイナリーデーター

次に、ストレージメディア上のバイナリーデーターを直接操作することを論じます。「データー保存のティップ」も参照下さい。

10.3.1. バイナリーデーターの閲覧と編集

もっとも基本的なバイナリーファイルを閲覧方法は "od -t x1" コマンドを使うことです。

表10.7 バイナリーデーターを閲覧や編集するパッケージのリスト

パッケージ ポプコン サイズ 説明
coreutils * V:92, I:99 13828 ファイルをダンプする od(1) がある基本パッケージ (HEX, ASCII, OCTAL, …)
bsdmainutils * V:81, I:99 768 ファイルをダンプする hd(1) があるユーティリティーパッケージ (HEX, ASCII, OCTAL, …)
hexedit * V:0.3, I:1.9 108 バイナリーエディターとビューワー (HEX, ASCII)
bless * V:0.08, I:0.3 1232 フル機能の16進エディター (GNOME)
okteta * V:0.4, I:3 2528 フル機能の16進エディター (KDE4)
ncurses-hexedit * V:0.07, I:0.5 192 バイナリーエディターとビューワー (HEX, ASCII, EBCDIC)
lde * V:0.04, I:0.3 992 Linux ディスクエディター
beav * V:0.03, I:0.3 164 バイナリーエディターとビューワー (HEX, ASCII, EBCDIC, OCTAL, …)
hex * V:0.01, I:0.09 84 16進ダンプツール (日本語2バイトコードをサポート)

[ティップ] ティップ

HEX はが16の16進フォーマットです。OCTAL はが8の8進フォーマットです。ASCII (アスキー) は情報交換用アメリカ標準コードで、通常の英文テキストです。EBCDIC (エビシディック) は IBM メインフレームオペレーティングシステム上で使われる拡張二進化十進数互換コードです。

10.3.2. ディスクをマウントせずに操作

ディスクをマウントせずに読出しや書込みをするツールがあります。

表10.8 ディスクをマウントせずに操作するパッケージのリスト

パッケージ ポプコン サイズ 説明
mtools * V:4, I:42 408 MSDOS ファイルをマウントせずに使うツール
hfsutils * V:0.19, I:1.6 236 HFS や HFS+ ファイルをマウントせずに使うツール

10.3.3. データーの冗長性

Linux カーネルが提供するソフトウエアー RAID システムは高いレベルのストレージ信頼性を達成するためにカーネルのファイルシステムのレベルでデーターの冗長性を提供します。

アプリケーションプログラムレベルでストレージの高い信頼性を達成するようにデーター冗長性を付加するツールもあります。

表10.9 ファイルにデーターの冗長性を追加するツールのリスト

パッケージ ポプコン サイズ 説明
par2 * V:0.5, I:1.7 272 ファイルのチェックと修理のためのパリティーアーカイブセット
dvdisaster * V:0.14, I:0.7 1388 CD/DVD メディアのデーターロス/傷つき/老化の防止
dvbackup * V:0.01, I:0.09 544 MiniDV カメラレコーダを使うバックアップツール (rsbep(1) を提供)
vdmfec * V:0.00, I:0.02 88 前方エラー修正を使って失われたブロックの復元

10.3.4. データーファイルの復元と事故の証拠解析

データーファイルの復元と事故の証拠解析のツールがあります。

表10.10 データーファイルの復元と事故の証拠解析のリスト

パッケージ ポプコン サイズ 説明
testdisk * V:0.3, I:3 4620 パーティションのスキャンとディスク復元のためのユーティリティー
magicrescue * V:0.07, I:0.5 344 マジックバイトを探してファイルを復元するユーティリティー
scalpel * V:0.03, I:0.2 124 質素で高性能なファイル彫刻刀
myrescue * V:0.02, I:0.18 84 破壊したハードディスクからデーターを救出
recover * V:0.07, I:0.6 104 ext2 ファイルシステム上のファイルの削除復元ユーティリティー
e2undel * V:0.07, I:0.5 244 ext2 ファイルシステム上のファイルの削除復元ユーティリティー
ext3grep * V:0.08, I:0.6 300 ext3 ファイルシステム上のファイルの削除復元ヘルプツール
scrounge-ntfs * V:0.03, I:0.4 80 NTFS ファイルシステム上のデーター復元プログラム
gzrt * V:0.01, I:0.12 68 gzip 復元ツールキット
sleuthkit * V:0.13, I:0.7 540 証拠解析のためのツール (Sleuthkit)
autopsy * V:0.07, I:0.4 1372 SleuthKit のための GUI
foremost * V:0.11, I:0.8 140 データー復元のための証拠解析アプリケーション
guymager * V:0.00, I:0.02 688 Qt 使用の証拠解析用イメージ作成ソフト
tct * V:0.03, I:0.2 604 証拠解析関連ユーティリティー
dcfldd * V:0.03, I:0.2 124 証拠解析とセキュリティーのための dd の強化版
rdd * V:0.01, I:0.11 200 証拠解析のためのコピープログラム

10.3.5. 大きなファイルを小さなファイルに分割

単一ファイルでバックアップするにはデーターが大きすぎる場合、そのファイル内容を例えば 2000MiB の断片にしてバックアップし、それらの断片を後日マージしてオリジナルのファイルに戻せます。

$ split -b 2000m large_file
$ cat x* >large_file
[注意] 注意

名前がかち合わないように "x" で始まるファイル名のファイルが無いようにします。

10.3.6. ファイル内容の消去

ログファイルのようなファイルの内容を消去するためには、rm(1) を使ってファイルを消去しその後新しい空ファイルを作成することは止めましょう。コマンド実行間にファイルがアクセスされているかもしれないのがこの理由です。次のようにするのがファイル内容を消去する安全な方法です。

$ :>file_to_be_cleared

10.3.7. ダミーファイル

次のコマンドはダミーや空のファイルを作成します。

$ dd if=/dev/zero    of=5kb.file bs=1k count=5
$ dd if=/dev/urandom of=7mb.file bs=1M count=7
$ touch zero.file
$ : > alwayszero.file

次のファイルを見つかります。

  • "5kb.file" は5KB のゼロの連続です。
  • "7mb.file" は7MB のランダムなデーターです。
  • "zero.file" は0バイト長のファイルかもしれません。もしファイルが存在する時は、その mtime を更新しその内容と長さを保持します。
  • "alwayszero.file" は常に0バイト長ファイルです。もしファイルが存在する時は mtime を更新しファイル内容をリセットします。

10.3.8. ハードディスクの全消去

"/dev/sda" にある USB メモリースティック等のハードディスク類似デバイス全体のデーターを完全に消すいくつかの方法があります。

[注意] 注意

次のコマンドを実行する前にまず USB メモリースティックの場所を mount(8) を使ってチェックします。"/dev/sda" によって指し示されるデバイスは SCSI ハードディスクかも知れませんしあなたの全システムのあるシリアル ATA ハードディスクかも知れません。

次のようにしてデーターを0にリセットして全消去します。

# dd if=/dev/zero of=/dev/sda

次のようにしてランダムデーターを上書きして全消去します。

# dd if=/dev/urandom of=/dev/sda

次のようにしてランダムデーターを非常に効率的に上書きして全消去します。

# shred -v -n 1 /dev/sda

Debian インストーラ CD 等の多くのブート可能な Linux の CD のシェルから dd(1) が利用可能ですから、"/dev/hda" や "/dev/sda" 等のシステムハードディスクに対して同類のメディアから消去コマンドを実行することでインストールされたシステムを完全に消去することができます。

10.3.9. ハードディスク未使用部分の全消去

データーの消去はファイルシステムからアンリンクされているだけなので、例えば "/dev/sdb1" のようなハードディスク (USB メモリースティック) 上の使用されていない領域には消去されたデーター自身が含まれているかもしれません。これらに上書きすることで綺麗に消去できます。

# mount -t auto /dev/sdb1 /mnt/foo
# cd /mnt/foo
# dd if=/dev/zero of=junk
dd: writing to `junk': No space left on device
...
# sync
# umount /dev/sdb1
[警告] 警告

あなたの USB メモリースティックにとってはこれで通常十分です。でもこれは完璧ではありません。消去されたファイル名や属性はファイルシステム中に隠れて残っているかもしれません。

10.3.10. 削除されたがまだオープン中のファイルの復活法

ファイルをうっかり消去しても、そのファイルが何らかのアプリケーション (読出しか書込み) によって使われている限り、そのようなファイルを回復出来ます。

例えば、次を試してみて下さい:

$ echo foo > bar
$ less bar
$ ps aux | grep ' less[ ]'
bozo    4775  0.0  0.0  92200   884 pts/8    S+   00:18   0:00 less bar
$ rm bar
$ ls -l /proc/4775/fd | grep bar
lr-x------ 1 bozo bozo 64 2008-05-09 00:19 4 -> /home/bozo/bar (deleted)
$ cat /proc/4775/fd/4 >bar
$ ls -l
-rw-r--r-- 1 bozo bozo 4 2008-05-09 00:25 bar
$ cat bar
foo

この代わりに、(lsof パッケージがインストールされている時) もう一つのターミナルで次のように実行します。

$ ls -li bar
2228329 -rw-r--r-- 1 bozo bozo 4 2008-05-11 11:02 bar
$ lsof |grep bar|grep less
less 4775 bozo 4r REG 8,3 4 2228329 /home/bozo/bar
$ rm bar
$ lsof |grep bar|grep less
less 4775 bozo 4r REG 8,3 4 2228329 /home/bozo/bar (deleted)
$ cat /proc/4775/fd/4 >bar
$ ls -li bar
2228302 -rw-r--r-- 1 bozo bozo 4 2008-05-11 11:05 bar
$ cat bar
foo

10.3.11. 全てのハードリンクを検索

ハードリンクのあるファイルは "ls -li" を使って確認できます、

$ ls -li
total 0
2738405 -rw-r--r-- 1 root root 0 2008-09-15 20:21 bar
2738404 -rw-r--r-- 2 root root 0 2008-09-15 20:21 baz
2738404 -rw-r--r-- 2 root root 0 2008-09-15 20:21 foo

"baz" も "foo" もリンク数が "2" (>1) でハードリンクがある事を示しています。これらの inode 番号は共通の "2738404" です。これはこれらがハードリンクされた同じファイルということを意味します。ハードリンクされた全てのファイルを偶然うまく見つけられない場合は、それを例えば "2738404" という inode で次のようにして探せます。

# find /path/to/mount/point -xdev -inum 2738404

10.3.12. 見えないディスクスペースの消費

削除されたがオープンされたままのファイルは、通常の du(1) では見えませんが、ディスクスペースを消費します。これらは次のようにすればそのサイズとともにリストできます。

# lsof -s -X / |grep deleted

10.4. データーセキュリティーのインフラ

データーのセキュリティーのインフラはデーターの暗号化のツールとメッセージダイジェストのツールと署名ツールの組み合わせで提供されます。

表10.11 データーセキュリティーインフラツールのリスト

コマンド パッケージ ポプコン サイズ 説明
gpg(1) gnupg * V:43, I:99 5288 GNU プライバシーガード - OpenPGP 暗号化ト署名ツール
N/A gnupg-doc * I:1.1 4124 GNU プライバシガード文書
gpgv(1) gpgv * V:59, I:99 436 GNU プライバシガード - 署名確認ツール
paperkey(1) paperkey * V:0.01, I:0.10 88 OpenPGP の秘密キーから秘密の情報だけを抜粋
cryptsetup(8), … cryptsetup * V:3, I:5 1172 暗号化されたブロックデバイス (dm-crypt / LUKS) のためのユーティリティー
ecryptfs(7), … ecryptfs-utils * V:0.2, I:0.3 416 ecryptfs スタックドファイルシステム暗号化のためのユーティリティー
md5sum(1) coreutils * V:92, I:99 13828 MD5 メッセージダイジェストを計算やチェック
sha1sum(1) coreutils * V:92, I:99 13828 SHA1 メッセージダイジェストを計算やチェック
openssl(1ssl) openssl * V:56, I:91 2380 "openssl dgst" を使ってメッセージダイジェストを計算やチェック (OpenSSL)

Linux カーネルモジュール経由で自動的データー暗号化のインフラを実現する dm-cryptoecryptfs に関しては 「データー暗号化ティップ」を参照下さい。

10.4.1. Gnupg のためのキー管理

基本的なキー管理に関する GNU プライバシガードコマンドを次に記します。

表10.12 キー管理のための GNU プライバシガードコマンドのリスト

コマンド 説明
gpg --gen-key 新規キーの生成
gpg --gen-revoke my_user_ID my_user_ID に関するリボークキーを生成
gpg --edit-key user_ID インタラクティブにキーを編集、ヘルプは "help"
gpg -o file --exports 全てのキーをファイルにエクスポート
gpg --imports file 全てのキーをファイルからインポート
gpg --send-keys user_ID user_ID のキーをキーサーバーに送信
gpg --recv-keys user_ID user_ID のキーをキーサーバーから受信
gpg --list-keys user_ID user_ID のキーをリスト
gpg --list-sigs user_ID user_ID の署名をリスト
gpg --check-sigs user_ID user_ID の署名をチェック
gpg --fingerprint user_ID user_ID のフィンガープリントをチェック
gpg --refresh-keys ローカルキーリングをアップデート

トラストコードの意味を次に記します。

表10.13 トラストコードの意味のリスト

コード 信用の説明
- 所有者への信用未付与/未計算
e 信用計算に失敗
q 計算用の情報不十分
n このキーを信用不可
m スレスレの信用
f フルに信用
u 究極の信用

次のようにすると私のキー "1DD8D791" をポピュラーなキーサーバー "hkp://keys.gnupg.net" にアップロード出来ます。

$ gpg --keyserver hkp://keys.gnupg.net --send-keys 1DD8D791

"~/.gnupg/gpg.conf" (もしくは古い場所 "~/.gnupg/options") 中の良いデフォールトのキーサーバーの設定は次を含みます。

keyserver hkp://keys.gnupg.net

次によってキーサーバーから知らないキーが獲得できます。

$ gpg --list-sigs --with-colons | grep '^sig.*\[User ID not found\]' |\
  cut -d ':' -f 5| sort | uniq | xargs gpg --recv-keys

OpenPGP 公開キーサーバー (バージョン0.9.6以前) に2つ以上サブキーのあるキーを壊すバグがありました。新しい gnupg (>1.2.1-2) パッケージはこのような壊れたサブキーを取り扱えます。gpg(1) の"--repair-pks-subkey-bug" オプションの説明を参照下さい。

10.4.2. GnuPG をファイルに使用

基本的なキー管理に関する GNU プライバシガードコマンドを次に記します。

表10.14 ファイルに使用する GNU プライバシーガードコマンドのリスト

コマンド 説明
gpg -a -s file ファイルを ASCII 文字化した file.asc と署名
gpg --armor --sign file , ,
gpg --clearsign file メッセージをクリアサイン
gpg --clearsign file|mail foo@example.org foo@example.org にクリアサインされたメッセージをメールする
gpg --clearsign --not-dash-escaped patchfile パッチファイルをクリアサイン
gpg --verify file クリアサインされたファイルを確認
gpg -o file.sig -b file 署名を別ファイルで作成
gpg -o file.sig --detach-sig file , ,
gpg --verify file.sig file file.sig を使ってファイルを確認
gpg -o crypt_file.gpg -r name -e file file からバイナリー crypt_file.gpg への name 宛公開キー暗号化
gpg -o crypt_file.gpg --recipient name --encrypt file , ,
gpg -o crypt_file.asc -a -r name -e file file から ASCII 文字化された crypt_file.asc への name 宛公開キー暗号化
gpg -o crypt_file.gpg -c file file からバイナリー crypt_file.gpg への対称暗号化
gpg -o crypt_file.gpg --symmetric file , ,
gpg -o crypt_file.asc -a -c file file から ASCII 文字化された crypt_file.asc への対称暗号化
gpg -o file -d crypt_file.gpg -r name 暗号解読
gpg -o file --decrypt crypt_file.gpg , ,

10.4.3. Mutt で GnuPG を使用

インデックスメニュー上で "S" とすれば GnuPG が使えるようにしておきながら、遅い GnuPG が自動的に起動しないように "~/.muttrc" に次の内容を追加します。

macro index S ":toggle pgp_verify_sig\n"
set pgp_verify_sig=no

10.4.4. Vim で GnuPG を使用

gnupg のプラグインを使うと ".gpg" や ".asc" や ".ppg" というファイル拡張子のファイルに対して透過的に GnuPG を実行できます。

# aptitude install vim-scripts vim-addon-manager
$ vim-addons install gnupg

10.4.5. MD5 和

md5sum(1) はrfc1321 の方法を使ってダイジェストファイルを作成し各ファイルをそれで確認するユーティリティーを提供します。

$ md5sum foo bar >baz.md5
$ cat baz.md5
d3b07384d113edec49eaa6238ad5ff00  foo
c157a79031e1c40f85931829bc5fc552  bar
$ md5sum -c baz.md5
foo: OK
bar: OK
[注記] 注記

MD5 和の計算は GNU プライバシーガード (GnuPG) による暗号学的署名の計算より CPU への負荷がかかりません。通常、一番上のレベルのダイジェストファイルだけがデーターの整合性のために暗号学的に署名されます。

10.5. ソースコードマージツール

ソースコードをマージする多くのツールがあります。次のコマンドが著者の目に止まりました。

表10.15 ソースコードマージツールのリスト

コマンド パッケージ ポプコン サイズ 説明
diff(1) diff * V:68, I:85 36 1行ごとにファイルを比較
diff3(1) diff * V:68, I:85 36 1行ごとにファイルを比較やマージ
vimdiff(1) vim * V:15, I:33 1792 vim で2つのファイルを並べて比較
patch(1) patch * V:10, I:92 244 差分ファイルをオリジナルに適用
dpatch(1) dpatch * V:1.4, I:11 344 Debian パッケージのためにパッチのシリーズを管理
diffstat(1) diffstat * V:2, I:15 92 差分ファイルによる変化のヒストグラム作成
combinediff(1) patchutils * V:1.8, I:14 292 2つの積み重ねパッチから1つの合計パッチを生成
dehtmldiff(1) patchutils * V:1.8, I:14 292 HTML ページから差分ファイルを抽出
filterdiff(1) patchutils * V:1.8, I:14 292 差分ファイルから差分ファイルを抽出や削除
fixcvsdiff(1) patchutils * V:1.8, I:14 292 CVS により作成された patch(1) が誤解する差分ファイルを修正
flipdiff(1) patchutils * V:1.8, I:14 292 古い2つのパッチを交換
grepdiff(1) patchutils * V:1.8, I:14 292 正規表現にマッチするパッチによって変更されるファイルを表示
interdiff(1) patchutils * V:1.8, I:14 292 2つのユニファイド差分ファイル間の違いを表示
lsdiff(1) patchutils * V:1.8, I:14 292 どのファイルがパッチによって変更されるかを表示
recountdiff(1) patchutils * V:1.8, I:14 292 ユニファイドコンテキスト差分ファイルのカウントやオフセットを再計算
rediff(1) patchutils * V:1.8, I:14 292 手編集された差分ファイルのカウントやオフセットを再計算
splitdiff(1) patchutils * V:1.8, I:14 292 増分パッチの分離
unwrapdiff(1) patchutils * V:1.8, I:14 292 ワードラップされたパッチを復元
wiggle(1) wiggle * V:0.01, I:0.11 232 リジェクトされたパッチを適用
quilt(1) quilt * V:1.5, I:9 872 パッチのシリーズを管理
meld(1) meld * V:0.7, I:2 2576 ファイルを比較やマージ (GTK)
xxdiff(1) xxdiff * V:0.2, I:1.3 1352 ファイルを比較やマージ (プレーン X)
dirdiff(1) dirdiff * V:0.08, I:0.6 224 ディレクトリーツリー間で相違点の表示と変更のマージ
docdiff(1) docdiff * V:0.01, I:0.14 688 2つのファイルをワード毎/文字毎に比較
imediff2(1) imediff2 * V:0.02, I:0.10 76 対話型フルスクリーンの2方マージツール
makepatch(1) makepatch * V:0.01, I:0.17 148 拡張パッチファイルの生成
applypatch(1) makepatch * V:0.01, I:0.17 148 拡張パッチファイルの適用
wdiff(1) wdiff * V:1.6, I:14 1024 テキストファイル間のワードの相違表示

10.5.1. ソースファイル間の相違の抽出

ファイルの場所次第で次の手順のひとつに従うとふたつのソースファイル間の相違を抽出しユニファイド差分ファイル "file.patch0" か "file.patch1" を作成します。

$ diff -u file.old file.new > file.patch0
$ diff -u old/file new/file > file.patch1

10.5.2. ソースファイルに更新をマージ

差分ファイル (別名、パッチファイル) はプログラム更新を送るのに使われます。受け取った側はこの更新を別のファイルに次のようにして適用します。

$ patch -p0 file < file.patch0
$ patch -p1 file < file.patch1

10.5.3. 3方マージによる更新

3つのバージョンのソースコードがある場合、diff3(1) を使って効率的に3方マージを次のように実行できます。

$ diff3 -m file.mine file.old file.yours > file

10.6. バージョンコントロールシステム

Debian システム上のバージョンコントロールシステム (VCS) のまとめを次に記します。

[注記] 注記

VCS システムを今始めて学ぶ場合には、人気が出て来ている Git から学び出すことをお薦めします。

表10.16 バージョンコントロールシステムツールのリスト

パッケージ ポプコン サイズ ツール VCS タイプ コメント
cssc * V:0.00, I:0.04 2240 CSSC ローカル Unix SCCS のクローン (非推奨)
rcs * V:1.3, I:7 772 RCS ローカル "Unix SCCS の本来あるべき姿"
cvs * V:3, I:21 3660 CVS リモート リモート VCS の過去の標準
subversion * V:10, I:31 4288 Subversion リモート "良く出来た CVS"、新しいリモート VCS のデファクト標準
git * V:5, I:17 10632 Git 分散型 C で書かれた高速 DVCS (Linux カーネル他が利用)
mercurial * V:1.8, I:6 368 Mercurial 分散型 Python と一部 C で書かれた DVCS
bzr * V:1.1, I:3 16220 Bazaar 分散型 tla に影響され Python で書かれた DVCS (Ubuntu が使用)
darcs * V:0.19, I:1.4 9504 Darcs 分散型 パッチに関して賢い計算をする DVCS (遅い)
tla * V:0.17, I:1.4 932 GNU arch 分散型 主に Tom Lord による DVCS (歴史的)
monotone * V:0.04, I:0.3 5272 Monotone 分散型 C++ で書かれた DVCS
tkcvs * V:0.08, I:0.4 2476 CVS, … リモート VCS (CVS, Subversion, RCS) レポジトリーツリーの GUI 表示
gitk * V:0.8, I:4 900 Git 分散型 VCS (Git) レポジトリーツリーの GUI 表示

VCS はリビジョンコントロールシステム (RCS) とかソフトウエアー設定管理 (SCM) という別名もあります。

Git のような分散 VCS が最近一番人気のツールです。CVS や Subversion は既存のオープンソースプログラム活動に参加するのにまだ有用かもしれません。

Debian はDebian Alioth サービス経由でフリーの VCS サービスを提供します。それは実質的に全ての VCS をサポートします。その説明文書は http://wiki.debian.org/Alioth にあります。

[注意] 注意

git パッケージは DVCS ではない "GNU インタラクティブツール" です。lenny では、git パッケージは "GNU インタラクティブツール" で、git-core パッケージが DVCS でした。

VCS アーカイブへの共有アクセスを作るための基本が数点あります。

10.6.1. VCS コマンドの比較

次に全体像を提供するべく元来の VCS コマンドを極端に簡略化した比較を示します。典型的なコマンド文字列はオプションや引数が必要となるかもしれません。

表10.17 本来の VCS コマンドの比較

CVS Subversion Git 機能
cvs init svn create git init (ローカル) レポジトリーを作成
cvs login - - リモートレポジトリーにログイン
cvs co svn co git clone リモートレポジトリーをワーキングツリーとしてチェックアウト
cvs up svn up git pull リモートレポジトリーをマージしてワーキングツリーを更新
cvs add svn add git add . VCS にワーキングツリー中のファイルを追加
cvs rm svn rm git rm VCS からワーキングツリー中のファイルを削除
cvs ci svn ci - リモートレポジトリーに変更をコミット
- - git commit -a ローカルレポジトリーに変更をコミット
- - git push ローカルレポジトリーでリモートレポジトリーを更新
cvs status svn status git status VCS に対するワーキングツリーの状態を表示
cvs diff svn diff git diff diff <参照レポジトリー> <ワーキングツリー>
- - git repack -a -d; git prune ローカルレポジトリーを単一パックにリパック
tkcvs tkcvs gitk VCS レポジトリーツリーの GUI 表示

[注意] 注意

git サブコマンドを直接 "git-xyz" としてコマンドラインから起動するのは2006年初以来推奨されません。

[ティップ] ティップ

tkcvs(1) や gitk(1) 等の GUI ツールはファイルの変更履歴を追跡するのに本当に役立ちます。多くの公開アーカイブが彼らのレポジトリーの中を閲覧するための提供しているウェッブインターフェースもまた非常に有用です。

[ティップ] ティップ

Git はgit-cvsgit-svn パッケージを使って CVS や Subversion によって提供されるレポジトリー等の他の VCS レポジトリーを直接処理したり、ローカル変更のためのローカルレポジトリーを提供します。git for CVS users「Subversion レポジトリー用の Git」を参照下さい。

[ティップ] ティップ

CVS や Subversion に等価コマンドが無いコマンドが Git にあります: "fetch"、"rebase"、"cherry-pick"、…

10.7. CVS

次を参照下さい。

  • cvs(1)
  • "/usr/share/doc/cvs/html-cvsclient"
  • "/usr/share/doc/cvs/html-info"
  • "/usr/share/doc/cvsbook"
  • "info cvs"

10.7.1. CVS レポジトリーの設定

CVS レポジトリーへのコミットを "src" グループメンバに限定し許可し、CVS の管理を "staff" グループメンバに限定し許可するように次の設定をすることでうっかりミスを予防できます。

# cd /var/lib; umask 002; mkdir cvs
# export CVSROOT=/srv/cvs/project
# cd $CVSROOT
# chown root:src .
# chmod 2775 .
# cvs -d $CVSROOT init
# cd CVSROOT
# chown -R root:staff .
# chmod 2775 .
# touch val-tags
# chmod 664 history val-tags
# chown root:src history val-tags
[ティップ] ティップ

"$CVSROOT" ディレクトリーの所有者を "root:staff" とし、そのパーミッションを "3775" と変更すると新規プロジェクトの作成を制限できます。

10.7.2. CVS へのローカルアクセス

デフォールトの CVS レポジトリーは "$CVSROOT" で指示されます。次はローカルアクセスのための "$CVSROOT" を設定します。

$ export CVSROOT=/srv/cvs/project

10.7.3. pserver を使った CVS へのリモートアクセス

多くの公開 CVS サーバーはアカウント名 "anonymous" で pserver サービス経由の読出しのみアクセスを提供します。例えば、Debian ウェッブサイト内容は webwml プロジェクトは Debian alioth サービスでの CVS を使ってメンテされています。次はこの CVS レポジトリーへのリモートアクセスのための "$CVSROOT" を設定します。

$ export CVSROOT=:pserver:anonymous@cvs.alioth.debian.org:/cvsroot/webwml
$ cvs login
[注記] 注記

pserver は盗聴攻撃されやすくインセキュアーなので、書込みアクセスはサーバーの管理者によって通常無効にされています。

10.7.4. ssh を使った CVS へのリモートアクセス

次は SSH を使い webwml プロジェクトの CVS レポジトリーをリモートアクセスするために "$CVS_RSH" と "$CVSROOT" を設定します。

$ export CVS_RSH=ssh
$ export CVSROOT=:ext:account@cvs.alioth.debian.org:/cvs/webwml

リモートパスワードプロンプトを無くすのに SSH を使ったパブリックキー認証を使えます。

10.7.5. 新規ソースを CVS にインポート

"~/path/to/module1" で新規のローカルソースツリーの場所を作成。

$ mkdir -p ~/path/to/module1; cd ~/path/to/module1

"~/path/to/module1" の下の新規のローカルソースツリーを埋める。

次のパラメーターを使って CVS にインポートします。

  • モジュール名: "module1"
  • ベンダータグ: Main-branch (全ブランチへのタグ)
  • リリースタグ: Release-initial (特定リリースタグ)
$ cd ~/path/to/module1
$ cvs import -m "Start module1" module1 Main-branch Release-initial
$ rm -Rf . # optional

10.7.6. CVS レポジトリーのファイルパーミッション

CVS は現レポジトリーファイルを上書きせず他のファイルで置き換えます。だからレポジトリーディレクトリーへの書込みパーミッションはクリチカルです。"module1" という新規レポジトリーを "/srv/cvs/project" に作成の際毎に、必要ならこの条件を満たすために次を実行します。

# cd /srv/cvs/project
# chown -R root:src module1
# chmod -R ug+rwX   module1
# chmod    2775     module1

10.7.7. CVS のワークフロー

次に CVS を使う典型的なワークフローを記します。

"$CVSROOT" で指される CVS プロジェクトから得られる全てのモジュールを次のようにしてチェックします。

$ cvs rls
CVSROOT
module1
module2
...

"module1" をそのデフォールトディレクトリーの "./module1" に次のようにしてチェックアウトします。

$ cd ~/path/to
$ cvs co module1
$ cd module1

必要に応じ内容に変更を加える。

次のようにして "diff -u [repository] [local]" と等価を作成し変更をチェックします。

$ cvs diff -u

あるファイル "file_to_undo" をひどく壊したが他のファイルは大丈夫な事に気づきます。

次のようにして "file_to_undo" ファイルを CVS からのクリーンコピーで上書きします。

$ cvs up -C file_to_undo

次のようにして更新されたローカルソースツリーを CVS に保存します。

$ cvs ci -m "Describe change"

次のようにして "file_to_add" ファイルを作成し CVS に追加します。

$ vi file_to_add
$ cvs add file_to_add
$ cvs ci -m "Added file_to_add"

次のようにして CVS から最新バージョンをマージします。

$ cvs up -d

コンフリクトある変更を意味する "C filename" で始まる行に注意します。

".#filename.version" 中の変更されていないコードを探します。

コンフリクトある変更はファイル中の "<<<<<<<" や ">>>>>>>" を探索します。

必要に応じコンフリクト解消のためにファイルを編集します。

次のようにしてリリースタグ "Release-1" を追加します。

$ cvs ci -m "last commit for Release-1"
$ cvs tag Release-1

さらに編集します。

次のようにリリースタグ "Release-1" を削除します。

$ cvs tag -d Release-1

次のように CVS へ変更をチェックインします。

$ cvs ci -m "real last commit for Release-1"

リリースタグ "Release-1" を更新した CVS の main の HEAD に次のようにして再付加します。

$ cvs tag Release-1

次のようにして "Release-initial" タグによってで指定されるオリジナルのバージョンから、スティッキーブランチタグが "Release-initial-bugfixes" のブランチを作成し、"~/path/to/old" ディレクトリーにチェックアウトします。

$ cvs rtag -b -r Release-initial Release-initial-bugfixes module1
$ cd ~/path/to
$ cvs co -r Release-initial-bugfixes -d old module1
$ cd old
[ティップ] ティップ

ブランチポイントとして特定の日付を指定するには "-r Release-initial" の代わりに "-D 2005-12-20" (ISO 8601 日付フォーマット) を使います。

オリジナルバージョンに基づいたスティッキータグ "Release-initial-bugfixes" が付いているこのローカルのソースツリーで作業をします。

このブランチで一人で作業をします … 誰か他の人がこの "Release-initial-bugfixes" ブランチに合流するまで。

次のようにして必要に応じて新規ディレクトリーを作りながらこのブランチ上の他の人が変更したファイルと同期します。

$ cvs up -d

必要に応じコンフリクト解消のためにファイルを編集します。

次のように CVS へ変更をチェックインします。

$ cvs ci -m "checked into this branch"

次のようにしてスティッキータグを削除し ("-A")、キーワード展開せずに ("-kk")、main の HEAD (最新版) をつかってローカルのツリーを更新します。

$ cvs up -d -kk -A

次のようにしてキーワード展開せずに ("-kk")、"Release-initial-bugfixes" ブランチをマージしてローカルのツリー (内容 = main の HEAD) を更新します。

$ cvs up -d -kk -j Release-initial-bugfixes

エディターを使ってコンフリクト解消します。

次のように CVS へ変更をチェックインします。

$ cvs ci -m "merged Release-initial-bugfixes"

次のようにしてアーカイブを作成します。

$ cd ..
$ mv old old-module1-bugfixes
$ tar -cvzf old-module1-bugfixes.tar.gz old-module1-bugfixes
$ rm -rf old-module1-bugfixes
[ティップ] ティップ

"cvs up" コマンドには、新規ディレクトリー作成には "-d" オプションを、また空ディレクトリーの摘み取りには "-P" オプションを指定できます。

[ティップ] ティップ

"cvs co module1/subdir" とサブディレクトリーの名前を提供して、"module1" のサブディレクトリーだけをチェックアウトすることが出来ます。

表10.18 CVS コマンドの特記すべきオプション (cvs(1) の最初の引数として使用)

オプション 意味
-n 空実行、効果無し
-t 各段階の CVS 活動が分かるようにメッセージを表示

10.7.8. CVS から最新ファイル

CVS から最新ファイルを取り込むには、次のように "tomorrow" (明日) を使います:

$ cvs ex -D tomorrow module_name

10.7.9. CVS の管理運営

モジュールのエリアス "mx" を CVS プロジェクト (ローカルサーバー) に追加します。

$ export CVSROOT=/srv/cvs/project
$ cvs co CVSROOT/modules
$ cd CVSROOT
$ echo "mx -a module1" >>modules
$ cvs ci -m "Now mx is an alias for module1"
$ cvs release -d .

さて、CVS から "new" ディレクトリーに "module1" (エリアス: "mx") を次のようにしてチェックアウトします。

$ cvs co -d new mx
$ cd new
[注記] 注記

上記プロシージャを行うには、適切なファイルパーミッションが設定されているべきです。

10.7.10. CVS チェックアウトの実行ビット

CVS からファイルをチェックアウトする時に、その実行パーミッションビットは保持されます。

チェックアウトされた例えば "filename" ファイルで実行ビットの問題にあった際には、次のコマンドを使い CVS レポジトリー中のそのパーミッションを変更します。

# chmod ugo-x filename

10.8. Subversion

Subversion は旧来の CVS を置き換える最近の世代のバージョンコントロールシステムです。Subversion にはタグとブランチを除く CVS のほとんどの機能をあります。

Subversion のサーバーをセットアップするには、subversionlibapache2-svnsubversion-tools パッケージをインストールする必要があります。

10.8.1. Subversion レポジトリーの設定

現状の subversion パッケージはレポジトリーの設定はしないので手動で設定を行う必要があります。レポジトリーを置く可能な場所の1つは "/srv/svn/project" 中です。

ディレクトリーを次のように作成します。

# mkdir -p        /srv/svn/project

レポジトリーデーターベースを次のように作成します。

# svnadmin create /srv/svn/project

10.8.2. Apach2 サーバーの経由の Subversion アクセス

Apache2 サーバー経由で Subversion レポジトリーにアクセスするだけなら、レポジトリーを次に記すように WWW サーバーのみによって書込み可とするだけが必要です。

# chown -R www-data:www-data /srv/svn/project

ユーザー認証経由でレポジトリーにアクセス許可するために "/etc/apache2/mods-available/dav_svn.conf" 中の次の部分を追加 (もしくはアンコメント) します。

<Location /project>
  DAV svn
  SVNPath /srv/svn/project
  AuthType Basic
  AuthName "Subversion repository"
  AuthUserFile /etc/subversion/passwd
<LimitExcept GET PROPFIND OPTIONS REPORT>
    Require valid-user
</LimitExcept>
</Location>

次のコマンドでユーザー認証ファイルを作成します。

# htpasswd2 -c /etc/subversion/passwd some-username

Apach2 を再スタート

あなたの新規の Subversion レポジトリーは "http://localhost/project" と (ウェッブサーバーの URL が"http://example.com/" と仮定すると) "http://example.com/project" の URL にてアクセスできます。

10.8.3. グループによる Subversion へのローカルアクセス

次は Subversion レポジトリーを例えば project というグループによってローカルアクセス出きるようにする設定です。

# chmod  2775     /srv/svn/project
# chown -R root:src /srv/svn/project
# chmod -R ug+rwX   /srv/svn/project

あなたの新しい Subversion レポジトリーは、project グループに属するローカルユーザーにとって svn(1) から "file:///localhost/srv/svn/project" か "file:///srv/svn/project" の URL からグループアクセスできます。グループアクセスを確実にするために、svnsvnservesvnlooksvnadmin 等のコマンドを "umask 002" の下で実行しなければいけません。

10.8.4. グループによる Subversion への SSH 経由のリモートアクセス

SSH から "example.com:/srv/svn/project" の URL にあるグループアクセス可能な Subversion レポジトリーは、svn(1) を使って "svn+ssh://example.com:/srv/svn/project" にてアクセスできます。

10.8.5. Subversion ディレクトリー構造

Subversion のブランチやタグの機能を欠くことを補うべく、多くのプロジェクトは次と似たようなディレクトリーツリーを使っています。

  ----- module1
    |   |-- branches
    |   |-- tags
    |   |   |-- release-1.0
    |   |   `-- release-2.0
    |   |
    |   `-- trunk
    |       |-- file1
    |       |-- file2
    |       `-- file3
    |
    `-- module2
[ティップ] ティップ

ブランチやタグをマークするためには "svn copy …" コマンドを使わなければいけません。こうすることで Subversion がファイルの変更履歴を適正な記録を確実にするとともに記録容量を節約できます。

10.8.6. 新規ソースを Subversion にインポート

"~/path/to/module1" で新規のローカルソースツリーの場所を作成。

$ mkdir -p ~/path/to/module1; cd ~/path/to/module1

"~/path/to/module1" の下の新規のローカルソースツリーを埋める。

ソースを次のパラメーターを使って Subversion にインポートします。

  • モジュール名: "module1"
  • Subversion サイトの URL: "file:///srv/svn/project",
  • Subversion ディレクトリー: "module1/trunk":
  • Subversion タグ: "module1/tags/Release-initial"
$ cd ~/path/to/module1
$ svn import file:///srv/svn/project/module1/trunk -m "Start module1"
$ svn cp file:///srv/svn/project/module1/trunk file:///srv/svn/project/module1/tags/Release-initial

この代わりに、次のようにも出来ます。

$ svn import ~/path/to/module1 file:///srv/svn/project/module1/trunk -m "Start module1"
$ svn cp file:///srv/svn/project/module1/trunk file:///srv/svn/project/module1/tags/Release-initial
[ティップ] ティップ

"file:///…" といった URL は、"http://…" や "svn+ssh://…" といったいかなる他形式の URL ででも置き換えられます。

10.8.7. Subversion のワークフロー

次に Subversion をその本来のクライアントとともに使う典型的なワークフローを記します。

[ティップ] ティップ

git-svn パッケージによって提供されるクライアントコマンドは git コマンドを使う Subversion の代替ワークフローを提供します。「Subversion レポジトリー用の Git」を参照下さい。

"file:///srv/svn/project" の URL で指定される Subversion プロジェクトから得られる全てのモジュールを次のようにしてチェックします。

$ svn list file:///srv/svn/project
module1
module2
...

次のようにして "module1/trunk" を"module1" ディレクトリーにチェックアウトします。

$ cd ~/path/to
$ svn co file:///srv/svn/project/module1/trunk module1
$ cd module1

必要に応じ内容に変更を加える。

次のようにして "diff -u [repository] [local]" と等価を作成し変更をチェックします。

$ svn diff

あるファイル "file_to_undo" をひどく壊したが他のファイルは大丈夫な事に気づきます。

次のようにして "file_to_undo" ファイルを Subversion からのクリーンコピーで上書きします。

$ svn revert file_to_undo

更新されたローカルソースツリーを次のようにして Subversion に保存します。

$ svn ci -m "Describe change"

次のようにして "file_to_add" ファイルを作成し Subversion に追加します。

$ vi file_to_add
$ svn add file_to_add
$ svn ci -m "Added file_to_add"

次のようにして Subversion から最新バージョンをマージします。

$ svn up

コンフリクトある変更を意味する "C filename" で始まる行に注意します。

"filename.r6" と "filename.r9" と "filename.mine" 等中の変更されていないコードを探します。

コンフリクトある変更はファイル中の "<<<<<<<" や ">>>>>>>" を探索します。

必要に応じコンフリクト解消のためにファイルを編集します。

次のようにしてリリースタグ "Release-1" を追加します。

$ svn ci -m "last commit for Release-1"
$ svn cp file:///srv/svn/project/module1/trunk file:///srv/svn/project/module1/tags/Release-1

さらに編集します。

次のようにリリースタグ "Release-1" を削除します。

$ svn rm file:///srv/svn/project/module1/tags/Release-1

次のようにして変更を Subversion にチェックインします。

$ svn ci -m "real last commit for Release-1"

リリースタグ "Release-1" を更新した Subversion の trunk の HEAD に再付加します。

$ svn cp file:///srv/svn/project/module1/trunk file:///srv/svn/project/module1/tags/Release-1

次のようにして "module1/tags/Release-initial" というパスで指定されるオリジナルのバージョンから、パスが "module1/branches/Release-initial-bugfixes" のブランチを作成し、"~/path/to/old" ディレクトリーにチェックアウトします。

$ svn cp file:///srv/svn/project/module1/tags/Release-initial file:///srv/svn/project/module1/branches/Release-initial-bugfixes
$ cd ~/path/to
$ svn co file:///srv/svn/project/module1/branches/Release-initial-bugfixes old
$ cd old
[ティップ] ティップ

ブランチポイントとして特定の日付を指定するには "module1/tags/Release-initial" の代わりに "module1/trunk@{2005-12-20}" (ISO 8601 日付フォーマット) を使います。

オリジナルバージョンに基づいたブランチ "Release-initial-bugfixes" を指定しているローカルのソースツリーで作業します。

このブランチで一人で作業をします … 誰か他の人がこの "Release-initial-bugfixes" ブランチに合流するまで。

次のようにしてこのブランチ上の他の人が変更したファイルと同期します。

$ svn up

必要に応じコンフリクト解消のためにファイルを編集します。

次のようにして変更を Subversion にチェックインします。

$ svn ci -m "checked into this branch"

trunk の HEAD を使って次のようにローカルツリーを更新します。

$ svn switch file:///srv/svn/project/module1/trunk

次のようにして "Release-initial-bugfixes" ブランチをマージしてローカルのツリー (内容 = trunk の HEAD) を更新します。

$ svn merge file:///srv/svn/project/module1/branches/Release-initial-bugfixes

エディターを使ってコンフリクト解消します。

次のようにして変更を Subversion にチェックインします。

$ svn ci -m "merged Release-initial-bugfixes"

次のようにしてアーカイブを作成します。

$ cd ..
$ mv old old-module1-bugfixes
$ tar -cvzf old-module1-bugfixes.tar.gz old-module1-bugfixes
$ rm -rf old-module1-bugfixes
[ティップ] ティップ

"file:///…" といった URL は、"http://…" や "svn+ssh://…" といったいかなる他形式の URL ででも置き換えられます。

[ティップ] ティップ

"svn co file:///srv/svn/project/module1/trunk/subdir module1/subdir" とサブディレクトリーの名前を提供して、"module1" のサブディレクトリーだけをチェックアウトすることが出来ます。

表10.19 Subversion コマンドの特記すべきオプション (svn(1) の最初の引数として使用)

オプション 意味
--dry-run 空実行、効果無し
-v svn 活動の詳細なメッセージを表示

10.9. Git

Git はローカルとリモートのソースコード管理の全機能があります。これはリモートレポジトリーとのネットワーク接続なしにソースコードへの変更を記録できるといことです。

10.9.1. Git クライアントの設定

Git は使うあなたの名前や email アドレス等を "~/.gitconfig" 中のいくつかのグローバル設定に設定したいなら次のようにします。

$ git config --global user.name "Name Surname"
$ git config --global user.email yourname@example.com

もしあなたが CVS や Subversion コマンドに慣れ過ぎている場合には、いくつかのコマンドエリアスの設定を次のようにするのも一計です。

$ git config --global alias.ci "commit -a"
$ git config --global alias.co checkout

あなたのグローバル設定は次のようにするとチェックできます。

$ git config --global --list

10.9.2. Git リファレンス

次を参照下さい。

git-gui(1) と gitk(1) コマンドは簡単に Git が利用出来るようにします。

[警告] 警告

たとえ gitk(1) 等の一部ツールが受け付けるからといって、タグ文字列中にスペースを使ってはいけません。他の git コマンドで支障が起こるかもしれません。

10.9.3. Git コマンド

アップストリームが異なる VCS を使っていようと、アップストリームへのネットワーク接続無しにローカルコピーを管理できるので、ローカル活動に git(1) を使うのは良い考えかもしれません。次は git(1) とともに使われるパッケージとコマンドのリストです。

表10.20 git 関連のパッケージとコマンドのリスト

コマンド パッケージ ポプコン サイズ 説明
N/A git-doc * I:3 7436 正式 Git 文書
N/A gitmagic * I:0.3 920 "Git マジック"、Git に関する分かり易いガイド
git(7) git * V:5, I:17 10632 git: 高速、スケーラブル、分散型リビジョンコントロールシステム
gitk(1) gitk * V:0.8, I:4 900 GUI による履歴付き Git レポジトリーブラウザー
git-gui(1) git-gui * V:0.3, I:2 1612 Git 用の GUI (履歴無し)
git-svnimport(1) git-svn * V:0.5, I:3 552 Subversion から Git へのデーターのインポート
git-svn(1) git-svn * V:0.5, I:3 552 Subversion と Git 間での双方向操作を提供
git-cvsimport(1) git-cvs * V:0.17, I:1.6 676 CVS から Git へのデーターのインポート
git-cvsexportcommit(1) git-cvs * V:0.17, I:1.6 676 Git から CVS チェックアウトに1コミットエキスポート
git-cvsserver(1) git-cvs * V:0.17, I:1.6 676 Git 用 CVS サーバーエミュレーター
git-send-email(1) git-email * V:0.12, I:1.7 404 Git からパッチの集合の email として送信
stg(1) stgit * V:0.07, I:0.7 1864 Git 上の quilt (Python)
git-buildpackage(1) git-buildpackage * V:0.2, I:1.1 596 Git を使って Debian パッケージ化を自動化
guilt(7) guilt * V:0.01, I:0.11 336 Git 上の quilt (SH/AWK/SED/…)

[ティップ] ティップ

git(1) では、多くのコミットをしながらローカルブランチ上で仕事をして "git rebase -i master" 等を使って後から変更履歴を整理します。こうすると綺麗な変更履歴が作れます。git-rebase(1) と git-cherry-pick(1) を参照下さい。

[ティップ] ティップ

作業中のディレクトリの現状を失わずにクリーンな作業ディレクトリを取り戻すには "git stash" を使えばできます。git-stash(1) を参照ください。

10.9.4. Subversion レポジトリー用の Git

"svn+ssh://svn.example.org/project/module/trunk" にある Subversion のレポジトリを "./dest" にあるローカルの Git レポジトリにチェックアウトでき、また Subversion レポジトリに戻すコミットができます。例えば:

$ git svn clone -s -rHEAD svn+ssh://svn.example.org/project dest
$ cd dest
... make changes
$ git commit -a
... keep working locally with git
$ git svn dcommit
[ティップ] ティップ

"-rHEAD" を使うことにより Subversion のレポジトリから過去の全コンテントを複製することが避けられます。

10.9.5. 設定履歴記録のための Git

Git ツールを使い設定の経時履歴をマニュアルで記録できます。次は "/etc/apt/" の内容を記録する単純な練習例です。

$ cd /etc/apt/
$ sudo git init
$ sudo chmod 700 .git
$ sudo git add .
$ sudo git commit -a

設定を説明とともにコミットします。

設定ファイルへの変更をします。

$ cd /etc/apt/
$ sudo git commit -a

設定を説明とともにコミットしそのままいろいろ作業をしていきます。

$ cd /etc/apt/
$ sudo gitk --all

フルの履歴を手中しています。

[注記] 注記

設定データーのどのファイルパーミッションでも機能するためには sudo(8) が必要です。ユーザーの設定データーの場合 sudo をスキップ出来るかもしれません。

[注記] 注記

上記例での "chmod 700 .git" コマンドはアーカイブデーターを不正読出しアクセスから守るために必要です。

[ティップ] ティップ

設定履歴の記録に関するより完全なセットアップは、etckeeper パッケージを見て下さい: 「設定ファイルの変更記録」