mirrordir(1)

名前
pslogin - 強力なストリーム cipher 暗号化と diffie-hellman 鍵交換を用いた安全なリモート tcp ログイン

forward - 任意の tcp ソケットを安全かつ暗号化されたチャネルにフォワードする

copydir, mirrordir - 変更された最小の部分のみを用いて (ローカル、FTP 経由、安全な tcp 接続経由で) ディレクトリツリーをコピーまたはミラーする

recursdir - ファイルの操作/検索や tar ファイル作成のために、ローカルまたはリモートのディレクトリを再帰的に探索する

書式
mirrordir
[-a, --access-times]
[-m, --strict-mtimes]
[--no-mtimes]
[--ignore-size]
[-A, --mtime-threshold ext]
[--time-offset [[+]|-][H]H[:MM]]
[-A, --always-write]
[-r, --restore-access]
[--no-chown]
[--no-chmod]
[-D, --only-delete]
[-b, -S, --backup-extension, --suffix ext]
[-N, --num-backups num]
[-O, --backup-outdate sec]
[-B, --block-size bytes]
[-M, --max-bytes num[K|M|G]]
[-s, --starting-file path]
[-i, --ignore-next-exclude]
[[-i] -X, --exclude path] [[-i] -X, --exclude path] ...
[[-i] -F, --exclude-from file] ...
[[-i] -G, --exclude-glob expr] [[-i] -G, --exclude-glob expr] ...
[[-i] -R, --exclude-regexp expr] [[-i] -R, --exclude-regexp expr] ...
[-C, --exclude-script [expr|file]] [-C, --exclude-script [expr|file]] ...
[-h, --help]
[-v, --verbose] [-v, --verbose] ...
[-V, --version]
[-k, --keep-files]
[-l, --no-hard-links]
[--follow-symlinks]
[-L, --strict-locking]
[-p, --password password]
[-P, --password-exact password]
[--test-login]
[--no-warn-first-login]
[--read-password-from-stdin]
[--allow-empty-ftp-dirs]
[--no-allow-empty-ftp-dirs]
[--netrc]
[--no-netrc]
[--proxy-host host]
[--secure]
[-z, --gzip]
[--gzip-backups]
[--case-insensitive]
[--to-lower]
[--to-upper]
[--no-use-passive-connections]
[-K, --key-size bits]
[--download-scripts]
[--tar-file filename]
[--tar-block-size N]
[-t, --dry-run, --test-only]
[--nice num] control mirror

mirrordir [-c | --copy-mode | --recurs-mode ] -[abBCdDFGhklMmNOopRrstvVX] src [src ...] dest

copydir -[abBCdeFGhklMmNOopRrstvVX] src [src ...] dest

recursdir -[abBCdeFGhklMmNOopRrstvVX] src [src ...]

pslogin [--key-size bits] [mc://][username@]hostname[:portnumber][/path]

しかし通常は単に:
mirrordir [--exclude path] control mirror
copydir src [src ...] dest
recursdir src [src ...] [-C program]
pslogin [username@]hostname[:portnumber]

説明
mirrordir はディレクトリを操作したりミラーする際に便利なユーティリティの集まりである。 ssh(1) の代替になるコマンド pslogin や、任意の TCP ソケット接続を暗号化された安全なチャネルにフォワードする forward(1) も含まれている。

mirrordir は 2 つのディレクトリ control と mirror との間で異なるファイルを、 control から mirror へとコピーする。 修正時刻 (modification time) またはサイズが異なるファイルがコピーされる。 ファイルの許可属性・所有者・修正時刻・アクセス時刻 (--access-time が用いられた場合のみ)・スティッキービット・ デバイスタイプが複製される。 シンボリックリンクはリンク先の解決をされずにそのままコピーされる。 シンボリックリンクの修正・アクセス時刻 (シンボリック自身のもので、 シンボリックが指すファイルのものではないことに注意) は保存されない。 ハードリンクされたファイルは単にコピーされる。 生成時刻は、私の知る限り Unix では設定できない。

mirrordir は危険なコマンドである。 mirror にあって control にないファイルやディレクトリは削除されるからである。もし control が完全に空の場合には、 mirror のすべてのファイルやディレクトリが削除される。もし mirror が完全に空の場合には、 control のすべてのファイルやディレクトリがコピーされる。

要するに mirrordir は mirror をディレクトリツリー control の完全なレプリカにし、またその際にあらゆるものを (定期的バックアップという目的に合致するなら) 可能な限り複製しようとする。当然 mirrordir はサブディレクトリの一番深いところまで降りていく。 ディレクトリミラーの際には、それに必要な最小の変更のみを調べ、 可能な限り効率的に動作しようとする。

アクセス時刻の複製は通常は必要なく、また不要な負荷を与えることになる。 よってこれはオプションになっている。

ディレクトリ control には、何の変化も与えない。--restore-access が与えられると、アクセス時刻は読み込みのたびに、 元の時刻に再設定される。

--strict-locking オプションをオンにすると、 control にあるコピー作業中のファイルは「共有読み込み (shared reading)」 にロックされる。これによって、 他のプロセスがそのファイルに頻繁に書き込みを行っている場合でも、 ファイルが不完全な状態や壊れた状態ではコピーされないことを保証する。

通常 mirrordir は問題があっても中断せず、 問題の報告を stderr へのエラーメッセージとして行い、 動作を継続する。

ディレクトリ mirror や dest は (たとえ空であっても) 存在していなければならない。

ディレクトリのすべてのファイルを削除する前に、 mirrordir は *--keep-me というファイル (ここで * は 0 または 1 つの文字) をチェックする。 このファイルが存在すると、エラーメッセージを出して中断する。 よって再帰的に削除されてはまずいディレクトリがあったら、 それぞれにこのようなファイルを作っておけば良い。

copydir は mirrordir -ck --no-erase-directories ... と等価である (-c には -k が含まれるが)。よって copydir は厳密な意味での cp(1) とよく似ているが、ファイル名は URL でも良く、 かつ古いファイルだけが置き換えられる。 ファイル転送には、ほとんどの場合 mirrordir ではなく copydir を使うほうがよい。本当に消してよい場合に限り、 mirrordir を使うようにすること。

recursdir はまたもう一つのプログラムで、 コマンドライン上でディレクトリを降りてゆくだけで何も行わない。 これは mirrordir --recures-mode ... と等価である。これは -C オプションが追加される前にできたプログラムで、より厳密な find(1) として、あるいは見つかったすべてのファイルを tar ファイルにパックする目的に、それぞれ利用できる。

pslogin はさらにもう一つのプログラムで、 これまでに挙げた 3 つとはほとんど関係がない。 pslogin は secure-mcserv を用いて安全なログインセッションを開始する。 これは mirrordir --login-mode --secure ... と等価である。 pslogin は logindir と呼ぶべきかもしれない。後述の --login-mode を参照のこと。

forward はさらにもう一つのプログラムで、 最初の 3 つとはほとんど関係がない。 これは任意のサービスを安全なチャネルにフォワードできる。 詳細は forward(1) を参照のこと。

このパッケージの重要な点は、 通常のファイル名に替えて URL を使える点にある。 よってファイルをネットワーク越しに操作できる。 現在サポートされている URL のタイプは、 ftp:// と mc:// である (http:// はファイルシステムではないので、サポートされていない)。 mc:// は Midnight Commander ファイルシステムで、 secure-mcserv デーモンによってサービスされるものである。 これには、暗号化された、 強く安全なファイル転送およびログインを提供するという長所がある。

recursdir コマンドと copydir コマンドには glob 表現も利用できる。 これらは再帰的に展開される。

セキュリティと暗号化
mirrordir は、強力なストリーム cipher 暗号化と、 何種類かの鍵サイズでの Diffie-Hellman 鍵交換をサポートしている。 安全な接続は mc:// の接続で動作する。オプション --secure, --key-size, --download-scripts を参照のこと。 デモは 例 の節を、公開鍵・秘密鍵の置場所については ファイル の節を参照のこと。

オプション

--help
    詳しいヘルプを出力して終了する。

--verbose
    mirror に対してなされたファイル修正に関して、 詳しい出力をするよう指定する。 このオプションは複数個指定でき、 たくさん指定するほどより詳しく出力する。 出力は標準出力に書き出される。

--restore-access
    読み込むを行うごとに、 control のアクセス時間を元に戻す。

--access-times
    control のアクセス時刻も複製する。

--always-write
    同じに見えるかどうかに関らず、 すべてのファイルを書き変えるよう強制する。

--recurs-mode
    これは recursdir ではデフォルトで有効になる。 指定したディレクトリを再帰的に読み、それらに対しては何も行わない。 このオプションは ファイルを検索したり、 -C と共に指定してシェルコマンドを実行したりするのに便利である。 なお C インタープリタでは system(), exec(), popen 関数が利用できる。

--login-mode
    このオプションは pslogin ではデフォルトでセットされる。これは secure-mcserv をサーバに使う rlogin とだいたい同じになる。 ssh(1) の代わりに使えるような、安全な暗号化された接続を提供する。 pslogin は暗黙のうちに --secure も指定する。このオプションを指定したり、 pslogin を用いた場合は、コマンドラインにはパスを 1 つだけ指定しなければならない。 指定の形式は [mc://][username@]hostname[:portnumber][/path] である。

    ログイン後直ちに、シェルプロンプトから cd /path が実行される。 pslogin は文字 #, $, > を調べ、 プロンプトが出たかどうか判断する。 これらが見つからないと、 pslogin はずっと止まったままになる。この動作を避けるには、 /path を / とすれば良い。するとログインディレクトリに留まったままになる。 あるいはシェルプロンプトを変更して、これらの文字を含めるようにしてもよい。

--copy-mode
    これは copydir ではデフォルトでセットされる。 コピー元・コピー先の各ファイルに対して cp(1) と同じように振る舞う。このオプションを用いると、暗黙のうちに --keep-files を指定したことになる。 コピー先の既存のファイル・ディレクトリのうち、 コピー元と同じ名前を持つものはすべて上書きされるが、 これ以外の理由でファイルやディレクトリが削除されることはない。 コピー元には複数のファイルやディレクトリを指定できる。 コピー先のパスはディレクトリでなければならない。

--no-erase-directories
    このオプションを指定すると、 コピー先のディレクトリとコピー元のファイルがおなじ名前で、 かつそのディレクトリが空でない場合、 エラーメッセージを表示して終了する。これは copydir のデフォルトの動作である。

--erase-directories
    このオプションを指定すると、 コピー先のディレクトリとコピー元のファイルがおなじ名前の場合、 コピー先のディレクトリは再帰的に削除される。これは mirrordir のデフォルトの動作である。

--allow-empty-ftp-dirs
    ftp サーバには、 . とか .. といったディレクトリを生成しないものがある。 そのような場合、ディレクトリへの読み取り許可がないように見えてしまう。 このオプションを用いると、この動作を変更し、 このような完全に空のディレクトリを単に空であるとみなしてエラーにしない。 unable to open directory: *: Permission denied というエラーになった場合は、このオプションを試してみるとよい。 このオプションはデフォルトでは有効になっている (次項を参照のこと)。

--no-allow-empty-ftp-dirs
    現在はディレクトリに cd してアクセス許可を調べるためにようになったので、 デフォルトの動作は空のディレクトリを許可するようにした。

--only-delete
    mirror に対して、利用しているディスクスペースを 増加させるような変更は一切行なわない。 これは容量の限られているドライブに対してバックアップを取る場合、 転送の最中に control に mirror を増加させてしまうような 変更がなされるときに便利である。 一度このオプションをつけて mirrordir を実行すれば、 次にこのオプションをつけて実行したときには、 利用できる領域を越えないことが通常は保証される。

-i, --ignore-next-exclude
    このオプションを指定すると、次の --exclude- タイプのオプションは、 対象ファイルが mirror ディレクトリにあろうと無かろうと、 それらを完全に無視することになる。 これは後述する --exclude-script オプションで IGNORE が返った場合と同じ効果を持つ。 これは特定のファイルを決して変更しないようにするのに利用できる。 例えば /etc/named.boot を決して変更したくない場合には、 mirrordir /mnt/1 /mnt/2 -i --exclude /mnt/1/etc/named.boot とすればよい。mirror ディレクトリではなく、 control ディレクトリのフルパスで指定することに注意。 --exclude /mnt/2/etc/named.boot では動作しない。 後者では、ファイルを削除したくない場合には そのファイルが control ディレクトリに存在しなければならない (たとえサイズ 0 であっても) という馬鹿げた動作となる。

--exclude path
    ファイルまたはディレクトリ path を除外する。コマンドラインにたくさんの exclude パスを指定すると、 動作が遅くなってしまう。除外されたパスは、 mirror ツリーに存在する場合は削除される (そのディレクトリまたはファイルが存在していない場合と同様である)。 これらのファイルを削除せずに無視して保持しておきたい場合は、 --ignore オプションを用いること。

    除外するファイルが長いリストになる場合は、 --exclude-from オプションを利用すること。

--exclude-glob glob
    glob 形式の表現 glob にマッチするファイルするディレクトリを除外する。 ファイルへのマッチではフルパスを用いない。 シェルにおいては、glob 表現を適切な引用符で括り、 解釈されないようにする必要がある。

--exclude-regexp regex
    フルパス名が regex にマッチするファイルやディレクトリを除外する。 シェルにおいては、正規表現を適切な引用符で括り、 解釈されないようにする必要がある。

--exclude-script [expr|file]
    各ファイルに対する処理を行なう前に、スクリプト expr を実行する。 このスクリプトは C 言語スタイルの文ブロックからなり、`return expression;' で終了する。 expression の値は INCLUDE, EXCLUDE, UNKNOWN IGNORE (上述の -ifP を見よ) のいずれかであり、そのファイルに対して成すべき動作を示す。 expr にセミコロン (;) が含まれていない場合は、 これはファイル名とみなされ、そのファイルがロードされる。 それ以外の場合は、テキストは高速化のために 逆ポーランド形式にコンパイルされる。 このオプションは複数指定でき、 その場合スクリプトは UNKNOWN 以外の値が返るまで、順に実行される。 UNKNOWN が返った場合は、コマンドラインにあるその他の --exclude- 形式のオプションが効力を持つ。

    インタープリタがおかしなエラーを報告したり、 セグメンテーションフォールトを起こした場合は、 その原因となったスクリプトを私に送ってほしい。

    このスクリプト言語自体は、C プログラミング言語のサブセットである。 例えば以下のようなものは正しいスクリプトである。

    /* PATH はファイルのフルパス名で、DIR は末尾に
       スラッシュ (/) の無いディレクトリ、CWD は
       カレントワーキングディレクトリ、dpath() は
       フォワードスラッシュ (/) の個数-1 を返す。*/
    if (depth (DIR) - depth (CWD) > 3) {
        printf ("%s: excluded\n", PATH);
        return EXCLUDE;
    } else
        return INCLUDE;

    このスクリプト言語は代入演算子をサポートしない。 したがってユーザ定義変数をサポートしない。

    以下の定義済みマクロを利用できる。 マクロの展開は、ディレクトリにもファイルと等しく同じように適用される。

    FILE
        現在のファイル (パス無し)

    NAME
        パス・拡張子の無いファイル名。末尾にドット (.) は付かない。

    EXTENSION
        ファイルの拡張子。先頭にドット (.) は付かない。

    DIR ファイル名の無いディレクトリ。末尾にスラッシュ (/) は付かない。

    PATH
        フルパスのファイル名

    CWD カレントワーキングディレクトリ

    TIME
        現在時刻 (秒単位)

    C のすべての論理演算子・算術演算子・ビット演算子がサポートされている。 すなわち ( ) >= <= > < != == && || ! - + * / % & ^ で、これらは全て C のものと同じ意味を持つ。

    さらに以下に示すマクロも利用できる。 各々は整数 (C での long int 型) を返す。 これらはそのファイルに対する lstat (または --follow-symlinks が用いられている場合は stat) を基にしている。詳しい説明は stat(2) を参照のこと。

    stat.st_dev - デバイス
    stat.st_ino - i-ノード
    stat.st_mode - 許可属性 (permission)
    stat.st_nlink - ハードリンクの数
    stat.st_uid - 所有者のユーザ id
    stat.st_gid - 所有者のグループ id
    stat.st_rdev - デバイスタイプ
    stat.st_size - ファイルサイズ (バイト単位)
    stat.st_blksize - ファイルシステム I/O のブロックサイズ
    stat.st_blocks - アロケート済みのブロック数
    stat.st_atime - 最後にアクセスされた時刻 (秒単位)
    stat.st_mtime - 最後に変更された時刻 (行単位)
    stat.st_ctime - 作成された時刻

    以下の関数はブール値を返す。

    strncmp(string1, string2, integer);
        string1 が string2 より小さい場合は 0 以下の整数を、 マッチする場合は 0 を、 大きい場合は 0 以上の整数を返す。

    glob(glob, string);
        string が glob 表現 glob にマッチする場合は 0 を返す。 下層の実装における効率を良くしたい場合は、 あなたが書くコードでの glob 表現をひとつに限ってみること。

    regexp(regexp, string);
        string が正規表現 regexp にマッチする場合は 0 を返す。 下層の実装における効率を良くしたい場合は、 あなたが書くコードでの正規表現をひとつに限ってみること。

    strstr(string1, string2);
        string1 の長さの範囲に最初に現れる string2 の位置を返す。現れない場合は 0 を返す。

    以下の関数もブール値を返す。これらは stat(2) で説明されているマクロに対応している。 これらは、指定された条件が真の場合に非ゼロの値を返す。

    S_ISLNK(integer); - ファイルはシンボリックリンク
    S_ISREG(integer); - ファイルは通常のファイル
    S_ISDIR(integer); - ファイルはディレクトリ
    S_ISCHR(integer); - ファイルはキャラクタデバイス
    S_ISBLK(integer); - ファイルはブロックデバイス
    S_ISFIFO(integer); - ファイルは fifo
    S_ISSOCK(integer); - ファイルはソケット

    以下の関数は文字列を操作する。

    strcat(string1, string2);
        string1 に string2 を連結して返す。 + 演算子も文字列を連結することに注意。

    depth(string);
        string に現れるフォワードスラッシュ (/) の個数から 1 を引いたものを返す。

    printf(format, ...);
        printf(3) のように動作する。ただし重要な例外がある: long int のフォーマット指定以外は使ってはならない。 これ以外の指定を行なったときの変換結果は未定義である。 例えば、"%d" ではなく "%ld" を用いること。 結果は標準出力に表示される。

    以下の関数はシステムコールを実行する。

    system(command);
        /bin/sh -c command を実行する。しかし C 言語のものとは異なり、 コマンドの終了コードを返す。 つまり、一行だけのシェルスクリプト command を実行する。

    exec(argv0, argv1, ...);
        プロセス argv0 を引数 argv1... で実行する。 argv0 フルパスで指定しなければならない。 これは sh を経由しないので system より速い。

    popen([string, ] shell_command);
        system と似ているが、 shell_command の出力を文字列として返す。 string が与えられている場合には、その文字列を shell_command の標準入力に与え、成功したら 0 を返す。

    以下の整数定数も利用可能で、stat.h で定義されているマクロ (説明は stat(2) にある) に対応する。

    S_IFMT S_IFSOCK S_IFLNK S_IFREG S_IFBLK S_IFDIR S_IFCHR S_IFIFO S_ISUID S_ISGID S_ISVTX S_IRWXU S_IRUSR S_IWUSR S_IXUSR S_IRWXG S_IRGRP S_IWGRP S_IXGRP S_IRWXO S_IROTH S_IWOTH S_IXOTH

    以下の定数のひとつを return 文を用いて返し、呼出し元に意図を伝える必要がある。 何も返さない場合は、返り値は UNKNOWN であるとみなされる。

    UNKNOWN
        どうすべきか分からない。引き続き他の --exclude- タイプのオプションを実行する。

    INCLUDE
        そのファイルを処理に含める。

    IGNORE
        そのファイルが mirror ディレクトリにあろうと無かろうと、 何も行なわない。

    EXCLUDE
        そのファイルが control ディレクトリに存在しないものとみなす。 よって mirror ディレクトリからは削除される (これは --keep-files オプションよりも優先される)。

    以下は C のようなフロー制御を行なう。

    以下の if 文は integer が真 (つまり非ゼロ) ならば statement1, statement2 などを実行し、 それ以外の場合は statementA, statementB などを実行する。 else {...} の部分は省略可能である。

        if (integer) {
            statement1;
            statement2;
            .
            .
            .
        } else {
            statementA;
            statementB;
            .
            .
            .
        }

    return 文は mirrordir に値を返し、スクリプトを終了させる。

        return expression;

    exit 関数は、 mirrordir を指定した終了コードで終了させる。

        exit(integer);

    通常 C スクリプトは、特定のファイルを除外するために用いる。 これはスクリプト言語の実装としてはやりすぎで、 機能のすべてを一般用途向けに書いたわけではない。 典型的なスクリプトは、例えばデバイスファイルを除外する、 という程度のことに留まるだろう。

    if (S_ISSOCK(stat.st_mode) || S_ISFIFO(stat.st_mode)
             || S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) {
        return EXCLUDE;
    } else
        return INCLUDE;

    --recurs-mode オプションとともに用いれば、 C スクリプトはファイルを検索するためにも利用できる (recursdir コマンドと同じ):

    /* core ファイルを全て削除する */
    /* この例は 例 セクションに移動した。 */

--exclude-from file
    ファイル file に書かれているリストに含まれるパスを除外する。 空行とコメント行 (行頭の文字が # の行) は無視される。 このファイルのリストはソートされ二分木探索されるので、 たくさんのファイル名を除外したい場合には、 ここにそれらのファイルを書く方が性能は良くなる。 このオプションは複数指定でき、複数個のファイルを指定できる。 バグ: file の最後に与えたパスは、改行で終らなければならない。

--backup-extension level
    ファイルを削除したり置き換えたりする前に、 それらのファイルのバックアップを作る。 extension は C 形式のフォーマット文字列で、例えば .ORIG.%d (% へのシェル代入に注意) のようにする。 level は保存しておくリビジョンの最大数。 extension がファイル名に追加され、古いファイルほど大きな番号を持つ。

--backup-outdate sec
    sec 秒よりも古いバックアップファイルを削除する。

--nice num
    時々スリープして、他のプロセスに対して行儀良く振る舞う。 --nice を指定すると、プロセスはアクティブであった時間の num 倍の時間スリープする。したがって 1 を指定すると (非常におおざっぱに言えば) コピーに要する時間は 2 倍になり、 3 を指定すれば 4 倍になる。 これは定期的なバックアップを、 CPU 負荷を小さくして行ないたい場合に利用するとよい。 システムによっては --nice は利用できないかもしれない。

--no-chmod
    通常はファイルの許可属性設定が行なわれる。 アクセス権限が制限されていて、許可属性を変更できない場合は、 このオプションを指定すれば許可属性設定を無効にできる。

--no-chown
    通常はファイルの所有権設定が行なわれる。 アクセス権限が制限されていて、所有者を変更できない場合は、 このオプションを指定すれば所有権設定を無効にできる。

--mtime-threshold sec
    mtime の違いがこの値よりも小さい場合には、 ファイルは上書きされない。ftp サイトをミラーした場合、 そのミラー中の mtime は分の単位の精度しか持たないので、 これを nfs ミラーしようとするとすべてのファイルがコピーされる。 これを直すには --mtime-threshold 60 を用いればよい。

--time-offset [[+]|-][H]H[:MM]
    vfs な (つまり ローカルでない) ディレクトリの時刻オフセットを設定する。 例えば私は New York より 8 時間東にいるので、 New York からミラーする場合には --time-offset -8:00 を使っている。

--test-only, --dry-run
    実際には変更を行なわない。 --verbose と共に用いると、 どのような変更がなされるかを表示できる。 これはディレクトリ間の比較をするのにも効果的な方法である。 これはテストされていない。 すなわち、このオプションが本当に変更をしないかどうかは、 私は保証できない。

--skip-symlinks
    シンボリックリンクは、読み込まれなかったかのように扱われる。 よってそれらが mirror ディレクトリにあると、削除される。

--keep-files
    ファイルが control に無い場合でも、そのファイルを mirror から削除しない。こうすると mirrordir はある意味 cp(1) のようになる。

--no-hard-links
    このオプションが指定されない限り、 mirrordir はハードリンク属性を正しくミラーする。 指定されると、ハードリンクは通常ファイルのようにコピーされる。

--follow-symlinks
    このオプションが指定されなければ、 mirrordir はシンボリックリンクを適切にミラーする。 指定されると、シンボリックリンクは通常ファイルとしてコピーされる。 Debian ツリーをミラーするときに便利である。 注意してほしいのは、 シンボリックリンクは control と mirror の両方で解決される、 という点である。 依ってシンボリックリンクが mirror ディレクトリに存在していると、 それらはそのままシンボリックリンクのまま残る。 --follow-symlinks を指定すると、暗黙のうちに --no-hard-links も指定したことになる。

--strict-locking
    ファイルを読み込むとき、共有読み込みのロックを作成する。 これはファイルコピーの事故を予防する。 特にメールディレクトリに対して有効である (メールプログラムは mirrordir がファイルを読み込もうとしているときに、 同時にそれらに書き込みを行なおうとするかもしれない)。 このオプションは仮想ファイルシステムに対しては効力を持たない。

--max-bytes [[num[k|M|G]]|num]
    このバイト数を越えると `filled up all blocks - first file/dir not mirrored: path' というメッセージが標準出力に表示される。 残りのファイルは mirror から削除されるが、 これはリストされた順序で行なわれる。よって mirrordir が走り続けていると、アーカイブの大きさが num を越えることがある。 この偶発分のゆとりをとって、 num は利用できるスペースより小さくしておくこと。 またファイルシステムによっては、 完全にいっぱいになる前に `No space left on device' というメッセージを出すことがある。 mirrordir には --starting-file path オプションがあり、 これを用いると別のデバイスで作業を継続できる。 こうすれば、複数のデバイスに対して mirrordir を用いたバックアップができる。 num には k, M, G (大文字小文字を区別する) のいずれかを後置でき、 それぞれキロバイト、メガバイト、ギガバイトを指定する。 どれかひとつのファイルがこの数値よりも大きいと、 エラーメッセージが表示される。 --block-size も参照のこと。

--password password
    FTP 接続・mc:// 接続に対するパスワードを設定する。 匿名接続の場合のパスワードは、 デフォルトで「ログイン名@ローカルマシン名」になっている。 それ以外のログインパスワードは、プロンプトが出て尋ねられる。 いつもの警告だが、 パスワードをスクリプトに含めるのはセキュリティ上のリスクがある。 パスワードは ~/.netrc ファイルに入れ、 --no-netrc オプションを指定しないかたちの方がずっと良い。 詳細は man ftp を見よ。

--password-exact password]
    匿名パスワードの前に - を前置しない。 ftp の匿名パスワードでは、通常パスワード文字列の前に - が置かれる。私は Midnight Commander vfs がなぜこのようにしていたのか知らないが、 あるユーザがこの問題に突き当たったので、 このオプションを設け、パスワードを password に指定した通りに送れるようにしている。

--test-login
    --login-mode や pslogin を用いるとき、非対話的なアクセスをテストしてみたいことがあるだろう (例えばシェルスクリプトで用いたいときなど)。 これを行なうには、 pslogin をこのオプションとともに実行し、終了ステータスを見ればよい。 secure-mcserv は、ユーザがパスワードサーバにログインできるかどうかを調べるために、 これを用いている。

--no-warn-first-login
    あるマシンに対して最初に安全な接続を試みた時は、 公開鍵がローカルマシンに存在しない。 よって「間に人」攻撃に対して無防備である。 この内容に関する警告が表示され、 ユーザにプロンプトが出され、継続したいかどうか尋ねられる。 このオプションはこの警告を出さないようにし、 一切を無視して先に進む。

--read-password-from-stdin
    パスワードをコマンドラインから指定するのではなく、 標準入力から与える。 これは見えないパスワードをタイプ入力するのと同じではない。 こちらは端末が無い場合にでも使える。 これは他のプログラムから、例えば popen(3) などを用いて利用する場合に都合が良い。 secure-mcserv は、ユーザがパスワードサーバにログインできるかどうかを調べるために、 これを用いている。

--netrc
    ~/.netrc をスキャンする。デフォルトでこのオプションは on になっている。

--no-netrc
    ~/.netrc ファイルの読み込みを行なわない。

--proxy-host host
    ftp ダウンロードのプロキシを設定する。 これがどのように動作するのか、 あるいは実際に動作するかどうかは私にはわからない。 プロキシのサポートについては mc(1) にあたってほしい。

--secure
    (この機能はβ段階である) 私は mirrordir 用に安全なソケット層を実装した。これはこのオプションで有効となり、 secure-mcserv の接続 (すなわち mc:// 形式の URL) に適用される。 安全なソケットのライブラリは libdiffie.a とヘッダファイル diffie-socket.h からなる。 sys/socket.h の後に diffie-socket.h をインクルードし、そのプログラムを際コンパイルすれば、 通常のソケットが全て安全なソケットになる (これは Unix のソケットコールを用いる、あらゆるプログラムに当てはまるが、 しかしテストはされていない)。 これをサポートする最初のサービスは secure-mcserv で、デフォルトでコンパイルされ、インストールされる。 よって、リモートのホストも secure-mcserv を走らせていれば、 mc:// ファイルシステムは --secure オプションで利用できる (secure-mcserv -h とすればヘルプが表示される)。 --secure は、DES などのブロック cipher よりずっと安全で高速なストリーム cipher を、 公開鍵サーバ認証 (Diffie-Hellman 及び p-NEW スキーム) の 離散対数鍵交換で用いている。 詳細はソース配布の diffie-socket.h を見てほしい。デフォルトの鍵のサイズは 512 ビットである。 gcc を用いている場合は、 mirrordir のコンパイル時に -O3 -fomit-frame-pointer -s -Wall オプションをつけると、鍵生成が高速化される。

--key-size bits
    デフォルトの鍵サイズは 512 ビットである。 サイズを変更するには素数を生成して fileld.c に書き込まなければならないので、 field.c にリストされているサイズだけがサポートされており、 現時点ではこれは 512, 768, 1024, 1536 である。 遅い計算機を用いている場合には、中程度のセキュリティとなる 768 を奨める。 それ以外なら、長い目で見れば 1536 も非合理で偏執的な値、というわけでもない。 巨大企業・良くつないでくるハッカー・政府などがあなたの接続を 盗聴している心配がなければ、512 でも構わないだろう。 ストリーム cipher は bits/2 の長さを持つので、クラックされる確率は、 宝くじを換金しているあいだに隕石にぶち当たる確率よりは低い。 ただしある人間が接続を盗聴し、長い間出力をとり続ければ、 破ることは不可能ではない。 20 年も経てば、1536 ビットの鍵も小さいと考えられるかもしれない。 また (ここで用いられている) 離散対数問題は、 素因数分解よりも解くのが難しいと考えられているので、 鍵は RSA よりも実効的にやや大きいことになる。 これは私の (どちらかというと無学な) 意見である。

--download-scripts
    mirrordir には 2 つの版、International 版と US 版がある (--version を見よ)。US 版は暗号化に類するコードを一切含んでいない。 その代わり、必要なアルゴリズムを (南アフリカ にある) encrypt.obsidian.co.za からダウンロードするようになっている。 これらは高速かつネイティブな、C 形式のインタープリタ言語で書かれている。 これらは 4 つのスクリプトからなる。それぞれ、 Diffie-Hellman 鍵交換サーバ、Diffie-Hellman 鍵交換クライアント、 ストリーム cipher の初期化、実際にストリーム cipher を用いた暗号化、 のためのものである。 mirrordir は、あなたがセキュリティ機能を用いようとすると、 自動的にこれらのスクリプトをダウンロードする。しかしこの --download-script オプションを用いると、いつでもダウンロードを実行できる。 International 版にはストリーム cipher が組み込まれていて、 2 つのスクリプトだけを用いるが、 これらは配布に含まれているのでダウンロードの必要はない。 Diffie-Hellman 交換をスクリプトで用いても、速度的な劣化は生じない。 しかし暗号化に関しては、 スクリプトと組み込みの間の違いが結構大きいかもしれない。

--version
    バージョン番号と、 この mirrordir が International 版か US 版かを表示する。 --download-scripts を見よ。

-z, --gzip
    mc:// 接続で圧縮を有効にする。 実際には符号化よりも低いレベルにある圧縮ソケット層を呼出す。 圧縮は gzip(1) の libz ライブラリを用いて行なう。圧縮の程度は、 転送時間を最小化するように動的に設定される。 高速なイーサネット接続なら無圧縮にまで低くなりうるし、 モデム経由の遅い接続では最大圧縮にまで高くなる。 このアルゴリズムは、TCP の write コールが、 同量のデータを deflate する (つまり圧縮する) 時間の 2〜5 % の範囲になるように、 圧縮レベルを調整する。

--gzip-backups
    バックアップは通常は単にファイルのコピーである。 このオプションを指定すると各ファイルは圧縮され、 .gz がデフォルトの拡張子として付加される。 バックアップの拡張として、あなたが自分で --backup-extension の指定を行なった場合は、その末尾が .gz で終らないと、比較が正しく動作しない。

--case-insensitive, --for-Robert-Seese
    ファイル名やリンク名の比較に、大文字小文字の違いを無視する。 これは、特定の頭の悪い OS と通信するときに便利だろう。 このオプションがすべての状況で正しく動作するかどうかは、あまり自信が無い。

--to-lower

--to-upper
    すべての新しいファイル名を大文字または小文字に変換する。 --case-insensitive と共に用いると、新しいファイルを作成する場合にのみ適用される。 --case-insensitive なしで指定すると、既存かどうかに関らす、 すべてのファイルが大文字・小文字に変換される。 このときの方法は非効率的なもので、 古いファイルを一度消してから、新しいファイルを再度コピーする。 これは、特定の頭の悪い OS と通信するときに便利だろう。 このオプションがすべての状況で正しく動作するかどうかは、あまり自信が無い。

--no-use-passive-connections
    could not setup passive mode というエラーメッセージを受け取った場合、 このオプションを有効にする必要があると考えられる。 私は `passive' の意味するところを完全には理解していないので、 私には聞かないでほしい。

--tar-file filename
    これは recursdir と共にのみ用いる。tar アーカイブを GNU tar(1) と同じフォーマットで作成し、 filename に保存する。先頭の特殊なプレフィックスと末尾のスラッシュは削除される。 すなわち http://machine/dir/file は dir/file になる。ファイル名の先頭文字が | の場合、 テキストの残りは出力がパイプされるコマンドとみなされる。 よって gzip 圧縮アーカイブは、例えば以下のようにすれば作成できる。
    recursdir ftp://machine/dir --tar-file '| gzip -d > foo.tar.gz'

--tar-block-size N
    tar 出力のブロックサイズを 512 * N にする。 これはデータをアーカイブに書き込むときの単位である。 デフォルトは 20。 これはブロックデバイスに書き込むときに限って意味を持つ。 これを --block-size と混同しないこと。

--block-size bytes
    デフォルトのブロックサイズは 1024 バイトである。 消費されるブロックの総数を計算する際、 ファイルサイズは隣接するブロック末尾に切り上げられる。 実際のブロックサイズがこの値よりも大きいと、 書き込み時に実際に利用されるブロック数よりも、 計算値が小さくなる可能性がある。 よって --max-bytes オプションを用いるときには、実際のブロックサイズと同じ、 またはより大きな値を指定することがとても大切である。

--strict-mtimes
    通常ファイルをコピーする場合、 mirrordir は通常 mirror のファイルが control のファイルよりも「古い」場合に限って上書きコピーを行なう。 このオプションを用いると、 ファイル間に修正時刻の「何らかの」差異があれば、コピーを行なう。

--no-mtimes
    サイズが違う場合に限ってコピーする。 ファイルの修正時刻は無視する。

--ignore-size
    ファイルのコピーを mtime に基づいて行ない、 サイズの違いは無視する。

--starting-file path
    path はファイルまたはディレクトリ。 path が読まれるまでは、ファイルやディレクトリは除外ファイル (つまり mirror にある場合は削除される) のように扱われる。 path を含むディレクトリは、存在していなければ作成される。 path が読み込まれると、ファイルやディレクトリは通常にミラーされる。 path そのものもミラーされる。 path またはそのサブディレクトリが存在していない場合は、 mirrordir は直ちに終了する。 これは mirrordir が作業前に終了する唯一の場合である。 これは path が見つからない場合に、ファイルシステム全体が削除されるのを防ぐためである。

FTP のサポート
ftp 転送が、 Midnight Commander の仮想ファイルシステム (Virtual File System: VFS) を利用する形でサポートされている。 要するにつまり、URL もローカルディレクトリと同じようにサポートされている。 以下に例を示そう。
    mirrordir --verbose \
	ftp://lava.obsidian.co.za/pub/mirrordir \
	    /home/mirrordir
あるいは
    mirrordir --verbose /home/mirrordir \
	ftp://psheer@lava.obsidian.co.za/home/ftp/pub/mirrordir
も動作する。ただし後者ではまずパスワードを尋ねられる。 ftp サーバに「アップロード」を行う場合は、 --strict-mtimes オプションは on にすべきでない。 ftp では修正時刻の設定はできないので、 すべてがコピーされてしまう。

(--verbose を設定すれば) mirrordir が繰り返し ftp で修正時刻とアクセス時刻をセットしようとしていることに気づくだろう。 用いている VFS のタイプにおける制限をユーザに知らせるために、 これらのメッセージは残しておくつもりである。 これらの試行は、明らかな性能の劣化としては現われない。 しかしこのプロトコルを用いたアップロードの性能が悪い場合は、代わりに mc:// を用いてみるといいだろう。 なおダウンロードは常にアップロードよりも高速である。

一般に cron ジョブでは ftp アップロードを用いるべきではない。 またディレクトリの同期を取る目的にも向いていない。 ディレクトリを同期したい場合は、反対側からのダウンロードを用いること。 アップロードは一回きりのアップロードにしか有用でない。

例
ここでは mirrordir を用いて行える、ちょっと気の効いた作業を紹介する。

ミニマリスト的コピー
    ソースツリーが 2 つあり、 古い版をパッチを適用するために保管しておきたいとする。 これには mkdir tree.OLD して、

          mirrordir -v tree tree.OLD

    するだけでよい。 もう一度 mirrordir を実行すれば、最小限の変更のみ (つまり更新されたファイルのみ) がコピーされる (実は cp(1) も同じことをする)。

システムバックアップ
    システムによっては、 定期的なバックアップをテープアーカイブに行っていることがある。 また RAID デバイスを用いて、 あるパーティションと同一のコピーを恒常的に保持しているシステムもあるだろう。 mirrordir はさらに別の選択肢を提供する。 システムに 2 台のドライブを装備する。ひとつは普段用いるもの、 もう一つはバックアップするためのものである。 そして mirrordir を cron(8) のテーブルに追加するのだ。 変更されたファイルのバックアップには、様々なオプションが利用できる。 バックアップディレクトリはユーザから読み取り可能にしておき、 各人のバックアップファイルを閲覧できるようにしておくといいだろう。 特定のファイルの古いバージョンを取り戻したいユーザは、 バックアップから入手できるようになる。 mirrordir は変更されたファイルの最小限だけを処理するので、非常に高速である。 一日に何回も実行したり、あるいは --nice オプションを付けて 途切れることなく実行させることさえ可能である。

    マシンが壊れたときに対する備えをさらに強固にしたければ、 FTP を用いてリモートマシンにバックアップを行うこともできる。

2 台のマシンを毎時バックアップする
    dar2 というマシン上で、私は次のような cron ジョブを 6 時間ごとに実行している。

    #!/bin/sh

    # (this is just in case of any bugs I don't know about,
    # but I don't think it is necessary)
    killall -9 tee
    killall mirrordir >& /dev/null
    sleep 2
    killall -9 mirrordir >& /dev/null

    (                                                               \
    date                                                        ;   \
    echo "mirrordir says (if it said nothing it is bad):"       ;   \
        mirrordir mc://dar1:12346/ -p abcdefg /mnt/dar1/            \
        -i --exclude-regexp '^mc://dar1:12346/var/lock/subsys/atd'  \
        --exclude-regexp '^mc://dar1:12346/proc/'                   \
        --exclude-regexp '^mc://dar1:12346/mnt/[^/]*/.*$'           \
        -i --exclude-regexp '^mc://dar1:12346/boot/'                \
        -i --exclude-regexp '^mc://dar1:12346/etc/lilo.conf'        \
        -C                                                          \
    '
    if (S_ISDIR (stat.st_mode)) {
        if (!regexp ("^mc://dar1:12346/[^/]*$", PATH))
            printf ("Backing up: %s, PATH);
    }
    '                                                   ;           \
    date                                                ;           \
    echo "Done"                                         ;           \
    ) 2>&1                                                          \
    | tee --ignore-interrupts --append /var/log/mirrordir.log       \
    | mail -s 'dar1 backup results' psheer@obsidian.co.za

安全な転送とログイン
    turing.co.uk において以下のコマンドを実行しておく
        secure-mcserv -p 12345 -d
    どこか外部のマシンから
        copydir --secure -K 512 -z \
        mc://alan@turing.co.uk:12345/usr/src/linux/.config .
    とすれば、512 ビットの鍵を用いた安全なファイルコピー (圧縮つき) ができる。 また
        pslogin mc://alan@turing.co.uk:12345/
    とすれば、このマシンに安全にログインできる。

FTP サイトのミラー
    ftp サイトでは ls の -R オプションが禁止されていることが多いので、 従来用いられてきた mirror (1) は失敗することがあった。 mirrordir にはこの制限はない。

        mirrordir -v ftp://metalab.unc.edu/pub /home/ftp/pub

FTP 転送
    よくある FTP 転送は、--copy-mode オプションを用いた 一行のコマンドで簡単に実現できる。 複数のファイルをどちら向きにも、 また別々の ftp サイトにすら (間接的にではあるが)、 cp(1) のようにコピーできる。
        copydir -v mirrordir-0.9.15.tar.gz \
        mirrordir.lsm ftp://metalab.unc.edu/incoming/Linux
    とすると mirrordir を sunsite にアップロードする。

    anonymous でない ftp 転送のパスワードは、標準的な ftp の慣習に従って ~/.netrc ファイルに置き、--netrc オプションを用いるのがよい。 あるいは ftp://myname@machine/ を用いてもかまわない。

ファイル探索
    recursdir / -C
    'if (!glob ("*.c", FILE)) printf ("%s\\n", PATH);'
    とするとシステムにあるすべての C ファイルを表示する。
    recursdir / -C
    'if (S_ISCHR(stat.st_mode)) printf ("%s\\n", PATH);'
    とすればシステムにあるすべてのキャラクタデバイスを表示する。

FTP サイトをテープにバックアップする
    リモートサイトをテープにバックアップするには
        recursdir ftp://user@remote.machine/ \
        --exclude-regexp '//[^/]*/proc/' --tar-file /dev/mt
    とすればよい。

core ファイルの削除
    これはシステムからすべての core ファイルを削除する:

    recursdir / -C '
    long l;
    if (strncmp (PATH, "/proc", 5)) {
        if (S_ISREG (stat.st_mode) && !strcmp ("core", FILE)) {
            if (strstr (popen ("file " + PATH), "ELF 32-bit LSB core")) {
                l = l + stat.st_size;
                printf ("removing: %s, cumu. total = %ldkB\n", PATH, l >> 10);
                exec ("rm", "-f", PATH);    /* could also use system() */
            }
        }
    }
    '

環境変数

TMPDIR
    一時的なファイルを保管させたいディレクトリ。 ftp ファイルシステムは、 まずファイルをこの一時ディレクトリにダウンロードし、 正しい場所にそのファイルをコピーする。後述の バグ を参照のこと。

    TMPDIR が指定されないと、 デフォルトでは現在進行中のファイルがあるディレクトリに保存される。

返り値
mirrordir は以下の値を返す:

0   成功。

1   何らかのエラー (書き込みエラー、許可属性エラーなど) が起った。 この場合、エラーの詳細は stderr に書き込まれているはずである。

2   あるファイルが利用中でコピーできなかったが、それ以外は成功した。 この場合は `unable to open control file for writing' というエラーが書き込まれているはずである。 標準エラーでこのメッセージを grep し、これらのファイルに対してのみ もう一度 mirrordir を実行すればよい。 grep(1) を参照のこと。

バグ
atd デーモンのあるバージョンでは、 ロックファイル (や pid ファイル?) をそのファイルもロック付きで作成するため、 secure-mcserv が永遠にブロックする。 これを防ぐには、 atd を停止させるか、このファイルを対象から除外しなければならない。

サマータイムの時間補正があるところと ftp でミラーを行うと、 1 時間の時間のオフセットが生じるように見える。 とりあえずの回避策としては --time-offset を用いてほしい。 これが mirrordir のせいなのかどうかは私にはわからない。

mirrordir のせいで CPU が食い尽くされ、停止してしまうように見えるバグは修正された。

コマンドラインから多数の --exclude 式を指定すると、 処理が遅くなる。たくさんのファイルのリストを除外対象したい人は、 そのリストをテキストファイルに書いて、 --exclude-from オプションを利用する方がよい。

シンボリックリンク (それが指すファイルではない) の修正時刻とアクセス時刻は複製されない。

以前にあった、ハードリンクファイルが通常ファイルとして扱われてしまうという 制限は解決された。--no-hard-links オプションを指定すれば、 0.9.8 以前の動作をエミュレート可能である。

ハードリンクがデバイスをまたいで作成されているかどうかはチェックしていない。 この場合はそれに見合ったエラーが報告されることになろう。

ftp ファイルシステムは、まずファイルを一時ディレクトリに *ftpfs* という名前でダウンロードする。 これはスペースの無駄だが、vfs ライブラリのデフォルトの動作なのだ。 このディレクトリに十分な容量がないと、おそらく mirrordir はハングする。 上述の 環境変数 を参照のこと。

ファイル除外に用いる C スクリプト言語は、 実装のやりすぎである。

ファイル

~/.netrc
    マシンとそのパスワードのリスト。 オプション --netrc を参照のこと。

/etc/ssocket/accept.cs
    このスクリプトは、接続のサーバ側で、鍵交換と署名生成を行う。

/etc/ssocket/connect.cs
    このスクリプトは、接続のクライアント側で、鍵交換と署名生成を行う。

/etc/ssocket/arcinit.cs
    ストリーム cipher 暗号化を初期化する (国際版では存在しない)。

/etc/ssocket/arcencrypt.cs
    ストリーム cipher 暗号化を行う (国際版では存在しない)。

/etc/ssocket/private/
    このディレクトリには、ホストの秘密鍵が置かれる。 鍵はそれぞれ別々のファイルに保存される。 ファイル名は 512, 1024 などである。 鍵のデータベースを使うようにすると、 鍵管理用のユーティリティが必要になるので、 こちらのほうがよい。 すぐに Reiser ファイルシステムが標準的になるだろうから、 データベースファイルはいずれにしても不要になるだろう。

/etc/ssocket/public/
    こちらは公開鍵のもの。後は /etc/ssocket/private/ と同様。

準拠
mirrordir は作成者の発明であり、 いかなる OS の標準にも従っていない (そうするべきではあるが!)

入手方法
このプログラムの最新版は、 ftp://metalab.unc.edu/pub/Linux/system/backup または ftp://lava.obsidian.co.za/pub/linux/mirrordir から入手できる。

著者
Paul Sheer <psheer@obsidian.co.za> <psheer@icon.co.za>

関連項目
mirror(1), pavuk(1), cp(1), scp(1), find(1), mc(1), ftp(1), ssh(1), tar(1), rlogin(1), rlogind(8), forward(1)