「Outline」や「Trilium Notes」、「AppFlowy」のような、いわゆるNotion代替のナレッジベースソフトはいくつかありますが、けっこう高機能なのが「AFFiNE」です。こちらもセルフホストが可能です。

LXDコンテナにセットアップ
Ubuntu 26.04ベースのLXDコンテナにセットアップするためのスクリプトです。コピペで動作するはず。
#!/usr/bin/env bash
# =============================================================================
# AFFiNE セルフホスト + Tailscale Serve セットアップスクリプト
# 対象: Ubuntu 26.04 LXD コンテナ (Tailscale 認証済み)
# 外部ポート: 3311 → 内部ポート: 3010 (AFFiNE)
# 既存の Tailscale Serve 設定は上書きしません
# =============================================================================
set -euo pipefail
# ── 色付きログ ───────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
success() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
die() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; }
# ── 設定値 ───────────────────────────────────────────────────────────────────
AFFINE_DIR="/opt/affine"
AFFINE_HOST_PORT=3010
AFFINE_TAILSCALE_PORT=3311
AFFINE_IMAGE="ghcr.io/toeverything/affine:stable"
# ── 事前確認 ─────────────────────────────────────────────────────────────────
info "事前チェックを開始します..."
command -v docker >/dev/null 2>&1 || die "Docker が見つかりません。先に Docker をインストールしてください。"
if ! docker compose version >/dev/null 2>&1; then
warn "docker compose プラグインが見つかりません。インストールします..."
apt-get update -qq
apt-get install -y -qq docker-compose-plugin
fi
command -v tailscale >/dev/null 2>&1 || die "tailscale コマンドが見つかりません。"
TS_STATUS=$(tailscale status --json 2>/dev/null \
| python3 -c "import sys,json; print(json.load(sys.stdin).get('BackendState','Unknown'))" 2>/dev/null \
|| echo "Unknown")
[[ "$TS_STATUS" == "Running" ]] \
|| die "Tailscale が Running 状態ではありません (現在: $TS_STATUS)。先に認証してください。"
TS_DOMAIN=$(tailscale status --json \
| python3 -c "
import sys, json
d = json.load(sys.stdin)
dns = d.get('Self', {}).get('DNSName', '')
print(dns.rstrip('.'))
" 2>/dev/null || echo "")
[[ -n "$TS_DOMAIN" ]] || die "Tailscale のドメイン名を取得できませんでした。"
success "Tailscale ドメイン: ${TS_DOMAIN}"
# ── 前回インストールのクリーンアップ ────────────────────────────────────────
if [[ -f "${AFFINE_DIR}/docker-compose.yml" ]]; then
warn "前回の ${AFFINE_DIR} が存在します。コンテナを停止して再インストールします..."
docker compose -f "${AFFINE_DIR}/docker-compose.yml" down --remove-orphans 2>/dev/null || true
fi
# ── ghcr.io の古い認証情報をクリア → 匿名 pull ──────────────────────────────
info "ghcr.io への匿名 pull を試みます..."
DOCKER_CONFIG_FILE="${HOME}/.docker/config.json"
if [[ -f "$DOCKER_CONFIG_FILE" ]]; then
python3 - <<PYEOF
import json
with open("${DOCKER_CONFIG_FILE}", "r") as f:
cfg = json.load(f)
removed = cfg.get("auths", {}).pop("ghcr.io", None)
with open("${DOCKER_CONFIG_FILE}", "w") as f:
json.dump(cfg, f, indent=2)
if removed:
print(" 既存の ghcr.io 認証情報を削除しました(匿名 pull に切り替え)")
PYEOF
fi
docker pull "${AFFINE_IMAGE}" \
|| die "イメージ pull に失敗しました。\nネットワーク疎通を確認してください: curl -I https://ghcr.io"
success "イメージ pull OK: ${AFFINE_IMAGE}"
# ── ポート衝突チェック ───────────────────────────────────────────────────────
if ss -tlnp | grep -q ":${AFFINE_HOST_PORT}\b"; then
die "ポート ${AFFINE_HOST_PORT} は既に使用されています。スクリプト先頭の AFFINE_HOST_PORT を変更してください。"
fi
# ── パスワード・シークレット生成 ─────────────────────────────────────────────
DB_PASSWORD="$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 32)"
SECRET_KEY="$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9' | head -c 48)"
# ── ディレクトリ作成 ─────────────────────────────────────────────────────────
info "ディレクトリを作成します: ${AFFINE_DIR}"
mkdir -p "${AFFINE_DIR}"/{config,storage,redis,postgres}
cd "${AFFINE_DIR}"
# ── .env 生成 ────────────────────────────────────────────────────────────────
info ".env ファイルを生成します..."
cat > "${AFFINE_DIR}/.env" <<EOF
# AFFiNE 環境設定 (自動生成: $(date '+%Y-%m-%d %H:%M:%S'))
# ⚠️ DB_PASSWORD / SECRET_KEY は初回起動後に変更しないでください
AFFINE_REVISION=stable
# DB
DB_USERNAME=affine
DB_PASSWORD=${DB_PASSWORD}
DB_DATABASE=affine
# ポート
PORT=3010
# 外部公開 URL (Tailscale Serve 経由)
AFFINE_SERVER_HTTPS=true
AFFINE_SERVER_EXTERNAL_URL=https://${TS_DOMAIN}:${AFFINE_TAILSCALE_PORT}
# テレメトリ・インデクサ
TELEMETRY_ENABLE=false
AFFINE_INDEXER_ENABLED=false
# 実行環境
NODE_ENV=production
SECRET_KEY=${SECRET_KEY}
# ボリュームパス(compose 変数展開用)
UPLOAD_LOCATION=${AFFINE_DIR}/storage
CONFIG_LOCATION=${AFFINE_DIR}/config
AFFINE_DIR_REDIS=${AFFINE_DIR}/redis
AFFINE_DIR_PG=${AFFINE_DIR}/postgres
EOF
chmod 600 "${AFFINE_DIR}/.env"
success ".env 生成完了"
# ── docker-compose.yml 生成 ──────────────────────────────────────────────────
info "docker-compose.yml を生成します..."
cat > "${AFFINE_DIR}/docker-compose.yml" <<'COMPOSE'
# AFFiNE docker-compose.yml
# イメージ: ghcr.io/toeverything/affine:stable (公式最新)
# 参照: https://docs.affine.pro/self-host-affine/references/docker-compose-yml
name: affine
services:
# ── マイグレーションジョブ(起動時のみ実行・完了後に終了) ────────────────
affine_migration:
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
container_name: affine_migration_job
command: ['sh', '-c', 'node ./scripts/self-host-predeploy.js']
depends_on:
affine_redis:
condition: service_healthy
affine_postgres:
condition: service_healthy
volumes:
- ${UPLOAD_LOCATION}:/root/.affine/storage
- ${CONFIG_LOCATION}:/root/.affine/config
env_file:
- .env
environment:
- REDIS_SERVER_HOST=affine_redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@affine_postgres:5432/${DB_DATABASE:-affine}
networks:
- affine_net
# ── メインアプリ ──────────────────────────────────────────────────────────
affine:
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
container_name: affine_server
ports:
- '${PORT:-3010}:3010'
depends_on:
affine_redis:
condition: service_healthy
affine_postgres:
condition: service_healthy
affine_migration:
condition: service_completed_successfully
volumes:
- ${UPLOAD_LOCATION}:/root/.affine/storage
- ${CONFIG_LOCATION}:/root/.affine/config
env_file:
- .env
environment:
- REDIS_SERVER_HOST=affine_redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@affine_postgres:5432/${DB_DATABASE:-affine}
logging:
driver: json-file
options:
max-size: 500m
max-file: '3'
restart: unless-stopped
networks:
- affine_net
# ── Redis ─────────────────────────────────────────────────────────────────
affine_redis:
image: redis:7-alpine
container_name: affine_redis
volumes:
- ${AFFINE_DIR_REDIS}:/data
healthcheck:
test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- affine_net
# ── PostgreSQL ────────────────────────────────────────────────────────────
affine_postgres:
image: postgres:16-alpine
container_name: affine_postgres
environment:
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_DATABASE:-affine}
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- ${AFFINE_DIR_PG}:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U ${DB_USERNAME} -d ${DB_DATABASE:-affine}']
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- affine_net
networks:
affine_net:
driver: bridge
COMPOSE
success "docker-compose.yml 生成完了"
# ── Docker サービス起動 ──────────────────────────────────────────────────────
info "AFFiNE コンテナを起動します..."
docker compose -f "${AFFINE_DIR}/docker-compose.yml" up -d
# 起動待機(最大 180 秒)
info "AFFiNE の起動を待機します (migration 完了まで最大 3 分)..."
WAIT=0
until curl -sf "http://localhost:${AFFINE_HOST_PORT}" >/dev/null 2>&1; do
sleep 5; WAIT=$((WAIT+5))
echo -n "."
if [[ $WAIT -ge 180 ]]; then
echo ""
warn "180秒経過しても応答なし。ログを確認してください:"
warn " docker compose -f ${AFFINE_DIR}/docker-compose.yml logs --tail=50 affine"
warn " docker compose -f ${AFFINE_DIR}/docker-compose.yml logs --tail=30 affine_migration"
break
fi
done
echo ""
if curl -sf "http://localhost:${AFFINE_HOST_PORT}" >/dev/null 2>&1; then
success "AFFiNE 起動確認 OK (port ${AFFINE_HOST_PORT})"
fi
# ── Tailscale Serve 設定(既存設定は保持) ───────────────────────────────────
info "既存の Tailscale Serve 設定をバックアップします..."
TS_SERVE_BACKUP="/tmp/tailscale-serve-backup-$(date +%Y%m%d%H%M%S).json"
tailscale serve status --json > "${TS_SERVE_BACKUP}" 2>/dev/null || echo '{}' > "${TS_SERVE_BACKUP}"
success "バックアップ: ${TS_SERVE_BACKUP}"
if tailscale serve status 2>/dev/null | grep -q ":${AFFINE_TAILSCALE_PORT}"; then
warn "Tailscale Serve ポート ${AFFINE_TAILSCALE_PORT} は既に設定済みです。スキップします。"
else
info "Tailscale Serve: ポート ${AFFINE_TAILSCALE_PORT} → localhost:${AFFINE_HOST_PORT} を追加..."
tailscale serve --https="${AFFINE_TAILSCALE_PORT}" --bg "http://localhost:${AFFINE_HOST_PORT}"
success "Tailscale Serve 設定追加完了"
fi
# ── systemd ユニット ─────────────────────────────────────────────────────────
info "systemd ユニットを作成します (affine.service)..."
cat > /etc/systemd/system/affine.service <<UNIT
[Unit]
Description=AFFiNE Self-Hosted (Docker Compose)
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=${AFFINE_DIR}
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=300
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload
systemctl enable affine.service
success "systemd ユニット登録完了"
# ── 完了サマリ ───────────────────────────────────────────────────────────────
echo ""
echo -e "${GREEN}╔══════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ AFFiNE セットアップ完了! ║${NC}"
echo -e "${GREEN}╚══════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e " 📝 アクセス URL:"
echo -e " ${CYAN}https://${TS_DOMAIN}:${AFFINE_TAILSCALE_PORT}${NC}"
echo ""
echo -e " 📁 インストール先: ${AFFINE_DIR}"
echo -e " 🔑 認証情報: ${AFFINE_DIR}/.env (chmod 600)"
echo -e " 💾 TS バックアップ: ${TS_SERVE_BACKUP}"
echo ""
echo -e " 🔧 管理コマンド:"
echo -e " 起動: docker compose -f ${AFFINE_DIR}/docker-compose.yml up -d"
echo -e " 停止: docker compose -f ${AFFINE_DIR}/docker-compose.yml down"
echo -e " ログ: docker compose -f ${AFFINE_DIR}/docker-compose.yml logs -f affine"
echo -e " 更新: docker compose -f ${AFFINE_DIR}/docker-compose.yml pull && \\"
echo -e " docker compose -f ${AFFINE_DIR}/docker-compose.yml up -d"
echo ""
echo -e " 📡 現在の Tailscale Serve 設定:"
tailscale serve status 2>/dev/null || true
echo ""
echo -e "${YELLOW} ⚠️ 初回アクセス時にメールアドレスとパスワードを設定してください${NC}"
echo -e "${GREEN}══════════════════════════════════════════════════════════════${NC}"
アカウント作成したあと日本語化
起動したらまずメールアドレスやパスワードを入力してアカウントを作成します。次にリロードして設定画面から日本語化出来ます。

とにかく多機能なので色々触ってみて判断という感じですね。

iPhoneやiPad用のアプリ
iPhoneやiPadで使えるクライアントアプリがあるのもポイントですね。普段はアプリで、いざという時もWebブラウザで、と使えます。
セルフホスト時のAFFiNE Cloudとローカル
AFFiNEをセルフホスト(Self-hosted)環境で利用する場合、Dockerなどを利用して自身のサーバー/PC上で動かすことになりますが、「AFFiNE Cloud」と「ローカル」があり混乱してしまいますが、どちらも公式のAFFiNE Web(app.affine.pro)には接続せず、完全に自分の環境だけで動作します。
Local Workspace(ローカル)データはデバイス(ブラウザのIndexedDBなど)のローカルストレージのみに保存
単一デバイスでの利用に最適。オフラインで完全に動作。
同期・リアルタイムコラボレーションは不可(他のデバイスやユーザーと共有できない)。
サーバー不要で、公式アプリやWeb版をローカルモードで使う場合に該当。
データ消失のリスクあり(ブラウザキャッシュクリアなど)。
Cloud Workspace(セルフホスト時のAFFiNE Cloud)セルフホストした自分のサーバー(Dockerなどで立てたバックエンド)にデータを保存・同期
自分のサーバーが「AFFiNE Cloud」の役割を果たすので、複数デバイス間同期、リアルタイムコラボレーション、メンバー招待などが可能。
公式AFFiNE Cloud(affine.pro)とは完全に別物。UI上では「AFFiNE Cloud」と表示されますが、自分のサーバーにしか接続しません(これが混乱の元で、GitHubイシューにもなっています)。
公式ドキュメントでは「AFFiNEはlocal-first」で、セルフホストでフル機能を使えると明記されています。結論から言うと、「どこまでデータを外部と同期させたいか」「機能制限をどこまで許容するか」が主な違いです。
1. セルフホスト時のAFFiNE Cloud利用
公式のDockerイメージを使用して、自身のサーバーでAFFiNEのサーバー機能(Cloud互換)をホストする場合です。
- 同期機能: ユーザー認証(ログイン)や他のユーザーとのワークスペース同期機能が利用可能になる。
- 運用形態: セルフホストでありながら、UIや機能が公式のAFFiNE Cloudに近くなる。
- データ管理: データは自身のサーバー内に保存されるため、公式のストレージに依存しない。
- メリット: 複数デバイスでの同期やチーム共有が可能。
- デメリット: Docker設定が多少複雑。 [1]
2. ローカル運用(ローカルサーバー/ブラウザ)
Dockerを使用せず、デスクトップアプリやブラウザのローカルストレージ(Local Storage)に直接データを保存する運用です。
- 同期機能: 基本的に同期機能はない(単一の端末でのみ利用可能)。
- データ管理: データはブラウザのローカルメモリやPC内のフォルダに保存される。
- メリット: セットアップが不要。完全にオフラインで動作し、データが外部に一切出ない。
- デメリット: 別の端末からアクセスできない。ブラウザキャッシュをクリアするとデータが消えるリスクがある。
比較まとめ
| 特徴 | セルフホストのCloud環境 | ローカル運用 (ローカルのみ) |
|---|---|---|
| データ保存先 | 自己のサーバー (Docker) | ローカル端末/ブラウザ |
| 同期 | 可能 (複数端末) | 不可 (単一端末) |
| セットアップ | 複雑 (Docker, DB等) | 不要 (アプリインストール等) |
| ログイン機能 | 有り | 無し |
| 主な用途 | チーム共有・複数デバイス利用 | 個人利用・オフライン作業 |
バックアップ・復元スクリプト
復元したあとは、登録したアカウントでサインインしてワークスペースを選択すれば表示されるはずです。
#!/bin/bash
set -euo pipefail
# =============================================================
# AFFiNE スクリプト インストーラー v5
#
# 同梱スクリプト:
# - affine-backup.sh v5: payload/サブディレクトリ構造で保存
# - affine-restore.sh v5: payload/対応・-U affine統一・postgres退避
#
# 使い方:
# sudo bash affine-install-v5.sh
# =============================================================
SCRIPT_DIR="/opt/lxd-data/script/affine"
BACKUP_DIR="/opt/lxd-data/affine"
GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
section() { echo -e "\n${CYAN}==> $*${NC}"; }
[ "$(id -u)" -eq 0 ] || { error "root または sudo で実行してください"; exit 1; }
echo ""
echo "════════════════════════════════════════════════"
echo " AFFiNE スクリプト インストーラー v5"
echo "════════════════════════════════════════════════"
echo ""
echo " インストール先: ${SCRIPT_DIR}/"
echo " バックアップ先: ${BACKUP_DIR}/"
echo ""
section "[Step 1] 自動バックアップ (cron) の設定"
echo ""
echo " [1] 毎日 深夜 3:00"
echo " [2] 毎週日曜 深夜 3:00"
echo " [3] 毎月1日 深夜 3:00"
echo " [4] cron に登録しない"
echo ""
CRON_CHOICE=""
while true; do
read -rp " 選択してください [1-4]: " CRON_CHOICE
case "${CRON_CHOICE}" in 1|2|3|4) break ;; *) warn "1〜4を入力してください" ;; esac
done
case "${CRON_CHOICE}" in
1) CRON_SCHEDULE="0 3 * * *" ; CRON_LABEL="毎日 深夜 3:00" ;;
2) CRON_SCHEDULE="0 3 * * 0" ; CRON_LABEL="毎週日曜 深夜 3:00" ;;
3) CRON_SCHEDULE="0 3 1 * *" ; CRON_LABEL="毎月1日 深夜 3:00" ;;
4) CRON_SCHEDULE="" ; CRON_LABEL="登録しない" ;;
esac
echo ""; info "cron 設定: ${CRON_LABEL}"
section "[Step 2] ディレクトリを作成..."
mkdir -p "${SCRIPT_DIR}" "${BACKUP_DIR}"
info "作成: ${SCRIPT_DIR}"
info "作成: ${BACKUP_DIR}"
section "[Step 3] スクリプトを展開..."
base64 -d << 'BASE64_BACKUP_EOF' > "${SCRIPT_DIR}/affine-backup.sh"
IyEvYmluL2Jhc2gKc2V0IC1ldW8gcGlwZWZhaWwKIyA9PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojICBB
RkZpTkUg44OQ44OD44Kv44Ki44OD44OX44K544Kv44Oq44OX44OIIHY1CiMKIyAg5L2/44GE5pa5
OgojICAgIHN1ZG8gYmFzaCBhZmZpbmUtYmFja3VwLnNoICAgICAgICAgICMg44OQ44OD44Kv44Ki
44OD44OX44KS5a6f6KGMCiMgICAgc3VkbyBiYXNoIGFmZmluZS1iYWNrdXAuc2ggbGlzdCAgICAg
IyDjg5Djg4Pjgq/jgqLjg4Pjg5fkuIDopqfjgpLooajnpLoKIyAgICBzdWRvIGJhc2ggYWZmaW5l
LWJhY2t1cC5zaCBjbGVhbiAgICAjIOWPpOOBhOODkOODg+OCr+OCouODg+ODl+OCkuWJiumZpAoj
CiMgIOODkOODg+OCr+OCouODg+ODl+S/neWtmOWFiDogL29wdC9seGQtZGF0YS9hZmZpbmUvCiMg
IOODkOODg+OCr+OCouODg+ODl+WvvuixoSAgOiAvb3B0L2FmZmluZS9zdG9yYWdlLywgL29wdC9h
ZmZpbmUvY29uZmlnLywKIyAgICAgICAgICAgICAgICAgICAgICAvb3B0L2FmZmluZS8uZW52ICAo
RELoqo3oqLzmg4XloLHjg7tTRUNSRVRfS0VZ44KS5ZCr44KAKQojICAgICAgICAgICAgICAgICAg
ICAgIC9vcHQvYWZmaW5lL2RvY2tlci1jb21wb3NlLnltbAojICAgICAgICAgICAgICAgICAgICAg
IFBvc3RncmVTUUwgREIg44OA44Oz44OXIChwZ19kdW1wKQojCiMgIOOCouODvOOCq+OCpOODluan
i+mAoDoKIyAgICBhZmZpbmVfWVlZWU1NRERfSEhNTVNTLnRhci5negojICAgIOKUlOKUgOKUgCBw
YXlsb2FkLyAgICAgICAgICDihpAg5b+F44Ga44GT44Gu44K144OW44OH44Kj44Os44Kv44OI44Oq
44Gr5qC857SNCiMgICAgICAgIOKUnOKUgOKUgCBzdG9yYWdlLwojICAgICAgICDilJzilIDilIAg
Y29uZmlnLwojICAgICAgICDilJzilIDilIAgLmVudgojICAgICAgICDilJzilIDilIAgZG9ja2Vy
LWNvbXBvc2UueW1sCiMgICAgICAgIOKUlOKUgOKUgCBwb3N0Z3Jlc19kdW1wLnNxbC5negojID09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09CgpBRkZJTkVfRElSPSIvb3B0L2FmZmluZSIKQkFDS1VQX0RJUj0i
L29wdC9seGQtZGF0YS9hZmZpbmUiClBPU1RHUkVTX0NPTlRBSU5FUj0iYWZmaW5lX3Bvc3RncmVz
IgpQT1NUR1JFU19VU0VSPSJhZmZpbmUiClBPU1RHUkVTX0RCPSJhZmZpbmUiCktFRVBfREFZUz03
CgpHUkVFTj0nXDAzM1swOzMybScKUkVEPSdcMDMzWzA7MzFtJwpZRUxMT1c9J1wwMzNbMTszM20n
CkNZQU49J1wwMzNbMDszNm0nCk5DPSdcMDMzWzBtJwoKaW5mbygpICAgIHsgZWNobyAtZSAiJHtH
UkVFTn1bSU5GT10ke05DfSAgJCoiOyB9Cndhcm4oKSAgICB7IGVjaG8gLWUgIiR7WUVMTE9XfVtX
QVJOXSR7TkN9ICAkKiI7IH0KZXJyb3IoKSAgIHsgZWNobyAtZSAiJHtSRUR9W0VSUk9SXSR7TkN9
ICQqIiA+JjI7IH0Kc2VjdGlvbigpIHsgZWNobyAtZSAiXG4ke0NZQU59PT0+ICQqJHtOQ30iOyB9
CgpwcmludF9iYW5uZXIoKSB7CiAgICBlY2hvICIiCiAgICBlY2hvICLilZDilZDilZDilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZAiCiAgICBlY2hvICIgIEFGRmlO
RSDjg5Djg4Pjgq/jgqLjg4Pjg5fjgrnjgq/jg6rjg5fjg4ggdjUiCiAgICBlY2hvICLilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZAiCiAgICBlY2hv
ICIiCn0KCnVzYWdlKCkgewogICAgcHJpbnRfYmFubmVyCiAgICBlY2hvICLkvb/jgYTmlrk6Igog
ICAgZWNobyAiICAkMCAgICAgICAgICAgICAjIOODkOODg+OCr+OCouODg+ODl+OCkuWun+ihjCIK
ICAgIGVjaG8gIiAgJDAgbGlzdCAgICAgICAgIyDjg5Djg4Pjgq/jgqLjg4Pjg5fkuIDopqfjgpLo
oajnpLoiCiAgICBlY2hvICIgICQwIGNsZWFuICAgICAgICMg5Y+k44GE44OQ44OD44Kv44Ki44OD
44OX44KS5YmK6ZmkICgke0tFRVBfREFZU33ml6Xku6XkuIrliY0pIgogICAgZWNobyAiIgogICAg
ZWNobyAi5L+d5a2Y5YWIOiAke0JBQ0tVUF9ESVJ9LyIKICAgIGVjaG8gIiIKfQoKY2hlY2tfcm9v
dCgpIHsKICAgIGlmIFsgIiQoaWQgLXUpIiAtbmUgMCBdOyB0aGVuCiAgICAgICAgZXJyb3IgIuOB
k+OBruOCueOCr+ODquODl+ODiOOBryByb290IOOBvuOBn+OBryBzdWRvIOOBp+Wun+ihjOOBl+OB
puOBj+OBoOOBleOBhCIKICAgICAgICBleGl0IDEKICAgIGZpCn0KCmNoZWNrX2FmZmluZV9kaXIo
KSB7CiAgICBpZiBbICEgLWQgIiR7QUZGSU5FX0RJUn0vc3RvcmFnZSIgXSAmJiBbICEgLWQgIiR7
QUZGSU5FX0RJUn0vY29uZmlnIiBdOyB0aGVuCiAgICAgICAgZXJyb3IgIkFGRmlORSDjg4fjgqPj
g6zjgq/jg4jjg6rjgYzopovjgaTjgYvjgorjgb7jgZvjgpM6ICR7QUZGSU5FX0RJUn0iCiAgICAg
ICAgZXJyb3IgIuOCueOCr+ODquODl+ODiOWFiOmgreOBriBBRkZJTkVfRElSIOOCkuato+OBl+OB
hOODkeOCueOBq+WkieabtOOBl+OBpuOBj+OBoOOBleOBhCIKICAgICAgICBleGl0IDEKICAgIGZp
Cn0KCmRvX2JhY2t1cCgpIHsKICAgIHByaW50X2Jhbm5lcgogICAgY2hlY2tfcm9vdAogICAgY2hl
Y2tfYWZmaW5lX2RpcgoKICAgIGxvY2FsIFRJTUVTVEFNUAogICAgVElNRVNUQU1QPSQoZGF0ZSAr
IiVZJW0lZF8lSCVNJVMiKQogICAgbG9jYWwgQkFDS1VQX0ZJTEU9IiR7QkFDS1VQX0RJUn0vYWZm
aW5lXyR7VElNRVNUQU1QfS50YXIuZ3oiCiAgICAjIHBheWxvYWQvIOOCteODluODh+OCo+ODrOOC
r+ODiOODque1jOeUseOBp+OCouODvOOCq+OCpOODliAocmVzdG9yZeWBtOOBqOani+mAoOOCkue1
seS4gCkKICAgIGxvY2FsIFdPUktfRElSCiAgICBXT1JLX0RJUj0kKG1rdGVtcCAtZCkKICAgIHRy
YXAgInJtIC1yZiAnJHtXT1JLX0RJUn0nIiBFWElUCiAgICBsb2NhbCBQQVlMT0FEPSIke1dPUktf
RElSfS9wYXlsb2FkIgogICAgbWtkaXIgLXAgIiR7UEFZTE9BRH0iCgogICAgc2VjdGlvbiAiWzEv
NV0g44OQ44OD44Kv44Ki44OD44OX44OH44Kj44Os44Kv44OI44Oq44KS5rqW5YKZLi4uIgogICAg
bWtkaXIgLXAgIiR7QkFDS1VQX0RJUn0iCiAgICBpbmZvICLkv53lrZjlhYg6ICR7QkFDS1VQX0RJ
Un0iCgogICAgIyDilIDilIAgUG9zdGdyZVNRTCDjg4Djg7Pjg5cg4pSA4pSA4pSA4pSA4pSA4pSA
4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA
4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA
4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACiAgICBzZWN0aW9uICJbMi81XSBQb3N0Z3Jl
U1FMIOODgOODs+ODl+OCkuWPluW+ly4uLiIKICAgIGlmIGRvY2tlciBwcyAtLWZvcm1hdCAne3su
TmFtZXN9fScgfCBncmVwIC1xICJeJHtQT1NUR1JFU19DT05UQUlORVJ9JCI7IHRoZW4KICAgICAg
ICBpZiBkb2NrZXIgZXhlYyAiJHtQT1NUR1JFU19DT05UQUlORVJ9IiBcCiAgICAgICAgICAgIHBn
X2R1bXAgLVUgIiR7UE9TVEdSRVNfVVNFUn0iIC1kICIke1BPU1RHUkVTX0RCfSIgXAogICAgICAg
ICAgICB8IGd6aXAgPiAiJHtQQVlMT0FEfS9wb3N0Z3Jlc19kdW1wLnNxbC5neiI7IHRoZW4KICAg
ICAgICAgICAgbG9jYWwgRFVNUF9TSVpFCiAgICAgICAgICAgIERVTVBfU0laRT0kKGR1IC1zaCAi
JHtQQVlMT0FEfS9wb3N0Z3Jlc19kdW1wLnNxbC5neiIgfCBjdXQgLWYxKQogICAgICAgICAgICBp
bmZvICJEQiDjg4Djg7Pjg5flrozkuoY6IHBvc3RncmVzX2R1bXAuc3FsLmd6ICgke0RVTVBfU0la
RX0pIgogICAgICAgIGVsc2UKICAgICAgICAgICAgZXJyb3IgIlBvc3RncmVTUUwg44OA44Oz44OX
44Gr5aSx5pWX44GX44G+44GX44GfIgogICAgICAgICAgICBybSAtcmYgIiR7V09SS19ESVJ9Igog
ICAgICAgICAgICBleGl0IDEKICAgICAgICBmaQogICAgZWxzZQogICAgICAgIHdhcm4gIlBvc3Rn
cmVTUUwg44Kz44Oz44OG44OKICgke1BPU1RHUkVTX0NPTlRBSU5FUn0pIOOBjOi1t+WLleOBl+OB
puOBhOOBvuOBm+OCkyIKICAgICAgICB3YXJuICJEQiDjg4Djg7Pjg5fjgpLjgrnjgq3jg4Pjg5fj
gZfjgb7jgZkiCiAgICAgICAgZWNobyAiU0tJUFBFRF9SRUFTT049Y29udGFpbmVyX25vdF9ydW5u
aW5nIiA+ICIke1BBWUxPQUR9L3Bvc3RncmVzX2R1bXAuU0tJUFBFRCIKICAgIGZpCgogICAgIyDi
lIDilIAgYWZmaW5lIOOCs+ODs+ODhuODiuOCkuS4gOaZguWBnOatoiDilIDilIDilIDilIDilIDi
lIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDi
lIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDi
lIDilIDilIAKICAgIHNlY3Rpb24gIlszLzVdIEFGRmlORSDjgrPjg7Pjg4bjg4rjgpLkuIDmmYLl
gZzmraIuLi4iCiAgICBsb2NhbCBBRkZJTkVfV0FTX1JVTk5JTkc9ZmFsc2UKICAgIGlmIGRvY2tl
ciBwcyAtLWZvcm1hdCAne3suTmFtZXN9fScgfCBncmVwIC1xICJeYWZmaW5lX3NlcnZlciQiOyB0
aGVuCiAgICAgICAgZG9ja2VyIGNvbXBvc2UgLWYgIiR7QUZGSU5FX0RJUn0vZG9ja2VyLWNvbXBv
c2UueW1sIiBzdG9wIGFmZmluZSAyPi9kZXYvbnVsbCBcCiAgICAgICAgICAgIHx8IGRvY2tlciBz
dG9wIGFmZmluZV9zZXJ2ZXIKICAgICAgICBpbmZvICJhZmZpbmVfc2VydmVyIOOCkuWBnOatouOB
l+OBvuOBl+OBnyIKICAgICAgICBBRkZJTkVfV0FTX1JVTk5JTkc9dHJ1ZQogICAgZWxzZQogICAg
ICAgIHdhcm4gImFmZmluZV9zZXJ2ZXIg44Gv5pei44Gr5YGc5q2i44GX44Gm44GE44G+44GZIgog
ICAgZmkKCiAgICAjIOKUgOKUgCDjg5XjgqHjgqTjg6vjgpLjgrPjg5Tjg7wg4pSA4pSA4pSA4pSA
4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA
4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA
4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACiAgICBzZWN0aW9uICJbNC81
XSDjg5XjgqHjgqTjg6vjgpLjgqLjg7zjgqvjgqTjg5YuLi4iCgogICAgWyAtZCAiJHtBRkZJTkVf
RElSfS9zdG9yYWdlIiBdICAgICAgICAgICAgJiYgY3AgLWEgIiR7QUZGSU5FX0RJUn0vc3RvcmFn
ZSIgICAgICAgICAgICAiJHtQQVlMT0FEfS9zdG9yYWdlIgogICAgWyAtZCAiJHtBRkZJTkVfRElS
fS9jb25maWciIF0gICAgICAgICAgICAgJiYgY3AgLWEgIiR7QUZGSU5FX0RJUn0vY29uZmlnIiAg
ICAgICAgICAgICAiJHtQQVlMT0FEfS9jb25maWciCiAgICBbIC1mICIke0FGRklORV9ESVJ9L2Rv
Y2tlci1jb21wb3NlLnltbCIgXSAmJiBjcCAgICAiJHtBRkZJTkVfRElSfS9kb2NrZXItY29tcG9z
ZS55bWwiICIke1BBWUxPQUR9LyIKICAgICMgLmVudiDjga/lv4XpoIggKERCX1BBU1NXT1JEIC8g
U0VDUkVUX0tFWSDjgpLlkKvjgoApCiAgICBpZiBbIC1mICIke0FGRklORV9ESVJ9Ly5lbnYiIF07
IHRoZW4KICAgICAgICBjcCAiJHtBRkZJTkVfRElSfS8uZW52IiAiJHtQQVlMT0FEfS8uZW52Igog
ICAgICAgIGluZm8gIi5lbnYg44KS44OQ44OD44Kv44Ki44OD44OX44GX44G+44GX44GfIChEQl9Q
QVNTV09SRCAvIFNFQ1JFVF9LRVkg44KS5ZCr44KAKSIKICAgIGVsc2UKICAgICAgICB3YXJuICIu
ZW52IOOBjOimi+OBpOOBi+OCiuOBvuOBm+OCkzogJHtBRkZJTkVfRElSfS8uZW52IgogICAgZmkK
CiAgICAjIOODkOODg+OCr+OCouODg+ODl+aDheWgsQogICAgY2F0ID4gIiR7UEFZTE9BRH0vYmFj
a3VwX2luZm8udHh0IiA8PCBJTkZPCkFGRmlORSBCYWNrdXAgSW5mb3JtYXRpb24KPT09PT09PT09
PT09PT09PT09PT09PT09PQpEYXRlICAgICAgOiAkKGRhdGUgJyslWS0lbS0lZCAlSDolTTolUycp
Ckhvc3RuYW1lICA6ICQoaG9zdG5hbWUpCkFGRklORV9ESVI6ICR7QUZGSU5FX0RJUn0KUEdfREIg
ICAgIDogJHtQT1NUR1JFU19EQn0KUEdfVVNFUiAgIDogJHtQT1NUR1JFU19VU0VSfQpQR19EdW1w
ICAgOiAkKFsgLWYgIiR7UEFZTE9BRH0vcG9zdGdyZXNfZHVtcC5zcWwuZ3oiIF0gJiYgZWNobyAi
T0siIHx8IGVjaG8gIlNLSVBQRUQiKQpFTlZfQmFja3VwOiAkKFsgLWYgIiR7UEFZTE9BRH0vLmVu
diIgXSAmJiBlY2hvICJPSyIgfHwgZWNobyAiTk9UIEZPVU5EIikKSU5GTwoKICAgICMgdGFyLmd6
IOOBq+Wcp+e4riAo44Ki44O844Kr44Kk44OW5qip6ZmQ44KSIDYwMCDjgafkv53lrZgpCiAgICB0
YXIgLWN6ZiAiJHtCQUNLVVBfRklMRX0iIC1DICIke1dPUktfRElSfSIgInBheWxvYWQiCiAgICBj
aG1vZCA2MDAgIiR7QkFDS1VQX0ZJTEV9IgogICAgcm0gLXJmICIke1dPUktfRElSfSIKICAgIHRy
YXAgLSBFWElUCgogICAgbG9jYWwgQkFDS1VQX1NJWkUKICAgIEJBQ0tVUF9TSVpFPSQoZHUgLXNo
ICIke0JBQ0tVUF9GSUxFfSIgfCBjdXQgLWYxKQogICAgaW5mbyAi44Ki44O844Kr44Kk44OW5a6M
5LqGOiAkKGJhc2VuYW1lICIke0JBQ0tVUF9GSUxFfSIpICgke0JBQ0tVUF9TSVpFfSkiCgogICAg
c2hhMjU2c3VtICIke0JBQ0tVUF9GSUxFfSIgPiAiJHtCQUNLVVBfRklMRX0uc2hhMjU2IgogICAg
Y2htb2QgNjAwICIke0JBQ0tVUF9GSUxFfS5zaGEyNTYiCiAgICBpbmZvICLjg4Hjgqfjg4Pjgq/j
grXjg6Dkv53lrZg6ICQoYmFzZW5hbWUgIiR7QkFDS1VQX0ZJTEV9Iikuc2hhMjU2IgoKICAgICMg
4pSA4pSAIEFGRmlORSDjgrPjg7Pjg4bjg4rjgpLlho3otbfli5Ug4pSA4pSA4pSA4pSA4pSA4pSA
4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA
4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA
4pSA4pSA4pSACiAgICBzZWN0aW9uICJbNS81XSBBRkZpTkUg44Kz44Oz44OG44OK44KS5YaN6LW3
5YuVLi4uIgogICAgaWYgWyAiJHtBRkZJTkVfV0FTX1JVTk5JTkd9IiA9IHRydWUgXTsgdGhlbgog
ICAgICAgIGNkICIke0FGRklORV9ESVJ9IgogICAgICAgIGRvY2tlciBjb21wb3NlIHVwIC1kCiAg
ICAgICAgaW5mbyAi44Kz44Oz44OG44OK44KS5YaN6LW35YuV44GX44G+44GX44GfIgogICAgZWxz
ZQogICAgICAgIHdhcm4gIuOCs+ODs+ODhuODiuOBr+WBnOatouS4reOBruOBvuOBvuOBq+OBl+OB
vuOBmSIKICAgICAgICB3YXJuICLmiYvli5Xotbfli5U6IGNkICR7QUZGSU5FX0RJUn0gJiYgZG9j
a2VyIGNvbXBvc2UgdXAgLWQiCiAgICBmaQoKICAgICMg5Y+k44GE44OQ44OD44Kv44Ki44OD44OX
44KS6Ieq5YuV5YmK6ZmkCiAgICBsb2NhbCBPTERfRklMRVMKICAgIE9MRF9GSUxFUz0kKGZpbmQg
IiR7QkFDS1VQX0RJUn0iIC1uYW1lICJhZmZpbmVfKi50YXIuZ3oiIFwKICAgICAgICAtbXRpbWUg
Iiske0tFRVBfREFZU30iIDI+L2Rldi9udWxsIHx8IHRydWUpCiAgICBpZiBbIC1uICIke09MRF9G
SUxFU30iIF07IHRoZW4KICAgICAgICBsb2NhbCBPTERfQ09VTlQKICAgICAgICBPTERfQ09VTlQ9
JChlY2hvICIke09MRF9GSUxFU30iIHwgd2MgLWwpCiAgICAgICAgZWNobyAiJHtPTERfRklMRVN9
IiB8IHdoaWxlIHJlYWQgLXIgRjsgZG8KICAgICAgICAgICAgcm0gLWYgIiR7Rn0iICIke0Z9LnNo
YTI1NiIKICAgICAgICAgICAgaW5mbyAi5Y+k44GE44OQ44OD44Kv44Ki44OD44OX44KS5YmK6Zmk
OiAkKGJhc2VuYW1lICIke0Z9IikiCiAgICAgICAgZG9uZQogICAgICAgIGluZm8gIiR7T0xEX0NP
VU5UfSDku7bjga7lj6TjgYTjg5Djg4Pjgq/jgqLjg4Pjg5fjgpLliYrpmaTjgZfjgb7jgZfjgZ8g
KCR7S0VFUF9EQVlTfeaXpeS7peS4iuWJjSkiCiAgICBmaQoKICAgIGVjaG8gIiIKICAgIGVjaG8g
IuKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKV
kOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKV
kOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkCIK
ICAgIGVjaG8gLWUgIiAgJHtHUkVFTn3inIUgIOODkOODg+OCr+OCouODg+ODl+WujOS6hu+8gSR7
TkN9IgogICAgZWNobyAi4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ
4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ
4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ
4pWQ4pWQ4pWQ4pWQIgogICAgZWNobyAiIgogICAgZWNobyAiICDwn5OmIOODleOCoeOCpOODqyAg
ICA6ICR7QkFDS1VQX0ZJTEV9IgogICAgZWNobyAiICDwn5OPIOOCteOCpOOCuiAgICAgIDogJHtC
QUNLVVBfU0laRX0iCiAgICBlY2hvICIgIPCflZAg5a6M5LqG5pmC5Yi7ICAgIDogJChkYXRlICcr
JVktJW0tJWQgJUg6JU06JVMnKSIKICAgIGVjaG8gIiIKfQoKZG9fbGlzdCgpIHsKICAgIHByaW50
X2Jhbm5lcgoKICAgIGlmIFsgISAtZCAiJHtCQUNLVVBfRElSfSIgXTsgdGhlbgogICAgICAgIHdh
cm4gIuODkOODg+OCr+OCouODg+ODl+ODh+OCo+ODrOOCr+ODiOODquOBjOWtmOWcqOOBl+OBvuOB
m+OCkzogJHtCQUNLVVBfRElSfSIKICAgICAgICBleGl0IDAKICAgIGZpCgogICAgbG9jYWwgRklM
RVMKICAgIEZJTEVTPSQoZmluZCAiJHtCQUNLVVBfRElSfSIgLW1heGRlcHRoIDEgLW5hbWUgImFm
ZmluZV8qLnRhci5neiIgXAogICAgICAgIC1wcmludGYgJyVUQCAlcFxuJyAyPi9kZXYvbnVsbCB8
IHNvcnQgLXJuIHwgY3V0IC1kJyAnIC1mMi0pCgogICAgaWYgWyAteiAiJHtGSUxFU30iIF07IHRo
ZW4KICAgICAgICB3YXJuICLjg5Djg4Pjgq/jgqLjg4Pjg5fjg5XjgqHjgqTjg6vjgYzopovjgaTj
gYvjgorjgb7jgZvjgpMiCiAgICAgICAgZXhpdCAwCiAgICBmaQoKICAgIGVjaG8gIuODkOODg+OC
r+OCouODg+ODl+S4gOimpzogJHtCQUNLVVBfRElSfSIKICAgIGVjaG8gIiIKICAgIHByaW50ZiAi
ICAlLTUwcyAgJThzICAlc1xuIiAi44OV44Kh44Kk44Or5ZCNIiAi44K144Kk44K6IiAi5L+d5a2Y
5pel5pmCIgogICAgZWNobyAiICAkKHByaW50ZiAnJS4wc+KUgCcgezEuLjc1fSkiCgogICAgd2hp
bGUgSUZTPSByZWFkIC1yIEZJTEU7IGRvCiAgICAgICAgbG9jYWwgQkFTRU5BTUUgU0laRSBNVElN
RQogICAgICAgIEJBU0VOQU1FPSQoYmFzZW5hbWUgIiR7RklMRX0iKQogICAgICAgIFNJWkU9JChk
dSAtc2ggIiR7RklMRX0iIHwgY3V0IC1mMSkKICAgICAgICBNVElNRT0kKHN0YXQgLWMgJyV5JyAi
JHtGSUxFfSIgfCBjdXQgLWQnLicgLWYxKQogICAgICAgIHByaW50ZiAiICAlLTUwcyAgJThzICAl
c1xuIiAiJHtCQVNFTkFNRX0iICIke1NJWkV9IiAiJHtNVElNRX0iCiAgICBkb25lIDw8PCAiJHtG
SUxFU30iCgogICAgZWNobyAiIgogICAgbG9jYWwgVE9UQUxfQ09VTlQgVE9UQUxfU0laRQogICAg
VE9UQUxfQ09VTlQ9JChlY2hvICIke0ZJTEVTfSIgfCB3YyAtbCkKICAgIFRPVEFMX1NJWkU9JChk
dSAtc2ggIiR7QkFDS1VQX0RJUn0iIHwgY3V0IC1mMSkKICAgIGVjaG8gIiAg5ZCI6KiIOiAke1RP
VEFMX0NPVU5UfSDku7YgLyAke1RPVEFMX1NJWkV9IgogICAgZWNobyAiIgp9Cgpkb19jbGVhbigp
IHsKICAgIHByaW50X2Jhbm5lcgogICAgY2hlY2tfcm9vdAoKICAgIGxvY2FsIE9MRF9GSUxFUwog
ICAgT0xEX0ZJTEVTPSQoZmluZCAiJHtCQUNLVVBfRElSfSIgLW1heGRlcHRoIDEgLW5hbWUgImFm
ZmluZV8qLnRhci5neiIgXAogICAgICAgIC1tdGltZSAiKyR7S0VFUF9EQVlTfSIgMj4vZGV2L251
bGwgfHwgdHJ1ZSkKCiAgICBpZiBbIC16ICIke09MRF9GSUxFU30iIF07IHRoZW4KICAgICAgICBp
bmZvICIke0tFRVBfREFZU33ml6Xku6XkuIrliY3jga7jg5Djg4Pjgq/jgqLjg4Pjg5fjga/jgYLj
gorjgb7jgZvjgpMiCiAgICAgICAgZXhpdCAwCiAgICBmaQoKICAgIHdhcm4gIuS7peS4i+OBruOD
leOCoeOCpOODq+OCkuWJiumZpOOBl+OBvuOBmSAoJHtLRUVQX0RBWVN95pel5Lul5LiK5YmNKToi
CiAgICBlY2hvICIke09MRF9GSUxFU30iIHwgd2hpbGUgcmVhZCAtciBGOyBkbwogICAgICAgIGVj
aG8gIiAgLSAkKGJhc2VuYW1lICIke0Z9IikgKCQoZHUgLXNoICIke0Z9IiB8IGN1dCAtZjEpKSIK
ICAgIGRvbmUKICAgIGVjaG8gIiIKICAgIHJlYWQgLXJwICIgIOWJiumZpOOBl+OBvuOBmeOBiz8g
W3kvTl06ICIgQ09ORklSTQogICAgaWYgW1sgISAiJHtDT05GSVJNfSIgPX4gXltZeV0kIF1dOyB0
aGVuCiAgICAgICAgd2FybiAi44Kt44Oj44Oz44K744Or44GX44G+44GX44GfIgogICAgICAgIGV4
aXQgMAogICAgZmkKCiAgICBlY2hvICIke09MRF9GSUxFU30iIHwgd2hpbGUgcmVhZCAtciBGOyBk
bwogICAgICAgIHJtIC1mICIke0Z9IiAiJHtGfS5zaGEyNTYiCiAgICAgICAgaW5mbyAi5YmK6Zmk
OiAkKGJhc2VuYW1lICIke0Z9IikiCiAgICBkb25lCgogICAgaW5mbyAi44Kv44Oq44O844Oz44Ki
44OD44OX5a6M5LqGIgogICAgZWNobyAiIgp9CgpDT01NQU5EPSIkezE6LWJhY2t1cH0iCgpjYXNl
ICIke0NPTU1BTkR9IiBpbgogICAgYmFja3VwfCIiKSAgZG9fYmFja3VwIDs7CiAgICBsaXN0KSAg
ICAgICBkb19saXN0ICAgOzsKICAgIGNsZWFuKSAgICAgIGRvX2NsZWFuICA7OwogICAgLWh8LS1o
ZWxwfGhlbHApIHVzYWdlIDs7CiAgICAqKQogICAgICAgIGVycm9yICLkuI3mmI7jgarjgrPjg57j
g7Pjg4k6ICR7Q09NTUFORH0iCiAgICAgICAgdXNhZ2UKICAgICAgICBleGl0IDEKICAgICAgICA7
Owplc2FjCg==
BASE64_BACKUP_EOF
info "作成: ${SCRIPT_DIR}/affine-backup.sh"
base64 -d << 'BASE64_RESTORE_EOF' > "${SCRIPT_DIR}/affine-restore.sh"
IyEvYmluL2Jhc2gKc2V0IC1ldW8gcGlwZWZhaWwKIyA9PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojICBB
RkZpTkUg5b6p5YWD44K544Kv44Oq44OX44OIIHY1CiMKIyAg5L2/44GE5pa5OgojICAgIHN1ZG8g
YmFzaCBhZmZpbmUtcmVzdG9yZS5zaAojCiMgIOODkOODg+OCr+OCouODg+ODl+S/neWtmOWFiDog
L29wdC9seGQtZGF0YS9hZmZpbmUvCiMgIOW+qeWFg+WFiCAgICAgICAgICAgIDog6Ieq5YuV5qSc
5Ye6ICjjgb7jgZ/jga/jg6bjg7zjgrbjg7zmjIflrpopCiMKIyAg5a++5b+c44Ki44O844Kr44Kk
44OW5qeL6YCgOgojICAgIGFmZmluZV8qLnRhci5negojICAgIOKUlOKUgOKUgCBwYXlsb2FkLyAg
ICAgICAgICDihpAgYmFja3VwIHY1IOOBruani+mAoAojICAgICAgICDilJzilIDilIAgc3RvcmFn
ZS8KIyAgICAgICAg4pSc4pSA4pSAIGNvbmZpZy8KIyAgICAgICAg4pSc4pSA4pSAIC5lbnYKIyAg
ICAgICAg4pSc4pSA4pSAIGRvY2tlci1jb21wb3NlLnltbAojICAgICAgICDilJTilIDilIAgcG9z
dGdyZXNfZHVtcC5zcWwuZ3oKIwojICB2NSDlpInmm7Tngrk6CiMgICAgLSBwYXlsb2FkLyDjgrXj
g5bjg4fjgqPjg6zjgq/jg4jjg6rmp4vpgKDjgavlr77lv5wgKGJhY2t1cCB2NSDjgajntbHkuIAp
CiMgICAgLSBEQuaTjeS9nOOCkiAtVSBhZmZpbmUg44Gr57Wx5LiAIChwb3N0Z3JlcyDjgrnjg7zj
g5Hjg7zjg6bjg7zjgrbjg7zkuI3opoEpCiMgICAgLSBEUk9QL0NSRUFURSBEQVRBQkFTRSDjgpIg
dGVtcGxhdGUxIOe1jOeUseOBp+Wun+ihjAojICAgIC0gc3RvcmFnZSAvIGNvbmZpZyAvIC5lbnYg
LyBwb3N0Z3JlcyDjgZnjgbnjgabjgpLpgIDpgb8KIyAgICAtIC5lbnYg44GM44Gq44GE5aC05ZCI
44Gv6YCA6YG/44GX44GfIC5lbnYg44KS6Ieq5YuV5rWB55SoCiMgPT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT0KCkJBQ0tVUF9ESVI9Ii9vcHQvbHhkLWRhdGEvYWZmaW5lIgpQT1NUR1JFU19VU0VSPSJhZmZp
bmUiClBPU1RHUkVTX0RCPSJhZmZpbmUiCgpHUkVFTj0nXDAzM1swOzMybScKUkVEPSdcMDMzWzA7
MzFtJwpZRUxMT1c9J1wwMzNbMTszM20nCkNZQU49J1wwMzNbMDszNm0nCk5DPSdcMDMzWzBtJwoK
aW5mbygpICAgIHsgZWNobyAtZSAiJHtHUkVFTn1bSU5GT10ke05DfSAgJCoiOyB9Cndhcm4oKSAg
ICB7IGVjaG8gLWUgIiR7WUVMTE9XfVtXQVJOXSR7TkN9ICAkKiI7IH0KZXJyb3IoKSAgIHsgZWNo
byAtZSAiJHtSRUR9W0VSUk9SXSR7TkN9ICQqIiA+JjI7IH0Kc2VjdGlvbigpIHsgZWNobyAtZSAi
XG4ke0NZQU59PT0+ICQqJHtOQ30iOyB9CgpwcmludF9iYW5uZXIoKSB7CiAgICBlY2hvICIiCiAg
ICBlY2hvICLilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZDilZAiCiAgICBlY2hvICIgIEFGRmlORSDlvqnlhYPjgrnjgq/jg6rjg5fjg4ggdjUiCiAgICBl
Y2hvICLilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZAiCiAgICBlY2hvICIiCn0KCmNoZWNrX3Jvb3QoKSB7CiAgICBpZiBbICIkKGlkIC11KSIgLW5l
IDAgXTsgdGhlbgogICAgICAgIGVycm9yICLjgZPjga7jgrnjgq/jg6rjg5fjg4jjga8gcm9vdCDj
gb7jgZ/jga8gc3VkbyDjgaflrp/ooYzjgZfjgabjgY/jgaDjgZXjgYQiCiAgICAgICAgZXhpdCAx
CiAgICBmaQp9CgojIOOCsOODreODvOODkOODq+WkieaVsApTRUxFQ1RFRF9CQUNLVVA9IiIKSEFT
X1BHX0RVTVA9ZmFsc2UKSEFTX0VOVj1mYWxzZQpSRVNUT1JFX0FGRklORV9ESVI9IiIKCiMg4pSA
4pSAIOODkOODg+OCr+OCouODg+ODl+ODleOCoeOCpOODq+mBuOaKniDilIDilIDilIDilIDilIDi
lIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDi
lIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDi
lIDilIDilIDilIDilIDilIDilIAKc2VsZWN0X2JhY2t1cF9maWxlKCkgewogICAgc2VjdGlvbiAi
5b6p5YWD44GZ44KL44OQ44OD44Kv44Ki44OD44OX44KS6YG45oqeLi4uIgoKICAgIGlmIFsgISAt
ZCAiJHtCQUNLVVBfRElSfSIgXTsgdGhlbgogICAgICAgIGVycm9yICLjg5Djg4Pjgq/jgqLjg4Pj
g5fjg4fjgqPjg6zjgq/jg4jjg6rjgYzlrZjlnKjjgZfjgb7jgZvjgpM6ICR7QkFDS1VQX0RJUn0i
CiAgICAgICAgZXhpdCAxCiAgICBmaQoKICAgIGxvY2FsIEZJTEVTPSgpCiAgICB3aGlsZSBJRlM9
IHJlYWQgLXIgbGluZTsgZG8KICAgICAgICBbIC1uICIke2xpbmV9IiBdICYmIEZJTEVTKz0oIiR7
bGluZX0iKQogICAgZG9uZSA8IDwoZmluZCAiJHtCQUNLVVBfRElSfSIgLW1heGRlcHRoIDEgLW5h
bWUgImFmZmluZV8qLnRhci5neiIgXAogICAgICAgIC1wcmludGYgJyVUQCAlcFxuJyAyPi9kZXYv
bnVsbCB8IHNvcnQgLXJuIHwgY3V0IC1kJyAnIC1mMi0pCgogICAgaWYgWyAkeyNGSUxFU1tAXX0g
LWVxIDAgXTsgdGhlbgogICAgICAgIGVycm9yICLjg5Djg4Pjgq/jgqLjg4Pjg5fjg5XjgqHjgqTj
g6vjgYzopovjgaTjgYvjgorjgb7jgZvjgpM6ICR7QkFDS1VQX0RJUn0iCiAgICAgICAgZXhpdCAx
CiAgICBmaQoKICAgIGVjaG8gIiIKICAgIHByaW50ZiAiICAlLTRzICAlLTQ4cyAgJThzICAlc1xu
IiAiTm8uIiAi44OV44Kh44Kk44Or5ZCNIiAi44K144Kk44K6IiAi5L+d5a2Y5pel5pmCIgogICAg
ZWNobyAiICAkKHByaW50ZiAnJS4wc+KUgCcgezEuLjgwfSkiCgogICAgbG9jYWwgaT0xCiAgICBm
b3IgRklMRSBpbiAiJHtGSUxFU1tAXX0iOyBkbwogICAgICAgIGxvY2FsIEJBU0VOQU1FIFNJWkUg
TVRJTUUKICAgICAgICBCQVNFTkFNRT0kKGJhc2VuYW1lICIke0ZJTEV9IikKICAgICAgICBTSVpF
PSQoZHUgLXNoICIke0ZJTEV9IiB8IGN1dCAtZjEpCiAgICAgICAgTVRJTUU9JChzdGF0IC1jICcl
eScgIiR7RklMRX0iIHwgY3V0IC1kJy4nIC1mMSkKICAgICAgICBpZiBbICIke2l9IiAtZXEgMSBd
OyB0aGVuCiAgICAgICAgICAgIHByaW50ZiAiICAke0dSRUVOfVslZF0ke05DfSAgJS00OHMgICU4
cyAgJXMgICR7R1JFRU59PC0g5pyA5pawJHtOQ31cbiIgXAogICAgICAgICAgICAgICAgIiR7aX0i
ICIke0JBU0VOQU1FfSIgIiR7U0laRX0iICIke01USU1FfSIKICAgICAgICBlbHNlCiAgICAgICAg
ICAgIHByaW50ZiAiICBbJWRdICAlLTQ4cyAgJThzICAlc1xuIiBcCiAgICAgICAgICAgICAgICAi
JHtpfSIgIiR7QkFTRU5BTUV9IiAiJHtTSVpFfSIgIiR7TVRJTUV9IgogICAgICAgIGZpCiAgICAg
ICAgaT0kKCggaSArIDEgKSkKICAgIGRvbmUKCiAgICBlY2hvICIiCiAgICBsb2NhbCBDSE9JQ0UK
ICAgIHdoaWxlIHRydWU7IGRvCiAgICAgICAgcmVhZCAtcnAgIiAg55Wq5Y+344KS6YG45oqe44GX
44Gm44GP44Gg44GV44GEIFsxLSQoKGktMSkpXTogIiBDSE9JQ0UKICAgICAgICBpZiBbWyAiJHtD
SE9JQ0V9IiA9fiBeWzAtOV0rJCBdXSBcCiAgICAgICAgICAgICYmIFsgIiR7Q0hPSUNFfSIgLWdl
IDEgXSBcCiAgICAgICAgICAgICYmIFsgIiR7Q0hPSUNFfSIgLWxlICQoKGktMSkpIF07IHRoZW4K
ICAgICAgICAgICAgYnJlYWsKICAgICAgICBmaQogICAgICAgIHdhcm4gIjEg44CcICQoKGktMSkp
IOOBrueVquWPt+OCkuWFpeWKm+OBl+OBpuOBj+OBoOOBleOBhCIKICAgIGRvbmUKCiAgICBTRUxF
Q1RFRF9CQUNLVVA9IiR7RklMRVNbJCgoQ0hPSUNFLTEpKV19IgogICAgaW5mbyAi6YG45oqeOiAk
KGJhc2VuYW1lICIke1NFTEVDVEVEX0JBQ0tVUH0iKSIKfQoKIyDilIDilIAg44OB44Kn44OD44Kv
44K144Og5qSc6Ki8ICYg44Ki44O844Kr44Kk44OW5YaF5a6556K66KqNIOKUgOKUgOKUgOKUgOKU
gOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKU
gOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAp2ZXJpZnlfY2hlY2tz
dW0oKSB7CiAgICBzZWN0aW9uICLjg4Hjgqfjg4Pjgq/jgrXjg6DjgpLmpJzoqLwuLi4iCiAgICBs
b2NhbCBTSEEyNTZfRklMRT0iJHtTRUxFQ1RFRF9CQUNLVVB9LnNoYTI1NiIKICAgIGlmIFsgLWYg
IiR7U0hBMjU2X0ZJTEV9IiBdOyB0aGVuCiAgICAgICAgaWYgc2hhMjU2c3VtIC1jICIke1NIQTI1
Nl9GSUxFfSIgLS1xdWlldCAyPi9kZXYvbnVsbDsgdGhlbgogICAgICAgICAgICBpbmZvICLjg4Hj
gqfjg4Pjgq/jgrXjg6AgT0siCiAgICAgICAgZWxzZQogICAgICAgICAgICBlcnJvciAi44OB44Kn
44OD44Kv44K144Og5qSc6Ki844Gr5aSx5pWX44GX44G+44GX44Gf77yB44OV44Kh44Kk44Or44GM
56C05pCN44GX44Gm44GE44KL5Y+v6IO95oCn44GM44GC44KK44G+44GZIgogICAgICAgICAgICBl
eGl0IDEKICAgICAgICBmaQogICAgZWxzZQogICAgICAgIHdhcm4gIuODgeOCp+ODg+OCr+OCteOD
oOODleOCoeOCpOODq+OBjOimi+OBpOOBi+OCiuOBvuOBm+OCk+OAguOCueOCreODg+ODl+OBl+OB
vuOBmSIKICAgIGZpCgogICAgbG9jYWwgQ09OVEVOVFMKICAgIENPTlRFTlRTPSQodGFyIC10emYg
IiR7U0VMRUNURURfQkFDS1VQfSIgMj4vZGV2L251bGwpCgogICAgaWYgZWNobyAiJHtDT05URU5U
U30iIHwgZ3JlcCAtcSAncG9zdGdyZXNfZHVtcFwuc3FsXC5neic7IHRoZW4KICAgICAgICBIQVNf
UEdfRFVNUD10cnVlCiAgICAgICAgaW5mbyAiUG9zdGdyZVNRTCDjg4Djg7Pjg5c6IOOBguOCiiDi
nJMiCiAgICBlbHNlCiAgICAgICAgSEFTX1BHX0RVTVA9ZmFsc2UKICAgICAgICB3YXJuICJQb3N0
Z3JlU1FMIOODgOODs+ODlzog44Gq44GXIgogICAgZmkKCiAgICBpZiBlY2hvICIke0NPTlRFTlRT
fSIgfCBncmVwIC1xRSAnKF58LylcLmVudiQnOyB0aGVuCiAgICAgICAgSEFTX0VOVj10cnVlCiAg
ICAgICAgaW5mbyAiLmVudiAoRELoqo3oqLzmg4XloLHlkKvjgoApOiDjgYLjgoog4pyTIgogICAg
ZWxzZQogICAgICAgIEhBU19FTlY9ZmFsc2UKICAgICAgICB3YXJuICIuZW52OiDjgarjgZciCiAg
ICBmaQp9CgojIOKUgOKUgCDlvqnlhYPlhYjjg4fjgqPjg6zjgq/jg4jjg6rjgpLjgrPjg7Pjg4bj
g4rjgYvjgonoh6rli5XmpJzlh7og4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA
4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA
4pSACnNlbGVjdF9yZXN0b3JlX2RpcigpIHsKICAgIHNlY3Rpb24gIuW+qeWFg+WFiCBBRkZpTkUg
44OH44Kj44Os44Kv44OI44Oq44KS56K66KqNLi4uIgoKICAgIGxvY2FsIERFVEVDVEVEX0RJUj0i
IgoKICAgIGlmIHRpbWVvdXQgNSBkb2NrZXIgcHMgLWEgLS1mb3JtYXQgJ3t7Lk5hbWVzfX0nIDI+
L2Rldi9udWxsIHwgZ3JlcCAtcSAiXmFmZmluZV9zZXJ2ZXIkIjsgdGhlbgogICAgICAgIERFVEVD
VEVEX0RJUj0kKHRpbWVvdXQgMTAgZG9ja2VyIGluc3BlY3QgYWZmaW5lX3NlcnZlciAyPi9kZXYv
bnVsbCBcCiAgICAgICAgICAgIHwgcHl0aG9uMyAtYyAiCmltcG9ydCBzeXMsIGpzb24sIG9zCmRh
dGEgPSBqc29uLmxvYWQoc3lzLnN0ZGluKQptb3VudHMgPSBkYXRhWzBdLmdldCgnTW91bnRzJywg
W10pIGlmIGRhdGEgZWxzZSBbXQpmb3IgbSBpbiBtb3VudHM6CiAgICBpZiBtLmdldCgnRGVzdGlu
YXRpb24nKSA9PSAnL3Jvb3QvLmFmZmluZS9zdG9yYWdlJzoKICAgICAgICBwcmludChvcy5wYXRo
LmRpcm5hbWUobS5nZXQoJ1NvdXJjZScsICcnKSkpCiAgICAgICAgYnJlYWsKIiAyPi9kZXYvbnVs
bCB8fCBlY2hvICIiKQogICAgZmkKCiAgICBpZiBbIC1uICIke0RFVEVDVEVEX0RJUn0iIF0gJiYg
WyAtZCAiJHtERVRFQ1RFRF9ESVJ9IiBdOyB0aGVuCiAgICAgICAgaW5mbyAi6Ieq5YuV5qSc5Ye6
OiAke0RFVEVDVEVEX0RJUn0iCiAgICAgICAgZWNobyAiIgogICAgICAgIHJlYWQgLXJwICIgIOOB
k+OBruWgtOaJgOOBq+W+qeWFg+OBl+OBvuOBmeOBiz8gW1kvbl06ICIgVVNFX0RFVEVDVEVECiAg
ICAgICAgaWYgW1sgIiR7VVNFX0RFVEVDVEVEfSIgPX4gXltObl0kIF1dOyB0aGVuCiAgICAgICAg
ICAgIERFVEVDVEVEX0RJUj0iIgogICAgICAgIGZpCiAgICBlbHNlCiAgICAgICAgREVURUNURURf
RElSPSIiCiAgICBmaQoKICAgIGlmIFsgLXogIiR7REVURUNURURfRElSfSIgXTsgdGhlbgogICAg
ICAgIHdhcm4gIkFGRmlORSDjgqTjg7Pjgrnjg4jjg7zjg6vlhYjjgpLmiYvli5XjgaflhaXlipvj
gZfjgabjgY/jgaDjgZXjgYQiCiAgICAgICAgcmVhZCAtcnAgIiAg44OH44Kj44Os44Kv44OI44Oq
44OR44K5ICjkvos6IC9vcHQvYWZmaW5lKTogIiBERVRFQ1RFRF9ESVIKICAgIGZpCgogICAgWyAt
eiAiJHtERVRFQ1RFRF9ESVJ9IiBdICYmIHsgZXJyb3IgIuODh+OCo+ODrOOCr+ODiOODquOBjOaM
h+WumuOBleOCjOOBvuOBm+OCk+OBp+OBl+OBnyI7IGV4aXQgMTsgfQogICAgWyAtZCAiJHtERVRF
Q1RFRF9ESVJ9IiBdIHx8IHsgd2FybiAi5a2Y5Zyo44GX44Gq44GE44Gf44KB5L2c5oiQ44GX44G+
44GZOiAke0RFVEVDVEVEX0RJUn0iOyBta2RpciAtcCAiJHtERVRFQ1RFRF9ESVJ9IjsgfQoKICAg
IFJFU1RPUkVfQUZGSU5FX0RJUj0iJHtERVRFQ1RFRF9ESVJ9IgogICAgaW5mbyAi5b6p5YWD5YWI
OiAke1JFU1RPUkVfQUZGSU5FX0RJUn0iCn0KCiMg4pSA4pSAIOODoeOCpOODs+W+qeWFg+WHpueQ
hiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDi
lIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDi
lIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDi
lIDilIDilIDilIAKZG9fcmVzdG9yZSgpIHsKICAgIHByaW50X2Jhbm5lcgogICAgY2hlY2tfcm9v
dAoKICAgICMg4pGgIOODleOCoeOCpOODq+mBuOaKngogICAgc2VsZWN0X2JhY2t1cF9maWxlCgog
ICAgIyDikaEg44OB44Kn44OD44Kv44K144Og5qSc6Ki8ICYg5YaF5a6556K66KqNCiAgICB2ZXJp
ZnlfY2hlY2tzdW0KCiAgICAjIOKRoiDlvqnlhYPlhYjnorroqo0KICAgIHNlbGVjdF9yZXN0b3Jl
X2RpcgoKICAgIGxvY2FsIENPTVBPU0VfRklMRT0iJHtSRVNUT1JFX0FGRklORV9ESVJ9L2RvY2tl
ci1jb21wb3NlLnltbCIKCiAgICAjIOKRoyDmnIDntYLnorroqo0KICAgIGxvY2FsIEJBQ0tVUF9T
SVpFCiAgICBCQUNLVVBfU0laRT0kKGR1IC1zaCAiJHtTRUxFQ1RFRF9CQUNLVVB9IiB8IGN1dCAt
ZjEpCiAgICBlY2hvICIiCiAgICB3YXJuICLku6XkuIvjga7lhoXlrrnjgaflvqnlhYPjgZfjgb7j
gZk6IgogICAgZWNobyAiICDjg5Djg4Pjgq/jgqLjg4Pjg5cgICAgICAgICA6ICQoYmFzZW5hbWUg
IiR7U0VMRUNURURfQkFDS1VQfSIpICgke0JBQ0tVUF9TSVpFfSkiCiAgICBlY2hvICIgIOW+qeWF
g+WFiCAgICAgICAgICAgICAgIDogJHtSRVNUT1JFX0FGRklORV9ESVJ9IgogICAgZWNobyAiICBQ
b3N0Z3JlU1FMIOW+qeWFgyAgICAgIDogJChbICIke0hBU19QR19EVU1QfSIgPSB0cnVlIF0gJiYg
ZWNobyAi44GC44KKIiB8fCBlY2hvICLjgarjgZcgKOOCueOCreODg+ODlykiKSIKICAgIGVjaG8g
IiAgLmVudiDlvqnlhYMgICAgICAgICAgICA6ICQoWyAiJHtIQVNfRU5WfSIgPSB0cnVlIF0gJiYg
ZWNobyAi44GC44KKIChEQuiqjeiovOaDheWgseWQq+OCgCkiIHx8IGVjaG8gIuOBquOBlyDihpIg
6YCA6YG/44OH44O844K/44GL44KJ5rWB55SoIikiCiAgICBlY2hvICIiCiAgICByZWFkIC1ycCAi
ICDnj77lnKjjga7jg4fjg7zjgr/jga/kuIrmm7jjgY3jgZXjgozjgb7jgZnjgILlvqnlhYPjgZfj
gb7jgZnjgYs/IFt5L05dOiAiIENPTkZJUk0KICAgIFtbICIke0NPTkZJUk19IiA9fiBeW1l5XSQg
XV0gfHwgeyB3YXJuICLlvqnlhYPjgpLjgq3jg6Pjg7Pjgrvjg6vjgZfjgb7jgZfjgZ8iOyBleGl0
IDA7IH0KCiAgICAjIOKRpCDjgrPjg7Pjg4bjg4rlgZzmraIKICAgIHNlY3Rpb24gIlsxLzVdIOOC
s+ODs+ODhuODiuOCkuWBnOatoi4uLiIKICAgIGlmIFsgLWYgIiR7Q09NUE9TRV9GSUxFfSIgXTsg
dGhlbgogICAgICAgIGNkICIke1JFU1RPUkVfQUZGSU5FX0RJUn0iCiAgICAgICAgZG9ja2VyIGNv
bXBvc2UgZG93biAyPi9kZXYvbnVsbCBcCiAgICAgICAgICAgICYmIGluZm8gImRvY2tlciBjb21w
b3NlIGRvd24g5a6M5LqGIiBcCiAgICAgICAgICAgIHx8IHdhcm4gImNvbXBvc2UgZG93biDjgavl
pLHmlZfjgZfjgb7jgZfjgZ8iCiAgICBlbHNlCiAgICAgICAgZm9yIEMgaW4gYWZmaW5lX3NlcnZl
ciBhZmZpbmVfcmVkaXMgYWZmaW5lX3Bvc3RncmVzIGFmZmluZV9taWdyYXRpb25fam9iOyBkbwog
ICAgICAgICAgICBkb2NrZXIgc3RvcCAiJHtDfSIgMj4vZGV2L251bGwgJiYgaW5mbyAiJHtDfSDj
gpLlgZzmraIiIHx8IHRydWUKICAgICAgICBkb25lCiAgICBmaQoKICAgICMg4pGlIOaXouWtmOOD
h+ODvOOCv+OCkumAgOmBvyAoc3RvcmFnZSAvIGNvbmZpZyAvIC5lbnYgLyBwb3N0Z3JlcyDjgZnj
gbnjgaYpCiAgICBzZWN0aW9uICJbMi81XSDml6LlrZjjg4fjg7zjgr/jgpLpgIDpgb8uLi4iCiAg
ICBsb2NhbCBFU0NBUEVfVElNRVNUQU1QCiAgICBFU0NBUEVfVElNRVNUQU1QPSQoZGF0ZSArIiVZ
JW0lZF8lSCVNJVMiKQogICAgbG9jYWwgRVNDQVBFX0RJUj0iJHtSRVNUT1JFX0FGRklORV9ESVJ9
L2RhdGFfYmVmb3JlX3Jlc3RvcmVfJHtFU0NBUEVfVElNRVNUQU1QfSIKICAgIG1rZGlyIC1wICIk
e0VTQ0FQRV9ESVJ9IgoKICAgIGZvciBJVEVNIGluIHN0b3JhZ2UgY29uZmlnIC5lbnYgcG9zdGdy
ZXM7IGRvCiAgICAgICAgbG9jYWwgRlVMTF9QQVRIPSIke1JFU1RPUkVfQUZGSU5FX0RJUn0vJHtJ
VEVNfSIKICAgICAgICBpZiBbIC1lICIke0ZVTExfUEFUSH0iIF07IHRoZW4KICAgICAgICAgICAg
bXYgIiR7RlVMTF9QQVRIfSIgIiR7RVNDQVBFX0RJUn0vIgogICAgICAgICAgICBpbmZvICLpgIDp
gb86ICR7SVRFTX0g4oaSICR7RVNDQVBFX0RJUn0vIgogICAgICAgIGZpCiAgICBkb25lCgogICAg
IyDikaYg44Ki44O844Kr44Kk44OW44KS5bGV6ZaLIChwYXlsb2FkLyDjgrXjg5bjg4fjgqPjg6zj
gq/jg4jjg6rmp4vpgKDjgavlr77lv5wpCiAgICBzZWN0aW9uICJbMy81XSDjg5Djg4Pjgq/jgqLj
g4Pjg5fjgpLlsZXplosuLi4iCiAgICBsb2NhbCBXT1JLX0RJUgogICAgV09SS19ESVI9JChta3Rl
bXAgLWQpCiAgICB0cmFwICJybSAtcmYgJyR7V09SS19ESVJ9JyIgRVhJVAoKICAgIHRhciAteHpm
ICIke1NFTEVDVEVEX0JBQ0tVUH0iIC1DICIke1dPUktfRElSfSIKCiAgICAjIHBheWxvYWQvIOOC
teODluODh+OCo+ODrOOCr+ODiOODquOBjOOBguOCjOOBsOOBneOBk+OCkuS9v+OBhuOAgeOBquOB
keOCjOOBsOebtOaOpQogICAgbG9jYWwgUEFZTE9BRF9QQVRICiAgICBpZiBbIC1kICIke1dPUktf
RElSfS9wYXlsb2FkIiBdOyB0aGVuCiAgICAgICAgUEFZTE9BRF9QQVRIPSIke1dPUktfRElSfS9w
YXlsb2FkIgogICAgICAgIGluZm8gIuOCouODvOOCq+OCpOODluani+mAoDogcGF5bG9hZC8g44K1
44OW44OH44Kj44Os44Kv44OI44Oq5b2i5byPIgogICAgZWxzZQogICAgICAgIFBBWUxPQURfUEFU
SD0iJHtXT1JLX0RJUn0iCiAgICAgICAgaW5mbyAi44Ki44O844Kr44Kk44OW5qeL6YCgOiDjg5Xj
g6njg4Pjg4jlvaLlvI8iCiAgICBmaQoKICAgICMgc3RvcmFnZSAvIGNvbmZpZyDjgpLlvqnlhYMK
ICAgIGZvciBESVIgaW4gc3RvcmFnZSBjb25maWc7IGRvCiAgICAgICAgaWYgWyAtZCAiJHtQQVlM
T0FEX1BBVEh9LyR7RElSfSIgXTsgdGhlbgogICAgICAgICAgICBjcCAtYSAiJHtQQVlMT0FEX1BB
VEh9LyR7RElSfSIgIiR7UkVTVE9SRV9BRkZJTkVfRElSfS8ke0RJUn0iCiAgICAgICAgICAgIGlu
Zm8gIuW+qeWFgzogJHtESVJ9LyIKICAgICAgICBmaQogICAgZG9uZQoKICAgICMgLmVudiDjgpLl
vqnlhYMKICAgIGlmIFsgIiR7SEFTX0VOVn0iID0gdHJ1ZSBdICYmIFsgLWYgIiR7UEFZTE9BRF9Q
QVRIfS8uZW52IiBdOyB0aGVuCiAgICAgICAgY3AgIiR7UEFZTE9BRF9QQVRIfS8uZW52IiAiJHtS
RVNUT1JFX0FGRklORV9ESVJ9Ly5lbnYiCiAgICAgICAgY2htb2QgNjAwICIke1JFU1RPUkVfQUZG
SU5FX0RJUn0vLmVudiIKICAgICAgICBpbmZvICLlvqnlhYM6IC5lbnYgKERCX1BBU1NXT1JEIC8g
U0VDUkVUX0tFWSDjgpLlkKvjgoApIgogICAgZWxzZQogICAgICAgIHdhcm4gIi5lbnYg44GM44OQ
44OD44Kv44Ki44OD44OX44Gr5ZCr44G+44KM44Gm44GE44G+44Gb44KTIgogICAgICAgIGlmIFsg
LWYgIiR7RVNDQVBFX0RJUn0vLmVudiIgXTsgdGhlbgogICAgICAgICAgICBjcCAiJHtFU0NBUEVf
RElSfS8uZW52IiAiJHtSRVNUT1JFX0FGRklORV9ESVJ9Ly5lbnYiCiAgICAgICAgICAgIGNobW9k
IDYwMCAiJHtSRVNUT1JFX0FGRklORV9ESVJ9Ly5lbnYiCiAgICAgICAgICAgIGluZm8gIumAgOmB
v+OBl+OBnyAuZW52IOOCkua1geeUqOOBl+OBvuOBmSIKICAgICAgICBlbHNlCiAgICAgICAgICAg
IGVycm9yICIuZW52IOOBjOimi+OBpOOBi+OCiuOBvuOBm+OCkyAo44OQ44OD44Kv44Ki44OD44OX
44Gr44KC6YCA6YG/44OH44O844K/44Gr44KC44GC44KK44G+44Gb44KTKSIKICAgICAgICAgICAg
ZXhpdCAxCiAgICAgICAgZmkKICAgIGZpCgogICAgIyBkb2NrZXItY29tcG9zZS55bWwg44KS5b6p
5YWDICjml6LlrZjjgYzjgYLjgozjgbDkv53mjIEpCiAgICBpZiBbIC1mICIke1JFU1RPUkVfQUZG
SU5FX0RJUn0vZG9ja2VyLWNvbXBvc2UueW1sIiBdOyB0aGVuCiAgICAgICAgaW5mbyAiZG9ja2Vy
LWNvbXBvc2UueW1sIOOBr+aXouWtmOOBruOCguOBruOCkue2reaMgeOBl+OBvuOBmSIKICAgIGVs
aWYgWyAtZiAiJHtQQVlMT0FEX1BBVEh9L2RvY2tlci1jb21wb3NlLnltbCIgXTsgdGhlbgogICAg
ICAgIGNwICIke1BBWUxPQURfUEFUSH0vZG9ja2VyLWNvbXBvc2UueW1sIiAiJHtSRVNUT1JFX0FG
RklORV9ESVJ9L2RvY2tlci1jb21wb3NlLnltbCIKICAgICAgICBpbmZvICLlvqnlhYM6IGRvY2tl
ci1jb21wb3NlLnltbCIKICAgIGZpCgogICAgaW5mbyAi44OV44Kh44Kk44Or5b6p5YWD5a6M5LqG
IOKGkiAke1JFU1RPUkVfQUZGSU5FX0RJUn0vIgoKICAgICMg4pGnIC5lbnYg44GL44KJIERCIOiq
jeiovOaDheWgseOCkuiqreOBv+i+vOOBvwogICAgbG9jYWwgREJfVVNFUk5BTUUgREJfUEFTU1dP
UkQgREJfREFUQUJBU0UKICAgIERCX1VTRVJOQU1FPSQoZ3JlcCAtRSAnXkRCX1VTRVJOQU1FPScg
IiR7UkVTVE9SRV9BRkZJTkVfRElSfS8uZW52IiAyPi9kZXYvbnVsbCB8IGN1dCAtZD0gLWYyIHwg
dHIgLWQgJyInIHx8IGVjaG8gIiR7UE9TVEdSRVNfVVNFUn0iKQogICAgREJfUEFTU1dPUkQ9JChn
cmVwIC1FICdeREJfUEFTU1dPUkQ9JyAiJHtSRVNUT1JFX0FGRklORV9ESVJ9Ly5lbnYiIDI+L2Rl
di9udWxsIHwgY3V0IC1kPSAtZjIgfCB0ciAtZCAnIicgfHwgZWNobyAiIikKICAgIERCX0RBVEFC
QVNFPSQoZ3JlcCAtRSAnXkRCX0RBVEFCQVNFPScgIiR7UkVTVE9SRV9BRkZJTkVfRElSfS8uZW52
IiAyPi9kZXYvbnVsbCB8IGN1dCAtZD0gLWYyIHwgdHIgLWQgJyInIHx8IGVjaG8gIiR7UE9TVEdS
RVNfREJ9IikKCiAgICAjIOKRqCBQb3N0Z3JlU1FMIOW+qeWFgwogICAgc2VjdGlvbiAiWzQvNV0g
UG9zdGdyZVNRTCDjg4fjg7zjgr/jg5njg7zjgrnjgpLlvqnlhYMuLi4iCiAgICBpZiBbICIke0hB
U19QR19EVU1QfSIgPSB0cnVlIF07IHRoZW4KICAgICAgICAjIHBvc3RncmVzIC8gcmVkaXMg44KS
5YWI44Gr6LW35YuVCiAgICAgICAgY2QgIiR7UkVTVE9SRV9BRkZJTkVfRElSfSIKICAgICAgICBp
ZiBbIC1mICIke0NPTVBPU0VfRklMRX0iIF07IHRoZW4KICAgICAgICAgICAgZG9ja2VyIGNvbXBv
c2UgdXAgLWQgYWZmaW5lX3JlZGlzIGFmZmluZV9wb3N0Z3JlcwogICAgICAgIGVsc2UKICAgICAg
ICAgICAgZG9ja2VyIHN0YXJ0IGFmZmluZV9wb3N0Z3JlcyAyPi9kZXYvbnVsbCB8fCB0cnVlCiAg
ICAgICAgZmkKCiAgICAgICAgaW5mbyAiUG9zdGdyZVNRTCDjga7otbfli5XjgpLlvoXmqZ/jgZfj
gb7jgZkuLi4iCiAgICAgICAgbG9jYWwgV0FJVD0wCiAgICAgICAgdW50aWwgdGltZW91dCA1IGRv
Y2tlciBleGVjIGFmZmluZV9wb3N0Z3JlcyBcCiAgICAgICAgICAgIHBnX2lzcmVhZHkgLVUgIiR7
REJfVVNFUk5BTUV9IiAtZCAiJHtEQl9EQVRBQkFTRX0iID4vZGV2L251bGwgMj4mMTsgZG8KICAg
ICAgICAgICAgc2xlZXAgMzsgV0FJVD0kKChXQUlUKzMpKTsgZWNobyAtbiAiLiIKICAgICAgICAg
ICAgWyAiJHtXQUlUfSIgLWdlIDYwIF0gJiYgeyBlY2hvICIiOyBlcnJvciAiUG9zdGdyZVNRTCDj
gYwgNjAg56eS44Gn6LW35YuV44GX44G+44Gb44KT44Gn44GX44GfIjsgZXhpdCAxOyB9CiAgICAg
ICAgZG9uZQogICAgICAgIGVjaG8gIiIKICAgICAgICBpbmZvICJQb3N0Z3JlU1FMIOi1t+WLleei
uuiqjSBPSyIKCiAgICAgICAgIyBEQiDjgpLliYrpmaTjg7vlho3kvZzmiJAgKC1VIGFmZmluZSDj
gacgdGVtcGxhdGUxIOe1jOeUsSkKICAgICAgICBkb2NrZXIgZXhlYyBhZmZpbmVfcG9zdGdyZXMg
XAogICAgICAgICAgICBwc3FsIC1VICIke0RCX1VTRVJOQU1FfSIgLWQgdGVtcGxhdGUxIC1jIFwK
ICAgICAgICAgICAgIkRST1AgREFUQUJBU0UgSUYgRVhJU1RTICR7REJfREFUQUJBU0V9OyIKICAg
ICAgICBkb2NrZXIgZXhlYyBhZmZpbmVfcG9zdGdyZXMgXAogICAgICAgICAgICBwc3FsIC1VICIk
e0RCX1VTRVJOQU1FfSIgLWQgdGVtcGxhdGUxIC1jIFwKICAgICAgICAgICAgIkNSRUFURSBEQVRB
QkFTRSAke0RCX0RBVEFCQVNFfTsiCiAgICAgICAgaW5mbyAi44OH44O844K/44OZ44O844K544KS
44Oq44K744OD44OI44GX44G+44GX44GfIgoKICAgICAgICAjIOODgOODs+ODl+OCkua1geOBl+i+
vOOCgAogICAgICAgIGd1bnppcCAtYyAiJHtQQVlMT0FEX1BBVEh9L3Bvc3RncmVzX2R1bXAuc3Fs
Lmd6IiBcCiAgICAgICAgICAgIHwgZG9ja2VyIGV4ZWMgLWkgYWZmaW5lX3Bvc3RncmVzIFwKICAg
ICAgICAgICAgICAgIHBzcWwgLVUgIiR7REJfVVNFUk5BTUV9IiAtZCAiJHtEQl9EQVRBQkFTRX0i
IC1xCiAgICAgICAgaW5mbyAiUG9zdGdyZVNRTCDlvqnlhYPlrozkuoYiCiAgICBlbHNlCiAgICAg
ICAgd2FybiAiREIg44OA44Oz44OX44GM44Gq44GE44Gf44KBIFBvc3RncmVTUUwg5b6p5YWD44KS
44K544Kt44OD44OX44GX44G+44GZIgogICAgICAgIHdhcm4gIm1pZ3JhdGlvbiDjgrjjg6fjg5bj
gYzml6LlrZjjg4fjg7zjgr/jgpLkvb/nlKjjgZfjgb7jgZkiCiAgICBmaQoKICAgICMg4pGpIOWF
qOOCs+ODs+ODhuODiui1t+WLlQogICAgc2VjdGlvbiAiWzUvNV0g44Kz44Oz44OG44OK44KS6LW3
5YuVLi4uIgogICAgbG9jYWwgU1RBUlRfT0s9dHJ1ZQogICAgaWYgWyAtZiAiJHtDT01QT1NFX0ZJ
TEV9IiBdOyB0aGVuCiAgICAgICAgY2QgIiR7UkVTVE9SRV9BRkZJTkVfRElSfSIKICAgICAgICBk
b2NrZXIgY29tcG9zZSB1cCAtZCAyPiYxICYmIGluZm8gImRvY2tlciBjb21wb3NlIHVwIC1kIOWu
jOS6hiIgfHwgU1RBUlRfT0s9ZmFsc2UKICAgIGVsc2UKICAgICAgICB3YXJuICJkb2NrZXItY29t
cG9zZS55bWwg44GM6KaL44Gk44GL44KK44G+44Gb44KTIgogICAgICAgIHdhcm4gIiAgY2QgJHtS
RVNUT1JFX0FGRklORV9ESVJ9ICYmIGRvY2tlciBjb21wb3NlIHVwIC1kIgogICAgICAgIFNUQVJU
X09LPWZhbHNlCiAgICBmaQoKICAgICMg6LW35YuV56K66KqNCiAgICBpZiBbICIke1NUQVJUX09L
fSIgPSB0cnVlIF07IHRoZW4KICAgICAgICBzbGVlcCAzCiAgICAgICAgbG9jYWwgQUNUVUFMX1NU
QVRVUwogICAgICAgIEFDVFVBTF9TVEFUVVM9JCh0aW1lb3V0IDUgZG9ja2VyIGluc3BlY3QgXAog
ICAgICAgICAgICAtLWZvcm1hdCAne3suU3RhdGUuU3RhdHVzfX0nIGFmZmluZV9zZXJ2ZXIgMj4v
ZGV2L251bGwgfHwgZWNobyAidW5rbm93biIpCiAgICAgICAgaWYgWyAiJHtBQ1RVQUxfU1RBVFVT
fSIgIT0gInJ1bm5pbmciIF07IHRoZW4KICAgICAgICAgICAgU1RBUlRfT0s9ZmFsc2UKICAgICAg
ICAgICAgd2FybiAiYWZmaW5lX3NlcnZlciDjga7jgrnjg4bjg7zjgr/jgrk6ICR7QUNUVUFMX1NU
QVRVU30iCiAgICAgICAgZmkKICAgIGZpCgogICAgIyDikaog5a6M5LqG44K144Oe44OqCiAgICBl
Y2hvICIiCiAgICBpZiBbICIke1NUQVJUX09LfSIgPSB0cnVlIF07IHRoZW4KICAgICAgICBlY2hv
ICLilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDi
lZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZAi
CiAgICAgICAgZWNobyAtZSAiICAke0dSRUVOfeKchSAg5b6p5YWD5a6M5LqG77yBJHtOQ30iCiAg
ICAgICAgZWNobyAi4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ
4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ
4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ
4pWQ4pWQ4pWQIgogICAgZWxzZQogICAgICAgIGVjaG8gIuKVkOKVkOKVkOKVkOKVkOKVkOKVkOKV
kOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKV
kOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKV
kOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkCIKICAgICAgICBlY2hvIC1lICIgICR7WUVM
TE9XfeKaoO+4jyAgIOODh+ODvOOCv+W+qeWFg+OBr+WujOS6huOBl+OBvuOBl+OBn+OBjOOAgeOC
s+ODs+ODhuODiui1t+WLleOBq+WVj+mhjOOBjOOBguOCiuOBvuOBmSR7TkN9IgogICAgICAgIGVj
aG8gIuKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKV
kOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKV
kOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKV
kCIKICAgICAgICBlY2hvICIiCiAgICAgICAgZWNobyAiICDmiYvli5Xjgafotbfli5XjgZfjgabj
gY/jgaDjgZXjgYQ6IgogICAgICAgIGVjaG8gIiAgICBjZCAke1JFU1RPUkVfQUZGSU5FX0RJUn0g
JiYgZG9ja2VyIGNvbXBvc2UgdXAgLWQiCiAgICAgICAgZWNobyAiICDjg63jgrDnorroqo06Igog
ICAgICAgIGVjaG8gIiAgICBkb2NrZXIgY29tcG9zZSAtZiAke0NPTVBPU0VfRklMRX0gbG9ncyAt
LXRhaWw9NTAiCiAgICBmaQogICAgZWNobyAiIgogICAgZWNobyAiICDwn5OmIOODkOODg+OCr+OC
ouODg+ODlyAgICAgIDogJChiYXNlbmFtZSAiJHtTRUxFQ1RFRF9CQUNLVVB9IikiCiAgICBlY2hv
ICIgIPCfk4Ig5b6p5YWD5YWIICAgICAgICAgICAgOiAke1JFU1RPUkVfQUZGSU5FX0RJUn0iCiAg
ICBlY2hvICIgIPCfm6HvuI8gIOmAgOmBv+ODh+ODvOOCvyAgICAgICAgOiAke0VTQ0FQRV9ESVJ9
IgogICAgZWNobyAiICDwn5WQIOWujOS6huaZguWIuyAgICAgICAgICA6ICQoZGF0ZSAnKyVZLSVt
LSVkICVIOiVNOiVTJykiCiAgICBlY2hvICIiCiAgICB3YXJuICLpgIDpgb/jg4fjg7zjgr/jgpLn
orroqo3lvozjgIHkuI3opoHjgarjgonliYrpmaTjgZfjgabjgY/jgaDjgZXjgYQ6IgogICAgZWNo
byAiICAgIHJtIC1yZiAke0VTQ0FQRV9ESVJ9IgogICAgZWNobyAiIgp9Cgpkb19yZXN0b3JlCg==
BASE64_RESTORE_EOF
info "作成: ${SCRIPT_DIR}/affine-restore.sh"
chmod +x "${SCRIPT_DIR}/affine-backup.sh" "${SCRIPT_DIR}/affine-restore.sh"
info "実行権限を付与しました"
section "[Step 4] 整合性チェック..."
bash -n "${SCRIPT_DIR}/affine-backup.sh" && info "affine-backup.sh : 構文 OK" || { error "構文エラー"; exit 1; }
bash -n "${SCRIPT_DIR}/affine-restore.sh" && info "affine-restore.sh : 構文 OK" || { error "構文エラー"; exit 1; }
section "[Step 5] cron の設定..."
if [ -n "${CRON_SCHEDULE}" ]; then
CRON_FILE="/etc/cron.d/affine-backup"
{ echo "# AFFiNE 自動バックアップ (${CRON_LABEL})";
echo "${CRON_SCHEDULE} root bash ${SCRIPT_DIR}/affine-backup.sh >> /var/log/affine-backup.log 2>&1"; } > "${CRON_FILE}"
chmod 644 "${CRON_FILE}"
info "cron 登録: ${CRON_FILE} (${CRON_LABEL})"
info "ログ: /var/log/affine-backup.log"
else
info "cron への登録をスキップしました"
fi
echo ""
echo "════════════════════════════════════════════════"
echo -e " ${GREEN}✅ インストール完了!${NC}"
echo "════════════════════════════════════════════════"
echo ""
echo " 📋 使い方:"
echo " sudo bash ${SCRIPT_DIR}/affine-backup.sh # 今すぐバックアップ"
echo " sudo bash ${SCRIPT_DIR}/affine-backup.sh list # 一覧表示"
echo " sudo bash ${SCRIPT_DIR}/affine-backup.sh clean # 古いものを削除"
echo " sudo bash ${SCRIPT_DIR}/affine-restore.sh # 復元 (対話形式)"
echo ""
[ -n "${CRON_SCHEDULE}" ] && echo " ⏰ 自動バックアップ: ${CRON_LABEL}" && echo ""
📋 使い方:
# バックアップを今すぐ実行
sudo bash /opt/lxd-data/script/affine/affine-backup.sh
# バックアップ一覧を表示
sudo bash /opt/lxd-data/script/affine/affine-backup.sh list
# 古いバックアップを削除
sudo bash /opt/lxd-data/script/affine/affine-backup.sh clean
# 復元 (対話形式でバックアップ・ディレクトリを選択)
sudo bash /opt/lxd-data/script/affine/affine-restore.sh

