月: 2025年11月

免責事項:これは甲斐谷忍先生の作品『ONE OUTS』に敬意を表したシステム名/ファンアートであり、公式(集英社、製作委員会など)とは一切関係ありません。

『ONE OUTS』システム番外:ipsetによるUFWの効率化。

はじめに

筆者が用いているWebへの攻撃を防ぐ、MOD_SECURITYとApache設定、シェルスクリプトの連携「ONE OUTSシステム」。これは「実際にWebサイトにアクセスした者」への盾として機能していますが、「アクセス未満」での低レイヤーでの攻撃を仕掛ける者を防ぎきることができません。

例えば、SYNフラッド攻撃はWebサイトへの攻撃を仕掛けるわけではないのでログに残らず、じわじわとリソースを奪っていきます。

かといって、これらのSYNフラッド攻撃は極めて広範囲のIPレンジから仕掛けてくるので

sudo ufw insert 1 deny from xxx.xxx.xxx.xxx

とするには、ufwでのルールが広範になりすぎてメンテナンス性ならびにシステムパフォーマンスの低下を招きます。

これを解決するための手段を設けました。

環境

  • Ubuntu 24.04
  • ufw導入済み

行ったこと

  1. ipsetコマンドをインストールします。
  2. ブロックリストの設定を行います。
  3. ipsetコマンドでSYNフラッド攻撃を行う攻撃者をレンジごとブロックします。

事前注意

これは、カーネルメモリにufwのブロックリストを付与する、「破壊的アップデート」の可能性が発生します。

  • セキュリティポリシー
  • 明確な運用基準

組織単位 で行う必要があります。

手順

ipsetコマンドのインストール

※筆者の好みでaptitudeを用いています。環境に合わせてapt等に読み替えます。

  • パッケージアップデート
sudo aptitude update
  • ipsetインストール
sudo aptitude install ipset

※ 要注意 ※

ここでは、ipset-persistantコマンドを入れていません。なぜなら、ufwと競合する結果、パッケージ管理はufwを破壊する可能性があるからです。

  • ipsetインストール確認
ipset -v
ipset v7.19, protocol version: 7
ipset v7.19: Kernel error received: Operation not permitted

※この、not permittedは、root権限で実行していないため許可されていないというメッセージです。

ipsetのルール変更

  • ブロックしたいIPを格納するための「セット」をメモリ上に作成します。

これは再起動時に消えます

sudo ipset create ufw-blocklist hash:net

ufwにipsetを参照するルールを追加します。

  • ufwの前段ルールをバックアップ
sudo cp -pi /etc/ufw/before.rules /path/to/backup/before.rules.$(date +%Y%m%d)

→ バックアップ先は任意のものを指定します

  • バックアップ確認
sudo diff -u /path/to/backup/before.rules.$(date +%Y%m%d) /etc/ufw/before.rules 

※ここでsudoを付与します。なぜなら、これはroot権限でしか読み取りできないからです

  • ファイル修正

上記、/etc/ufw/before.rulesの内容を慎重に修正します。 *.filterのすぐ下の行です。

# ===================================================================
# "ufw-blocklist" セットに含まれるIPからの全パケットを破棄する
-A ufw-before-input -m set --match-set ufw-blocklist src -j DROP
# ===================================================================

# ok all existing rules
-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
  • ファイル修正確認
sudo diff -u /path/to/backup/before.rules.$(date +%Y%m%d) /etc/ufw/before.rules 

以下の差分になっていることを確認します。

 *filter
+# ===================================================================
+# "ufw-blocklist" セットに含まれるIPからの全パケットを破棄する
+-A ufw-before-input -m set --match-set ufw-blocklist src -j DROP
+# ===================================================================
+
+# ok all existing rules

リロード前確認(最重要)

さて、ここまで手順通りに行えばufwのリロードは正常に完了します。しかし、ここで今一度

  • sudo ipset create ufw-blocklist hash:netを実行したか?
  • /etc/ufw/before.rulesを編集したか?
  • この編集は既存ファイルの内容を削除していない(追記のみ)か?

を確認しましょう。確認しなければ、この先に待ち構えているのは「失敗した場合の自分自身のロックアウト」にもつながります。

ufwリロード

よく深呼吸しましょう。実行前に何か飲み物を飲んでおいてもいいぐらいです。

sudo ufw reload

ファイアウォールを再読込しましたのメッセージが出れば成功です!

sudo ufw status

でも状態:アクティブを確認します。

ipset のリストを「永続化」する

ipset-persistent の代わりに、UFW自身の起動・停止スクリプトに、リストの保存・復元を組み込みます。

  • A. 保存用ファイルのパスを定義

まず、ipset のリストを保存するファイルを決めておきましょう。 ここではIPTABLES_IPSET_SAVE_FILE="/etc/ufw/ipsets.save"と定義します。

  • B. UFW起動時にリストを「復元」する設定

ufw が起動する前に、保存したリストを読み込むようにします。

sudo cp -pi /etc/ufw/before.init /path/to/backup/before.init.$(date +%Y%m%d)

でバックアップを取ります。(バックアップディレクトリを一括にしているならbefore.init.$(date +%Y%m%d)の前にbefore.rules.$(date +%Y%m%d)を作っているはず。「タブの補間はせず、確実にファイルのバックアップを取りましょう)

sudo diff -u /path/to/backup/before.init.$(date +%Y%m%d) /etc/ufw/before.init

で、バックアップが成功していることも確認します。※diffでもsudoを付与します。なぜなら、これはroot権限でしか読み取りできないからです

/etc/ufw/before.initを編集します。

ファイルの一番上(#!/bin/sh の直後)に、以下の行を追記します。

IPTABLES_IPSET_SAVE_FILE="/etc/ufw/ipsets.save"

# 起動時に ipset リストをファイルから復元する
if [ -f "$IPTABLES_IPSET_SAVE_FILE" ]; then
    ipset restore -f "$IPTABLES_IPSET_SAVE_FILE"
fi
sudo diff -u /path/to/backup/before.init.$(date +%Y%m%d) /etc/ufw/before.init
 #!/bin/sh
+IPTABLES_IPSET_SAVE_FILE="/etc/ufw/ipsets.save"
+
+# 起動時に ipset リストをファイルから復元する
+if [ -f "$IPTABLES_IPSET_SAVE_FILE" ]; then
+    ipset restore -f "$IPTABLES_IPSET_SAVE_FILE"
+fi

を確認。

  • UFW停止時にリストを「保存」する設定

ufw が停止(またはリロード、シャットダウン)する後に、現在のリストをファイルに保存するようにします。

sudo cp -pi /etc/ufw/after.init /etc/conf_backup/after.init.$(date +%Y%m%d)
sudo diff -u /etc/conf_backup/after.init.$(date +%Y%m%d) /etc/ufw/after.init 

※diffでもsudoを付与します。なぜなら、これはroot権限でしか読み取りできないからです

/etc/ufw/after.initを管理者権限で編集します。 ファイルの一番上(#!/bin/sh の直後)に、以下の行を追記します。

IPTABLES_IPSET_SAVE_FILE="/etc/ufw/ipsets.save"

# 停止時に現在の ipset リストをファイルに保存する
ipset save -f "$IPTABLES_IPSET_SAVE_FILE"

追記後、

sudo diff -u /etc/conf_backup/after.init.$(date +%Y%m%d) /etc/ufw/after.init 

で差分を確認します。

 #!/bin/sh
+IPTABLES_IPSET_SAVE_FILE="/etc/ufw/ipsets.save"
+
+# 停止時に現在の ipset リストをファイルに保存する
+ipset save -f "$IPTABLES_IPSET_SAVE_FILE"
  • コマンド実行権付与
sudo chmod +x /etc/ufw/before.init /etc/ufw/after.init

→ コマンドを追記しているので重要です!

再度のufwリロード前の確認

ここでも

  • /etc/ufw/before.initを編集し、差分通りか?
  • etc/ufw/before.initを編集し、差分通りか?
  • この編集は既存ファイルの内容を削除していない(追記のみ)か?
  • /etc/ufw/before.init /etc/ufw/after.initに実行権限が付与されているか?

を確認しましょう。確認しなければ、こちらも自分自身のロックアウトにつながります。

ufwリロード

よく深呼吸しましょう。今度は手元にあればお茶菓子を食べてもいいぐらいです。

sudo ufw reload

ファイアウォールを再読込しましたのメッセージが出れば成功です!

sudo ufw status

でも状態:アクティブを確認します。

ここまで来たら:SYNフラッド攻撃への対処

これは、対象のIPアドレスをシャットアウトする「慈悲なき王」です。

ブロック対象は慎重に慎重を期します。

  • メモリ上のリストに即時追加
sudo ipset add ufw-blocklist IPアドレス・NWアドレス

→ 実際のIPアドレスを半角で入力しましょう。

  • メモリ上のリストをファイルに「永続化」
sudo ipset save ufw-blocklist -f /etc/ufw/ipsets.save

(sudo ipset save ではない点に注意してください)

  • 永続化確認
cat /etc/ufw/ipsets.save 

として

create ufw-blocklist hash:net family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xcce80b68
add ufw-blocklist IPアドレス・NWアドレス

等と表示されれば成功です。

※この作業はufwリロード不要です。※

まとめ

「相手が回りくどい攻撃をしてきたら、更に回りくどい方法をとらなければならない」という形。

正直、この作業は二度とやりたくない部類に入ります。ですが、一度設定してしまえば

sudo ipset add ufw-blocklist IPアドレス・NWアドレス

で永続的に執拗な攻撃を仕掛ける攻撃者に対処することが可能です。

「杖」に選ばれる買い物のために。(要件定義、してみましょう)

はじめに

ハリー・ポッターシリーズ。ハリーがダイアゴン横丁で杖を手に入れる際のオリバンダー翁の言葉。

The wand chooses the wizard, Mr. Potter. It's not always clear why
「杖が魔法使いを選ぶのです、Mr.ポッター。何故そうなるかは、はっきりとは分かりませんが」

この「何故」に焦点を当てつつ、システム開発における大事なフェイズ「要件定義」になぞらえ

  • 何故これが大切なのか?
  • そして、これが上手くいくとシステム開発が上手くいく(つまり、システムが魔法使いというユーザーを選ぶ)のか?
  • この要件定義を日常生活に落とし込むには?

の3ステップほどで話してみようと思います。

そもそも要件定義とは?

システム開発における要件定義とは、「何を作るか」「何を実現するか」を明確にする、プロジェクトの最も土台となる工程です。

具体的には、ユーザー(魔法使い)がシステム(杖)に何を求めているのか、どのような課題を解決したいのかを徹底的にヒアリングし、その要求を機能や性能の仕様として具体化していく作業を指します。

これは、システムの設計図や仕様書を作成するための「羅針盤」を決める作業であり、「ユーザーが本当に必要とするものは何か?」を深く掘り下げ、開発チームとユーザーの間で共通の認識を築くためのものです。

これが上手くいくと?

オリバンダー翁の言葉のように、「杖が魔法使いを選ぶ」という関係性がシステム開発にも当てはまります。要件定義が上手くいくと、システムはユーザーの真のニーズに応える「まさにその杖」となり、開発全体がスムーズに進みます。

The wand chooses the wizard, Mr. Potter.

この「選ばれた状態」とは、単に機能が揃っているというだけではありません。ユーザーの潜在的な要求や、言葉にはなっていない「不便さ」までを汲み取り、それを解決する最適な形(システム)が提供されることを意味します。

要件定義が成功することで、開発の途中で「思っていたものと違う」といった手戻りや、不要な機能の開発を防ぐことができ、結果として

  • 予算とスケジュールの遵守
  • 高品質なシステムの実現
  • ユーザー(魔法使い)の満足度向上

といった、すべての関係者にとって良い結果(システムが魔法使いというユーザーを選ぶ)に繋がるのです。

自分自身の例:スマートウォッチを選んだ理由と機種選定までの流れ

何故必要だったのか

健康診断で芳しくない数値が出たことからこの話は始まります。

加齢から来る体調不良は目に見えて明らかでしたし、「このままでは危険」と判断。一念発起して体調管理できる方法を考えました。

そのためには「今の自分がどういう状況にあるのか?」を客観的、絶対的な目線で確認する(自分自身のロギング)は必要不可欠だと結論づけます。

なぜなら、

  • 節食しているのに太るのはどうして?
  • 眠れないとき/眠れたときの状態でパフォーマンスの差

などを考慮しないと、どのようなトレーニングをしても非効率/或いは心身を痛めることになるのは目に見えて明らかだからです。

「どこに進むか(どのような健康を改善するか)を決めるためには自分自身の現在地(体調)を知る」

を前提として考えないと、どのような健康法/ダイエット方法を試したところで無意味。この、自分自身の体調を知るために最もシンプルな方法が

「スマートウォッチによる自分の体調の視覚化」

でした。

特に

  • 歩数(動きの)管理
  • 睡眠

に焦点を当てます。

逆算して必要だったスマートウォッチ

  • 自分の性格上、フィットネスジムや健康管理を診てもらうというのは性に合わないし、強制されるのはそもそも嫌い。
  • それなら、ウェアラブルデバイスによって自分のペースで確認する方が以下の三者にとっていい結果になる。
    • 自分自身
    • お金(ジムの入会費やサブスク)
    • サービス提供者

と定義したのが私の「最初の要件定義」。ここが定まれば

変な健康商法や怪しいダイエットなんぞで大金と時間、健康を失いたくない。その値段を考えたら、多少の出費は投資と考える

で、どんなモデルを選ぶかを考えていきます。

つまり、要件定義と軽々に言ったところで

  • 自分(顧客)にとって本当に必要な商品/サービスは何か
  • そのためのシンプルな/或いはハイテクな解決手段とは

を確認しないと、要件定義の失敗は必至。その後の商品選定も単なる衝動買いに終わります。

商品選定基準

肯定要素(Affirmative)と否定要素(Negative)の2軸を元に考えました。

○ 肯定要素(Affirmative)

  • 睡眠管理のためバッテリーが長持ちすること。
    • 眠る前に充電のために時計を外したり、眠っている間のバッテリー切れは論外です。
  • 視認性。
    • 時計本来の「現在地の把握」のため、液晶がオフのままというのは避けたい事象です。
    • “Watch”の名前を冠するなら、その本来機能「確実な時の刻み」は外せません。
  • タフネス。
    • 風雨に晒される / 水仕事による時計の故障は考えたくありません。

○否定要素(Negative)

  • タッチ操作
    • 多くのスマートウォッチが採用するタッチ操作は不要でした。
    • べたついた手で触る可能性が高いことや時計そのものの文字の細かさは少々辛くなった年齢にさしかかっています。
    • このタッチ操作による誤操作の可能性は極力ゼロに抑えたいです。
  • 大きな筐体
    • キーボードを使う職業であるため、大きな文字盤が手首と干渉する事態は避けたいです。
    • キーボードを使うときに時計を外すのは、大前提の条件である「健康管理」という目的から逸脱します。

この時点でApple Watch / Pixel Watchの2つは対象から外れます。必要なのは機能であってブランドではないのです。

そして選ばれたGarmin Instinct

この選定基準が定まったら、後は実店舗での確認です。これはとても重要です。どんなに上記の条件に充たしたとしても、最終的な、最後の一藁は

  • 「何かデザインが違う」
  • 「気に入らない」

にかかっているからです。幸いにも、この目的を伝えることができれば、(良心的な大型量販店であれば)いい物を提案してくれます。この「わがまま」といえる肯定要素と否定要素全てをクリアしたのがGarmin Instinctでした。

  • 下手したら3週間は持つ驚異的なスタミナ
  • アプリ連携による体調(特に睡眠)管理
  • タフネスさは多くのサイクリストやマラソンランナーなどの愛好者がいることで証明済み。
  • 物理ボタン5つという無骨なデザインで確実な操作
  • 常時表示され、直射日光でも確実に視認できる液晶
  • 筐体の小ささ。40mmの直径でもOK

そして、一番大切だったフィット感。この軽さ / フィット感は、まさに「杖が魔法使いを選んだ瞬間」でした。こうして迎えられたスマートウォッチは無事に購入手続きが終わり、

  • 時間
  • 歩数
  • 睡眠

を確実に記録し、健康改善のきっかけとなりました。

で、結局使い続けられているのか? / 効果はあったのか?

その両者ともに「肯定(Affirmative)」です。

2年半ほど使い続け、この記録を元に、食生活と睡眠習慣を改めます。それにより、特に運動を増やしたわけでもなく1年で5kgほどの自然な体重減と、翌年以降の健康診断でも数値は目に見えて改善されました。

そして、その2年半の記録を続けた2年半後。バッテリーの持ちが悪くなってきたため新たに後継モデル

Garmin Instinct E

という、新たなウェアラブルデバイスを求めたほど。こちらも「更なる軽さ」と「フィット感」により、確実な時の刻みと健康の管理に役立ってくれることでしょう。

まとめに変えて「デジタルの方がいい場合もある」

これは、「デジタルよりアナログに重きを置いている」という筆者の記事に対する突っ込みの反証となります。

睡眠を管理するというのはメモ帳などに頼るのは到底無理です。

  • 何時に寝て
  • 何時に起きたか

はある程度判別できるでしょう。しかし、

  • 完全に熟睡状態に入ったのはいつか
  • 何回ぐらい起きたのか
  • どのぐらい深い眠りがあったのか

を覚えているというのはどだい無理な話です。この「睡眠管理」並びに「寝付けたのか否か」を判断するのはできません。

「常に自分自身を記録する静かな目」

はデジタルのハイテク機器である必要があったのです。

以下、『マクベス』第二幕第2場の以下の言葉。

“Sleep no more! Macbeth does murder sleep”
— the innocent sleep,
Sleep that knits up the ravelled sleave of care,
The death of each day's life, sore labour's bath,
Balm of hurt minds, great nature's second course,
Chief nourisher in life's feast.

「もう眠れない!マクベスは眠りを殺した!」
— 汚れなき眠り、
心の糸のほつれを繕う眠り、
一日の命の死、疲れた労働を癒す湯、
傷ついた心に塗る軟膏、
大自然の第二の恵み、
生命の宴の主なる滋養。

私にとってのGarmin Instinctは、マクベスが殺した『心の糸のほつれを繕う眠り』を取り戻すための、デジタルな『軟膏(Balm of hurt minds)』だったという強引なオチで本稿を締めくくります。

ボードゲーム『ロストシティ タイルゲーム』感想。

オリジナルは未プレイ。再販と同時にタイルバージョンが出ていたのでプレイしました。正直、ここまで面白いとは思いませんでした。

冒険の本質である「行くか、行かざるか。それが問題だ(To Go, or Not to Go, that is the question)」に迫る

  • 進むか留まるかのジレンマ
  • リスク計算と駆け引き
  • 強烈なインタラクション

を極めてシンプルなコンポーネントに落とし込んだ2人専用の傑作です。

ゲームの概要とルール

プレイヤーは探検家となり、様々な遺跡を探検していきます。

ゲームのルールはシンプル。

  • 場に伏せられたタイルをめくって探検する(自分の場に配置)か、しないか(取り置く)を決める。
  • 既に公開されたタイルで探検を進める。
  • 取り置いたタイルで探検を進める。

の3つのみ。ここからルールに従ってタイルを配置。タイルがすべて公開されたらゲーム終了。

タイルの得点が高い方が勝者となります。

このゲームの素晴らしいところ

言語依存のないシンプルなコンポーネントとルール

なんと、数字(と記号)が描かれたタイルとログブック(一時置き場)のみ。スリーブもインサートも不要。

この数字がわかりやすくもジレンマ満載のルールに落とし込まれています。

一度置いたタイルは昇順でしか置くことができません。(黄色のタイルに2を置いて、7を置いたら3~6を置けない)このルールにより、「進むか、引くか」のチキンレース要素を加速させます。

盛大なマイナスとプラスの乗算

得点計算は自分が配置したすべての得点を足した後に「20を引いた数」。この、足きりどころではない減点要素により「栄光(勝利)のためには進むべき」という道を示します。

そして、事前調査「×2」のタイルの存在。このタイルを前もって置くことができれば、この合計得点(合計点数-20)の倍の数値を得ることができます。

この「減点要素」が加わると「破滅」もあり得るリスクがあります。

例を見てみましょう。

  • 黄色い列に「×2」タイルを置いた状態で2 , 5, 7, 8, 9を置きました。合計は31。ここから20を引くことで11。そして×2で22点を取得。
  • 茶色い列に「×2」タイルを置いた状態で4しかおけませんでした。ここから20を引くことで-16。そして×2は、-32。
  • 青い列には何も置きませんでした。この場合は0。得点は得られませんが失点も起きません。

つまり、中途半端な探検は身の破滅。完遂した探検は栄光の階という、非常にリアルな探検要素がシンプルなルールで研ぎ澄まされています。

明らかになるにつれ動きづらくなる逆説

先に挙げた昇順でしか置けないルールが加わると、「このタイルは置けないから公開したままにする」機会が増えます。この公開情報は相手を利する結果になります。(公開されたタイルを置くことができるので)

「後で使うかもしれないから」とログブックに留め置いたとしても、この上限はわずかに2。これによって、「相手の狙いと自分の欲望を秤にかける」インタラクションが産まれます。

この、探検には己の運も必要というリアルな点と機会損失/相手の利得の利用もまた、本作の醍醐味でした。

このゲームの少しの問題点

色合い

青と紫の判別が、会場によっては見えづらかったのが気になりました。

運ゲーに見えた実力ゲー

ランダムなタイルをめくるという運の要素がありながらも

  • 自分の意図
  • 相手の意図

を読んだ上で

  • 残りの枚数はどれぐらいかの確率計算
  • それを見越したディシジョンメイキング
  • 損切りと行動力
  • いつ終了トリガーを引くか
  • 「運の流れはどちらにあるか?」の直感

などが必要。実力が拮抗していないとワンサイドゲームになります。

まとめ

この『ロストシティ タイル』は冒険の本質である「進むか引くかの判断力」と「大胆さと慎重さの二面性」をシンプルなルールと深い読み合いにまとめた素晴らしい作品。

この深い読み合いが20分程度(慣れれば10分程度)で終わるというのも驚嘆すべきものです。性質上、リプレイ性も高いので長く遊べる作品ですので「比較的短いプレイ時間でひりつく勝負がしたい」方には文句なしにおすすめできる優等生的な作品です。

「あなたにとっての“ナイフ”」とは?-1- (『MASTERキートン』“プロフェッサー”に学ぶ道具のセレクト)

「信頼の置ける道具、持っていますか?」という問いかけと私の回答というお話。

はじめに

漫画『MASTERキートン』に以下のやりとりがあります。

「やめておけ」
「…………」
「拳銃の方が、ナイフよりも速いと思っているんだろう。
 だが、拳銃はデリケートな道具だ。
 弾が出ないかもしれないし、
思い通り的に当たるとは限らん。
おまけに拳銃は、
抜き、構え、引き金を引くまでに三動作(スリーアクション)……
 その点ナイフは、一動作(ワンアクション)で終わる。
この距離なら、絶対に俺が勝つ!!
どうする? それでもやってみるかね?」

これは「至近距離でのナイフの有用性」を示したものであり、実際にその通りだという説得力があるものです。

では、この言説は本当なのか? ということで、AIによる試算を行います。

ナイフ vs. 拳銃:速さの決定的な差

この原則は、「21フィート・ルール(タフ・テスト)」と呼ばれる、銃器を携行する際の安全距離を示す経験則で裏付けられます。

拳銃の「三動作」にかかる時間

拳銃で有効な射撃を行うには、

  1. 抜き(ドロー)
  2. 構え
  3. 引き金を引く

最低限の三動作が必要です。

動作所要時間(訓練された者)
ドローから有効射撃まで約 1.5 秒 ~ 2.0 秒

ナイフ攻撃の「一動作」にかかる時間

ナイフを持った人間が相手に致命的な一撃を加える動作は一動作で完了し、さらに相手に向かって距離を詰める速度が加わります。

動作所要時間(突進・刺突)
約 6.4メートル(21フィート)を詰める約 1.5秒

速さの結論(21フィート・ルール)

ナイフを持った人間は、約 6.4メートル(21フィート)の距離から突進してくる場合、銃を抜いて発砲するまでの時間とほぼ同等で相手に到達できます。

  • 漫画のシーンのように、21フィートよりも遥かに近い距離(数フィート)の場合、拳銃の三動作が完了する前に、ナイフの一動作による攻撃は確実に相手に到達し、致命傷を与えることが可能です。
  • プロフェッサーの「この距離なら、絶対に俺が勝つ!!」という言葉は、この時間と距離の絶対的な差に基づいた、極めて正確な戦術的宣言なのです。
  • (もちろん、拳銃に慣れていない/ナイフの熟達、生死のやりとりの覚悟ができていない/できているの差は一番大きいでしょう)

拳銃の「デリケートさ」がもたらすリスク

プロフェッサーが指摘する「拳銃はデリケートな道具だ」という点も、至近距離戦においてナイフの優位性を裏付けます。

  • 機能不全のリスク:
    • 弾が出ないかもしれない(ジャミング、装填不良)。機械的な構造を持つ拳銃は、至近距離でのもみ合いや、些細な不具合で機能不全を起こすリスクがゼロではありません。
  • 命中精度の問題:
    • 思い通り的に当たるとは限らん(照準の困難)。突発的な近接戦闘では、冷静に狙いを定める余裕がなく、また物理的な妨害により、有効な射撃が困難になります。

この「デリケートさ」と「動作の多さ」は、そのまま私の道具を選ぶポイントにも表れています。

「デジタル器具の逆説」

私は当ブログにおいて

  • Redmine
  • Growi
  • Nextcloud
  • BookStack
  • (Firefly等も)

といった、様々なOSSのWeb記録ツール、そしてそれらを扱うPCやスマートデバイスなどを紹介してきましたが、そもそもの問題として私は「デジタルな道具を完全に信じていません」。その証拠にこちらの道具群をご覧ください。

道具群

  • ペンケース
    • ほとんどがLAMY Safari万年筆
  • 手帳類
    • ほぼ日手帳
    • ジブン手帳
    • トラベラーズノート
    • 情報カード
      等。これらは全て普段から持ち歩いているものです。(当然、鞄はギッシリです)ですが、それなりに理由があります。

「アイディアの揮発性」

閃いたアイディア、特に「100文字程度の短いひらめき」は、掴まえようとしなければ水蒸気のようにたちまち消えてしまいます。この一瞬の勝負において、私はデジタルツールを信用していません。

プロフェッサーの言葉を借りるならば、アイディアを捕捉するこの至近距離の戦闘では、デジタルツール(拳銃)の「三動作」は、紙とペン(ナイフ)の「一動作」に敗北します。

アイデア記録における「動作」と「時間」の比較

以下は、100文字程度のアイディアを記録し終えるまでにかかる動作と時間の比較です。

道具道具の比喩記録までの動作所要時間(目安)思考の中断リスク
紙とペンナイフ1 動作約 20 秒極小
デジタルツール拳銃3 動作約 38 秒以上

紙とペン(ナイフ):確実な「一動作」

紙とペンは、「書く」という一動作で記録が完了します。この約 20 秒間、思考の流れを一切止めることなく、揮発性の高いアイディアを紙の上に瞬時に定着させることが可能です。これは、プロフェッサーが示した最短距離、最小動作で確実に仕留めるという原則そのものです。

デジタルツール(拳銃):遅延を生む「三動作」

スマートフォンやPCのアプリで記録する場合、必ず以下の「三動作」が介入します。

  1. 起動(抜き):スリープ解除、パスコード解除、アプリ起動。
  2. 新規作成(構え):新規メモ画面への遷移、ツール内のファイル選択。
  3. 入力(発射):タイピング。

この「抜き、構え」のプロセスで生じる約 20 秒弱のタイムラグこそが、拳銃がデリケートな道具である最大の理由です。アイディアは、ツールを起動し構えている間に、すでに空中に消え去っている可能性があるのです。

 → このアイディアの揮発性というのは非常に致命的なものであるというのは皆様も経験があると思います。

それ以上に大切な「デジタルメモのデリケートさ」

スマートデバイスの動作不良の確率は、メモやペンよりも高いことに異論は無いと思います。

それ以上に

  • NW不調によりログイン不可(Webサービスを用いている場合)
  • 同期の不安定
  • 何よりもサービス終了の恐怖

はつきまといます。

反面、紙とペンなら

  • ほぼ確実に書くことができます。
  • 忘れたとしても(都会であればなおさら)すぐに手に入ります。
  • 「自分さえ分かれば」どんな言語、記号、絵だろうと分かるという自由度があります。
  • 何よりも「ペンと紙が生産終了になる」というケースはかなりの世紀末の状況になると思われます。

まとめ

「ちょっとしたアイディアのメモ」という

  • 即時性
  • 確実性
  • 安定性

が求められる状況下においては、紙と筆記具がこそが、思考を守る最も信頼できる道具です。

なぜなら、思考の戦いにおいては以下のブチャラティの言葉に集約されます。

“ぶっ殺してやる”ってセリフは終わってから言うもんだぜ
俺たちギャングの世界ではな
――『ジョジョの奇妙な冒険 黄金の風 偉大なる死(ザ・グレイトフル・デッド)』

「思いついたときには書き終えている」。この「一動作(ワンアクション)の速さ」こそが、紙とペンの持つ最大の魅力であり、
アイディアを確実に仕留める「ナイフ」なのです。

  • それぞれの道具を選ぶ理由
  • もちろん、デジタルが優れている場面

等はまた後の話に(気が向いたときに)記します。

「Update-motd」を使おう(ユースケース:カスタマイズスクリプトによる遊び心と有用性の追加)

はじめに

筆者が大好きな言葉かつ「何かあったときの道しるべ」としている言葉があります。

In every job that must be done, there is an element of fun. You find the fun and—snap! The job's a game.

映画『メリー・ポピンズ』の『お砂糖ひとさじで / A Spoonful of Sugar』の歌い出しとなっている言葉。

この、

  • どんな仕事にも遊びの要素がある
  • その遊びの要素を見つければ仕事はゲームになる

の2点を『自分自身のLinuxサーバの運用』に組み込んだという話です。

サーバー運用というのは、本来、堅牢性と安定性が求められる、どちらかというと無味乾燥な作業になりがちです。しかし、この単調な作業のどこかに「遊びの要素」を見出し、毎日ログインするのが楽しくなる**ような仕掛けを作れないかと考えました。

その答えが、「ログインコンソールに遊び心を持たせつつ、重要な情報を一瞥できるようにする」という試みです。これにより、単調な作業の始まりが、「今日の情報ブリーフィング」と「ちょっとした楽しみ」に変わります。

いつものようにとりとめない話を強引に組み立てていますが、与太話の延長として読んでいただければ幸いです。

Update-motdとは?

さて、サーバーの「入り口」をゲームのように変えるための舞台装置こそが、Linuxにおける MotD (Message of the Day) の仕組みです。

これは、/etc/update-motd.d/ ディレクトリ配下に配置されたシェルスクリプトやプログラムを順番に実行し、その出力結果を統合してユーザーに表示する仕組みです。

ポイント:

従来の MotD (/etc/motd) が再起動しない限り変わらない「貼り紙」だとすれば、Update-motd はログインのたびに最新の情報に更新される「ニュースフィード」のようなものです。

この動的な特性を利用することで、先述の「遊び心と有用性の追加」というテーマを実現しました。

筆者の例

といっても「なんのこっちゃ」になると思いますので、以下に該当しない方はこれ以降は読まなくて結構です。

  • そもそもLinuxサーバと言われても分からない
  • 仕事は仕事であり遊び心も実用性も不要

では、

/etc/update-motd.d/99-custom に組み込んだ例がこちらです。

#!/bin/bash
# Show weather information. Change the city name to fit your location
ansiweather -l City1 -s true -d true -a false
ansiweather -l City2 -s true -d true -a false

echo "CAST IN NAME OF GOD, YE NOT GUILTY."

# 現在の言語ロケールを保存します。
original_locale=$(locale | grep "LANG=" | cut -d= -f2)

# ロケールを英語に修正します。
export LANG="en_US.UTF-8"

# ロサンゼルス(カリフォルニア)の曜日を調べます。
day_of_week=$(TZ="America/Los_Angeles" date +"%A")

# 金曜日だった場合のみメッセージを表示します。
if [ "$day_of_week" == "Friday" ]; then
    echo "Today is Friday in California."
fi

# 元の言語ロケールに戻します。
export LANG="$original_locale"

ruby /home/user/script/ruby/ssl_checker.rb domain1.example.com domain2.example.com domain3.example.com

bash /home/user/script/bbc_headline.sh

スクリプトの構成と設計思想

このカスタムスクリプトは、

  • ログインコンソールに遊び心を持たせる
  • 重要な情報を一瞥できるようにする

という目的に沿って、大きく四つの機能ブロックで構成されています。

パーソナルな情報の表示と遊び心の追加

コマンド/機能目的と意義
ansiweather -l City1 ...関心のある地域(例:City1, City2)の天気を、カラフルで分かりやすい形式で表示します。作業開始前に個人的な関心事を満たします。
echo "CAST IN NAME OF GOD, YE NOT GUILTY."固定の引用句やメッセージを表示し、ログイン体験にユーモアや個人的なタッチを加えます。
Friday in California Check実行環境のタイムゾーンではなく、特定のタイムゾーン(LA)の曜日をチェックしてメッセージを表示する、技術的な遊び心です。ロケールを一時的に変更し、環境を汚染しないよう元に戻す配慮も含まれています。

サーバー運用上の重要情報チェック

コマンド/機能目的と意義
ruby /home/user/script/...自作のSSL証明書チェッカーを実行し、管理対象のウェブサイトの証明書期限(残日数)をチェックします。期限が近い場合は色を変えて警告するため、サービスの維持に必要な最重要情報を瞬時に把握できます。

外部のニュース情報取得

コマンド/機能目的と意義
bash /home/user/script/...自作のBBCヘッドライン取得スクリプトを実行し、世界のニュースの要約(ヘッドライン)を表示します。作業に入る前にグローバルな視点を持てるようにします。

さっくり言うと

この /etc/update-motd.d/99-custom スクリプトは、ログイン直後の数秒間を、

  1. 個人的な関心事の確認
  2. サーバーの緊急運用リスクのチェック
  3. 世界の主要情報のブリーフィングに使うため

多機能なパーソナルダッシュボードとしての役割を果たしています。

では、各スクリプトを見ていきましょう。

個人的な関心事の確認

  • ansiweather -l City1 ...
    • これは天気をコマンドラインで知るためのコマンド。(ビルトインコマンドではないので sudo apt install ansiweatherでインストールします。
    • これによって、自分が住む町や興味のある都市、行きたい場所などの情報をつかみます。
  • echo "CAST IN NAME OF GOD, YE NOT GUILTY."
    • 単に標準出力にメッセージを流すためのコマンド。サーバ接続を「ショータイム!」とするために仕込んでいます。
  • Friday in California Check
    • 『忍者戦隊カクレンジャー』発の有名なインターネットミーム『Today is Friday in California』をカリフォルニア(ロスアンゼルス)時間の金曜日にのみ表示するというスクリプト。
    • 筆者にとっては金曜日カレーのような意味合いを持ちます。

サーバ運用上のスクリプト

これはAIの力を借りながらも極めて丁寧で重要なスクリプトにしました。なので、スクリプトの意味に関してはChatGPTなりGoogle Geminiなりに聞きましょう。無料アカウントでも親切に教えてくれます。

#!/usr/bin/env ruby

require 'openssl'
require 'socket'
require 'date'
require 'uri'
require 'timeout'

# 色付け用の定数
COLOR_RED = "\e[31m"
COLOR_YELLOW = "\e[33m"
COLOR_GREEN = "\e[32m"
COLOR_RESET = "\e[0m"

# URLの最終的な到達先を取得するメソッド
def get_effective_url(url)
  # curlを使ってリダイレクトを追いかけ、最終的なURLを取得する
  # -s: サイレント, -L: リダイレクト追従, -I: ヘッダのみ, -o /dev/null: ボディ破棄, -w '%{url_effective}': 最終URLを出力
  effective_url = `curl -sLI -o /dev/null -w '%{url_effective}' "#{url}"`
  effective_url.empty? ? nil : effective_url
end

# 証明書の有効期限を取得するメソッド
def get_certificate_expiry_date(url)
  uri = URI.parse(url)
  hostname = uri.host
  port = uri.port || 443 # ポートがなければ443を使う
  ssl_socket = nil
  tcp_client = nil

  begin
    Timeout.timeout(5) do
      tcp_client = TCPSocket.new(hostname, port)
      ssl_context = OpenSSL::SSL::SSLContext.new
      ssl_socket = OpenSSL::SSL::SSLSocket.new(tcp_client, ssl_context)
      ssl_socket.hostname = hostname
      ssl_socket.connect

      cert = ssl_socket.peer_cert
      expiration_date = DateTime.parse(cert.not_after.to_s)
      days_remaining = (expiration_date - DateTime.now).to_i

      return expiration_date, days_remaining
    end
  rescue Timeout::Error
    return nil, "サーバーへの接続がタイムアウトしました。"
  rescue => e
    return nil, e.to_s
  ensure
    ssl_socket&.close
    tcp_client&.close
  end
end

# 結果を表示するメソッド
def print_result(url, expiration_date, days_remaining)
  if expiration_date
    formatted_date = expiration_date.strftime("%Y/%m/%d")
    
    # 残り日数に応じて色を選択
    color = if days_remaining < 14
              COLOR_RED
            elsif days_remaining < 30
              COLOR_YELLOW
            else
              COLOR_GREEN
            end

    puts "サイト #{url} の有効期限は #{formatted_date} です。#{color}残り #{days_remaining} 日です。#{COLOR_RESET}"
  else
    puts "#{COLOR_RED}サイト #{url} の証明書取得に失敗しました: #{days_remaining}#{COLOR_RESET}"
  end
end

# メイン処理
def main
  # コマンドライン引数があるかどうかで処理を分岐
  domains_to_check = if ARGV.empty?
                       # 引数がない場合は、対話式で入力を受け付ける
                       print "チェックしたいサイトのドメインを入力してください(例: example.com): "
                       [gets.chomp]
                     else
                       # 引数がある場合は、それらを全てチェック対象とする
                       ARGV
                     end

  # 各ドメインをチェック
  domains_to_check.each do |domain|
    # 対話モードで空エンターされた場合などをスキップ
    next if domain.nil? || domain.strip.empty?
    
    # http/httpsから始まらない場合はhttpsを付与
    initial_url = domain.start_with?('http') ? domain : "https://#{domain}"
    
    puts "Checking: #{initial_url} ..."
    final_url = get_effective_url(initial_url)

    if final_url.nil?
      puts "#{COLOR_RED}サイト #{initial_url} にアクセスできませんでした。#{COLOR_RESET}"
      next
    end
    
    expiration_date, days_remaining = get_certificate_expiry_date(final_url)
    print_result(final_url, expiration_date, days_remaining)
  end
end

# メイン処理を呼び出し
main

このスクリプトはWebサーバ管理上、とても重要です。

筆者はLet's Encryptのワイルドカード証明書を用いているため、この適切な時期でのチェック(Let's Encryptは90日と短いです)が

  • 「そろそろ準備をしないと」
  • 「まだゆっくりできる」

の判断が可能になります。

BBC Headline

これも、ほぼビルトインコマンドで完結。必要な外部モジュールもxmlintのみ。

#!/bin/bash

# デフォルト値の設定
default_section="world"
default_count=3

# メインセクションのリスト
main_sections=("world" "uk" "business" "politics" "health" "education" "science_and_environment" "technology" "entertainment_and_arts")

# グローバルセクションのリスト
global_sections=("africa" "asia" "europe" "latin_america" "middle_east" "us_and_canada")

# 全セクションのリストを統合
all_sections=("${main_sections[@]}" "${global_sections[@]}")

# 引数の処理
if [[ "$1" =~ ^[0-9]+$ ]]; then
    section=$default_section
    count=$1
else
    section=${1:-$default_section} # 引数1が指定されていない場合はデフォルト値を使用
    count=${2:-$default_count}     # 引数2が指定されていない場合はデフォルト値を使用
fi

# 引数の短縮形を対応する正式名に変換
case "$section" in
    "usa" | "n-usa") section="us_and_canada" ;;
    "me") section="middle_east" ;;
    "latam" | "la") section="latin_america" ;;
    "eu") section="europe" ;;
    "science") section="science_and_environment" ;;
    "entertainment") section="entertainment_and_arts" ;;
    *) section=$section ;; # その他はそのまま
esac

# セクションの検証
if [[ ! " ${all_sections[@]} " =~ " ${section} " ]]; then
    echo "Error: Invalid section '${section}'. Valid sections are: ${all_sections[*]}"
    exit 1
fi

# URLの構築
if [[ " ${main_sections[@]} " =~ " ${section} " ]]; then
    url="https://feeds.bbci.co.uk/news/${section}/rss.xml"
else
    url="https://feeds.bbci.co.uk/news/world/${section}/rss.xml"
fi

# 最初に一度だけRSSフィードをダウンロードし、変数に格納する
xml_content=$(curl -s "$url")

# コンテンツが取得できなかった場合はエラー終了
if [ -z "$xml_content" ]; then
    echo "Error: No headlines found for section '${section}'. Please check the section name or try again later."
    exit 1
fi

# フィードの最終更新日時を取得し、フォーマットする
# 2>/dev/null は、xmllintが出す軽微なエラーを非表示にするため
feed_date_raw=$(echo "$xml_content" | xmllint --xpath "string(//channel/lastBuildDate)" - 2>/dev/null)
if [ -n "$feed_date_raw" ]; then
    # JSTに変換して表示フォーマットを整える
    feed_date_formatted=$(date -d "$feed_date_raw" '+%Y/%m/%d %H:%M:%S %Z')
fi

# 見出しを取得
headlines=$(echo "$xml_content" | xmllint --xpath "//item/title/text()" - 2>/dev/null | sed -e 's/<!\[CDATA\[//g' -e 's/\]\]>//g' | head -n "$count")

# 見出しの表示
echo "BBC News - ${section} section (${count} headlines)"
# 取得した日付を表示
if [ -n "$feed_date_formatted" ]; then
    echo "As of: ${feed_date_formatted}"
fi
echo "--------------------------------------------------" #区切り線
echo "$headlines"

これは

./bbc_headline.sh

とすることで

BBC News - asia section (7 headlines)
As of: 2025/11/02 20:04:03 JST
--------------------------------------------------
300 million tourists just visited China's stunning Xinjiang region. There's a side they didn't see
Devastation on repeat: How climate change is worsening Pakistan's deadly floods
Shein accused of selling childlike sex dolls in France
Cruise cancelled following death of woman left behind on island
From the fringe to the final - India's phenomenon
Why the Indian passport is falling in global ranking
China to loosen chip export ban to Europe after Netherlands row

等の表示が可能になります。

この、日付とニュースの同時表示というのは

「このときにこんなニュースがあった」と、日付と行動の紐付け並びに重要なフックが可能になります。

やや強引なまとめ

と、スクリプトはちょっとした知識とAIの助けがあれば構築可能なものばかりではありますが、

冒頭に掲げた

Spoonful sugar helps medicine goes down(スプーン一杯の砂糖で苦い薬も平気で飲める)

という工夫は何にでも応用可能という言葉で本記事を締めます。

横須賀とランチタイム。

平日休み、横須賀を訪れました。

記念艦三笠は公園含めて改修中。

悪天候が続く中での隙間を縫うかのような晴天に恵まれて、一通り公園を回った後、お昼の時間です。

ご当地サイダーで一息ついた後、出てきたのは

フライドチキン乗せのクリームパスタでした。

ただの濃厚なクリームパスタにあらず。クラムチャウダーの野菜やピクルスを加えることで、味に刺激感とフライドチキンとの調和を図っています。

「ボリューム軽め」のものとして提案いただいたのがこれでしたが、確かにこの味の工夫であれば全体的に軽くなるでしょう。

そして、食べ終わった後に驚きの要素がありました。

「ん? このパスタ皿のロゴは VSOE……?」

恐る恐る皿の裏を見ると「Richard Ginori」の文字。

ビンゴでした。『オリエント急行/Venice Simplon-Orient-Express』で出される皿!

こぢんまりとした店で、これが見られるとは思わず。この、大衆的なご当地グルメの店で出会えたささやかな感動でした。

状況に応じた解決策の提示:スニーカーネットの思考実験を添えて

ここ最近、ゲームの記事やLinuxサーバに関するもの以外の雑多なことを書きたいと思う機会がより高まりました。そこで、ブログのカテゴリに雑多な記事を書く『IDEA SPHERE』を新設し、とりとめのない記事を書いていこうと思います。

このカテゴリの第一弾は思考実験とユースケースです。

はじめに

「大容量のデータを東京→大阪へ転送する場合は、NWを増強したりサーバを高性能にするよりも、データディスクを新幹線(のぞみ)で運んだ方が早い」

という真理に近いジョークがあります。これは、TCP/IPを用いたネットワークよりも物理的な手段(スニーカーネットワーク)の方が早いというもの。

このジョークは本当なのか? ということで思考実験を行いました。

思考実験の定義

対決:NW転送 vs スニーカーネット

写真やテキスト、ビジネス文書などが入った大容量データを対象として、これらのデータを「東京オフィス → 大阪オフィス」へ転送した場合、NW転送とスニーカーネットワーク、どちらが早く完了するかを計算します。この複雑な試算に関してはAIの力を用いています。

前提条件

データ群の条件はこちらです。

  • データ: 4TB (4,194,304 MB)
    • ファイル構造: 超多重構造のファイル群(数万単位)
  • ストレージ: SSD
    • 冗長化されていて、ホットスペアとしてすぐに取り出せる。
  • サーバ: 4コア / 16GB メモリ
  • 回線: 1Gbps (理論最大 125 MB/s)
  • オフィスの位置:東京駅および新大阪駅からタクシーで15分程度。

スタートとゴール

  • NW転送側のスタートとゴール:東京側のファイルの転送指示 → 大阪側の転送完了まで
  • スニーカーネットワークのスタートとゴール:東京側のディスクをホットスペアから取り外し、大阪側のサーバに取り付けてRAIDリビルドが完了するまで。

NW転送の試算

A. 理論上の最速値(ベストケース)

回線速度を一切のロスなく維持し、オーバーヘッドが「ゼロ」と仮定した理想値です。

  • 計算:
    4,194,304 MB ÷ 125 MB/s = 33,554 秒
  • 換算:
    33,554 秒 ÷ 60 ÷ 60 ≒ 約 9.3 時間

B. 現実的な試算(オーバーヘッド考慮)

WAN経由での超多重構造ファイルの転送は、ファイルごとのプロトコル処理、メタデータ転送、TCP/IPのACK遅延により効率が大きく低下します。実効速度が理論値の約24%に低下すると仮定します。

  • 理論値:125 MB/s
  • 現実的な実効速度:30 MB/s(理論値の約24%)
  • 計算:
    4,194,304 MB ÷ 30 MB/s = 139,810 秒
  • 所要時間:
    139,810 秒 ÷ 60 ÷ 60 ≒ 約 38.8 時間(約 1.6 日)

試算2:スニーカーネットワーク

反面、スニーカーネットワーク側の速度を試します。こちらはNWの遅延よりも確実な物理変数が加わります。

A. 移動・準備時間

SSDをホットスワップで取り外し、大阪で接続するまでの時間です。

作業内訳所要時間
SSD取り外し・梱包東京側30 分
東京側移動オフィス → 東京駅ホーム30 分
新幹線移動待機・乗車・ホーム移動3.0 時間 (180 分)
大阪側移動新大阪駅 → 大阪オフィス30 分
開梱・サーバ接続大阪側30 分
小計 (物理移動)4.5 時間

B. データ復旧(リビルド)時間

データ転送が完了する(リビルドが完了する)までをゴールとします。ローカルSSD間のリビルド実効速度を 300MB/s と仮定します。

  • 計算式:
    4,194,304 MB ÷ 300 MB/s = 13,981 秒
  • 所要時間:
    13,981 秒 ÷ 60 ÷ 60 ≒ 約 3.88 時間(余裕を見て 4.0 時間とする)

スニーカーネットワーク全体の所要時間

  • 移動時間:4.5 時間
  • リビルド時間:4.0 時間
合計4.5 時間 + 4.0 時間 = 8.5 時間

整理と勝敗

比較対象ゴール所要時間(試算)
NW転送 (理論値)転送完了まで約 9.3 時間
NW転送 (現実値)転送完了まで約 38.8 時間
スニーカーネットワークリビルド完了まで約 8.5 時間

整理した結果、スニーカーネットワーク(約8.5時間)は、ネットワーク転送の理論上の最速値(約9.3時間)よりも速い可能性が高いことがわかりました。

「超多重構造のファイル群」という条件がある限り、ネットワーク転送の現実的な所要時間は著しく悪化するため、スニーカーネットワークが圧倒的に優位となります。

更なる遅延要素: ウィルス対策システムによるスキャン

ただし、上記の計算値は現実的な要素とは言えません。なぜなら、東京と大阪に拠点を持つオフィスであれば導入されていない方がおかしいシステム「ウィルス対策/EPP/EDRの存在」です。

○NW転送時(38.8時間)の影響:

  • エンドポイント
    • 東京側からのPC/Serverファイル読み出し自、及び大阪側PC\Serverの書き込み時に、EPP/EDRなどのセキュリティソフトがファイルI/Oをフックし、リアルタイムスキャンを実行。
  • ゲートウェイ
    • 東京・大阪間の境界セキュリティ(次世代FW)などを持っている場合:
      • このゲートウェイがトラフィックのペイロード(中身)をスキャン。特にZIPファイルなどの圧縮形式は再帰的な解凍・検査が必要となり、GWのCPUに極大的な負荷をかけます。

これは、ネットワーク転送による実効速度の低下に加え、さらに致命的な処理時間の追加を意味し、38.8時間という試算は最低限の時間であり、実際には遥かに長くなる可能性が高いです。

○ スニーカーネット (約3.88時間) への影響
大阪側のサーバーが、SSDからローカルストレージへコピー(300MB/s程度)する際にも、同様に書き込みスキャンが発生します。

速度低下: 300MB/sという高速コピーも、スキャン処理によって低下します。

とはいえ、ボトルネックはネットワークではなくローカルI/Oです。たとえスキャンによってコピー時間が2倍(約7.76時間)になったとしても、ネットワーク転送の現実値(38.8時間)とは比較にすらなりません。

アナログな知恵:個人のデジタルライフに適用する

この前置きは「アナログな/あるいはアナクロな手段がはるかに効果的である」という主張を補強するためのものです。ここからが本番。

母より以下の相談を受けました。

「10年にも及ぶ数万単位の写真ファイルと、極めて重要な住所録ファイルがある。これを新しいPCに移行したい」

この写真には

  • 家族の思い出(筆者や亡き父、祖父母との写真)
  • 推し活(趣味含む)
  • 友人との旅行の記録

など亡くしてはならないデータ群。

これらを確実にバックアップし、新しいPCにコピーする手段として筆者が選んだのは、1TBのUSB-SSDです。

自室に設置しているNASや筆者が用いるクラウドストレージではなく、あえてUSB-SSDという「物理媒体による移動」を選んだのは、前述の思考実験と同じ真理に基づきます。

1. ネットワークボトルネックの完全回避による実効速度の最大化

思考実験で証明された通り、「数万単位の多重ファイル」の転送は、ファイル処理のオーバーヘッドとレイテンシがボトルネックになります。USB接続では、それがほぼゼロになります。

転送方法ボトルネックとなる要素
NAS 経由LAN 速度、プロトコル処理、多重ファイルのメタデータ処理
USB-SSD旧 HDD の読み込み速度、USB接続のSSD書き込み速度

旧PCのHDDの読み込み速度が最大のボトルネックとなりますが、USB-SSDはそれを最大限に引き出すことができ、NAS経由より遥かに高速でデータを吸い出すことができます。

2. データ移行と一次バックアップの同時実現

作業自体がバックアップ生成となります。

  1. 旧PCのHDDからSSDにデータをコピーする。
    • → この時点でSSDが完全なバックアップとなります。
  2. 新PCにSSDを接続し、データをコピーする。
    • → 移行が完了し、SSDはそのまま一次バックアップ媒体として保管できます。

クラウドやNASにアップロード、ダウンロードする二重の手間と転送時間が不要です。

3. コストパフォーマンスの最適化

  • USB-SSD:筆者が購入した1TBのスティック型SSDは1万円以下。
  • NAS:同容量のNASは最低でも2万円以上の初期投資が必要です。

移行が一回限りのタスクである場合、NASの過剰な機能に高額を支払うよりも、安価で高速な「ツール」であるSSDを選ぶ方が、最もコスト効率が高い選択となります。

4. データの独立性と安全性(世代管理)

移行専用のSSDであるため、筆者のNASの既存データと母の「亡くしてはならないデータ群」が混在するリスクが完全に排除されます。また、「このSSDは、旧PCからデータを吸い出したときの原本である」という形で、データ移行の起点となる世代を物理的に隔離でき、高い安全性をもたらします。

5. ITリテラシーへの配慮と安心感

ITリテラシーが低い人にとって、「ネットワーク」や「クラウド」といった実体のない場所にあるデータよりも、「この手のひらサイズの箱に、すべての思い出が入っている」という方が、圧倒的な安心感につながります。操作も「新PCに挿す」だけで完結するため、サポートの手間もかかりません。


まとめ

USB-SSDによる物理移動は、

  1. 実効転送速度
  2. バックアップの確実性
  3. データ管理のシンプルさ
  4. コスト効率

の四点において、高価で複雑なネットワークソリューションを凌駕しました。これは、東京〜大阪間の思考実験で導かれた結論が、そのまま個人のデジタルライフにも適用できることを示しています。

結局のところ、データ移行において最も重要なのは、最新の技術やスペックではなく、「状況とデータ特性を見極め、最も確実で効率的な手段を選ぶ知恵」である、という話。

  • 目的のためなら手段は正当化される:『君主論』
  • 世の中には手段のためなら目的を選ばないというどうしようもない人間がいる:『HELLSING』

の二律背反がありますが、ここに私は

「利用者の目的が達成されるならばシンプルな手段が効果的な場合がある」

の第三軸を加えた上で、本記事を締めくくります。

Powered by WordPress & Theme by Anders Norén