えんでぃの技術ブログ

えんでぃの技術ブログ

ネットワークエンジニアの視点で、IT系のお役立ち情報を提供する技術ブログです。

Timeshift の仕組みを調べてわかったこと

timeshift_black_bold
引用元:timeshift_black_bold.png

前の記事

Timeshift の機能や特徴、基本的な使い方を紹介しました。

endy-tech.hatenablog.jp

お伝えしたいこと

Timeshift の内部動作に踏み込んで確認し、わかったことをまとめます。
Timeshift を普通に使う上では不要な知識かもしれませんが、以下の内容が気になった方はぜひ読んでみてください。

  • Timeshift が内部的にどのようにcronと連携しているのか
  • そもそもcrondとanacronは何が違うのか
  • Timeshift はrsyncコマンドをどのオプションをつけて実行しているのか

特にrsyncコマンドはオプションが多いため、既成品が使っているオプションを見るだけでも参考になると思います。

ソースコードにはほぼ触れず、Timeshift の実行ログやLinuxの設定ファイルを確認することで考察します。

バックアップ処理の定期実行の仕組み

Timeshift 定期実行の概要

後述のシステム起動からTimeshift トリガーまでの動きを追ってみるに書いてあるとおり、 Timeshift は crond によって毎時バックアップ処理をトリガーされています。
そして、Timeshiftのソースコードによると、バックアップが最後に実行された時刻を内部的に管理し、設定したとおりの実行周期 (日次や週次) となるようにバックアップ処理をスキップしたり実行したりしています。
Timeshift のこういった動きは、crondよりも寧ろanacronに近いです。

cron と anacron の違い

さて、anacron は cron と同様にインターバルを置きながら処理を繰り返したい場合に使われますが、cronと比較していくつかの違いがあります。
以下の2枚のスライドで、その要点を示します。

赤字部分が重要なポイントです。
また前のセクションで記載の通り、Timeshift は anacron に近い性質を持っているので、anacron の性質には特にご注目ください。

cron_vs_anacron_summary

cron_vs_anacron_example

crond は指定した時刻にPCを起動していないと日次ジョブ実行されません。
一方、anacronであれば1時間ほどPCを起動していれば起動時刻が何時であっても日次ジョブが実行されます。
パソコン用途としては、anacronの方が扱いやすい印象を受けます。

次のセクションでcronとanacronの違いについて、詳細を補足します。

(参考) cron の詳細

cronの設定ファイルである /etc/crontabは、以下のような構造になっています。
何曜、何月、何日、何時、何分に実行するかを明確に記述し、定刻に処理を実行する作りであることが読み取れると思います。
また、設定ファイルに記述できる最小単位がminuteであることから、最小実行間隔は「毎分」です。

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed

man crondによると、crondの設定ファイルは、以下の3箇所のいずれかに配置可能です。

  • /etc/crontab
  • /etc/cron.d/*
  • /var/spool/cron/<username>

各ファイルは、デフォルトでrootユーザのみ編集可能となるようパーミッションが設定されています。
ただし、/var/spool/cron/<username>だけは例外で、crontab -eコマンドで一般ユーザーの権限で編集できます。

anacron の詳細

anacronの設定ファイルである /etc/anacrontabは、以下のような構造になっています。
anacronは1日を最小単位として、一定時間間隔でコマンド実行する作りであることがわかると思います。

#period in days   delay in minutes   job-identifier   command
1  5  cron.daily      nice run-parts /etc/cron.daily
7  25 cron.weekly     nice run-parts /etc/cron.weekly
@monthly 45    cron.monthly        nice run-parts /etc/cron.monthly

システム起動からTimeshift トリガーまでの動きを追ってみる

コマンドの出力を順に貼りつつ紹介します。
出力は一部のみ抜き出しています。

最初に、システム起動の過程でcrond.serviceが起動します。
そこで、systemctl cat crondコマンドによって crond.service の中身を見てみました。
/etc/sysconfig/crondによると、$CRONDARGSの中身は空っぽでした。
つまり、サービス起動時に実行しているコマンドは /usr/sbin/crond -n です。
-n はフォアグラウンド実行という意味で、サービスから起動する際にしばしば指定するオプションのようです。

$ systemctl cat crond
# /usr/lib/systemd/system/crond.service
# (略)
[Service]
EnvironmentFile=/etc/sysconfig/crond
ExecStart=/usr/sbin/crond -n $CRONDARGS
# (略)

man crondによると、crondが起動した時には以下の3ファイルを読み込みます。

  • /etc/crontab
  • /etc/cron.d/*
  • /var/spool/cron/<username>

/etc/cron.d/timeshift-hourlytimeshift --check --scriptedコマンドを毎時0分 (hh:00) に発行し、Timeshiftの定期実行をトリガーしていました。
このコマンドを発行したタイミングが Timeshift に設定した定期バックアップの間隔以降であれば、バックアップを取得します。
それ以外のタイミングでトリガーされた場合は、処理がスキップされます。
ちなみに、このファイルは毎日/毎週/毎月/N日のスケジュール実行を指定している場合のみ生成されます。

$ cat /etc/cron.d/timeshift-hourly
# (略)
0 * * * * root timeshift --check --scripted

また、「OS起動時」のスケジュール実行を指定している場合は、/etc/cron.d/timeshift-bootが生成します。

@rebootによって「OS起動時」を表現しています (man 5 crontab参照)。

$ cat /etc/cron.d/timeshift-boot
# (略)
@reboot root sleep 10m && timeshift --create --scripted --tags B

(参考) 続き

以下は Timeshift とは関係ありませんが、参考情報としてcronの動きの続きを追ってみます。
/etc/cron.d/0hourly/etc/cron.hourly/ディレクトリ配下の実行ファイルを毎時の定刻 (hh:01) に実行していました。
run-partsとは、指定したディレクトリ配下の実行ファイルを全て実行するコマンドです。

$ cat /etc/cron.d/0hourly
# (略)
01 * * * * root run-parts /etc/cron.hourly

/etc/cron.hourly/0anacron が一時間ごとにanacron コマンドをトリガーしています。

$ cat /etc/cron.hourly/0anacron
# (略)
/usr/sbin/anacron -s

anacronコマンドは、/etc/anacrontabを読み取って実行します。
/etc/anacrontabから、/etc/cron.daily/etc/cron.weekly/etc/cron.monthlyを実行しています。
つまり、cronの日次実行、週次実行、月次実行はanacronによって実行されています。
昔はこれらの実行が/etc/crontabに書かれていたのですが、ある時点でanacronが利用されるようになりました (man run-partsにそう書かれていました)。

$ cat /etc/anacrontab
# (略)
#period in days   delay in minutes   job-identifier   command
1  5  cron.daily      nice run-parts /etc/cron.daily
7  25 cron.weekly     nice run-parts /etc/cron.weekly
@monthly 45    cron.monthly        nice run-parts /etc/cron.monthly

Timeshift が実行しているrsyncコマンド

コマンドの確認方法

Timeshift のログから、Timeshift が実行しているrsyncコマンドを確認できます。
※バックアップ実行中にps auxで確認するという手も恐らくあります

Timeshift を起動し、下図の赤枠部分 (Menu > View TimeShift Logs) を選択することでログを開けます。

timeshift_logs

2種類のログファイルが存在します。

  • yyyy-mm-dd_hh-mm-ss_backup.log
    • anacron により、1時間に1度timeshift --check --scriptedコマンドが実行される度に生成する
    • 定期バックアップ処理がスキップされても実行されてもこのファイルが生成する
    • rsync のオプションを確認できるのは、定期バックアップ処理が実行された時のログファイルのみ
  • yyyy-mm-dd_hh-mm-ss_gui.log
    • GUI操作のログ
    • バックアップの手動実行の際のログも含まれる

コマンドの中身

Timeshift が実行していたコマンドを貼り付けます。
以下のコマンドでは、コピー元が / で、コピー先が/run/timeshift/backup/timeshift/snapshots/2020-11-07_17-00-02/localhost/ です。

rsync \
-aii \
--recursive \
--verbose \
--delete \
--force \
--stats \
--sparse \
--delete-excluded \
--link-dest='/run/timeshift/backup/timeshift/snapshots/2020-11-02_23-00-01/localhost/' \
--log-file='/run/timeshift/backup/timeshift/snapshots/2020-11-07_17-00-02/rsync-log' \
--exclude-from='/run/timeshift/backup/timeshift/snapshots/2020-11-07_17-00-02/exclude.list' \
--delete-excluded \
'/' \
'/run/timeshift/backup/timeshift/snapshots/2020-11-07_17-00-02/localhost/'

オプションの意味は以下の通りです (man rsync より)。
-a, --delete, --exclude-from, --link-destが特に重要です。

オプション 意味
-a, --archive -rlptgoD と同等。
-A, -H, -X は含まない
-r, --recursive ディレクトリ配下もコピーする
-l, --links シンボリックリンクをそのままコピーする
一方で-L, --copy-linksを指定すると、リンクを追跡してファイルの実体をコピーする
-p, --perms パーミッションを保持する
-t, --times 更新時刻を保持する。
ファイルのタイムスタンプが同じだった場合にコピーをスキップさせたい場合は、必須のオプション
-g, --group 所有グループを保持する
-o, --owner オーナーユーザーを保持する
-D --devices --specials と同義
--devices バイスファイル (/dev/*) も送れるようにする
--specials 特殊ファイル (named sockets, fifo など) も送れるようにする
-i, --itemize-changes 変更点のあったファイルを一覧表示する。
-iiのように繰り返すと、変更されていないファイルも一覧表示する
v, --verbose より詳細に画面/ログ出力する
--delete バックアップ先のディレクトリ内のファイルで、対応するバックアップ元のディレクトリに存在しないものがあった場合、そのファイルを削除する
この挙動はバックアップ元のパスにディレクトリを指定した場合のみ有効となる
--force バックアップ先の空でないディレクトリ名とバックアップ元のファイル名が同じだった場合、ディレクトリを削除してファイルをコピーする
--stats コピー完了後に表示される統計値をより詳細にする
-S, --sparse スパースファイルを認識し、スパースファイルとしてコピーする
--delete-excluded --excluded--exclude-fromなどによってコピー対象から除外されたファイルも、コピー先に存在した場合は削除する
--link-dest=<DIR> 差分バックアップをしたいときに指定する。
--link-destを指定しなかった場合は、コピー先に既にコピー元と同じファイルが存在していると認識された場合はコピーをスキップする。
--link-destを指定した場合は、スキップする代わりに<DIR>からのハードリンクを生成する。
Timeshiftは、<DIR>に前回のスナップショットを指定することで、ハードリンクによる差分バックアップを実現している
--log-file=<FILE> rsyncの実行ログを<FILE>に出力する
--exclude-from=<FILE> コピー対象から除外するファイル・ディレクトリの一覧を<FILE>から読み取る。
コマンドラインに除外条件を直接書く場合は、--exclude=<PATTERN>を使う

--exclude-fromに指定されていたファイルは、TimeshiftのSettngs > Filters > Summary と同じ内容が書かれていました。

(考察) Timeshiftはハードリンクを保持しない

Timeshiftでは -A, -H, -X は指定されていませんでした。
従って、以下の挙動となります。

  • -A, --acls指定なし → ACLを保持しない
  • -X, --xattrs指定なし → 拡張ファイル属性を保持しない
  • -H, --hard-links指定なし → コピー元のハードリンクを認識せず、ハードリンクについても別ファイルとしてそれぞれコピーする

特に気になるのは、-Hが指定されていない点です。
Linux のシステムディレクトリでは、ハードリンクを使用している箇所が多数あります。
ハードリンクの関係にあるファイル群のうち一つを編集すると他のハードリンクにも反映されるという特徴は、ハードリンクファイルを編集する手順に影響する重要な要素だと思います。
実際に Timeshift を利用しているユーザーから特に問題提起がされていないことから、実はそれほど大きな問題ではない可能性もあります。

しかし、どうしても気になる場合は、Timeshift と rsync を使い分けるのがおすすめです。
Timeshift の定期実行・差分管理と、rsyncのハードリンク保持で手軽にバックアップ周期とハードリンク保持のメリットを享受できます。
また、rsync は Timeshift のサポート範囲外であるデータバックアップにも使うことができます。
詳細は、次の記事で紹介します。

/run/timeshift/backup

理由は不明ですが、Timeshiftはスナップショット保存先のディレクトリを/run/timeshift/backup/ にマウントする仕様のようです。
このことはmountコマンドや、Timeshiftの実行ログから確認できます。

私はスナップショットの保存先に/homeを指定しているのですが、/run/timeshift/backup/配下にもバックアップが生成していました。
初めて気づいたときは二重にバックアップを取得していると思って焦ったのですが、そんなことはなく、問題ありませんでした。

$ mount | grep timeshift
/dev/mapper/fedora_pc-home on /run/timeshift/backup type ext4 (rw,relatime,seclabel)

Linux PC関連まとめ

endy-tech.hatenablog.jp

次の記事

Timeshift と rsync を併用し、システムバックアップとデータバックアップに両対応したバックアップ方式を紹介します。

endy-tech.hatenablog.jp

まとめ

Timeshift に関連して気になった点をメモしました。
最初は興味だけで調べていたのですが、cronとanacronの連携、Timeshiftが rsync -AHXを指定していないことがわかり、私としては役に立つ情報が得られました。
結果として、Timeshift と rsync を併用するバックアップ方式を考案できたのは大きかったです。

皆様にとっても参考になる情報があれば幸いです。