月: 2025年5月 Page 1 of 3

nvmによるnpmアップデートとGrowiの起動スクリプト修正。

Growiサーバのメンテナンス中、「新しいnpmのバージョンが出ている」ということで、

以下のコマンドを実施。

sudo npm install -g npm@11.4.0

しかし、以下のエラーが出てきました。

npm error code EBADENGINE
npm error engine Unsupported engine
npm error engine Not compatible with your version of node/npm: npm@11.4.0
npm error notsup Not compatible with your version of node/npm: npm@11.4.0
npm error notsup Required: {"node":"^20.17.0 || >=22.9.0"}
npm error notsup Actual:   {"npm":"10.9.0","node":"v20.15.1"}
npm error A complete log of this run can be found in: /root/.npm/_logs/2025-05-20T01_02_55_477Z-debug-0.log 

これを解決するため、結構なハマり案件があったのでメモを残します。(実施日:2025/05/20)

動作前環境

  • Ubuntu 22.04
  • Growi v7.2.4
  • node.js 20.15.1
  • npm 10.9.0
  • pnpm 9.12.3
  • MongoDB/Apacheによるリバースプロキシーは割愛します。

以下を参考にインストールしています。

https://barrel.reisalin.com/books/growi/page/ubuntu2404growi-v7v710-ImY

(盛大にハマったものの)最終的に解決した手順

  1. nvm (Node Version Manager)のインストールと環境設定
  2. Growiサービス(systemd 経由)起動時でのバージョン不一致の特定
  3. 起動スクリプトの修正

nvmインストール

  • root昇格

※growiをroot権限で実行するため

sudo su -
  • growiサービス停止
systemctl stop growi.service
  • growiサービス停止確認
systemctl status growi.service

inactive(dead)を確認

  • nvmインストールスクリプトの実行
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
  • nvm環境の有効化と確認
export NVM_DIR="$HOME/.nvm" 
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" 

一度セッションを切り、再度sudoを行いました。

nvm --version

0.39.7と表示されることを確認。

(まだrootです)

  • nvm経由でNode.jsをインストール

npm@11.4.0と互換性があるNode.jsをインストールします。

nvm install v20.19.2
  • Node.jsバージョンの使用とデフォルト設定
nvm use v20.19.2
nvm alias default v20.19.2
  • Node.jsバージョン確認
node -v

v20.19.2を確認

npm -v

10.7.0を確認

  • npmのインストール
npm install -g npm@11.4.0
  • npmバージョン確認
npm -v

11.4.0を確認

  • 事前にインストールされているpnpmの削除
rm -rf /root/.local/share/pnpm
  • コマンドパスのキャッシュクリア
hash -r
  • pnpmインストール
npm install -g pnpm
  • pnpmバージョン確認
pnpm -v

10.11.0を確認

  • rootから抜ける
exit

Growiとのバージョン不一致と原因確認

  • growi起動
sudo systemctl start growi.service
  • growi起動確認
systemctl status growi.service

とし、Growiの管理画面にアクセスしましたが、バージョンは変わらず。

システム上は確かにバージョンアップされているにもかかわらず、です。

そこで、

pgrep growi

で原因を探し、

ls -l /proc/<PID>/exe

を確認したところ、systemdから起動されたGrowiのNode.jsプロセスが、バージョンアップ前の

/usr/local/bin/nodeを利用していることを確認。

これは、上述したリンク先のsystemdサービスの実行環境が、nvmの環境変数(PATH)を正しく引き継いでいなかったからです。

起動スクリプトの修正

  • growiサービス停止
sudo systemctl stop growi.service
  • growiサービス停止確認
systemctl status growi.service

inactive(dead)を確認

  • Growi起動ディレクトリに移動
cd /path/to/growi/root/directory && pwd

筆者環境/home/www-data/growi

  • 起動スクリプトのバックアップ
sudo cp -pi growi-start.sh /path/to/backup/diretory/growi-start.sh.$(date +%Y%m%d)

任意のバックアップディレクトリを指定します。

  • diffによるバックアップ確認
diff -u /path/to/backup/diretory/growi-start.sh.$(date +%Y%m%d) growi-start.sh

差分が無いことを確認します。

  • スクリプト修正

growi-start.shを、任意の手段で修正します。

#!/bin/bashの直下、起動スクリプトの直上に以下のように記載します。

# NVM environmentをロード (NVM_DIRを直接指定)
export NVM_DIR="/root/.nvm" # $HOMEの代わりに直接パスを指定
if [ -s "$NVM_DIR/nvm.sh" ]; then
  \. "$NVM_DIR/nvm.sh"  # nvmをロード
  # 次の行でスクリプト実行時のnodeとnpmのバージョンをログに出力
  echo "NVM for GROWI startup script loaded. Using Node version: $(node -v), npm version: $(npm -v)" > /tmp/growi_nvm_load.log
else
  # NVMが見つからない場合もログに出力
  echo "NVM_DIR ($NVM_DIR) not found or nvm.sh not found for GROWI startup script." > /tmp/growi_nvm_load.log
fi

# GROWIの起動コマンド
  • 修正確認
diff -u /path/to/backup/diretory/growi-start.sh.$(date +%Y%m%d) growi-start.sh
+
+# NVM environmentをロード (NVM_DIRを直接指定)
+export NVM_DIR="/root/.nvm" # $HOMEの代わりに直接パスを指定
+if [ -s "$NVM_DIR/nvm.sh" ]; then
+  \. "$NVM_DIR/nvm.sh"  # nvmをロード
+  # 次の行でスクリプト実行時のnodeとnpmのバージョンをログに出力
+  echo "NVM for GROWI startup script loaded. Using Node version: $(node -v), npm version: $(npm -v)" > /tmp/growi_nvm_load.log
+else
+  # NVMが見つからない場合もログに出力
+  echo "NVM_DIR ($NVM_DIR) not found or nvm.sh not found for GROWI startup script." > /tmp/growi_nvm_load.log
+fi
+
+# GROWIの起動コマンド

修正確認

  • growi起動
sudo systemctl start growi.service
  • growi起動確認
systemctl status growi.service

この後、Growiに管理者権限でアクセスし、管理画面に移動します。

項目
GROWI7.2.4
node.js20.19.2
npm11.4.0
pnpm10.11.0

となっていたため、正しく参照できています。

『ユミアのアトリエ』シバーシュ地方のメインシナリオ完了までにアクセス可能な宝物庫一覧。(ネタバレあり)

こちらの記事の続き、シバーシュ地方のメインシナリオ完了までにアクセス可能な宝物庫は

  • シバーシュ地方:11個
  • リグナス地方:2個

の計13個です。

注意事項

これらの宝物庫には家具や装備品も手に入らない「ハズレ宝物庫」と言うべきものがあります。

これに関しては開けない方が無難です。(実績には関係ありません)

シバーシュ地方

ファルトナ天文台・北西 ※開拓任務で必要な宝物庫※

  • 宝箱1:
    • 【家具】壁掛けの照明F
    • 《調合アイテム》コーラルチップ
  • 宝箱2:
    • 【家具】絵画C
    • 〔特性結晶〕マルチブースト(Rank.3)

シバーシュ調査拠点・北東※開拓任務で必要な宝物庫※

  • 宝箱1:
    • 【家具】一人崖用の椅子B
    • 《装備品》ピクシーローブ
  • 宝箱2:
    • 【家具】シックなソファ
    • 《装備品》闘志のバングル
  • 宝箱3:
    • 【家具】噴水
    • 《装備品》キャバリエプレート

シバーシュ調査拠点・西※開拓任務で必要な宝物庫※

  • 家具1
    • 【家具】木のテーブル
    • 《装備品》帝王の威光
  • 家具2
    • 《装備品》カーススポイラー
    • 【家具】泉

ネル族の隠れ里・西※開拓任務で必要な宝物庫※

  • 宝箱1:
    • 【家具】照明B
    • 《調合アイテム》プラジオライト×3
  • 宝箱2:
    • 【家具】チェストC
    • 〔特性結晶〕マルチブースト(Rank.3)
  • 宝箱3:
    • 【家具】絵画E
    • 〔特性結晶〕マルチブースト(Rank.3)

[LM]セクレム滝壺・東※開拓任務で必要な宝物庫※

  • 宝箱1:
    • 【家具】ふかふかのベッド
    • 《使用アイテム》リョーヤククチニニガシ
  • 宝箱2:
    • 《使用アイテム》ミラージュソード
  • 宝箱3:
    • 【家具】ガラスA
    • 【家具】ガラスB
    • 《使用アイテム》快晴のてるてる坊主
      • ノーマルクエストでも納品するアイテムです。

[LM]カリギナ鉱山入口・西※キャラクタークエストで必要な宝物庫※

  • 宝箱1:
    • 【家具】壁掛けの照明C
    • 《装備品》闘志のバングル
  • 宝箱2:
    • 《調合アイテム》ヴァイオエルツ×3
  • 宝箱3:
    • 【家具】収集棚
      • ルトガーのキャラクタークエストで必要
    • 《調合アイテム》ヴァイオエルツ×3

備考

アウルーマ地方で発生する、ルトガーのキャラクタークエストでこの家具が必要になります。

シバーシュ調査拠点・東※キャラクタークエストで必要な宝物庫※

  • 宝箱1:
    • 《使用アイテム》リバイバルブーケ
  • 宝箱2:
    • 《使用アイテム》久遠の星時計
  • 宝箱3:
    • 《使用アイテム》ディアブルポット
    • 【家具】バスケット
      • ニーナのキャラクタークエストで必要

備考

アウルーマ地方で発生する、ニーナのキャラクタークエストでこの家具が必要になります。

[LM]孤独の高台

  • 宝箱1:
    • 【家具】壁掛け小物C
    • 《調合アイテム》プラジオライト×3
  • 宝箱2:
    • 【家具】壁掛けの照明B
    • 〔特性結晶〕シングルブースト(Rank.3)

[LM]夕暮れの海岸・北

  • 宝箱1:
    • 【家具】1人用のソファ
    • 《調合アイテム》フェトルクロス×3
  • 宝箱2:
    • 【家具】受付テーブル
    • 《使用アイテム》ネバーオープン

ファルトナ天文台・西

  • 宝箱1:
    • 《調合アイテム》コーラルチップ×3
  • 宝箱2:
    • 【家具】照明C
    • 〔特性結晶〕シングルブースト(Rank.3)
  • 宝箱3:
    • 【家具】アクアリウム
    • 《装備品》グレイスリボン

ヴィア・イデア・北(ハズレ宝物庫)

  • 宝箱1:
    • 《調合アイテム》はねとばり×3
  • 宝箱2:
    • 《調合アイテム》はねとばり×3
  • 宝箱3:
    • 《調合アイテム》プラジオライト×3
備考:

いわゆるハズレ宝物庫です。きちんと調合している方にはこれらの調合アイテムは不要です。

リグナス地方

[LM]廃村中央・南

  • 宝箱1:
    • 〔特性結晶〕スキル強化(Rank.1)
  • 宝箱2:
    • 【家具】黒板
    • 〔特性結晶〕スキル強化(Rank.1)
  • 宝箱3:
    • 〔特性結晶〕スキル強化(Rank.1)
備考

開拓クエストで、シバーシュ地方経由で訪れます。

[LM]ペグス山道・東

  • 宝箱1:
    • 【家具】床照明
    • 〔特性結晶〕スキル強化(Rank.1)
  • 宝箱2:
    • 〔特性結晶〕スキル強化(Rank.1)
  • 宝箱3:
    • 〔特性結晶〕スキル強化(Rank.1)
備考

開拓クエストで、シバーシュ地方経由で訪れます。

『ユミアのアトリエ』中盤の調合TIPS-万能素材:ぷにぷに玉:虹-(ネタバレあり)

『ドンケルハイト』が終盤で役立つ素材であれば、中盤『アウルーマ地方』での万能素材がぷにぷに玉:虹です。

浮遊マナ獲得量が倍の「浮遊マナボーナス」

材料投入を行ったアトラスコアの効果レベル+1

により、「適当に放り込んだだけでレシピの効果を最大限まで発揮」という、これまた何かおかしい効果が書かれています。

入手先

この、ビスマステンを入手した地下洞窟内にいる虹色のぷにを倒すことで入手可能です。

調合効果

このように、第1層の時点で「効果1: 調合 攻撃力上昇+ Lv.7」と、ほぼ最大レベルまで達しています。

第2層の時点でカンストしました。

中和剤を作るときも大活躍です。

これも、温室で増殖させる価値がある素材です。

『ユミアのアトリエ』宝物庫探しのTIPS。

  • 開拓任務
  • ノーマルクエスト
  • キャラクタークエスト

などで開ける必要がある宝物庫。

何度か言っているように「宝物庫の鍵を見つけにくいこと」「宝物庫と同数のみ用意されている(余りがない)」ことから、

  • 必要な分だけ宝物庫を開けて
  • 後で余裕があったら残りを見つける

というのが運用法となります。調査を進めていく中、全体マップから宝物庫を見つける時のちょっとしたTIPSです。

全体マップのフィルタリング

そんなとき、役に立つのがフィルター機能。

ここで、非常に見分けがつきにくい

  • 小さな祠
  • 洞窟
  • 祈念の社

をチェックから外します。

その結果がこちら。

そして、宝物庫の鍵を用いた(開けた)宝物庫は赤いチェックがつきますので、この二点でも調査は捗ります。

Google Geminiによるシェルスクリプト。(SSLの整合性確認)

Google Geminiに

「発行/別サーバからインポートしたSSL証明書の整合性確認を行うシェルスクリプト」

を書いてほしいと尋ねました。

条件は

  • コマンド [SSL証明書の入ったディレクトリ]形式
  • 証明書は
    • ドメイン名.crt.yyyymm
    • Let's Encryptのように証明書と中間証明書が結合された形式
  • 秘密鍵は
    • ドメイン名.key.yyyymm

の2つが入ったディレクトリを想定。

できあがったスクリプト

#!/bin/bash

# SSL証明書と秘密鍵の情報を表示するスクリプト
# サーバー証明書の有効期限、ドメイン名、発行局を表示します。
# また、対応する秘密鍵の存在と一致確認も行います。

# 使用法を表示する関数
usage() {
  echo "使用法: $0 <証明書と鍵が格納されているディレクトリ>"
  echo "ディレクトリには '[ドメイン名].crt.yyyymm' のような名前の証明書ファイルを配置してください。"
  echo "また、対応する秘密鍵ファイルは '[ドメイン名].key.yyyymm' の形式です。"
  echo "証明書ファイルは、サーバー証明書と中間証明書が結合された形式を想定しています。"
  exit 1
}

# 引数が指定されているか確認
if [ -z "$1" ]; then
  usage
fi

TARGET_DIR="$1"

# ディレクトリが存在するか確認
if [ ! -d "$TARGET_DIR" ]; then
  echo "エラー: ディレクトリ '$TARGET_DIR' が見つかりません。"
  exit 1
fi

# openssl コマンドが利用可能か確認
if ! command -v openssl &> /dev/null; then
    echo "エラー: openssl コマンドが見つかりません。OpenSSLをインストールしてください。"
    exit 1
fi

echo "ディレクトリ '$TARGET_DIR' 内のSSL証明書情報:"
echo "=================================================="

CERT_FILES_FOUND=0 # 処理した証明書ファイルのカウンタを初期化

# プロセス置換を使用して、CERT_FILES_FOUND が現在のシェルで更新されるようにする
while IFS= read -r -d $'\0' CERT_FILE; do
  CERT_FILES_FOUND=$((CERT_FILES_FOUND + 1)) # カウンタを増やす
  FILENAME=$(basename "$CERT_FILE")
  echo "処理中の証明書: $FILENAME"

  # --- 有効期限 ---
  EXPIRY_DATE_FULL=$(openssl x509 -noout -enddate -in "$CERT_FILE" 2>/dev/null)
  if [ $? -ne 0 ] || [ -z "$EXPIRY_DATE_FULL" ]; then
      EXPIRY_DATE_DISPLAY="有効期限の抽出エラー"
  else
      EXPIRY_DATE_DISPLAY=$(echo "$EXPIRY_DATE_FULL" | sed 's/notAfter=//')
  fi
  echo "  有効期限: $EXPIRY_DATE_DISPLAY"

  # --- ドメイン名 (サブジェクトのコモンネーム(CN) および サブジェクト代替名(SANs)) ---
  DOMAIN_NAME_DISPLAY="N/A"
  SUBJECT_CN_RAW=$(openssl x509 -noout -subject -nameopt multiline -in "$CERT_FILE" 2>/dev/null | grep 'commonName')
  SUBJECT_CN=""
  if [ $? -eq 0 ] && [ -n "$SUBJECT_CN_RAW" ]; then # grep で commonName が見つかった場合
    SUBJECT_CN=$(echo "$SUBJECT_CN_RAW" | sed -e 's/^\s*commonName\s*=\s*//' -e 's/\s*(Default)\s*$//' | head -n 1)
  fi
  
  # SANs を取得 (もしあれば最初の SAN 行のみ)
  SANS_TEXT=$(openssl x509 -noout -text -in "$CERT_FILE" 2>/dev/null | awk '/X509v3 Subject Alternative Name:/ {found=1; getline; print; exit} END{if(!found)print ""}')
  SANS_TEXT_CLEANED=$(echo "$SANS_TEXT" | sed 's/^\s*//') # 先頭の空白を削除
  SANS_LIST=""
  PRIMARY_SAN_DOMAIN=""

  if [[ "$SANS_TEXT_CLEANED" == "DNS:"* ]]; then
      # SANsリストを整形: DNS:プレフィックスを除去、空白除去、カンマ区切り、重複除去
      SANS_LIST=$(echo "$SANS_TEXT_CLEANED" | sed 's/DNS://g' | tr -d ' ' | tr ',' '\n' | awk '!seen[$0]++' | tr '\n' ',' | sed 's/,$//')
      if [ -n "$SANS_LIST" ]; then
        PRIMARY_SAN_DOMAIN=$(echo "$SANS_LIST" | cut -d',' -f1) # 最初のSANを主要ドメインとする
      fi
  fi

  if [ -n "$PRIMARY_SAN_DOMAIN" ]; then # 主要SANがある場合
      DOMAIN_NAME_DISPLAY="$PRIMARY_SAN_DOMAIN"
      # 主要SAN以外のSANがあれば表示
      OTHER_SANS=$(echo "$SANS_LIST," | sed "s/$PRIMARY_SAN_DOMAIN,//" | sed 's/,$//') 
      if [ -n "$OTHER_SANS" ]; then
          DOMAIN_NAME_DISPLAY="$PRIMARY_SAN_DOMAIN (他のSAN: $OTHER_SANS)"
      fi
      # CNが存在し、かつ主要SANと異なる場合にCNも表示
      if [ -n "$SUBJECT_CN" ] && [ "$SUBJECT_CN" != "$PRIMARY_SAN_DOMAIN" ]; then
          DOMAIN_NAME_DISPLAY="$DOMAIN_NAME_DISPLAY [CNも存在: $SUBJECT_CN]"
      fi
  elif [ -n "$SUBJECT_CN" ]; then # 主要SANが無く、CNがある場合
      DOMAIN_NAME_DISPLAY="$SUBJECT_CN"
      if [ -n "$SANS_LIST" ]; then # SANリスト自体は存在する (CNが主要となるケース)
          IS_CN_IN_SANS=0
          # SANS_LISTを配列に変換して確認しやすくする
          IFS=',' read -r -a SAN_ARRAY <<< "$SANS_LIST"
          for san_entry in "${SAN_ARRAY[@]}"; do
            if [ "$san_entry" = "$SUBJECT_CN" ]; then IS_CN_IN_SANS=1; break; fi
          done
          
          if [ $IS_CN_IN_SANS -eq 0 ]; then # CNがSANリストに含まれていない場合
             # SANリストがCNと異なる場合にのみSANリストを表示 (CNが唯一のSANである場合を除く)
             if [ "$SANS_LIST" != "$SUBJECT_CN" ]; then
                DOMAIN_NAME_DISPLAY="$SUBJECT_CN (SAN: $SANS_LIST)" # SAN -> SANs に統一すべきか検討
             fi
          else # CNがSANリストに含まれている場合、CN以外のSANがあれば表示
             OTHER_SANS_THAN_CN=""
             TEMP_SANS_LIST=""
             for san_entry in "${SAN_ARRAY[@]}"; do
                if [ "$san_entry" != "$SUBJECT_CN" ]; then
                    TEMP_SANS_LIST="${TEMP_SANS_LIST}${san_entry},"
                fi
             done
             OTHER_SANS_THAN_CN=$(echo "$TEMP_SANS_LIST" | sed 's/,$//')

             if [ -n "$OTHER_SANS_THAN_CN" ]; then
                DOMAIN_NAME_DISPLAY="$SUBJECT_CN (他のSAN: $OTHER_SANS_THAN_CN)"
             fi
          fi
      fi
  else # CNもSANも取得できなかった場合
      DOMAIN_NAME_DISPLAY="エラー: コモンネームまたはサブジェクト代替名を抽出できませんでした。"
  fi
  echo "  ドメイン名: $DOMAIN_NAME_DISPLAY"

  # --- 発行局 (サーバー証明書を発行した中間認証局) ---
  # 証明書ファイル内の最初の証明書のIssuerを取得
  ISSUER_CN_RAW=$(openssl x509 -noout -issuer -nameopt multiline -in "$CERT_FILE" 2>/dev/null | grep 'commonName')
  ISSUER_CN="N/A"
  if [ $? -eq 0 ] && [ -n "$ISSUER_CN_RAW" ]; then # grepでcommonNameが見つかったか確認
      ISSUER_CN=$(echo "$ISSUER_CN_RAW" | sed -e 's/^\s*commonName\s*=\s*//' -e 's/\s*(Default)\s*$//' | head -n 1)
  fi
  
  ISSUER_FULL_RAW=$(openssl x509 -noout -issuer -nameopt oneline,-space_eq,-show_type -in "$CERT_FILE" 2>/dev/null)
  ISSUER_FULL="N/A"
  if [ $? -eq 0 ] && [ -n "$ISSUER_FULL_RAW" ]; then
      ISSUER_FULL=$(echo "$ISSUER_FULL_RAW" | sed 's/issuer=//')
  fi

  if [ "$ISSUER_CN" != "N/A" ]; then
    echo "  発行局 (CN): $ISSUER_CN"
    echo "  発行局 (詳細): $ISSUER_FULL"
  else
    echo "  発行局 (詳細): $ISSUER_FULL (CNが見つからないか、CNの抽出エラーです)"
  fi

  # --- 秘密鍵の確認 ---
  # 証明書ファイル名から対応する秘密鍵ファイル名を推測 (例: domain.crt.yyyymm -> domain.key.yyyymm)
  KEY_FILE_CANDIDATE_NAME=$(basename "$CERT_FILE" | sed -E 's/\.crt\.([0-9]{6})$/.key.\1/')
  POTENTIAL_KEY_FILE="$TARGET_DIR/$KEY_FILE_CANDIDATE_NAME"

  if [ -f "$POTENTIAL_KEY_FILE" ]; then
    echo "  秘密鍵ファイル: $(basename "$POTENTIAL_KEY_FILE")"
    KEY_MATCH_STATUS="未確定 (エラーまたは非対応の鍵タイプ)"
    KEY_TYPE="不明"

    CERT_PUBKEY=$(openssl x509 -noout -pubkey -in "$CERT_FILE" 2>/dev/null) # 証明書から公開鍵を抽出
    KEY_IS_ENCRYPTED_OR_BAD_FORMAT=0
    PRIV_KEY_PUBKEY="" # 初期化

    # 鍵の種類を特定し、その公開鍵コンポーネントを取得 ('openssl pkey' は汎用的な鍵読み取り試行)
    if openssl pkey -in "$POTENTIAL_KEY_FILE" -noout >/dev/null 2>&1; then # まず鍵として読めるか
        if openssl rsa -in "$POTENTIAL_KEY_FILE" -noout -check >/dev/null 2>&1; then # RSA鍵か
            KEY_TYPE="RSA"
            PRIV_KEY_PUBKEY=$(openssl rsa -in "$POTENTIAL_KEY_FILE" -pubout 2>/dev/null) # RSA秘密鍵から公開鍵を抽出
        elif openssl ec -in "$POTENTIAL_KEY_FILE" -noout -check >/dev/null 2>&1; then # EC鍵か
            KEY_TYPE="EC"
            PRIV_KEY_PUBKEY=$(openssl ec -in "$POTENTIAL_KEY_FILE" -pubout 2>/dev/null) # EC秘密鍵から公開鍵を抽出
        else # その他の鍵タイプ (DSAなど) か、上記チェックをパスしないがpkeyでは読める鍵
            KEY_TYPE="その他 ('openssl pkey'で解析可能)"
            PRIV_KEY_PUBKEY=$(openssl pkey -in "$POTENTIAL_KEY_FILE" -pubout 2>/dev/null) # 汎用的に公開鍵抽出を試行
        fi
        if [ $? -ne 0 ] || [ -z "$PRIV_KEY_PUBKEY" ]; then # 公開鍵の抽出に失敗した場合
             KEY_IS_ENCRYPTED_OR_BAD_FORMAT=1 # 暗号化されているか、形式に問題がある可能性
        fi
    else # 'openssl pkey' で解析不可の場合
        KEY_IS_ENCRYPTED_OR_BAD_FORMAT=1 # 破損または暗号化の可能性が高い
        KEY_TYPE="読み取り不可または暗号化"
    fi

    if [ "$KEY_IS_ENCRYPTED_OR_BAD_FORMAT" -eq 1 ]; then
        KEY_MATCH_STATUS="鍵の読み取りエラー (暗号化、パスワード保護、または不正な形式の可能性あり)。検出された鍵タイプ: $KEY_TYPE"
    elif [ -n "$CERT_PUBKEY" ] && [ -n "$PRIV_KEY_PUBKEY" ]; then # 証明書の公開鍵と秘密鍵由来の公開鍵が両方取得できた場合
      if [ "$CERT_PUBKEY" = "$PRIV_KEY_PUBKEY" ]; then # 公開鍵同士を比較
        KEY_MATCH_STATUS="証明書と一致 ($KEY_TYPE)"
      else
        KEY_MATCH_STATUS="証明書と不一致 ($KEY_TYPE)"
      fi
    elif [ -z "$CERT_PUBKEY" ]; then # 証明書から公開鍵が取得できなかった場合
      KEY_MATCH_STATUS="証明書からの公開鍵生成エラー"
    else # 秘密鍵ファイルから公開鍵が取得できなかった場合 (鍵は読めたが公開鍵抽出に失敗)
      KEY_MATCH_STATUS="秘密鍵ファイルからの公開鍵生成エラー ($KEY_TYPE)"
    fi
    echo "    鍵の状態: $KEY_MATCH_STATUS"
  else
    echo "  秘密鍵ファイル: $(basename "$KEY_FILE_CANDIDATE_NAME") 見つかりません"
  fi
  echo "--------------------------------------------------"
done < <(find "$TARGET_DIR" -type f -name "*.crt.*[0-9][0-9][0-9][0-9][0-9][0-9]" -print0) # プロセス置換の終了

# このチェックで、ファイルが処理されたかどうかが正しく反映される
if [ "$CERT_FILES_FOUND" -eq 0 ]; then
    echo "ディレクトリ '$TARGET_DIR' 内に *.crt.*[数字6桁] のパターンに一致する証明書ファイルは見つかりませんでした。"
    echo "(例: domain.com.crt.202312)"
fi

これを `ssl-check.sh` として保存し、実行権限を付けます。

使用例

./ssl-check.sh /ディレクトリのフルパス

で実行した結果、

ディレクトリ '/hoge/' 内のSSL証明書情報:
==================================================
処理中の証明書: hoge.example.com.crt.202505
  有効期限: Aug 28 23:17:58 2025 GMT
  ドメイン名: *.hoge.example.com
  発行局 (CN): E5
  発行局 (詳細): C=US, O=Let's Encrypt, CN=E5
  秘密鍵ファイル: hoge.example.com.202505
    鍵の状態: 証明書と一致 (EC)
--------------------------------------------------

と、

  • 有効期限
  • ドメイン名
  • 自己証明でないか(発行局から発行されているか)

が明示的に分かるようになりました。

『ユミアのアトリエ』「試供品」による探索。

リグナス地方、

アルボール植物園解放後、調査団員に話しかけると、

ランダムで

  • 炸裂弾
  • 切弾

をもらうことができます。

これは、「探索ポーチ」から配備し直すことで使うことが可能です。

これを使うことにより、先んじてこういう菌糸で覆われた壁を

突破することができます。ただし、このサンプルはレシピを得ていない状態だと使うことができないため、使いどころには注意しましょう。

Geminiの学びからのフィギュア配置。

ここにより

  • 高低差を付ける
  • 余白を作る

などを学んだ結果、フィギュア棚を更に整理しました。

高さのある立像を中心にして三角形になるよう配置。

フィギュアの代償を取り入れ、額装という余白を作っていきました。

百均で購入した中華まんのスクイーズもワンポイントとして役立てています。

これにより、全体の統一感を図ることができました。

『ユミアのアトリエ』リグナス地方のメインシナリオ完了までにアクセス可能な宝物庫一覧。(ネタバレあり)

宝物庫の鍵を用いて開けられる宝物庫。

  • ノーマルクエスト
  • 開拓任務
  • キャラクタークエスト

でも必要なので、「有限の宝物庫の鍵に対し、必要と思われる宝物庫は何か?」

のまとめです。

リグナス地方のメインシナリオ完了までに得られる宝物庫の鍵は19個。

そのため、以下10個の宝物庫は十分余裕を持って開けることができます。

リグナス地方調査拠点・北

  • 宝箱1:
    • 〔特性結晶〕攻速上昇(Rank.3)
  • 宝箱2:
    • 《調合アイテム》クロース
    • 【家具】石の道(直線)
    • 【家具】石の道(曲線)
  • 宝箱3:
    • 〔特性結晶〕アイテム使用回数増加(Rank.2)

アルバーの集落・南

  • 宝箱1:
    • 《装備品》ハンターウェア
    • 【家具】花束
  • 宝箱2:
    • 《装備品》サペンニアアニュラス
    • 【家具】シーリングファン
  • 宝箱3:
    • 【家具】丸形のカーペットC
    • 《使用アイテム》樹林の治療薬

アルバーの集落・西

  • 宝箱1:
    • 《使用アイテム》ハピレスシャトル
  • 宝箱2:
    • 〔特性結晶〕攻防上昇(Rank.3)
    • 【家具】草塊
  • 宝箱3:
    • 〔特性結晶〕防速上昇(Rank.3)

[LM]大樹の爪先・北

  • 宝箱1:
    • 【家具】アーチ橋
    • 《装備品》流浪の福
  • 宝箱2:
    • 《使用アイテム》ルフト
    • 【家具】ガーデンパラソル

[LM]オブリエ大地・東

  • 宝箱1:
    • 《使用アイテム》エンハンスフルート
  • 宝箱2:
    • 【家具】巨木
    • 《調合アイテム》インゴット×3

備考

ここの宝物庫へのアクセスは炸裂弾が必要です。

[LM]残塔の入口・北※ノーマルクエストで必要な家具※

  • 宝箱1:
    • 【家具】柵・塀
    • 《使用アイテム》ルフト
  • 宝箱2:
    • 【家具】壁掛け照明E
    • 《使用アイテム》レヘルン
  • 宝箱3:
    • 【家具】普通のカーペットC
    • 《使用アイテム》プラジグ

備考

こちらのノーマルクエスト『畑荒らしを退治せよ2』で必要になります。

[LM]秘された花園・東

  • 宝箱1:
    • 《使用アイテム》フラム
  • 宝箱2:
    • 【家具】枝垂れ柳
    • 特性結晶〕防速上昇(Rank.3)
  • 宝箱3:
    • 《装備品》スカーレットスカーフ

備考

  • キャンプ場などが近くにあるものの、アクセスしやすい方法がこのランドマーク経由です。
  • また、リペアツール:木材ではしごを直してからの方が無難です。

[LM]樹海関門・北

  • 宝箱1:
    • 〔特性結晶〕アイテム使用回数増加(Rank.2)
  • 宝箱2:
    • 【家具】花の門
    • 〔特性結晶〕経験値ボーナス(Rank.2)
  • 宝箱3:
    • 《調合アイテム》アンブロイド×3

[LM]エレミトの谷・北

  • 宝箱1:
    • 【家具】ローテーブル
    • 〔特性結晶〕攻防上昇(Rank.3)
  • 宝箱2:
    • 【家具】外階段
    • 〔特性結晶〕攻速上昇(Rank.3)

[LM]地脈の樹窟・南

  • 宝箱1:
    • 【家具】スイングハンモック
    • 《調合アイテム》インゴット×3
  • 宝箱2:
    • 【家具】かわいいソファ
    • 〔特性結晶〕アイテム使用回数増加(Rank.2)
  • 宝箱3:
    • 【家具】絵画B
    • 〔特性結晶〕攻防上昇(Rank.3)

Ubuntu 24.04 aptitude updateエラー対応メモ(aptコマンドのLabel変更にによるパッケージリストの変更)

ちょっとハマったのでメモです。

環境

  • OS: Ubuntu 24.04

発生した問題

sudo aptitude update を実行した際に、特定のPPA (PHPリポジトリ) でエラーが発生し、パッケージリストの更新に失敗しました。
(※筆者の好みでaptitudeを用いています)

エラーメッセージの抜粋:

E: Repository 'https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble InRelease' changed its 'Label' value from '***** The main PPA for supported PHP versions with many PECL extensions *****' to 'PPA for PHP'
E: Failed to download some files
W: https://ppa.launchpadcontent.net/ondrej/php/ubuntu/dists/noble/InRelease を取得できませんでした:
E: 一部のインデックスファイルのダウンロードに失敗しました。無視されたか古いものを代わりに利用しています。

Ubuntu24.04をインストールしたばかりの頃に追加したリポジトリが古くなり、アップグレードができないという状態でした。

対処方法

以下の通りに実施しました。

リポジトリの Label 変更を許可

sudo apt update --allow-releaseinfo-change

変更許可後のupdate

sudo aptitude update

これにより、上記のエラーが解消され、正常にパッケージのアップグレードが成功しました。

MSI Claw用のモバイルバッテリー導入。

携帯できるSteam環境と言うことで運用しているMSI Claw。

アトリエシリーズ程度であればきちんと動き、フリーズなども特になし。

しかし、「ゲーム中のバッテリーの持ち」という課題は常につきまといます。参考までに

  • ライザのアトリエ3:1時間半程度
  • ユミアのアトリエ:1時間15分程度
  • BLUE REFLECTION(無印):1時間程度

などと、やや心許ないものがありました。それを解決するために用意したのがこちら。

Anker Prime Power Bank (27650mAh, 250W) 。

圧倒的な容量を誇り、250Wということから、ノートPCへの充電も可能なバッテリーです。(※そもそもMSI Claw自体がPC扱いなのでこれにしました)

開封した結果はこの通り。大きいです。そして、「鉄でも詰まっているのか」ぐらいの密度と重さ。(650gほど)

ケーブルを接続するとしっかり充電されます。

つなげたときでも、充電を示すマークが表していました。

Page 1 of 3

Powered by WordPress & Theme by Anders Norén