第10章 データー管理

# 第10章 データー管理

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

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

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

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

- データーアーカイブの作成

- 遠隔ストレージアクセス

- 複製

- 変更履歴の追跡

- データー共有のアシスト

- 不正なファイルへのアクセスの防止

- 不正なファイルの改変の検出

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

- アーカイブと圧縮ツール

- コピーと同期ツール

- ネットワークファイルシステム

- リムーバブルストレージメディア

- セキュアーシェル

- 認証システム

- バージョンコントロールシステムツール

- ハッシュや暗号学的暗号化ツール

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

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

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

パッケージ | ポプコン | サイズ | 拡張子 | コマンド | コメント
--- | --- | --- | --- | --- | ---
`tar` | V:908, I:1000 | 3085 | `.tar` | tar(1) | 標準アーカイバー (デファクト標準)
`cpio` | V:352, I:999 | 1201 | `.cpio` | cpio(1) | Unix System V スタイルのアーカイバー、find(1) とともに使用
`binutils` | V:190, I:640 | 1119 | `.ar` | ar(1) | 静的ライブラリー生成用のアーカイバー
`fastjar` | V:1.0, I:9.6 | 182 | `.jar` | fastjar(1) | Java 用のアーカイバー (zip 類似)
`pax` | V:5.5, I:9.6 | 167 | `.pax` | pax(1) | 新規 POSIX 標準アーカイバー、`tar` と `cpio` の間の妥協点
`gzip` | V:904, I:1000 | 256 | `.gz` | gzip(1), zcat(1), … | GNU LZ77 圧縮ユーティリティー (デファクト標準)
`bzip2` | V:163, I:972 | 113 | `.bz2` | bzip2(1), bzcat(1), … | gzip(1) より高い圧縮比 (`gzip` より遅い、類似シンタックス) の Burrows-Wheeler ブロック並び替え圧縮ユーティリティー
`lzma` | V:1, I:10 | 349 | `.lzma` | lzma(1) | gzip(1) より高い圧縮比の LZMA 圧縮ユーティリティー (非推奨)
`xz-utils` | V:318, I:982 | 1520 | `.xz` | xz(1), xzdec(1), … | bzip2(1) より高い圧縮比の XZ 圧縮ユーティリティー (`gzip` より遅いが `bzip2` より早い、LZMA 圧縮ユーティリティーの代替)
`zstd` | V:318, I:803 | 2309 | `.zstd` | zstd(1), zstdcat(1), … | Zstandard 高速ロスレス圧縮ユーティリティー
`p7zip` | V:6, I:198 | 8 | `.7z` | 7zr(1), p7zip(1) | 高い圧縮比をもつ 7-Zip 圧縮ユーティリティー (LZMA 圧縮)
`p7zip-full` | V:20, I:222 | 12 | `.7z` | 7z(1), 7za(1) | 高い圧縮比をもつ 7-Zip 圧縮ユーティリティー (LZMA 圧縮、他)
`lzop` | V:12, I:134 | 164 | `.lzo` | lzop(1) | gzip(1) より高い圧縮と解凍の速度 (`gzip` より低い圧縮比、類似シンタックス) の LZO 圧縮ユーティリティー
`zip` | V:49, I:361 | 627 | `.zip` | zip(1) | InfoZIP: DOS アーカイブと圧縮ツール
`unzip` | V:110, I:749 | 387 | `.zip` | unzip(1) | InfoZIP: DOS アーカイブ解凍と圧縮解凍ツール

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

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

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

- tar(1) 等の FOSS ツールでのポピュラーな圧縮方法は以下のように変遷しています: `gzip` → `bzip2` → `xz`

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

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

- Libreoffice データーファイルの内部構造は "`.jar`" ファイルで、`unzip` で開くことができます。

- デファクトのクロスプラットフォームのアーカイブツールは `zip` です。最大限のコンパチビリティーのためには "`zip -rX`" として使って下さい。もし最大ファイルサイズが問題となる際には "`-s`" オプションも使って下さい。

### 10.1.2. コピーと同期ツール

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

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

パッケージ | ポプコン | サイズ | ツール | 機能
--- | --- | --- | --- | ---
`coreutils` | V:911, I:1000 | 17994 | GNU cp | ファイルやディレクトリーのローカルコピー ("-a" で再帰的実行)
`openssh-client` | V:915, I:996 | 4210 | scp | ファイルやディレクトリーのリモートコピー (クライアント、"`-r`" で再帰実行)
`openssh-server` | V:768, I:819 | 3359 | sshd | ファイルやディレクトリーのリモートコピー (リモートサーバー)
`rsync` | V:195, I:541 | 835 |  | 単方向リモート同期とバックアップ
`unison` | V:3, I:12 | 14 |  | 双方向リモート同期とバックアップ

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

- 転送元のファイルと転送先の既存ファイル間の相違のみを送信する差分転送アルゴリズム

- サイズか最終変更時間に変更があったファイルのみを探す (デフォルトで採用される) 急速確認アルゴリズム

- tar(1) 類似の "`--exclude`" や "`--exclude-from`" オプション

- 転送先に追加ディレクトリーレベルを作成しなくする「転送元ディレクトリ後スラシュ (/) 付加」文法

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

### 10.1.3. アーカイブの慣用句

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

GNU tar(1):

    $ tar -cvJf archive.tar.xz ./source
    $ tar -xvJf archive.tar.xz

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

    $ find ./source -xdev -print0 | tar -cvJf archive.tar.xz --null -T -

cpio(1):

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

### 10.1.4. コピーの慣用句

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

- ローカルコピー: "`./source`" ディレクトリー → "`/dest`" ディレクトリー

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

rsync(8):

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

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

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

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

    # cd ./source; find . -print0 | rsync -aHAXSv0 --files-from=- . /dest
    # cd ./source; find . -print0 | rsync -aHAXSv0 --files-from=- . 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

"`.`" を含むすべての例で "`.`" は"`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)

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

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

アーカイブやコピーコマンド (「アーカイブの慣用句」と「コピーの慣用句」を参照下さい) のためや xargs(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 ".*\.cpio|.*~" -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. 正規表現 "`.*\.cpio`" か "`.*~`" にマッチするファイルを処理停止をすることで探索から除外

4. 正規表現 "`.*/\.git`" にマッチするディレクトリーを処理停止をすることで探索から除外

5. 9MiB(1048576バイトの単位) より大きいファイルを処理停止をすることで探索から除外

6. 上記の探索条件に合致し "`/path/to/timestamp`" より新しいファイル名をプリントします

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

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

### 10.1.6. アーカイブメディア

重要なデーターアーカイブのためのコンピューターデーターストレージメディアを選ぶ時にはそれらの限界について注意を払うべきです。小さな個人的なバックアップのためには、著者としては名前が知られている会社の 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回しか書けないので、本質的に重ね書きで間違ってデーターを消すことを防げます。これは、利点です!

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

| ヒント
もし書き換え可能なメディアをバックアップに使っている場合には、 リードオンリーのスナップショットをサポートする btrfs や zfs のようなファイルシステムを使うのも一策です。

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

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

- USB フラッシュドライブ

- Hard ディスクドライブ

- 光学ディスクドライブ

- デジタルカメラ

- デジタル音楽プレーヤー

これらは以下の何れかで接続できます。

- USB

- IEEE 1394 / FireWire

- PC カード

GNOME や KDE のような最近のデスクトップ環境は、"`/etc/fstab`" エントリーにマッチが無いリムーバブルデバイスを自動的にマウントする事ができます。

- `udisks2` パッケージは、これらのデバイスをマウントやアンマウントするためのデーモンと関連するユーティリティーを提供します。

- D-bus は、自動的なプロセスを開始するイベントを作成します。

- PolicyKit が必要な特権を提供します。

| ヒント
自動的にマウントされたデバイスは、umount(8) によって利用される "`uhelper=`" マウントオプションが設定されているかもしれません。

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

最新のデスクトップ環境下では以下のようにしてカスタマイズ可能なマウント点として "`/media/username/disk_label`" が選ばれます。

- FAT ファイルシステムでは、mlabel(1) を使います。

- ISO9660 ファイルシステムでは、genisoimage(1) を"`-V`" オプションとともに使います。

- ext2/ext3/ext4 ファイルシステムでは、tune2fs(1) を"`-L`" オプションとともに使います。

| ヒント
符号化方式 (エンコーディング) の選択をマウントオプションとして与える必要があるかもしれません (「ファイル名の符号化方式」を参照下さい)。

| ヒント
ファイルシステムをアンマウントする際に GUI メニューを使うと、動的に生成された "`/dev/sdc`" 等のデバイスノード削除するかもしれません。もしそのデバイスノードの削除したくない場合にはシェルのコマンドプロンプトから umount(8) コマンドを使いアンマウントします。

### 10.1.8. データー共有用のファイルシステム選択

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

| 注記
ハードディスク (HDD) に関する文言は、SSD / USB フラッシュデバイス / メモリーカード /... のようなストレージデバイスのような他のストレージデバイスにも適用できます。例中の`/dev/sda` のようなデバイス名は、該当するデバイス名 `/dev/nvme0`, `/dev/mmcblk0`, ... に置き換えます。

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

ファイルシステム名 | 典型的使用シナリオ
--- | ---
FAT12 | フロッピーディスク上のクロスプラットフォームのデーター共有 (<32MiB)
FAT16 | 小さなハードディスク類似のデバイス上のクロスプラットフォームのデーター共有 (<2GiB)
FAT32 | 大きなハードディスク類似のデバイス上のクロスプラットフォームのデーター共有 (<8TiB, MS Windows95 OSR2 以降でサポート有り)
exFAT | 大きなハードディスク類似のデバイス上のクロスプラットフォームのデーター共有 (<512TiB, WindowsXPとMac OS X Snow Leopard 10.6.5とLinux kernel 5.4 リリース以降でサポート有り)
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 システムとハードディスク類似デバイス上のデーターを共有
ext4 | 現行の Linux システムとハードディスク類似デバイス上のデーターを共有
btrfs | 現行の 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) を使ってアーカイブファイルに最初にファイルをアーカイブすることで長いファイル名やシンボリックリンクやオリジナルの 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 では ext4 ファイルシステムを普通使うべきです。

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

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

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

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

ネットワークサービス | 典型的使用シナリオの説明
--- | ---
Samba を使う SMB/CIFS ネットワーク経由マウントファイルシステム | "Microsoft Windows Network" 経由でのファイル共有、smb.conf(5) と The Official Samba 3.x.x HOWTO and Reference Guide か `samba-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.2. バックアップと復元

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

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

### 10.2.1. バックアップと復元のポリシー

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

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

   - あなた自身が作成したデーターファイル: "`~/`" 中のデーター

   - あなた自身が使用したアプリケーションが作成したデーターファイル: "`/var/`" ("`/var/cache/`" と "`/var/run/`" と "`/var/tmp/`" は除外) 中のデーター

   - システム設定ファイル: "`/etc/`" 中のデーター

   - ローカル プログラム: "`/usr/local/`" とか "`/opt/`" 中のデーター

   - システムインストール情報: 要点 (パーティション、…) をプレーンテキストで書いたメモ

   - 実証済みのデーターセット: 事前の実験復元操作で確認

     - ユーザープロセスでの cron ジョブ: "`/var/spool/cron/crontabs`" ディレクトリー中のファイルと cron(8) の再スタート。cron(8) と crontab(1) に関しては「タスク定期実行のスケジュール」を参照下さい。

     - ユーザープロセスでの systemd タイマージョブ: "`~/.config/systemd/user` ディレクトリー中のファイル。systemd.timer(5) や systemd.service(5) を参照下さい。

     - ユーザープロセスでの自動スタートジョブ: "`~/.config/autostart`" ディレクトリー中のファイル。Desktop Application Autostart Specification を参照下さい。

2. バックアップと復元の方法を知っていること

   - セキュアーなデーターのストレージ: 上書きやシステム障害の防止

   - 頻繁なバックアップ: スケジュールされたバックアップ

   - 冗長なバックアップ: データーのミラーリング

   - フルプルーフなプロセス: 簡単な単一コマンドバックアップ

3. 関わっているリスクと費用の評価

   - データー消失時のリスク

     - データーはファイルシステム破壊に耐えるように、できれば異なるディスクやマシン上の、最低限異なるディスクパーティション上に置くべきです。重要データーは読み取り専用ファイルシステムに保存するのが好ましい。[4]

   - データ侵害の際のデーターのリスク

     - "`/etc/ssh/ssh_host_*_key`" や "`~/.gnupg/*`" や "`~/.ssh/*`" や "`/etc/passwd`" や "`/etc/shadow`" や "`/etc/fetchmailrc`" や "`popularity-contest.conf`" や "`/etc/ppp/pap-secrets`" や "`/etc/exim4/passwd.client`" 等の慎重に扱うべきアイデンティティ関連のデーターファイルは暗号化してバックアップする必要があります。[5] (「データー暗号化ティップ」を参照下さい。)

     - たとえ信頼できるシステム上でも、システムの login パスワードや暗号化解除パスフレーズは、いかなるスクリプト中にもハードコードしてはいけません。(「パスワード キーリング」を参照下さい。)

   - 故障モードとその確率

     - ハードウエアー (特に HDD) はいずれ壊れます

     - ファイルシステムは壊れるかもしれないし、その中のデーターは失われるかもしれません

     - セキュリティー侵害に関してリモート ストレージ システムは信用できません。

     - 脆弱なパスワードによる保護は簡単に破られます

     - ファイルパーミッションシステムが不正アクセスを許すようになるかもしてません

   - バックアップに必要なリソース: 人的、ハードウエアー、ソフトウェアー、…

     - cron ジョブや systemd タイマー ジョブでする自動スケジュールバックアップ

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

| 注記
`/proc` や `/sys` や `/tmp` や `/run` 上にある擬似ファイルシステム (「procfs と sysfs」 と 「tmpfs」 参照) の内容をバックアップしてはいけません。あなた自身が自分がしていることの意味を余程よく分かっていなければ、これらの内容は巨大で無用なデーターです。

| 注記
データーをバックアップする際には MTA (「メール転送エージェント (MTA)」を参照下さい) 等のアプリケーションデーモンを停止するのも一計です。

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

Debian システム上で利用可能でバックアップユーティリティーのスイートのなかで際立った選ばれたリストを記します。

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

パッケージ | ポプコン | サイズ | 説明
--- | --- | --- | ---
`bacula-common` | V:6.3, I:7.2 | 2501 | Bacula: ネットワークバックアップ、復元および検証 - 共通のサポートファイル
`bacula-client` | V:0.3, I:1.9 | 199 | Bacula: ネットワークバックアップ、復元および検証 - クライアントメタパッケージ
`bacula-console` | V:0.7, I:2.1 | 112 | Bacula: ネットワークバックアップ、復元および検証 - テキストコンソール
`bacula-server` | I:0.60 | 199 | Bacula: ネットワークバックアップ、復元および検証 - サーバーメタパッケージ
`amanda-common` | V:0.6, I:2.2 | 9851 | Amanda: Advanced Maryland Automatic Network Disk Archiver (ライブラリー)
`amanda-client` | V:0.6, I:2.2 | 1099 | Amanda: Advanced Maryland Automatic Network Disk Archiver (クライアント)
`amanda-server` | V:0.11, I:0.23 | 1093 | Amanda: Advanced Maryland Automatic Network Disk Archiver (サーバー)
`backuppc` | V:1.4, I:1.7 | 3088 | BackupPC は高性能でエンタープライズ級の、PC をバックアップするためのシステム (ディスクベース)
`duplicity` | V:6, I:47 | 2670 | (リモート) 増分バックアップ
`deja-dup` | V:29, I:43 | 5274 | duplicity の GUI フロントエンド
`borgbackup` | V:13, I:28 | 3485 | (リモート) 重複回避バックアップ
`borgmatic` | V:3.2, I:4.4 | 946 | borgbackup のヘルパー
`rdiff-backup` | V:2.3, I:6.6 | 1207 | (リモート) 増分バックアップ
`restic` | V:6, I:12 | 41560 | (リモート) 増分バックアップ
`backupninja` | V:2.2, I:2.6 | 360 | 軽量で拡張可のメタバックアップシステム
`slbackup` | V:0.11, I:0.13 | 147 | (リモート) 増分バックアップ
`backup-manager` | V:0.43, I:0.77 | 573 | コマンドラインのバックアップツール
`backup2l` | V:0.38, I:0.53 | 110 | マウントできるメディアのための低メンテナンスのバックアップ/復旧ツール (ディスクベース)

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

- Mondo Rescue を使うと、普通のインストールプロセスを経ずにバックアップ CD/DVD 等から完全なシステムを迅速に復旧できます。

- Bacula と Amanda と BackupPC は、ネットワーク越しの定期的バックアップに焦点のあるフル機能のバックアップスイートです。

- Duplicity や Borg は典型的ワークステーション向けの比較的簡単なバックアップユーティリティーです。

### 10.2.3. バックアップのティップ

個人用ワークステーションでは、サーバー環境用に設計されたフル装備バックアップユーティリティー一式はうまく機能しないかもしれません。同時に、既存のワークステーション用のバックアップユーティリティーでは足りない面があるかもしれません。

ここに最小限のユーザー努力でより簡単にバックアップできるようするティップスを示します。これらの技法はどのバックアップユーティリティーにでも使えます。

例示のために、主ユーザーとグループ名を `penguin` とし、バックアップとスナップショット用スクリプト例 "`/usr/local/bin/bkss.sh`" を以下として作成します:

    #!/bin/sh -e
    SRC="$1" # source data path
    DSTFS="$2" # backup destination filesystem path
    DSTSV="$3" # backup destination subvolume name
    DSTSS="${DSTFS}/${DSTSV}-snapshot" # snapshot destination path
    if [ "$(stat -f -c %T "$DSTFS")" != "btrfs" ]; then
      echo "E: $DESTFS needs to be formatted to btrfs" >&2 ; exit 1
    fi
    MSGID=$(notify-send -p "bkup.sh $DSTSV" "in progress ...")
    if [ ! -d "$DSTFS/$DSTSV" ]; then
      btrfs subvolume create "$DSTFS/$DSTSV"
      mkdir -p "$DSTSS"
    fi
    rsync -aHxS --delete --mkpath "${SRC}/" "${DSTFS}/${DSTSV}"
    btrfs subvolume snapshot -r "${DSTFS}/${DSTSV}" ${DSTSS}/$(date -u --iso=min)
    notify-send -r "$MSGID" "bkup.sh $DSTSV" "finished!"

ここでは、基本ツールの rsync(1) のみを使いシステムのバックアップが実現され、Btrfs を使うことでストレージスペースが有効利用されています。

| ヒント
参考: 当著者は、自作の類似シェルスクリプト "bss: Btrfs Subvolume Snapshot Utility" を自身のワークステーションで使用しています。

#### 10.2.3.1. GUI バックアップ

単一 GUI クリックによるバックアップの設定例をここに示します。

- USB ストレージデバイスをバックアップ用に準備します。

  - "`BKUP`" というラベル名のついた btrfs の 1 パーティションがあるように USB ストレージデバイスをフォーマットします。これは暗号化されていても良いです(「dm-crypt/LUKS を使ったリムーバブルディスクの暗号化」を参照下さい)。

  - これをあなたのシステムに挿入します。デスクトップシステムがそれを "`/media/penguin/BKUP`" をして自動マウントするはずです。

  - 当該ユーザーにより書き込みできるように "`sudo chown penguin:penguin /media/penguin/BKUP`" と実行します。

- 「GUI からプログラムをスタート」 中に記載された技法に則り "`~/.local/share/applications/BKUP.desktop`" を以下のように作成します:

      [Desktop Entry]
      Name=bkss
      Comment=Backup and snapshot of ~/Documents
      Exec=/usr/local/bin/bkss.sh /home/penguin/Documents /media/penguin/BKUP Documents
      Type=Application

各 GUI クリック毎に、あなたのデーターが "`~/Documents`" から USB ストレージデバイスにバックアップされ、リードオンリーのスナップショットが作成されます。

#### 10.2.3.2. マウントイベントがトリガーするバックアップ

マウントイベントによりトリガーされる自動バックアップの設定例をここに記します。

- 「GUI バックアップ」 と同様にし、USB ストレージデバイスをバックアップ用に準備します。

- systemd サービスユニットファイル "`~/.config/systemd/user/back-BKUP.service`" を以下のように作成します:

      [Unit]
      Description=USB Disk backup
      Requires=media-%u-BKUP.mount
      After=media-%u-BKUP.mount

      [Service]
      ExecStart=/usr/local/bin/bkss.sh %h/Documents /media/%u/BKUP Documents
      StandardOutput=append:%h/.cache/systemd-snap.log
      StandardError=append:%h/.cache/systemd-snap.log

      [Install]
      WantedBy=media-%u-BKUP.mount

- 以下のようにして systemd のユニット設定を有効化します。

       $ systemctl --user enable bkup-BKUP.service

各マウントイベント毎に、あなたのデーターが "`~/Documents`" から USB ストレージデバイスにバックアップされ、リードオンリーのスナップショットが作成されます。

ここで、systemd が現在メモリー上に保持する systemd のマウント unit 名を、呼び出ているユーザーのサービスマネージャーに問い合わすには、"`systemctl --user list-units --type=mount`" を使います。

#### 10.2.3.3. タイマーイベントがトリガーするバックアップ

タイマーイベントによりトリガーされる自動バックアップの設定例をここに記します。

- 「GUI バックアップ」 と同様にし、USB ストレージデバイスをバックアップ用に準備します。

- systemd タイマーユニットファイル "`~/.config/systemd/user/snap-Documents.timer`" を以下のように作成します:

      [Unit]
      Description=Run btrfs subvolume snapshot on timer
      Documentation=man:btrfs(1)

      [Timer]
      OnStartupSec=30
      OnUnitInactiveSec=900

      [Install]
      WantedBy=timers.target

- systemd サービスユニットファイル "`~/.config/systemd/user/snap-Documents.service`" を以下のように作成します:

      [Unit]
      Description=Run btrfs subvolume snapshot
      Documentation=man:btrfs(1)

      [Service]
      Type=oneshot
      Nice=15
      ExecStart=/usr/local/bin/bkss.sh %h/Documents /media/%u/BKUP Documents
      IOSchedulingClass=idle
      CPUSchedulingPolicy=idle
      StandardOutput=append:%h/.cache/systemd-snap.log
      StandardError=append:%h/.cache/systemd-snap.log

- 以下のようにして systemd のユニット設定を有効化します。

       $ systemctl --user enable snap-Documents.timer

各タイマーイベント毎に、あなたのデーターが "`~/Documents`" から USB ストレージデバイスにバックアップされ、リードオンリーのスナップショットが作成されます。

ここで、systemd が現在メモリー上に保持する systemd のタイマー unit 名を、呼び出ているユーザーのサービスマネージャーに問い合わすには、"`systemctl --user list-units --type=mount`" を使います。

現代的なデスクトップシステムでは、この systemd を使うアプローチのほうが at(1) や cron(8) や anacron(8) を使う伝統的 Unix アプローチよりより精緻な制御を提供できます。

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

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

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

パッケージ | ポプコン | サイズ | コマンド | 説明
--- | --- | --- | --- | ---
`gnupg` | V:398, I:867 | 464 | gpg(1) | GNU プライバシーガード - OpenPGP 暗号化と署名ツール
`gpgv` | V:234, I:939 | 555 | gpgv(1) | GNU プライバシーガード - OpenPGP 署名検証ツール
`sq` | V:1, I:27 | 23948 | sq(1) | Sequoia-PGP - OpenPGP 暗号化と署名ツール
`sqv` | V:416, I:487 | 1702 | sqv(1) | Sequoia-PGP - OpenPGP 署名検証ツール
`paperkey` | V:1, I:13 | 58 | paperkey(1) | OpenPGP の秘密キーから秘密の情報だけを抜粋
`cryptsetup` | V:35, I:78 | 462 | cryptsetup(8), … | 暗号化されたブロックデバイス (dm-crypt / LUKS) のためのユーティリティー
`coreutils` | V:911, I:1000 | 17994 | md5sum(1) | MD5 メッセージダイジェストを計算やチェック
`coreutils` | V:911, I:1000 | 17994 | sha1sum(1) | SHA1 メッセージダイジェストを計算やチェック
`openssl` | V:847, I:996 | 2532 | `openssl`(1ssl) | "`openssl dgst`" を使ってメッセージダイジェストを計算やチェック (OpenSSL)
`libsecret-tools` | V:1, I:11 | 45 | secret-tool(1) | パスワードの保存と読出し (CLI)
`seahorse` | V:75, I:261 | 7971 | seahorse(1) | キー管理ツール (GNOME)

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

### 10.3.1. Gnupg のためのキー管理

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

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

コマンド | 説明
--- | ---
`gpg --gen-key` | 新規キーの生成
`gpg --gen-revoke my_user_ID` | my_user_ID に関するリボークキーを生成
`gpg --edit-key user_ID` | インタラクティブにキーを編集、ヘルプは "help"
`gpg -o file --export` | 全ての公開キーをファイルにエクスポート
`gpg -o file --export-secret-keys` | 全ての秘密キーをファイルにエクスポート
`gpg --import 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.8 トラストコードの意味のリスト

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

以下のようにすると私のキー "`9563FC29932C409F1A77F9C1AB8A1522D8234C6A`" を作成出来ます。

    $ gpg --gen-key
    gpg (GnuPG) 2.4.7; Copyright (C) 2024 g10 Code GmbH
    ...
    GnuPG needs to construct a user ID to identify your key.

    Real name: Osamu Aoki
    Email address: osamu@debian.org
    You selected this USER-ID:
        "Osamu Aoki <osamu@debian.org>"

    Change (N)ame, (E)mail, or (O)kay/(Q)uit? o
    ...
    public and secret key created and signed.

    pub   ed25519 2026-02-14 [SC] [expires: 2029-02-13]
          9563FC29932C409F1A77F9C1AB8A1522D8234C6A
    uid                      Osamu Aoki <osamu@debian.org>
    sub   cv25519 2026-02-14 [E] [expires: 2029-02-13]

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

    $ gpg --keyserver hkp://keys.gnupg.net --send-keys 9563FC29932C409F1A77F9C1AB8A1522D8234C6A

"`~/.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`" オプションの説明を参照下さい。

SHA-1 をハッシュに使うのは非推奨です。あなたの古い RSA ベースの openPGP キーが SHA-1 を使用していれば、FixKeyWithSha1 を用いて修正しましょう。

| ヒント
sq(1) と sqv(1) コマンドは openPGP コマンドの代替セットです。sq user documentation と A Practical Introduction to using sq, Sequoia PGP’s CLI を参照ください。

### 10.3.2. GnuPG をファイルに使用

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

表10.9 ファイルに使用する 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-sign 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.3.3. Mutt で GnuPG を使用

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

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

### 10.3.4. Vim で GnuPG を使用

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

    $ sudo aptitude install vim-scripts
    $ echo "packadd! gnupg" >> ~/.vim/vimrc

### 10.3.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.3.6. パスワード キーリング

GNOME システム上では、seahorse(1) がキーリング `~/.local/share/keyrings/*` 中にパスワードを管理し保存します。

secret-tool(1) はコマンドラインからパスワードをキーリングに保存できます。

ディスクイメージを LUKS/dm-crypt 暗号化するためのパスフレーズを保存します。

    $ secret-tool store --label='LUKS passphrase for disk.img' LUKS my_disk.img
    Password: ********

cryptsetup(8) のような他のプログラムに、こうして保存されたパスワードを読み出し供給できます。

    $ secret-tool lookup LUKS my_disk.img | \
      cryptsetup open disk.img disk_img --type luks --keyring -
    $ sudo mount /dev/mapper/disk_img /mnt

| ヒント
スクリプト中でパスワードを供給する必要がある際はいつも `secret-tool` を使いパスフレーズを直接ハードコードすることは避けます。

## 10.4. ソースコードマージツール

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

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

パッケージ | ポプコン | サイズ | コマンド | 説明
--- | --- | --- | --- | ---
`patch` | V:103, I:726 | 242 | patch(1) | 差分ファイルをオリジナルに適用
`vim` | V:85, I:347 | 4135 | vimdiff(1) | vim で2つのファイルを並べて比較
`imediff` | V:0.03, I:0.26 | 329 | imediff(1) | 対話型フルスクリーンの2方/3方マージツール
`meld` | V:5, I:24 | 3992 | meld(1) | ファイルを比較やマージ (GTK)
`wiggle` | V:0.01, I:0.12 | 175 | wiggle(1) | リジェクトされたパッチを適用
`diffutils` | V:896, I:998 | 1768 | diff(1) | 1行ごとにファイルを比較
`diffutils` | V:896, I:998 | 1768 | diff3(1) | 1行ごとにファイルを比較やマージ
`quilt` | V:2, I:17 | 880 | quilt(1) | パッチのシリーズを管理
`wdiff` | V:6, I:40 | 651 | wdiff(1) | テキストファイル間のワードの相違表示
`diffstat` | V:9, I:98 | 79 | diffstat(1) | 差分ファイルによる変化のヒストグラム作成
`patchutils` | V:11, I:97 | 269 | combinediff(1) | 2つの積み重ねパッチから1つの合計パッチを生成
`patchutils` | V:11, I:97 | 269 | dehtmldiff(1) | HTML ページから差分ファイルを抽出
`patchutils` | V:11, I:97 | 269 | filterdiff(1) | 差分ファイルから差分ファイルを抽出や削除
`patchutils` | V:11, I:97 | 269 | fixcvsdiff(1) | CVS により作成された patch(1) が誤解する差分ファイルを修正
`patchutils` | V:11, I:97 | 269 | flipdiff(1) | 古い2つのパッチを交換
`patchutils` | V:11, I:97 | 269 | grepdiff(1) | 正規表現にマッチするパッチによって変更されるファイルを表示
`patchutils` | V:11, I:97 | 269 | interdiff(1) | 2つのユニファイド差分ファイル間の違いを表示
`patchutils` | V:11, I:97 | 269 | lsdiff(1) | どのファイルがパッチによって変更されるかを表示
`patchutils` | V:11, I:97 | 269 | recountdiff(1) | ユニファイドコンテキスト差分ファイルのカウントやオフセットを再計算
`patchutils` | V:11, I:97 | 269 | rediff(1) | 手編集された差分ファイルのカウントやオフセットを再計算
`patchutils` | V:11, I:97 | 269 | splitdiff(1) | 増分パッチの分離
`patchutils` | V:11, I:97 | 269 | unwrapdiff(1) | ワードラップされたパッチを復元
`dirdiff` | V:0.1, I:1.4 | 167 | dirdiff(1) | ディレクトリーツリー間で相違点の表示と変更のマージ
`docdiff` | V:0.03, I:0.25 | 554 | docdiff(1) | 2つのファイルをワード毎/文字毎に比較
`makepatch` | V:0.02, I:0.16 | 99 | makepatch(1) | 拡張パッチファイルの生成
`makepatch` | V:0.02, I:0.16 | 99 | applypatch(1) | 拡張パッチファイルの適用

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

ふたつのソースファイル間の相違を抽出したユニファイド差分ファイル は、以下の要領でファイル位置に対応し "`file.patch0`" か "`file.patch1`" として作成されます。

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

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

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

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

### 10.4.3. インタラクティブなマージ

2つのバージョンのソースコードがある場合、imediff(1) をインタラクティブに使って効率的に2方マージを以下のように実行できます。

    $ imediff -o file.merged file.old file.new

3つのバージョンのソースコードがある場合、imediff(1) をインタラクティブに使って3方マージを以下のように実行できます。

    $ imediff -o file.merged file.yours file.base file.theirs

## 10.5. Git

最近は、ローカルとリモートの両方のコード管理一切が可能なGitがバージョンコントロールシステム (VCS) として最優先の選択肢です。

Debian は Debian Salsa サービス経由でフリーの Git サービスを提供します。その説明文書は https://wiki.debian.org/Salsa にあります。

Git関連パッケージは以下です。

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

パッケージ | ポプコン | サイズ | コマンド | 説明
--- | --- | --- | --- | ---
`git` | V:406, I:616 | 50972 | git(7) | git: 高速、スケーラブル、分散型リビジョンコントロールシステム
`gitk` | V:4, I:27 | 2022 | gitk(1) | GUI による履歴付き Git レポジトリーブラウザー
`qgit` | V:0.2, I:2.0 | 1431 | qgit(1) | GUI による履歴付き Git レポジトリーブラウザー
`git-cola` | V:0.7, I:4.6 | 5005 | git-cola(1) | GUI による履歴付き Git レポジトリーブラウザー
`tig` | V:2, I:12 | 1243 | tig(1) | コンソールによる履歴付き Git レポジトリーブラウザー
`lazygit` | V:0.9, I:3.6 | 24167 | lazygit(1) | コンソールによる履歴付き Git レポジトリーブラウザー
`git-gui` | V:1, I:17 | 2525 | git-gui(1) | Git 用の GUI (履歴無し)
`git-email` | V:0.4, I:9.8 | 1204 | git-send-email(1) | Git からパッチの集合の email として送信
`git-buildpackage` | V:1.2, I:7.1 | 2027 | git-buildpackage(1) | Git を使って Debian パッケージ化を自動化
`dgit` | V:0.2, I:1.0 | 738 | dgit(1) | Debian アーカイブと git の相互運用性
`imediff` | V:0.03, I:0.26 | 329 | git-ime(1) | インタラクティブな git コミット分割ヘルパーツール
`stgit` | V:0.08, I:0.50 | 6181 | stg(1) | Git 上の quilt (Python)
`git-doc` | I:11 | 14896 | N/A | 正式 Git 文書
`gitmagic` | I:0.52 | 721 | N/A | "Git マジック"、Git に関する分かり易いガイド

### 10.5.1. Git クライアントの設定

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

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

以下によって Git のデフォルトの動作をカスタマイズしてもいいです。

    $ git config --global init.defaultBranch main
    $ git config --global pull.rebase true
    $ git config --global push.default current

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

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

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

    $ git config --global --list

### 10.5.2. 基本 Git コマンド

Git 操作にはいくつかのデーターが関与します。

- ユーサーから見えるファイルを保持しかつ変更の対象とする、ワーキングツリー

  - 記録すべき変更は、インデックスに明示的に選択して候補として挙げなければいけません。これは、`git add` や `git rm` コマンドです。

- 候補として挙げたファイルを保持するインデックス

  - 候補として挙げたファイルはそれに続くリクエストでローカルのレポジトリーにコミットされるでしょう。これは、`git commit` コマンドです。

- コミットされたファイルを保持するローカルのレポジトリー

  - Git はコミットされたデーターのリンクされた履歴をレポジトリー中にブランチとして整理して保存します。

  - `git push` コマンドによって、ローカルレポジトリーはリモートレポジトリーにデーターを送信できます。

  - `git fetch` や `git pull` コマンドによって、ローカルレポジトリーはリモートレポジトリーからデーターを受信できます。

    - `git pull` コマンドは `git fetch` コマンドの後で `git merge` か `git rebase` コマンドを実行します。

    - ここで、`git merge` は、2 つの別々の履歴のブランチの最後を 1 点にまとめます。(これは、カスタマイズされていないデフォルトの場合の `git pull` で、多くの人に向けてブランチを公開するアップストリームに好適です。)

    - ここで、`git rebase` は、リモートブランチの履歴の後ろにローカルブランチの履歴が繋がった連続履歴の単一ブランチを生成します。(これは、`pull.rebase true` カスタマイゼイションの場合で、残りの我々に好適です。)

- コミットされたファイルを保持するリモートレポジトリー

  - リモートレポジトリーとの通信は SSH か HTTPS 等のセキュアー通信プロトコルを使います。

ワーキングツリーは `.git/` ディレクトリーの外のファイルです。`.git/` ディレクトリーの内部のファイルはインデックス、ローカル レポジトリー データー、いくつかの git 設定のテキストファイルを保持します。

主要 Git コマンドの概論です。

表10.12 主要 Git コマンド

Git コマンド | 機能
--- | ---
`git init` | (ローカル) レポジトリーを作成します
`git clone URL` | リモートレポジトリーをワーキングツリー付きローカルレポジトリーとしてクローンします
`git pull origin main` | ローカルの `main` ブランチをリモート レポジトリーの `origin` を使って更新します
`git add .` | インデックス中にのみ既に存在するファイルに関してワーキングツリー中のファイルをインデックスに追加します
`git add -A .` | ワーキングツリー内の全てのファイルを全てのファイルに関するインデックスに削除を含め加えます
`git rm filename` | ワーキングツリーとインデックスからファイルを削除します
`git commit` | ローカルレポジトリーにインデックス中の挙げられた変更をコミットします
`git commit -a` | ワーキングツリー中の全ての変更をインデックスに追加し、それらをローカルレポジトリーにコミットします (add + commit)
`git push -u origin branch_name` | リモート レポジトリー `origin` をローカルの `branch_name` ブランチで更新します (最初の呼び出し)
`git push origin branch_name` | リモート レポジトリー `origin` をローカルの `branch_name` ブランチで更新します (その後の呼び出し)
`git diff treeish1 treeish2` | treeish1 コミットと treeish2 コミットの間の相違を表示します
`gitk` | VCS レポジトリーのブランチ ヒストリー ツリーの GUI 表示をします

### 10.5.3. Git ティップ

以下はGit ティップです。

表10.13 Git ティップ

Git コマンドライン | 機能
--- | ---
`gitk --all` | Git 全履歴を閲覧し HEAD を別のコミットにリセットし、パッチをチェリーピックし、タグやブランチを生成するような、Git 履歴への操作を加えます
`git stash` | データーを消失無くクリーンなワーキングツリーを得ます
`git remote -v` | リモートに関する設定をチェックします
`git branch -vv` | ブランチに関する設定をチェックします
`git status` | ワーキングツリーの状態を表示します
`git config -l` | git 設定のリストをします
`git reset --hard HEAD; git clean -x -d -f` | 全てのワーキングツリーの変更を元に戻し完全にクリーンアップします
`git rm --cached filename` | `git add filename` で変更された候補のインデックスを元に戻します
`git reflog` | レファレンスログを取得します(削除したブランチからコミットを復元するのに有用です)
`git branch new_branch_name HEAD@{6}` | reflog 情報から新規ブランチを生成します
`git remote add new_remote URL` | URL によって指される `new_remote` リモート レポジトリーを追加します
`git remote rename origin upstream` | リモート レポジトリー名を `origin` から `upstream` に変更します
`git branch -u upstream/branch_name` | リモート レポジトリー `upstream` とそのブランチ名 `branch_name` にリモート トラッキングを設定します。
`git remote set-url origin https://foo/bar.git` | `origin` の URL を変更します
`git remote set-url --push upstream DISABLED` | `upstream` へのプシュを無効化します (`.git/config` を編集して再有効化)
`git remote update upstream` | `upstream` レポジトリー中の全リモートブランチの更新を取得します
`git fetch upstream foo:upstream-foo` | ローカルの (孤立しているかもしれない) `upstream-foo` ブランチを、`upstream` レポジトリー中の `foo` ブランチのコピーとして作成します
`git checkout -b topic_branch ; git push -u topic_branch origin` | 新規 `topic_branch` を作成しそれを `origin` にプシュします
`git branch -m oldname newname` | ローカル ブランチ名を変更します
`git push -d origin branch_to_be_removed` | リモート ブランチを削除します (新手法)
`git push origin :branch_to_be_removed` | リモート ブランチを削除します (旧手法)
`git checkout --orphan unconnected` | 新 `unconnected` ブランチを生成します
`git rebase -i origin/main` | きれいなブランチ履歴のために、`origin/main` からのコミットを順序変更/削除/押し潰します
`git reset HEAD^; git commit --amend` | 最後の 2 コミットを 1 つに押し潰します
`git checkout topic_branch ; git merge --squash topic_branch` | 全 `topic_branch` を1 つのコミットに押し潰します
`git fetch --unshallow --update-head-ok origin '+refs/heads/*:refs/heads/*'` | 浅いクローンをブランチのフルクローンに変換します
`git ime` | 最後のコミットを分割して一連のファイル毎の小さなコミット等に分割します (`imediff` パッケージが必要)
`git repack -a -d; git prune` | ローカル レポジトリーを単一の梱包に再梱包します(こうすると消去したブランチ等からのデーター復元の可能性を制限するかもしれません)

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

| 注意
もしリモートレポジトリーにプッシュしたローカルブランチがリベースしたりスクワッシュした場合には、このブランチをプッシュするのはリスクがあるし、`--force` オプションが必要です。これは `main` ブランチでは通常許容されませんが、`main` ブランチにマージする前のトピックブランチでは許容されます。

| 注意
`git` サブコマンドを直接 "`git-xyz`" としてコマンドラインから起動するのは2006年初以来非推奨です。

| ヒント
`$PATH` で指定されたパス中に実行可能ファイル `git-foo` が存在する場合、ハイフン無しの "`git foo`" をコマンドラインに入力するとこの `git-foo` が起動されます。これは `git` コマンドの機能です。

### 10.5.4. Git リファレンス

次を参照下さい。

- マンページ: git(1) (`/usr/share/doc/git-doc/git.html`)

- Git ユーザーマニュアル (`/usr/share/doc/git-doc/user-manual.html`)

- git へのチュートリアル導入 (`/usr/share/doc/git-doc/gittutorial.html`)

- git へのチュートリアル導入: 第2部 (`/usr/share/doc/git-doc/gittutorial-2.html`)

- 約20のコマンドを使って毎日 GIT (`/usr/share/doc/git-doc/giteveryday.html`)

- Git マジック (`/usr/share/doc/gitmagic/html/index.html`)

### 10.5.5. 他のバージョンコントロールシステム

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

Debian システム上で利用可能な特記すべき他の 非Git の VCS のまとめを以下に記します。

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

パッケージ | ポプコン | サイズ | ツール | VCS タイプ | コメント
--- | --- | --- | --- | --- | ---
`mercurial` | V:3, I:26 | 2575 | Mercurial | 分散型 | Python と一部 C で書かれた DVCS
`darcs` | V:0.2, I:3.3 | 38856 | Darcs | 分散型 | パッチに関して賢い計算をする DVCS (遅い)
`tla` | V:0.04, I:0.72 | 1022 | GNU arch | 分散型 | 主に Tom Lord による DVCS (歴史的)
`bzr` | V:0.1, I:4.3 | 28 | GNU Bazaar | 分散型 | `tla` に影響され Python で書かれた DVCS (歴史的)
`subversion` | V:10, I:57 | 4849 | Subversion | リモート | "良く出来た CVS"、新しいリモート VCS の標準 (歴史的)
`cvs` | V:3, I:25 | 4835 | CVS | リモート | リモート VCS の過去の標準 (歴史的)
`tkcvs` | V:0.12, I:0.88 | 34 | CVS, … | リモート | VCS (CVS, Subversion, RCS) レポジトリーツリーの GUI 表示
`rcs` | V:1.7, I:9.5 | 578 | RCS | ローカル | "Unix SCCS の本来あるべき姿" (歴史的)
`cssc` | V:0.01, I:0.35 | 2044 | CSSC | ローカル | Unix SCCS のクローン (歴史的)

[4] 重要データーは上書き事故を防ぐために CD/DVD-R のような1回書込みメディアに貯蔵するのが好ましいです。(シェルコマンドラインからストレージメディアにどうして書き込むかについては「バイナリーデーター」を参照下さい。GNOME デスクトップの GUI 環境ではメニュー: "Places→CD/DVD Creator" で簡単に書込みできます。)

[5] このようなデーターの一部は、システムに同一の入力文字列を入力しても再生成できません。

[6] もし、"`~/.vim/vimrc`" に代えて "`~/.vimrc`" を使う場合は、それに合わせて置換して下さい。

第9章 システムに関するティップ |  | 第11章 データー変換