<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on sonohen's tech blog</title><link>https://sonohen.net/posts/</link><description>Recent content in Posts on sonohen's tech blog</description><generator>Hugo -- gohugo.io</generator><language>ja-JP</language><lastBuildDate>Fri, 30 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://sonohen.net/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Cachixを使用する</title><link>https://sonohen.net/posts/2026/10/30/</link><pubDate>Fri, 30 Oct 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/10/30/</guid><description>&lt;h2 id="課題と目的"&gt;課題と目的
&lt;/h2&gt;&lt;p&gt;私の環境では &lt;code&gt;emacs-unstable-pgtk&lt;/code&gt; と &lt;code&gt;openlogi&lt;/code&gt; は、更新が入る度にビルドが走る。それはそれで構わないのだが、一方で日常作業をしている裏でリソースを取られるのも少し違う気がした。&lt;/p&gt;
&lt;p&gt;そこで、以下のような構成を実装した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GitHub(master) &amp;lt;--[checkout]-- GitHub Actions(毎週金曜日4:30起動 / Ubuntu) --[push]--&amp;gt; Cachix
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ^ |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; `--------[git pull]-------- ThinkPad E14 Gen 3 &amp;lt;--------[nixos-rebuild switch]--------/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;この構成により、最も時間を要している &lt;code&gt;emacs-unstable-pgtk&lt;/code&gt; と &lt;code&gt;openlogi&lt;/code&gt; はGitHub Hosted Runnerでビルドされるので、
ThinkPadで &lt;code&gt;nixos-rebuild switch --flake ./nixos#thinkpad&lt;/code&gt; を実行したときに、ローカルビルド時間を大幅に短縮できるというのが目論見である。
(ローカルビルドを完全に無くすとは言っていない)&lt;/p&gt;
&lt;h2 id="日常の運用"&gt;日常の運用
&lt;/h2&gt;&lt;p&gt;以下の通りになる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;毎週金曜日4:30 GitHub Actionsが起動する。
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;flake.lock&lt;/code&gt; の更新&lt;/li&gt;
&lt;li&gt;&lt;code&gt;emacs-unstable-pgtk&lt;/code&gt; のビルドとCachixへの転送&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openlogi&lt;/code&gt; のビルドとCachixへの転送&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flake.lock&lt;/code&gt; のコミットとリポジトリへのプッシュ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;毎週土曜日に、ThinkPadで &lt;code&gt;git pull&lt;/code&gt;, &lt;code&gt;sudo nixos-rebuild switch --flake ./nixos#thinkpad&lt;/code&gt; を実行。
&lt;ul&gt;
&lt;li&gt;このタイミングで、 &lt;code&gt;emacs-unstable-pgtk&lt;/code&gt; や &lt;code&gt;openlogi&lt;/code&gt; はビルドされず、Cachixからダウンロードされる。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="実装"&gt;実装
&lt;/h2&gt;&lt;h3 id="configuration-dot-nix"&gt;&lt;code&gt;configuration.nix&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;cachix.org&lt;/code&gt; からnixバイナリキャッシュを取得するように設定する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;nix&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-nix" data-lang="nix"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;extra-substituters &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://&amp;lt;キャッシュ名&amp;gt;.cachix.org&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;extra-trusted-public-keys &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;キャッシュ名&amp;gt;.cachix.org-1:&amp;lt;公開鍵&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="flake-dot-nix"&gt;&lt;code&gt;flake.nix&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;ストアパスが一致するように設定する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;nix&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-nix" data-lang="nix"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;outputs &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { self&lt;span style="color:#f92672"&gt;,&lt;/span&gt; nixpkgs&lt;span style="color:#f92672"&gt;,&lt;/span&gt; home-manager&lt;span style="color:#f92672"&gt;,&lt;/span&gt; nixvim&lt;span style="color:#f92672"&gt;,&lt;/span&gt; openlogi&lt;span style="color:#f92672"&gt;,&lt;/span&gt; beancount-mode&lt;span style="color:#f92672"&gt;,&lt;/span&gt; emacs-overlay&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt; }: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; packages&lt;span style="color:#f92672"&gt;.&lt;/span&gt;x86_64-linux &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; emacs &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nixosConfigurations&lt;span style="color:#f92672"&gt;.&lt;/span&gt;thinkpad&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pkgs&lt;span style="color:#f92672"&gt;.&lt;/span&gt;emacs-unstable-pgtk;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; openlogi &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nixosConfigurations&lt;span style="color:#f92672"&gt;.&lt;/span&gt;thinkpad&lt;span style="color:#f92672"&gt;.&lt;/span&gt;config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;programs&lt;span style="color:#f92672"&gt;.&lt;/span&gt;openlogi&lt;span style="color:#f92672"&gt;.&lt;/span&gt;package;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; nixosConfigurations &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; thinkpad &lt;span style="color:#f92672"&gt;=&lt;/span&gt; nixpkgs&lt;span style="color:#f92672"&gt;.&lt;/span&gt;lib&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nixosSystem {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; system &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;x86_64-linux&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; modules &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;./common/configuration.nix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;./thinkpad/configuration.nix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; home-manager&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nixosModules&lt;span style="color:#f92672"&gt;.&lt;/span&gt;home-manager
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; openlogi&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nixosModules&lt;span style="color:#f92672"&gt;.&lt;/span&gt;default
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; nixpkgs&lt;span style="color:#f92672"&gt;.&lt;/span&gt;overlays &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; emacs-overlay&lt;span style="color:#f92672"&gt;.&lt;/span&gt;overlays&lt;span style="color:#f92672"&gt;.&lt;/span&gt;emacs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; home-manager&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sharedModules &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; nixvim&lt;span style="color:#f92672"&gt;.&lt;/span&gt;homeModules&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nixvim
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; home-manager&lt;span style="color:#f92672"&gt;.&lt;/span&gt;extraSpecialArgs &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;inherit&lt;/span&gt; beancount-mode;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; home-manager&lt;span style="color:#f92672"&gt;.&lt;/span&gt;useGlobalPkgs &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; home-manager&lt;span style="color:#f92672"&gt;.&lt;/span&gt;useUserPackages &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; home-manager&lt;span style="color:#f92672"&gt;.&lt;/span&gt;users&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sonohen &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;./common/home.nix&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="dot-github-workflows-nixos-parts-build-dot-yml"&gt;&lt;code&gt;.github/workflows/nixos-parts-build.yml&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;これが毎週金曜日4:30に起動する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;YAML&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Update and Build NixOS Packages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;schedule&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;cron&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;30 4 * * 5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;timezone&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Asia/Tokyo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;workflow_dispatch&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;permissions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;contents&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;write&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;concurrency&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;group&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;nixos-update-build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cancel-in-progress&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;runs-on&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ubuntu-24.04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;timeout-minutes&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;360&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Checkout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803&lt;/span&gt; &lt;span style="color:#75715e"&gt;# v6.1.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ref&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;master&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;persist-credentials&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Install Nix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3&lt;/span&gt; &lt;span style="color:#75715e"&gt;# v31.10.6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;extra_nix_config&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; max-jobs = 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; cores = 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Setup Cachix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cachix/cachix-action@38b082610b782e7e93e209c35fd730d399dee866&lt;/span&gt; &lt;span style="color:#75715e"&gt;# v17&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;sonohen-cachix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;authToken&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;${{ secrets.CACHIX_AUTH_TOKEN }}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Update flake.lock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;working-directory&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;nixos&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;run&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;nix flake update&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Build Emacs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;run&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; nix build ./nixos#emacs \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; --no-link \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; --print-build-logs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Build OpenLogi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;run&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; nix build ./nixos#openlogi \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; --no-link \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; --print-build-logs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Commit and push flake.lock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;run&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; if git diff --quiet -- nixos/flake.lock; then
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; echo &amp;#34;No updates&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; exit 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fi
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; git config user.name &amp;#34;github-actions[bot]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; git config user.email &amp;#34;41898282+github-actions[bot]@users.noreply.github.com&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; git add nixos/flake.lock
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; git commit -m &amp;#34;chore(nix): update flake.lock&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; git -c http.extraheader=&amp;#34;AUTHORIZATION: basic $(printf &amp;#39;x-access-token:%s&amp;#39; &amp;#34;$GH_TOKEN&amp;#34; | base64 -w0)&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; push origin HEAD:master&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;env&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;GH_TOKEN&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="結果"&gt;結果
&lt;/h2&gt;&lt;h3 id="ビルドの所要時間と容量"&gt;ビルドの所要時間と容量
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;emacs-unstable-pgtk&lt;/code&gt; のビルド時間は、2026-10-30現在の &lt;code&gt;emacs-unstable-pgtk-31.1&lt;/code&gt; で35分35秒。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openlogi&lt;/code&gt; のビルド時間は、2026-10-30現在の &lt;code&gt;0.8.19&lt;/code&gt; で27分20秒。&lt;/li&gt;
&lt;li&gt;Cachixの利用容量は642.6 MiB。
&lt;ul&gt;
&lt;li&gt;無料で利用できる容量が5.0GiBなので、5~6世代持たせておけばよいかな。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="今後の課題"&gt;今後の課題
&lt;/h2&gt;&lt;p&gt;neovimをこの構成のなかに入れておくかどうするかを検討する必要がある。次の更新のタイミングで検討することにしたい。&lt;/p&gt;</description></item><item><title>NixOSでZFSからデータを救出する</title><link>https://sonohen.net/posts/2026/10/26/</link><pubDate>Mon, 26 Oct 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/10/26/</guid><description>&lt;h2 id="概要"&gt;概要
&lt;/h2&gt;&lt;p&gt;Ubuntu Linuxを使用していたが、自分のLinux環境をファイルで定義できるNixOSに興味を持ち、この週末に移行した。
Ubuntu LinuxではLUKSで暗号化したZFSパーティションを使用していたため、NixOSからZFSなパーティションをマウントしてデータ移行する必要があった。その対応の記録をしたので、ブログにまとめることにする。&lt;/p&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;NixOS 26.05&lt;/li&gt;
&lt;li&gt;ThinkPad E14 Gen 3
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/dev/nvme0n1&lt;/code&gt;: KBG40ZNT256G(Toshiba) - NixOSインストール済&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/dev/nvme1n1&lt;/code&gt;: Samsung SSD 980 500GB - Ubuntu Linuxインストール済&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="目的"&gt;目的
&lt;/h2&gt;&lt;p&gt;以下を実現することを目的とする。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/dev/nvme1n1&lt;/code&gt; から &lt;code&gt;/dev/nvme0n1&lt;/code&gt; に &lt;code&gt;/home&lt;/code&gt; のデータを移行する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/dev/nvme1n1&lt;/code&gt; を消去し、新たにext4のパーティションを作成し、それをNixOSの &lt;code&gt;/home&lt;/code&gt; にマウントする&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="データ移行の流れ"&gt;データ移行の流れ
&lt;/h2&gt;&lt;p&gt;大きくは以下の4つの手順を踏む。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;現状の把握&lt;/li&gt;
&lt;li&gt;LUKS鍵の取り出し&lt;/li&gt;
&lt;li&gt;ZFSパーティションのマウントとデータの移行&lt;/li&gt;
&lt;li&gt;ディスクのフォーマットと /home ヘのマウント&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="現状の把握"&gt;現状の把握
&lt;/h2&gt;&lt;h3 id="ディスクの状況"&gt;ディスクの状況
&lt;/h3&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lsblk -o NAME,PATH,SIZE,TYPE,FSTYPE,UUID,MOUNTPOINTS,MODEL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME PATH SIZE TYPE FSTYPE UUID MOUNTPOINTS MODEL
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nvme0n1 /dev/nvme0n1 238.5G disk KBG40ZNT256G TOSHIBA MEMORY
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─nvme0n1p1 /dev/nvme0n1p1 2G part vfat E29B-9551 /boot
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─nvme0n1p2 /dev/nvme0n1p2 24G part swap 15f27874-dfbd-4afb-92cb-56bd089cea04 [SWAP]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└─nvme0n1p3 /dev/nvme0n1p3 212.5G part ext4 ad329431-4846-495f-b312-67d24b2a005c /nix/store
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nvme1n1 /dev/nvme1n1 465.8G disk Samsung SSD 980 500GB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─nvme1n1p1 /dev/nvme1n1p1 1G part vfat FACF-1404
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─nvme1n1p2 /dev/nvme1n1p2 2G part zfs_member 12601984913637652299
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─nvme1n1p3 /dev/nvme1n1p3 8G part
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└─nvme1n1p4 /dev/nvme1n1p4 454.7G part zfs_member 14549146316260236921&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="zfs-の状態"&gt;&lt;code&gt;ZFS&lt;/code&gt; の状態
&lt;/h3&gt;&lt;p&gt;あらかじめ &lt;code&gt;configuration.nix&lt;/code&gt; に以下の記述を入れたうえでビルドしておく必要がある。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;nix&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-nix" data-lang="nix"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;networking&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hostId &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;1aeba738&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;boot&lt;span style="color:#f92672"&gt;.&lt;/span&gt;supportedFilesystems &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [ &lt;span style="color:#e6db74"&gt;&amp;#34;zfs&amp;#34;&lt;/span&gt; ];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;boot&lt;span style="color:#f92672"&gt;.&lt;/span&gt;zfs&lt;span style="color:#f92672"&gt;.&lt;/span&gt;forceImportRoot &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;なお &lt;code&gt;networking.hostId&lt;/code&gt; には、以下を実行して取得した値を設定する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;head -c &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; /etc/machine-id&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以下のように &lt;code&gt;nix shell nixpkgs#zfs&lt;/code&gt; を実行すれば環境を汚すこともないので便利である。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#zfs -c zpool import&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;無事に認識されていることがわかる。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pool: bpool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id: 12601984913637652299
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; state: ONLINE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;status: The pool was last accessed by another system.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;action: The pool can be imported using its name or numeric identifier and
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	the &amp;#39;-f&amp;#39; flag.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-EY
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;config:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	bpool ONLINE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 nvme-eui.002538db11c4531d-part2 ONLINE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pool: rpool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id: 14549146316260236921
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; state: ONLINE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;status: The pool was last accessed by another system.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;action: The pool can be imported using its name or numeric identifier and
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	the &amp;#39;-f&amp;#39; flag.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-EY
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;config:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	rpool ONLINE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 nvme-eui.002538db11c4531d-part4 ONLINE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ちなみに &lt;code&gt;rpool&lt;/code&gt; がUbuntu Linuxで言うところの &lt;code&gt;/&lt;/code&gt; である。&lt;/p&gt;
&lt;h2 id="luks鍵の取り出し"&gt;LUKS鍵の取り出し
&lt;/h2&gt;&lt;p&gt;Ubuntu Linuxの &lt;code&gt;/&lt;/code&gt; をマウントするためのディレクトリとして &lt;code&gt;/mnt/zfs-recovery/&lt;/code&gt; を作成する。マウントし &lt;code&gt;rpool&lt;/code&gt; の状態を確認する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#zfs -c zpool import -f -o readonly&lt;span style="color:#f92672"&gt;=&lt;/span&gt;on -N -R /mnt/zfs-recovery rpool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#zfs -c zfs list -r -o name,mountpoint,canmount,encryption,keystatus rpool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME MOUNTPOINT CANMOUNT ENCRYPTION KEYSTATUS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool /mnt/zfs-recovery off aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT none off aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3 /mnt/zfs-recovery on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/srv /mnt/zfs-recovery/srv on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/usr /mnt/zfs-recovery/usr off aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/usr/local /mnt/zfs-recovery/usr/local on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var /mnt/zfs-recovery/var off aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var/games /mnt/zfs-recovery/var/games on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var/lib /mnt/zfs-recovery/var/lib on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var/lib/AccountsService /mnt/zfs-recovery/var/lib/AccountsService on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var/lib/NetworkManager /mnt/zfs-recovery/var/lib/NetworkManager on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var/lib/apt /mnt/zfs-recovery/var/lib/apt on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var/lib/dpkg /mnt/zfs-recovery/var/lib/dpkg on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var/log /mnt/zfs-recovery/var/log on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var/mail /mnt/zfs-recovery/var/mail on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var/snap /mnt/zfs-recovery/var/snap on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var/spool /mnt/zfs-recovery/var/spool on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/ROOT/ubuntu_094mo3/var/www /mnt/zfs-recovery/var/www on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/USERDATA none off aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/USERDATA/home_lqdl5w /mnt/zfs-recovery/home on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/USERDATA/root_lqdl5w /mnt/zfs-recovery/root on aes-256-gcm unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/keystore - - off -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;rpool/USERDATA/home_lqdl5w&lt;/code&gt; が &lt;code&gt;/home&lt;/code&gt; のデータセットであることがわかる。
&lt;code&gt;KEYSTATUS&lt;/code&gt; が &lt;code&gt;unavailable&lt;/code&gt; になっているので、 &lt;code&gt;encryptionroot&lt;/code&gt; を確認する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#zfs -c zfs get -o property,value encryptionroot,keylocation,keyformat,keystatus,mountpoint,canmount rpool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PROPERTY VALUE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;encryptionroot rpool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;keylocation file:///run/keystore/rpool/system.key
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;keyformat raw
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;keystatus unavailable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mountpoint /mnt/zfs-recovery
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;canmount off&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Ubuntu Linux では &lt;code&gt;rpool/keystore/system.key&lt;/code&gt; が存在し、起動時に &lt;code&gt;/run/keystore/rpool&lt;/code&gt; にマウントされる。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#cryptsetup -c cryptsetup open --readonly /dev/zvol/rpool/keystore keystore-rpool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以下のコマンドを実行し、確認する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lsblk -f /dev/mapper/keystore-rpool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;keystore-rpool ext4 1.0 keystore-rpool d18e3c3c-d0fb-4507-94bc-61327e95edc4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;期待される場所(&lt;code&gt;keylocation file:///run/keystore/rpool/system.key&lt;/code&gt;)で参照できるようにマウントする。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo mkdir -p /run/keystore/rpool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo mount -o ro,noload /dev/mapper/keystore-rpool /run/keystore/rpool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo test -s /run/keystore/rpool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#zfs -c zfs load-key rpool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="zfsパーティションのマウントとデータの移行"&gt;ZFSパーティションのマウントとデータの移行
&lt;/h2&gt;&lt;p&gt;ここまでで rpool を読み込むための鍵を入手できたので &lt;code&gt;rpool/USERDATA/home_lqdl5w&lt;/code&gt; をマウントする。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#zfs -c zpool get altroot rpool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#zfs -c zfs get mountpoint,canmount,keystatus rpool/USERDATA/home_lqdl5w&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;keystatus = available&lt;/code&gt;, &lt;code&gt;canmount = on&lt;/code&gt; であることが確認できる。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME PROPERTY VALUE SOURCE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool altroot /mnt/zfs-recovery local
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME PROPERTY VALUE SOURCE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/USERDATA/home_lqdl5w mountpoint /mnt/zfs-recovery/home local
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/USERDATA/home_lqdl5w canmount on local
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rpool/USERDATA/home_lqdl5w keystatus available -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;マウントし、内容を確認する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo mkdir -p /mnt/zfs-recovery/home
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#zfs -c zfs mount rpool/USERDATA/home_lqdl5w
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo findmnt -S rpool/USERDATA/home_lqdl5w
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ls -la /mnt/zfs-recovery/home&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TARGET SOURCE FSTYPE OPTIONS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/mnt/zfs-recovery/home
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rpool/USERDATA/home_lqdl5w
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; zfs ro,nodev,relatime,xattr,posixac
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total 22
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x 3 root root 3 Oct 4 09:43 .
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x 3 root root 4096 Oct 25 14:33 ..
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-x---+ 32 sonohen 1000 59 Oct 24 23:07 sonohen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ここまできたら、あとは &lt;code&gt;rsync&lt;/code&gt; を使用してデータを救出すればよい。
&lt;code&gt;/dev/nvme1n1p1&lt;/code&gt; を &lt;code&gt;/mnt/new-home&lt;/code&gt; にマウントし、 &lt;code&gt;/home&lt;/code&gt; の全データを &lt;code&gt;rsync&lt;/code&gt; で移行する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo mkdir -p /mnt/new-home
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo mount /dev/nvme1n1p1 /mnt/new-home
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#rsync -c rsync -aHAXx --numeric-ids /home/ /mnt/new-home/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;blkid -s UUID -o value /dev/nvme1n1p1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="ディスクのフォーマットと-home-へのマウント"&gt;ディスクのフォーマットと /home へのマウント
&lt;/h2&gt;&lt;h3 id="rpool-の切り離し"&gt;&lt;code&gt;rpool&lt;/code&gt; の切り離し
&lt;/h3&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#zfs -c zfs unmount rpool/USERDATA/home_lqdl5w
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo umount /run/keystore/rpool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#cryptsetup -c cryptsetup close keystore-rpool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#zfs -c zpool export rpool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;切り離し後の確認を行う。nvme1n1がマウントされていないことを確認する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo findmnt -T /
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo findmnt -T /boot
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo findmnt -T /home
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lsblk -o NAME,SIZE,MODEL,FSTYPE,MOUNTPOINTS /dev/nvme1n1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TARGET SOURCE FSTYPE OPTIONS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/ /dev/nvme0n1p3 ext4 rw,relatime
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TARGET SOURCE FSTYPE OPTIONS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/boot /dev/nvme0n1p1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vfat rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=is
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TARGET SOURCE FSTYPE OPTIONS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/ /dev/nvme0n1p3 ext4 rw,relatime
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME SIZE MODEL FSTYPE MOUNTPOINTS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nvme1n1 465.8G Samsung SSD 980 500GB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─nvme1n1p1 1G vfat
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─nvme1n1p2 2G zfs_member
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─nvme1n1p3 8G
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└─nvme1n1p4 454.7G zfs_member&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="パーティションを作成する"&gt;パーティションを作成する
&lt;/h3&gt;&lt;p&gt;この作業は破壊的であるため、データのバックアップが完了していることを再確認してから実行する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#gptfdisk -c sgdisk --clear --new&lt;span style="color:#f92672"&gt;=&lt;/span&gt;1:0:0 --typecode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;1:8300 -change-name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;1:home /dev/nvme1n1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nix shell nixpkgs#parted -c partprobe /dev/nvme1n1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo udevadm settle
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo wipefs -a /dev/nvme1n1p1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo mkfs.ext4 -L home /dev/nvme1n1p1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS /dev/nvme1n1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME SIZE TYPE FSTYPE MOUNTPOINTS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nvme1n1 465.8G disk
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└─nvme1n1p1 465.8G part ext4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="configuration-dot-nix-の修正"&gt;&lt;code&gt;configuration.nix&lt;/code&gt; の修正
&lt;/h3&gt;&lt;p&gt;以下を追記し、リビルドして再起動する。再起動後 &lt;code&gt;/dev/nvme1n1p1&lt;/code&gt; が &lt;code&gt;/home&lt;/code&gt; にマウントされていることを確認する。なお、=/dev/nvme1n1p1= (ext4ファイルシステム) のUUIDは &lt;code&gt;blkid -s UUID -o value /dev/nvme1n1p1&lt;/code&gt; で取得できる。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;nix&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-nix" data-lang="nix"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fileSystems&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/home&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; device &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/dev/disk/by-uuid/66cbb556-4c8b-4480-8ec5-b40484996a4b&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fsType &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ext4&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="後始末"&gt;後始末
&lt;/h3&gt;&lt;p&gt;冒頭で &lt;code&gt;configuration.nix&lt;/code&gt; に追記した以下の記述は不要なので消す。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;nix&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-nix" data-lang="nix"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;networking&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hostId &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;1aeba738&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;boot&lt;span style="color:#f92672"&gt;.&lt;/span&gt;supportedFilesystems &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [ &lt;span style="color:#e6db74"&gt;&amp;#34;zfs&amp;#34;&lt;/span&gt; ];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;boot&lt;span style="color:#f92672"&gt;.&lt;/span&gt;zfs&lt;span style="color:#f92672"&gt;.&lt;/span&gt;forceImportRoot &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="感想"&gt;感想
&lt;/h2&gt;&lt;p&gt;順を追って対応すればなんら難しくはないのだが、面倒臭い作業ではある。当面対応したくはないのだが、また機会がありそうなので、記録しておく。&lt;/p&gt;</description></item><item><title>Ubuntu 26.04 LTSでScanSnap S1100を使う</title><link>https://sonohen.net/posts/2026/10/17/</link><pubDate>Sat, 17 Oct 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/10/17/</guid><description>&lt;p&gt;ScanSnap S1100をUbuntu 26.04 LTSで使えるようにした。ファームウェアを配置し、SANEの設定を変更したところ、スキャナーとして認識された。gscan2pdfからのスキャンもできたので、当面はこの構成で使うことにした。&lt;/p&gt;
&lt;h2 id="ファームウェアを配置する"&gt;ファームウェアを配置する
&lt;/h2&gt;&lt;p&gt;まず、今回使用したファームウェア&lt;code&gt;1100_0A00.nal&lt;/code&gt;をダウンロードした。取得元はGitHubの&lt;a class="link" href="https://github.com/stevleibelt/scansnap-firmware" target="_blank" rel="noopener"
 &gt;stevleibelt/scansnap-firmware&lt;/a&gt;だ。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd ~/Downloads/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wget https://github.com/stevleibelt/scansnap-firmware/raw/refs/heads/master/1100_0A00.nal
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ls -alh 1100_0A00.nal
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;file 1100_0A00.nal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;ls&lt;/code&gt;では約65KBのファイルとして表示され、&lt;code&gt;file&lt;/code&gt;の結果は次のとおりだった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1100_0A00.nal: data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;続いて、ファームウェアを&lt;code&gt;/usr/share/sane/epjitsu/&lt;/code&gt;に配置した。以下は管理者権限で行った操作を、&lt;code&gt;sudo&lt;/code&gt;付きのコマンドで示している。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo mkdir -p /usr/share/sane/epjitsu/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo cp ~/Downloads/1100_0A00.nal /usr/share/sane/epjitsu/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ls -alh /usr/share/sane/epjitsu/1100_0A00.nal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;配置後は、所有者が&lt;code&gt;root&lt;/code&gt;、パーミッションが&lt;code&gt;-rw-r--r--&lt;/code&gt;になっていることを確認した。&lt;/p&gt;
&lt;h2 id="epjitsuconfのファームウェア指定を変更する"&gt;epjitsu.confのファームウェア指定を変更する
&lt;/h2&gt;&lt;p&gt;設定を編集する前に、&lt;code&gt;/etc/sane.d/epjitsu.conf&lt;/code&gt;をバックアップした。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo cp /etc/sane.d/epjitsu.conf /etc/sane.d/epjitsu.conf.20261017&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;その後、設定ファイルのファームウェア指定を、配置したファイルのパスへ変更した。今回の記録で、変更前に指定されていたのは次のパスだった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;firmware /usr/share/sane/epjitsu/1100_0B00.nal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;変更後の有効な指定は次のとおりだ。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;firmware /usr/share/sane/epjitsu/1100_0A00.nal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;firmware&lt;/code&gt;の指定が対応する&lt;code&gt;usb&lt;/code&gt;の指定より前にあることも確認した。変更内容はバックアップとの差分で確認できる。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;diff /etc/sane.d/epjitsu.conf /etc/sane.d/epjitsu.conf.20261017&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;今回の差分は次のとおりだった。&lt;code&gt;&amp;lt;&lt;/code&gt;が編集後の設定、&lt;code&gt;&amp;gt;&lt;/code&gt;がバックアップの内容になる。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;diff&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;73,74c73
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt; # firmware /usr/share/sane/epjitsu/1101_0B00.nal
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt; firmware /usr/share/sane/epjitsu/1100_0A00.nal
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;&amp;gt; firmware /usr/share/sane/epjitsu/1100_0B00.nal
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="scansnap-s1100の認識を確認する"&gt;ScanSnap S1100の認識を確認する
&lt;/h2&gt;&lt;p&gt;設定後にScanSnap S1100をUbuntuのマシンへ接続し、次のコマンドを実行した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;scanimage -L&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;結果は次のとおりだった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;device `v4l:/dev/video0&amp;#39; is a Noname Integrated Camera: Integrated C virtual device
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;device `epjitsu:libusb:001:011&amp;#39; is a FUJITSU ScanSnap S1100 scanner&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;2行目に&lt;code&gt;FUJITSU ScanSnap S1100 scanner&lt;/code&gt;と表示され、ScanSnapが認識されていることを確認できた。&lt;/p&gt;
&lt;h2 id="gscan2pdfでスキャンする"&gt;gscan2pdfでスキャンする
&lt;/h2&gt;&lt;p&gt;gscan2pdfを起動し、次の設定でスキャンを試した。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;項目&lt;/th&gt;
 &lt;th&gt;設定値&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;ページ数&lt;/td&gt;
 &lt;td&gt;全て&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;スキャンプロファイル&lt;/td&gt;
 &lt;td&gt;Default&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Postprocessingの認識する言語&lt;/td&gt;
 &lt;td&gt;日本語&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;この状態でスキャンできた。ただし、日本語の文字認識精度までは今回の記録では評価していない。&lt;/p&gt;
&lt;p&gt;Windowsでは、実際のドキュメントのサイズに合わせて自動で切り抜く機能を使えていた。今回のLinux環境では、それに相当する設定項目を見つけられなかった。自動切り抜きの方法は確認できていないが、スキャン自体はできるようになったので、まずはこの設定で使ってみる。&lt;/p&gt;</description></item><item><title>Blenderの2回目の起動でウィンドウが透明になる：XWayland経由で回避する</title><link>https://sonohen.net/posts/2026/10/16/</link><pubDate>Fri, 16 Oct 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/10/16/</guid><description>&lt;p&gt;UbuntuでBlenderを使っていたところ、1回目は起動するのに、終了して2回目を開くと画面が表示されなくなった。よく見ると、ウィンドウが透明になっているようだった。&lt;/p&gt;
&lt;p&gt;今回の環境では、&lt;code&gt;WAYLAND_DISPLAY&lt;/code&gt;を空にしてXWayland経由で起動すると回避できた。毎回端末から起動するのは不便なので、ユーザー用のランチャーにも同じ指定を追加した。変更後はアイコンからの起動も確認できた。&lt;/p&gt;
&lt;p&gt;調査とランチャーの変更はCodexに依頼し、端末とアイコンからの起動確認は自分で行った。Wayland側の表示経路に問題を絞れたが、Blender、GPUドライバー、コンポジターのどこに不具合があるかまでは特定していない。&lt;/p&gt;
&lt;h2 id="発生環境と症状"&gt;発生環境と症状
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;項目&lt;/th&gt;
 &lt;th&gt;確認した環境&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;OS&lt;/td&gt;
 &lt;td&gt;Ubuntu 26.04.1 LTS&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Linux Kernel&lt;/td&gt;
 &lt;td&gt;7.0.0-38-generic&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Blender&lt;/td&gt;
 &lt;td&gt;Snap版 5.2.2 LTS、revision 7803&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;デスクトップセッション&lt;/td&gt;
 &lt;td&gt;Wayland&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;GPU&lt;/td&gt;
 &lt;td&gt;AMD Lucienne&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;最初は起動していないと思ったが、画面が表示されない状態でもプロセスは残っていた。ホストの端末で確認した結果は次のとおりだった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pgrep -a -f &lt;span style="color:#e6db74"&gt;&amp;#39;blender|snap-confine&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;14617 /snap/blender/7803/blender&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;終了ログには1回目の&lt;code&gt;Blender quit&lt;/code&gt;があり、その直後に次の起動要求も記録されていた。起動要求が届いていないという状態ではなかった。&lt;/p&gt;
&lt;h2 id="初期設定でも再現しログは描画処理まで進んでいた"&gt;初期設定でも再現し、ログは描画処理まで進んでいた
&lt;/h2&gt;&lt;p&gt;まず&lt;code&gt;--debug&lt;/code&gt;で起動したが、画面が使えない状態は変わらなかった。続いて、初期設定で詳細ログを取った。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;blender --factory-startup --debug-all &amp;gt; ~/blender-factory-debug.log 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;この条件でも透明なウィンドウになる症状は再現した。ログには、次のようにスプラッシュやメニューの描画処理が記録されていた。関係する行を抜粋する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;menutype_draw: opening menu &amp;#34;WM_MT_splash&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ghost_event_proc: ghost redraw decor 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;screen_refresh_if_needed: set screen
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;menutype_draw: opening menu &amp;#34;TOPBAR_MT_editor_menus&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;描画処理まで進んでいたため、起動前に停止しているという見立てを改めた。初期設定でも再現することから、保存済みの設定だけが原因である可能性も下がった。ただし、ログに描画処理があっても、画面に正常に表示されたことまでは意味しない。&lt;/p&gt;
&lt;h2 id="waylandを無効にすると2回とも起動できた"&gt;Waylandを無効にすると、2回とも起動できた
&lt;/h2&gt;&lt;p&gt;次に、初期設定の条件を保ったまま、Waylandを無効にして起動した。以下のコマンドは、Blenderを使っているホストの端末で実行する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WAYLAND_DISPLAY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; blender --factory-startup&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;この起動では画面が表示された。一度終了し、同じコマンドで再び起動しても表示できた。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WAYLAND_DISPLAY&lt;/code&gt;を空にしてX11を使わせる方法は、&lt;a class="link" href="https://projects.staging.blender.org/blender/blender-manual/src/branch/main/manual/getting_started/installing/linux_windowing_environment.rst" target="_blank" rel="noopener"
 &gt;Blender公式マニュアルのLinux Windowing Environment&lt;/a&gt;にも記載されている。Waylandセッション内では、X11アプリを動かすXWayland経由での起動になる。デスクトップ全体をX11セッションに切り替える必要はない。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;起動条件&lt;/th&gt;
 &lt;th&gt;結果&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;通常の起動&lt;/td&gt;
 &lt;td&gt;1回目は表示され、2回目は透明になる&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--factory-startup --debug-all&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;透明になる症状が再現した&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;WAYLAND_DISPLAY=&amp;quot;&amp;quot;&lt;/code&gt;と&lt;code&gt;--factory-startup&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;終了後の再起動を含め、2回とも表示された&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;この比較から、今回の問題はWayland側の表示経路にある可能性が高いと判断した。具体的な不具合箇所を直したわけではなく、XWaylandを使う回避策だ。&lt;/p&gt;
&lt;h2 id="アイコンからもxwayland経由で起動する"&gt;アイコンからもXWayland経由で起動する
&lt;/h2&gt;&lt;p&gt;毎回コマンドを入力せずに済むよう、Snap版のランチャーをユーザー側にコピーし、起動コマンドを変更した。ここからのパスとファイル名は、今回使っていたSnap版のものだ。&lt;/p&gt;
&lt;p&gt;コピー先は&lt;code&gt;~/.local/share/applications/blender_blender.desktop&lt;/code&gt;とする。以下は&lt;code&gt;XDG_DATA_HOME&lt;/code&gt;を変更していない環境向けの手順で、既存ファイルがある場合は上書きせず内容を確認する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir -p ~/.local/share/applications
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp -i /var/lib/snapd/desktop/applications/blender_blender.desktop &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ~/.local/share/applications/blender_blender.desktop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;コピーしたファイルをエディターで開き、元の&lt;code&gt;Exec&lt;/code&gt;行を変更する。&lt;/p&gt;
&lt;p&gt;変更前：&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;ini&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Exec&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/snap/bin/blender %f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;変更後：&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;ini&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Exec&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/usr/bin/env WAYLAND_DISPLAY= /snap/bin/blender %f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Exec&lt;/code&gt;では&lt;code&gt;env&lt;/code&gt;を実行し、その引数として環境変数を渡す。ファイルを開くための&lt;code&gt;%f&lt;/code&gt;や、アイコンなどの他の項目はそのまま残す。普段の設定を読み込むため、切り分け用の&lt;code&gt;--factory-startup&lt;/code&gt;は付けない。&lt;/p&gt;
&lt;p&gt;ユーザー側にも同名のファイルを置くのは、元のランチャーと同じdesktop file IDで優先させるためだ。この仕組みは&lt;a class="link" href="https://specifications.freedesktop.org/desktop-entry/latest/file-naming.html" target="_blank" rel="noopener"
 &gt;Desktop Entry Specification&lt;/a&gt;と&lt;a class="link" href="https://specifications.freedesktop.org/basedir/latest/" target="_blank" rel="noopener"
 &gt;XDG Base Directory Specification&lt;/a&gt;に基づく。システム側のランチャーは変更しない。&lt;/p&gt;
&lt;p&gt;今回の変更後は、次のコマンドで構文検証とデータベース更新を行い、どちらも成功した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;desktop-file-validate ~/.local/share/applications/blender_blender.desktop
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;update-desktop-database ~/.local/share/applications&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;その後、自分でアイコンから起動し、画面が表示されることも確認できた。端末で検証した回避策を、普段の起動にも適用できた。&lt;/p&gt;
&lt;p&gt;元に戻す場合は、今回作成したユーザー用の&lt;code&gt;blender_blender.desktop&lt;/code&gt;を削除する。コピーしたランチャーには、Snap側の将来の変更が自動では反映されないため、Blenderの更新後に起動方法やアイコンが変わった場合は元ファイルと比較する。&lt;/p&gt;</description></item><item><title>DockerのAppArmor適用失敗：プロファイルの読み込みとreadby権限で対処</title><link>https://sonohen.net/posts/2026/10/12/</link><pubDate>Mon, 12 Oct 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/10/12/</guid><description>&lt;p&gt;UbuntuでCodex用のDockerコンテナを起動したところ、AppArmorプロファイルの適用に失敗した。原因は、起動時に指定したカスタムプロファイルがホストに読み込まれていなかったことだった。読み込むとコンテナは起動したが、続いてコンテナ内のbubblewrapで権限不足が見つかり、プロファイルの修正も必要になった。&lt;/p&gt;
&lt;p&gt;この記事では、Dockerを使う技術者に向けて、拒否ログによる切り分けと対処を説明する。今回確認した問題は次の2段階だった。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;発生段階&lt;/th&gt;
 &lt;th&gt;ログの手掛かり&lt;/th&gt;
 &lt;th&gt;対処&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;コンテナの起動時&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;label not found&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;指定したプロファイルをホストに読み込む&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;起動後のbubblewrap実行時&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;denied_mask=&amp;quot;readby&amp;quot;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;同じプロファイルのプロセス間に&lt;code&gt;readby&lt;/code&gt;を許可する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;調査はCodexに依頼し、ホストの設定変更とコマンド実行は自分で行った。修正後はコンテナへのプロファイル適用を確認し、提示した直近5分のログに拒否はなかった。その後、ホストの再起動後も自分で確認し、問題なかった。&lt;/p&gt;
&lt;h2 id="この環境でのapparmorとbubblewrapの役割"&gt;この環境でのAppArmorとbubblewrapの役割
&lt;/h2&gt;&lt;p&gt;AppArmorは、プロセスが実行できる操作をプロファイルで制限するLinuxのセキュリティ機構だ。今回の環境では、Dockerコンテナに&lt;code&gt;codex-bwrap&lt;/code&gt;というカスタムプロファイルを適用していた。これは自分の環境で用意した名前で、Docker標準のプロファイル名ではない。&lt;/p&gt;
&lt;p&gt;コンテナ内では、Codexのコマンド実行を制限するためにbubblewrap（実行ファイル名は&lt;code&gt;bwrap&lt;/code&gt;）も使っている。コンテナが起動した後も、その中のプロセスはAppArmorの制約を受けるため、bubblewrapの動作に必要な操作をプロファイルで許可する必要がある。&lt;/p&gt;
&lt;p&gt;また、プロファイルには次の3つの状態がある。設定ファイルがあるだけでは、コンテナに適用できない。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;状態&lt;/th&gt;
 &lt;th&gt;今回の対象・確認方法&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;設定ファイルが存在する&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;~/work/codex-docker/codex-bwrap.apparmor&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ホストのLinux Kernelに読み込まれている&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;apparmor_parser&lt;/code&gt;で読み込み、&lt;code&gt;aa-status&lt;/code&gt;で確認&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;コンテナに適用されている&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;docker inspect&lt;/code&gt;の&lt;code&gt;AppArmorProfile&lt;/code&gt;で確認&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;以下のコマンドは、Dockerデーモンが動いているUbuntuホストの通常のユーザー端末で実行する。パスとプロファイル名は自分の環境に合わせて読み替える必要がある。掲載するルールは既存プロファイルの変更箇所であり、プロファイル全体ではない。&lt;/p&gt;
&lt;h2 id="発生したエラーと環境"&gt;発生したエラーと環境
&lt;/h2&gt;&lt;p&gt;実行したのは、自作のCodex用Docker起動スクリプトだ。このスクリプトは、コンテナの起動時に&lt;code&gt;codex-bwrap&lt;/code&gt;を指定する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;~/work/codex-docker/run-codex.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;出力は次のとおりだった。末尾のヘルプ案内は省略している。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Docker AppArmor setting: codex-bwrap
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: unable to apply apparmor profile: apparmor failed to apply profile: write fsmount:fscontext:proc/thread-self/attr/apparmor/exec: no such file or directory&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;unable to apply apparmor profile&lt;/code&gt;から、コンテナを準備するOCIランタイムがAppArmorを適用する段階で失敗したと分かる。コンテナ内のCodexは、まだ動き始めていなかった。調査時に確認した環境は次のとおり。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;項目&lt;/th&gt;
 &lt;th&gt;バージョン・状態&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Ubuntu&lt;/td&gt;
 &lt;td&gt;26.04.1 LTS&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Linux Kernel&lt;/td&gt;
 &lt;td&gt;7.0.0-38-generic&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Docker Client / Server&lt;/td&gt;
 &lt;td&gt;29.9.0 / 29.9.0&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Docker context&lt;/td&gt;
 &lt;td&gt;default&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;containerd&lt;/td&gt;
 &lt;td&gt;v2.4.1&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;runc&lt;/td&gt;
 &lt;td&gt;1.5.2&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;AppArmor parser&lt;/td&gt;
 &lt;td&gt;5.0.2&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;AppArmor&lt;/td&gt;
 &lt;td&gt;有効、&lt;code&gt;codex-bwrap&lt;/code&gt;を指定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="起動時の拒否ログからプロファイル未読み込みを確認する"&gt;起動時の拒否ログから、プロファイル未読み込みを確認する
&lt;/h2&gt;&lt;p&gt;エラー末尾は&lt;code&gt;no such file or directory&lt;/code&gt;だが、Codexが確認すると、ホストの&lt;code&gt;/proc/thread-self/attr/apparmor/exec&lt;/code&gt;は存在していた。&lt;/p&gt;
&lt;p&gt;原因を判断する手掛かりになったのは、Linux Kernelのログだった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo aa-status | rg &lt;span style="color:#e6db74"&gt;&amp;#39;codex-bwrap&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo journalctl -k -b --no-pager --grep&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;codex-bwrap|label not found&amp;#39;&lt;/span&gt; -n &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;aa-status&lt;/code&gt;の抽出結果に&lt;code&gt;codex-bwrap&lt;/code&gt;の行はなく、ログには次の拒否が記録されていた。時刻やホスト名などを省略し、メッセージ部分を抜粋している。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apparmor=&amp;#34;DENIED&amp;#34; operation=&amp;#34;change_onexec&amp;#34; class=&amp;#34;file&amp;#34; info=&amp;#34;label not found&amp;#34; error=-2 profile=&amp;#34;runc&amp;#34; name=&amp;#34;codex-bwrap&amp;#34; pid=8853 comm=&amp;#34;runc:[2:INIT]&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ここでいうラベルは、AppArmorがプロファイルを識別するための名前だ。&lt;code&gt;name=&amp;quot;codex-bwrap&amp;quot;&lt;/code&gt;と&lt;code&gt;info=&amp;quot;label not found&amp;quot;&lt;/code&gt;から、起動時に指定したプロファイルを見つけられなかったと分かる。&lt;a class="link" href="https://raw.githubusercontent.com/opencontainers/runc/v1.5.2/libcontainer/apparmor/apparmor_linux.go" target="_blank" rel="noopener"
 &gt;runc 1.5.2の実装&lt;/a&gt;では、exec属性への書き込みでプロファイルを指定する。今回の書き込みエラーは、パス自体が存在しないという意味には限定できなかった。&lt;/p&gt;
&lt;p&gt;Codexが起動スクリプトを調べたところ、AppArmorを自動選択する&lt;code&gt;CODEX_APPARMOR=auto&lt;/code&gt;設定は、DockerのAppArmor対応だけを確認していた。カスタムプロファイルの登録確認や読み込みは行っていなかった。&lt;a class="link" href="https://docs.docker.com/engine/security/apparmor/" target="_blank" rel="noopener"
 &gt;Dockerの公式資料&lt;/a&gt;でも、カスタムプロファイルは先に読み込み、その後でコンテナに指定する手順になっている。&lt;/p&gt;
&lt;p&gt;今回の&lt;code&gt;aa-status&lt;/code&gt;と拒否ログを合わせると、指定したプロファイルをホストに読み込む必要があった。ただし、以前の登録が再起動などで失われたのか、別の理由で未読み込みだったのかは特定できていない。&lt;/p&gt;
&lt;h2 id="プロファイルを読み込んで起動エラーを解消した"&gt;プロファイルを読み込んで起動エラーを解消した
&lt;/h2&gt;&lt;p&gt;Codexがプロファイルの実ファイルを確認し、自分で次のコマンドを実行した。&lt;code&gt;apparmor_parser&lt;/code&gt;は設定ファイルを解析してホストに読み込むコマンドで、&lt;code&gt;-r&lt;/code&gt;は既存のプロファイルがあれば置き換える指定だ。&lt;/p&gt;
&lt;p&gt;ここではファイルの場所が明確になるよう、絶対パスを使っている。管理者権限の実行環境では、&lt;code&gt;$HOME&lt;/code&gt;が通常ユーザーのホームを指すとは限らない。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apparmor_parser -r -W /home/sonohen/work/codex-docker/codex-bwrap.apparmor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo aa-status | rg &lt;span style="color:#e6db74"&gt;&amp;#39;codex-bwrap&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;実行した結果、&lt;code&gt;apparmor_parser&lt;/code&gt;の終了コードは0となり、&lt;code&gt;aa-status&lt;/code&gt;にも&lt;code&gt;codex-bwrap&lt;/code&gt;が表示された。コンテナの&lt;code&gt;docker inspect&lt;/code&gt;でも同じプロファイル名を確認でき、元のOCI起動エラーは解消した。&lt;/p&gt;
&lt;h2 id="起動後の拒否ログからreadby権限を追加する"&gt;起動後の拒否ログから、readby権限を追加する
&lt;/h2&gt;&lt;p&gt;コンテナへの適用を確認した後、Linux Kernelのログに別の拒否が出ていた。&lt;code&gt;comm=&amp;quot;bwrap&amp;quot;&lt;/code&gt;はbubblewrapのプロセスを示す。最初の起動エラーが解消しても、プロファイルの内容が実行時の操作に足りるとは限らなかった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apparmor=&amp;#34;DENIED&amp;#34; operation=&amp;#34;ptrace&amp;#34; class=&amp;#34;ptrace&amp;#34; profile=&amp;#34;codex-bwrap&amp;#34; pid=11588 comm=&amp;#34;bwrap&amp;#34; requested_mask=&amp;#34;readby&amp;#34; denied_mask=&amp;#34;readby&amp;#34; peer=&amp;#34;codex-bwrap&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;当時のプロファイルには、次のルールがあった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ptrace (read, trace) peer=codex-bwrap,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;このログでは、&lt;code&gt;profile&lt;/code&gt;と&lt;code&gt;peer&lt;/code&gt;がともに&lt;code&gt;codex-bwrap&lt;/code&gt;で、拒否された権限は&lt;code&gt;readby&lt;/code&gt;だ。同じプロファイルが適用されたプロセス同士のアクセスで、読まれる側の許可が不足していた。&lt;/p&gt;
&lt;p&gt;AppArmorの&lt;code&gt;ptrace&lt;/code&gt;ルールは、デバッガによる操作に加え、一部の&lt;code&gt;/proc&lt;/code&gt;経由のプロセス情報へのアクセスも制御する。&lt;code&gt;read&lt;/code&gt;は相手の情報を読む側、&lt;code&gt;readby&lt;/code&gt;は相手に読まれる側の許可を表す。&lt;a class="link" href="https://manpages.ubuntu.com/manpages/resolute/man5/apparmor.d.5.html" target="_blank" rel="noopener"
 &gt;Ubuntu 26.04のAppArmorマニュアル&lt;/a&gt;でも、アクセスする側と受ける側の双方に許可が必要とされる。同じプロファイルのプロセス間でも、&lt;code&gt;read&lt;/code&gt;だけでは足りなかった。&lt;/p&gt;
&lt;p&gt;Codexの提案に従い、元ファイル&lt;code&gt;/home/sonohen/work/codex-docker/codex-bwrap.apparmor&lt;/code&gt;の該当ルールを次のように変更した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ptrace (read, readby, trace) peer=codex-bwrap,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;許可対象は&lt;code&gt;peer=codex-bwrap&lt;/code&gt;のままにした。今回の拒否ログでは&lt;code&gt;tracedby&lt;/code&gt;は要求されていないため、追加していない。&lt;/p&gt;
&lt;h2 id="修正版をホストへ配置し再起動後も読み込めるようにする"&gt;修正版をホストへ配置し、再起動後も読み込めるようにする
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;apparmor_parser&lt;/code&gt;による読み込みは、現在動いているLinux Kernelに対する操作だ。再起動後も読み込めるよう、修正版のファイルをホストのAppArmor設定ディレクトリ&lt;code&gt;/etc/apparmor.d/codex-bwrap&lt;/code&gt;へ配置した。&lt;/p&gt;
&lt;p&gt;作業時には、初回の配置で宛先ファイルが存在しないことを確認していた。その後の&lt;code&gt;readby&lt;/code&gt;追加では、配置済みのファイルをバックアップしてから更新した。以下の掲載例は、既存ファイルがある場合だけバックアップする形にまとめている。&lt;/p&gt;
&lt;p&gt;バックアップは&lt;code&gt;/var/backups&lt;/code&gt;に置く。元の作業手順では&lt;code&gt;/etc/apparmor.d&lt;/code&gt;内に置いていたが、&lt;a class="link" href="https://gitlab.com/apparmor/apparmor/-/raw/v5.0.2/libraries/libapparmor/src/private.c" target="_blank" rel="noopener"
 &gt;AppArmor 5.0.2の実装&lt;/a&gt;では、&lt;code&gt;.bak-日時&lt;/code&gt;は読み込みの除外対象にならない。古いファイルも読み込み対象になり得るため、掲載例では配置先を変更した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo install -d -m &lt;span style="color:#ae81ff"&gt;0700&lt;/span&gt; /var/backups/codex-apparmor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; -f /etc/apparmor.d/codex-bwrap &lt;span style="color:#f92672"&gt;]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sudo cp -a /etc/apparmor.d/codex-bwrap &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /var/backups/codex-apparmor/codex-bwrap.bak-&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;date +%Y%m%d-%H%M%S&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo install -m &lt;span style="color:#ae81ff"&gt;0644&lt;/span&gt; /home/sonohen/work/codex-docker/codex-bwrap.apparmor &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /etc/apparmor.d/codex-bwrap
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apparmor_parser -r -W /etc/apparmor.d/codex-bwrap
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo aa-status | rg &lt;span style="color:#e6db74"&gt;&amp;#39;codex-bwrap&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ホストのポリシー変更、配置、再読み込みは自分で実施した。Codexは元ファイルの&lt;code&gt;readby&lt;/code&gt;追加と、配置済みファイルとの一致を読み取りで確認した。&lt;/p&gt;
&lt;h2 id="適用結果と再起動後の確認"&gt;適用結果と再起動後の確認
&lt;/h2&gt;&lt;p&gt;配置と再読み込みが終わったら、コンテナを起動して適用結果を確認する。自作スクリプトの&lt;code&gt;CODEX_APPARMOR=required&lt;/code&gt;は、AppArmorを必須にする設定だ。作業対象のディレクトリで次を実行する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CODEX_APPARMOR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;required ~/work/codex-docker/run-codex.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;起動後、別の端末から対象コンテナと拒否ログを確認する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker ps
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker inspect --type container --format &lt;span style="color:#e6db74"&gt;&amp;#39;{{.AppArmorProfile}}&amp;#39;&lt;/span&gt; CONTAINER_ID
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo journalctl -k --since &lt;span style="color:#e6db74"&gt;&amp;#39;5 minutes ago&amp;#39;&lt;/span&gt; --no-pager &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --grep&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;codex-bwrap|apparmor=&amp;#34;DENIED&amp;#34;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;CONTAINER_ID&lt;/code&gt;には、&lt;code&gt;docker ps&lt;/code&gt;で確認した実際のIDを指定する。期待する結果は、コンテナが起動し、&lt;code&gt;AppArmorProfile&lt;/code&gt;が&lt;code&gt;codex-bwrap&lt;/code&gt;となり、対象の操作時に新しい拒否ログが出ないことだ。確認に5分以上かかる場合は、&lt;code&gt;--since&lt;/code&gt;の範囲を起動時刻まで広げる。&lt;/p&gt;
&lt;p&gt;自分が提示した修正後の結果では、&lt;code&gt;docker inspect&lt;/code&gt;の出力は&lt;code&gt;codex-bwrap&lt;/code&gt;だった。直近5分のログには次の更新通知だけがあり、&lt;code&gt;DENIED&lt;/code&gt;はなかった。メッセージ部分を抜粋する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apparmor=&amp;#34;STATUS&amp;#34; operation=&amp;#34;profile_replace&amp;#34; profile=&amp;#34;unconfined&amp;#34; name=&amp;#34;codex-bwrap&amp;#34; pid=12838 comm=&amp;#34;apparmor_parser&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ここにある&lt;code&gt;profile=&amp;quot;unconfined&amp;quot;&lt;/code&gt;は、更新を行ったプロセス側の表示だ。コンテナに適用されたプロファイルは&lt;code&gt;docker inspect&lt;/code&gt;の結果で確認した。&lt;/p&gt;
&lt;p&gt;ここまでの適用結果とログは調査記録に残っている。再起動後の自動読み込みは、その記録をまとめた時点では未確認だったが、その後、自分でホストを再起動して確認し、問題なかった。&lt;/p&gt;
&lt;p&gt;ただし、当初行おうとしていたCodexの具体的な操作の成否は、調査記録には残っていない。コンテナ起動とAppArmor適用の確認だけで、Codexの全機能が動作したとは判断していない。また、修正後に拒否がなかったという判断は、提示したログの時間範囲に基づく。&lt;/p&gt;
&lt;h2 id="同じ症状を調べるときの確認順序"&gt;同じ症状を調べるときの確認順序
&lt;/h2&gt;&lt;p&gt;今回の調査では、エラー末尾の&lt;code&gt;no such file or directory&lt;/code&gt;だけでは原因を判断できなかった。Linux Kernelのログでラベル解決失敗を確認し、読み込み後には別の権限不足を切り分けた。同じ症状を調べる場合は、次の順序で確認すると、今回の2つの問題を区別できる。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;aa-status&lt;/code&gt;と起動時の拒否ログで、指定したプロファイルが読み込まれているか確認する。&lt;/li&gt;
&lt;li&gt;起動できたら、&lt;code&gt;docker inspect&lt;/code&gt;でコンテナへの適用を確認する。&lt;/li&gt;
&lt;li&gt;対象の操作を実行し、新しい拒否ログの&lt;code&gt;profile&lt;/code&gt;、&lt;code&gt;peer&lt;/code&gt;、&lt;code&gt;denied_mask&lt;/code&gt;から不足している許可を調べる。&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>CodexでレシートPDFからBeancountへの仕訳登録を自動化した</title><link>https://sonohen.net/posts/2026/10/11-beancount-receipts/</link><pubDate>Sun, 11 Oct 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/10/11-beancount-receipts/</guid><description>&lt;p&gt;PDFで保存したレシートを、Beancountの帳簿へ転記する作業をCodexに任せることにした。既存の勘定科目を使って仕訳案を作り、人間が確認したら帳簿へ書き込む。登録するたびに&lt;code&gt;bean-check&lt;/code&gt;を実行し、成功するまで次の取引へ進まない運用にした。&lt;/p&gt;
&lt;p&gt;自動化したのは読取り、仕訳案の作成、証跡の整理、帳簿への転記と検証である。仕訳案の最終確認は人間が行う。ファイル監視で無人処理する仕組みにはしていない。&lt;/p&gt;
&lt;p&gt;全体の流れは次のとおりである。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;人間がレシートをPDFで保存し、ファイル名に支払方法を付ける。&lt;/li&gt;
&lt;li&gt;Codexが全ページを読み、既存科目と支払方法から仕訳案を作る。&lt;/li&gt;
&lt;li&gt;人間が仕訳案と証跡の組合せを確認する。&lt;/li&gt;
&lt;li&gt;補助ツールが証跡を保存し、1取引ずつ帳簿へ登録する。&lt;/li&gt;
&lt;li&gt;各登録の直後に&lt;code&gt;bean-check&lt;/code&gt;を実行し、成功したら次へ進む。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="codexが判断しpythonが書き込む"&gt;Codexが判断し、Pythonが書き込む
&lt;/h2&gt;&lt;p&gt;帳簿は次の構成で管理している。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;ファイル&lt;/th&gt;
 &lt;th&gt;役割&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;account.beancount&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;勘定科目と日本語の名称&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;year/2026.beancount&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;2026年の仕訳&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;main.beancount&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;科目、各年の仕訳などを読み込む入口&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Codexには、レシートの内容に加えて&lt;code&gt;account.beancount&lt;/code&gt;と既存の仕訳を読ませる。店舗名だけで費用科目を決めず、酒類、書籍、レジ袋などを品目に応じて分ける。消費税も既存の記帳方法に合わせて別科目へ計上する。&lt;/p&gt;
&lt;p&gt;読取りと判断はCodex、金額の検証とファイル操作はPythonの補助ツールに分担した。補助ツール自体にはOCRやAI APIの呼出しを組み込んでいない。&lt;/p&gt;
&lt;p&gt;実装環境はPython 3、Beancount 3.2.0、Popplerである。手順はリポジトリの&lt;code&gt;AGENTS.md&lt;/code&gt;に記載し、補助ツールを&lt;code&gt;scripts/receipt.py&lt;/code&gt;として作成した。&lt;/p&gt;
&lt;h2 id="抽出テキストだけで転記しない"&gt;抽出テキストだけで転記しない
&lt;/h2&gt;&lt;p&gt;スキャンしたPDFには抽出可能なテキストが入っていても、数字や店舗名に誤読があった。そこで、&lt;a class="link" href="https://manpages.debian.org/trixie/poppler-utils/pdftotext.1.en.html" target="_blank" rel="noopener"
 &gt;&lt;code&gt;pdftotext&lt;/code&gt;&lt;/a&gt;で抽出した内容を、&lt;a class="link" href="https://manpages.debian.org/trixie/poppler-utils/pdftoppm.1.en.html" target="_blank" rel="noopener"
 &gt;&lt;code&gt;pdftoppm&lt;/code&gt;&lt;/a&gt;で画像化した全ページと照合する。取引日、合計、税額、割引は画像でも確認する。&lt;/p&gt;
&lt;p&gt;実際に、ファイル名の日付と取引日が違うレシートがあった。ファイル名が&lt;code&gt;2026-10-11&lt;/code&gt;で始まるPDFに、10月8日の給油が記載されていた。別のPDFも、ファイル名は&lt;code&gt;2026-10-11&lt;/code&gt;で始まるが取引日は10月9日だった。&lt;/p&gt;
&lt;p&gt;帳簿の日付にはレシートの取引日を使う。読めない数字や証跡間の矛盾があれば、推測して登録せず人間に質問させる。&lt;/p&gt;
&lt;h2 id="支払方法はファイル名に書く"&gt;支払方法はファイル名に書く
&lt;/h2&gt;&lt;p&gt;最初は、レシートを読むたびに支払方法を質問させていた。カード払いと分かっても、どのカードかは帳簿の科目へ対応させる必要があるためだ。&lt;/p&gt;
&lt;p&gt;毎回回答する手間を減らすため、自分でPDF名の末尾に支払方法を付けることにした。次のような形式である。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;日付.店舗名.支払方法.pdf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;次の表は対応の一例で、今回使った支払方法を示している。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;ファイル名の支払方法&lt;/th&gt;
 &lt;th&gt;支払科目&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;現金&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Assets:Cash:Purse&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;モバイルSuica&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Assets:ICCard:MobileSuica&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ビックカメラVIEW&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Liabilities:CreditCard:BiccameraVIEWSuicaCard&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;補助ツールは&lt;code&gt;.pdf&lt;/code&gt;の直前の要素を対応表で変換する。店舗名の一部から支払方法を推測することはない。&lt;/p&gt;
&lt;p&gt;ファイル名から判別できれば、支払方法の質問は省略する。未記載、未知の表記、PDFの内容との明確な不一致がある場合は質問する。仕訳案の最終確認は、支払方法が分かっていても省略しない。&lt;/p&gt;
&lt;h2 id="pdfの数と取引の数を分ける"&gt;PDFの数と取引の数を分ける
&lt;/h2&gt;&lt;p&gt;領収書とカードの利用票は、同じ購入を示す別の証跡である。これらを別取引として登録すると、費用を二重計上してしまう。&lt;/p&gt;
&lt;p&gt;同じPDFの再取込みは、ファイルごとのSHA-256で検出する。ハッシュを&lt;code&gt;document&lt;/code&gt;のメタデータへ保存し、取込み済みの証跡と照合する。別のPDFが同じ購入を示している場合は、取引情報でも確認する。&lt;/p&gt;
&lt;p&gt;注文番号や伝票番号を優先し、店舗、日付、金額も使って同じ取引の証跡をまとめる。複数PDFの組合せはCodexが候補を提示し、人間が確認する。1つのPDFに領収書と利用票の2ページがある場合も、1取引として扱う。&lt;/p&gt;
&lt;p&gt;仕訳と証跡はBeancountのリンクで紐づける。次は今回登録した給油の例で、店舗名とPDF名は説明用に置き換えている。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;beancount&lt;/div&gt;
 &lt;pre tabindex="0"&gt;&lt;code class="language-beancount" data-lang="beancount"&gt;2026-10-08 * &amp;#34;ガソリンスタンド&amp;#34; &amp;#34;ハイオク給油&amp;#34; ^receipt-example
 Expenses:Car:Gasoline 2696 JPY
 Expenses:Tax:Consumption-Tax 270 JPY
 Liabilities:CreditCard:BiccameraVIEWSuicaCard -2966 JPY

2026-10-08 document Expenses:Car:Gasoline &amp;#34;../Expenses/Car/Gasoline/receipt.pdf&amp;#34; ^receipt-example&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;既存取引と日付、店舗、費用総額が一致した場合も確認を求める。後から別の証跡を受け取った場合は、既存取引に証跡だけを追加できる。&lt;/p&gt;
&lt;p&gt;PDFは費用科目に応じたフォルダへ移動する。複数科目がある場合は、税を除いて費用額が最大の科目を保管先にする。複数取引で共有するPDFは1回だけ保存し、関連する全取引の登録が終わるまで元ファイルを残す。&lt;/p&gt;
&lt;h2 id="1取引ずつbean-checkを通す"&gt;1取引ずつbean-checkを通す
&lt;/h2&gt;&lt;p&gt;補助ツールは、Codexが作ったJSON形式の仕訳案を受け取り、次の順序で処理する。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;既存の帳簿にエラーがないことを確認する。&lt;/li&gt;
&lt;li&gt;今回の1取引を一時帳簿で検証する。&lt;/li&gt;
&lt;li&gt;PDFを保管先へコピーし、ハッシュを確認する。&lt;/li&gt;
&lt;li&gt;その取引だけを本帳簿へ書き込む。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bean-check main.beancount&lt;/code&gt;を実行する。&lt;/li&gt;
&lt;li&gt;成功したら処理済みとし、不要になった元PDFを削除する。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;通常のコピー、書込み、検証に失敗した場合は、今回の帳簿変更を戻して元PDFを残す。失敗した取引を飛ばして後続の処理を進めない。&lt;/p&gt;
&lt;p&gt;専用ツールの&lt;code&gt;check&lt;/code&gt;は事前検証、&lt;code&gt;commit&lt;/code&gt;は1取引の登録を行う。ここでの&lt;code&gt;commit&lt;/code&gt;はGitのコミットではない。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;python3 scripts/receipt.py check proposal.json --transaction receipt-example
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;python3 scripts/receipt.py commit proposal.json --transaction receipt-example&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;今回作成したツール専用のコマンドなので、Beancountをインストールするだけでは使えない。この記事は実装と運用の記録であり、ツールの配布手順は扱っていない。&lt;/p&gt;
&lt;p&gt;最初にPDFを1件登録し、続いて5件を登録した。後者では領収書と利用票を含む全8ページを確認し、各取引の登録直後に検証が成功した。証跡の移動後はハッシュの一致も確認できた。&lt;/p&gt;
&lt;p&gt;補助ツールの13件のテストも通った。対象には、複数証跡、重複候補、未確認の仕訳、ファイル名の支払方法、コピー失敗、検証失敗後の停止と再開が含まれる。&lt;/p&gt;
&lt;h2 id="残高照合で未記帳のチャージを見つけた"&gt;残高照合で未記帳のチャージを見つけた
&lt;/h2&gt;&lt;p&gt;レシートのない鉄道、飲料、Suicaチャージも、日付、金額、支払方法を伝えて登録した。その後、自分が確認したモバイルSuicaの実残高を帳簿に追記した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;beancount&lt;/div&gt;
 &lt;pre tabindex="0"&gt;&lt;code class="language-beancount" data-lang="beancount"&gt;2026-10-11 balance Assets:ICCard:MobileSuica 11362 JPY&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;この時点で&lt;code&gt;bean-check&lt;/code&gt;は失敗した。識別に必要なメッセージを抜粋すると、次の内容だった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Balance failed for &amp;#39;Assets:ICCard:MobileSuica&amp;#39;: expected 11362 JPY != accumulated 1362 JPY (10000 too little)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;帳簿が実残高より10,000円少なかった。自分が10月5日のチャージを思い出して伝えると、Codexがその日の帳簿にチャージがないことを確認した。ビックカメラVIEW Suicaカードからの10,000円チャージを追加したところ、残高照合を含めて検証が成功した。&lt;/p&gt;
&lt;p&gt;仕訳の検証が通っていても、取引の漏れまでは見つからない。実残高を&lt;code&gt;balance&lt;/code&gt;で照合したことで、未記帳を発見できた。&lt;/p&gt;
&lt;p&gt;現状の対象は2026年の日本円による通常の購入で、外貨や返品は扱っていない。また、突然のプロセス終了や電源断に対して、帳簿とPDFの更新を完全に一体化する保証はない。今回確認できたのは、通常の失敗時の巻き戻しと、対話で確認した仕訳を順番に登録する運用である。&lt;/p&gt;</description></item><item><title>サスペンド復帰後にNextDNSが応答しなくなる問題を調べ、自動再起動を設定した</title><link>https://sonohen.net/posts/2026/10/11/</link><pubDate>Sun, 11 Oct 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/10/11/</guid><description>&lt;p&gt;Ubuntuの端末をサスペンドから復帰させると、NextDNSから応答を得られなくなることがあった。そのたびに自分でNextDNSを手動再起動していた。毎回操作するのは面倒なので、Codexに症状の調査と自動再起動の実装を依頼した。&lt;/p&gt;
&lt;p&gt;NetworkManagerの接続イベントを受け、約5秒後に稼働中のNextDNSを再起動する仕組みを設定した。内部原因は未特定で、自動再起動による復旧効果は今後確認する。&lt;/p&gt;
&lt;h2 id="調査した環境"&gt;調査した環境
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;項目&lt;/th&gt;
 &lt;th&gt;バージョン&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Ubuntu&lt;/td&gt;
 &lt;td&gt;26.04.1 LTS&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Linux Kernel&lt;/td&gt;
 &lt;td&gt;7.0.0-38-generic&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;NextDNS CLI&lt;/td&gt;
 &lt;td&gt;1.47.3&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;NetworkManager&lt;/td&gt;
 &lt;td&gt;1.54.3-2ubuntu3.1&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;systemd&lt;/td&gt;
 &lt;td&gt;259.5-0ubuntu3.4&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;以下の実装は、NetworkManagerで接続を管理し、NextDNS CLIがsystemdの&lt;code&gt;nextdns.service&lt;/code&gt;として動作する環境を前提とする。&lt;/p&gt;
&lt;h2 id="wi-fiが戻ってもdns問い合わせは失敗していた"&gt;Wi-Fiが戻ってもDNS問い合わせは失敗していた
&lt;/h2&gt;&lt;p&gt;Codexにログ調査を依頼した。10月11日のホストのjournalでは、次の時系列を確認できた。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;journalctl -b -u nextdns -u systemd-suspend -u NetworkManager &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --since &lt;span style="color:#e6db74"&gt;&amp;#39;2026-10-11 09:05:00&amp;#39;&lt;/span&gt; --until &lt;span style="color:#e6db74"&gt;&amp;#39;2026-10-11 09:35:00&amp;#39;&lt;/span&gt; --no-pager&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;時刻&lt;/th&gt;
 &lt;th&gt;ログで確認した内容&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;09:17:40&lt;/td&gt;
 &lt;td&gt;サスペンドを開始し、Wi-Fiを切断&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;09:31:19&lt;/td&gt;
 &lt;td&gt;サスペンドから復帰&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;09:31:25&lt;/td&gt;
 &lt;td&gt;NetworkManagerが&lt;code&gt;CONNECTED_GLOBAL&lt;/code&gt;を報告&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;09:32:24以降&lt;/td&gt;
 &lt;td&gt;NextDNSのエンドポイント取得がタイムアウト&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;09:34:04&lt;/td&gt;
 &lt;td&gt;DNS問い合わせのタイムアウトが多数発生&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;09:34:13&lt;/td&gt;
 &lt;td&gt;自分でNextDNSを再起動&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;09:34:18&lt;/td&gt;
 &lt;td&gt;新しいプロセスがDoH接続を再確立&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;名前解決のエラーには、次の文字列が含まれていた。ログ全文ではなく、識別に必要なメッセージ部分を抜粋している。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;doh resolve: context deadline exceeded&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;エンドポイント取得でも、次のエラーが出ていた。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;exchange: roundtrip: context deadline exceeded&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Wi-Fiの接続復旧が報告された後も、同じNextDNSプロセスでDNS問い合わせの失敗が続いていた。この事例では、サービスが落ちたというより、動いたまま上流への通信を回復できていないように見える。&lt;/p&gt;
&lt;p&gt;内部原因は未特定で、NetworkManagerの接続状態だけでは外部との通信が正常とは言い切れない。手動再起動後のログではDoH接続の再確立が記録されており、自分でもDNSの実応答を確認した。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/nextdns/nextdns/issues/699" target="_blank" rel="noopener"
 &gt;NextDNSの公式リポジトリにあるIssue #699&lt;/a&gt;にも、サスペンド復帰後のDNS問い合わせのタイムアウトが報告されている。こちらはNextDNS 1.37.11とUbuntu 22.04の事例だ。今回と同じ原因とは限らない。&lt;/p&gt;
&lt;h2 id="接続イベントから再起動する"&gt;接続イベントから再起動する
&lt;/h2&gt;&lt;p&gt;プロセスが生きたまま応答できなくなる症状には、終了時の再起動を設定するだけでは対応できない。Codexはこの症状に対応するため、NetworkManagerの接続イベントからNextDNSを再起動する構成を実装した。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://networkmanager.dev/docs/api/latest/NetworkManager-dispatcher.html" target="_blank" rel="noopener"
 &gt;NetworkManagerのdispatcher仕様&lt;/a&gt;では、&lt;code&gt;up&lt;/code&gt;はインターフェースの接続完了、&lt;code&gt;vpn-up&lt;/code&gt;はVPNの接続完了を表す。Codexの実装では、この2つを対象にしている。&lt;/p&gt;
&lt;p&gt;処理は次の順序で進む。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;dispatcherが&lt;code&gt;up&lt;/code&gt;または&lt;code&gt;vpn-up&lt;/code&gt;を受け取る。&lt;/li&gt;
&lt;li&gt;NextDNSが稼働中なら、systemd timerを再始動する。&lt;/li&gt;
&lt;li&gt;timerが約5秒後にサービスを呼び出す。&lt;/li&gt;
&lt;li&gt;稼働中のNextDNSを再起動する。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;実装には、接続直後の状態が落ち着くまでの猶予として5秒の待ち時間を設けている。外部との通信が復旧したことを確認する処理ではない。&lt;/p&gt;
&lt;p&gt;タイマーの待ち時間中に別の接続イベントを受け取ると、待ち時間を設定し直す。そのため、接続イベントが短時間に続いても、最後のイベントから約5秒後にNextDNSを1回だけ再起動する。通常のWi-Fi再接続やVPN接続でも動作するため、サスペンド復帰だけに限定した仕組みではない。再起動時には短時間DNSが途切れる。&lt;/p&gt;
&lt;h2 id="dispatchertimerserviceの内容"&gt;dispatcher、timer、serviceの内容
&lt;/h2&gt;&lt;h3 id="接続イベントを受け取るスクリプト"&gt;接続イベントを受け取るスクリプト
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;/etc/NetworkManager/dispatcher.d/90-nextdns-reconnect&lt;/code&gt;に配置する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# NetworkManager dispatcher: coalesce connection activation events.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PATH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/usr/sbin:/usr/bin:/sbin:/bin
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;export PATH
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;2&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; in
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; up|vpn-up&lt;span style="color:#f92672"&gt;)&lt;/span&gt; ;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; *&lt;span style="color:#f92672"&gt;)&lt;/span&gt; exit &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; ;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;esac&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Do not undo an intentional stop of NextDNS.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemctl is-active --quiet nextdns.service &lt;span style="color:#f92672"&gt;||&lt;/span&gt; exit &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;exec systemctl --no-block restart nextdns-reconnect.timer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;--no-block&lt;/code&gt;でタイマーの再始動を依頼し、dispatcher内では待たない。&lt;code&gt;dns-change&lt;/code&gt;には反応しないため、NextDNSの再起動に伴うDNS設定変更が次の再起動を誘発するループを避けられる。&lt;/p&gt;
&lt;h3 id="5秒後に処理するタイマー"&gt;5秒後に処理するタイマー
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;/etc/systemd/system/nextdns-reconnect.timer&lt;/code&gt;に配置する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;ini&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Description&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;Delay NextDNS restart after network activation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;[Timer]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;OnActiveSec&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;5s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;AccuracySec&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;1s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Unit&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;nextdns-reconnect.service&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="nextdnsを再起動するサービス"&gt;NextDNSを再起動するサービス
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;/etc/systemd/system/nextdns-reconnect.service&lt;/code&gt;に配置する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;ini&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Description&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;Restart running NextDNS after network activation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ExecStart&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/usr/bin/systemctl try-restart nextdns.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;TimeoutStartSec&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;45s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Codexは&lt;code&gt;try-restart&lt;/code&gt;を使い、管理者が停止しているNextDNSを勝手に起動しないようにした。&lt;/p&gt;
&lt;h2 id="実機へのインストール"&gt;実機へのインストール
&lt;/h2&gt;&lt;p&gt;Codexはインストール用の&lt;a class="link" href="files/install.sh" &gt;install.sh&lt;/a&gt;も作成した。既存の同名ファイルがあれば停止し、ユニットの検証後に設定を配置する。&lt;/p&gt;
&lt;p&gt;同じディレクトリに次の5つを保存すると、インストール・アンインストールのスクリプトを利用できる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="files/90-nextdns-reconnect" &gt;90-nextdns-reconnect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="files/nextdns-reconnect.timer" &gt;nextdns-reconnect.timer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="files/nextdns-reconnect.service" &gt;nextdns-reconnect.service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="files/install.sh" &gt;install.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="files/uninstall.sh" &gt;uninstall.sh&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;保存したディレクトリで、ホストの端末から実行する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo sh ./install.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;dispatcherはroot所有で実行可能にし、グループやほかのユーザーから書き込めない権限にする。インストールスクリプトでは&lt;code&gt;0755&lt;/code&gt;、ユニットファイルは&lt;code&gt;0644&lt;/code&gt;に設定している。&lt;/p&gt;
&lt;p&gt;NetworkManager自体の再起動やタイマーの&lt;code&gt;enable&lt;/code&gt;は不要だ。インストール直後にNextDNSを再起動せず、次の接続イベントから動作する。&lt;/p&gt;
&lt;p&gt;Codex環境からはsudo認証できなかったため、自分でホストの別ターミナルからインストールした。&lt;/p&gt;
&lt;h2 id="検証状況と復帰後の確認"&gt;検証状況と復帰後の確認
&lt;/h2&gt;&lt;p&gt;Codexは&lt;code&gt;sh -n&lt;/code&gt;でシェルの構文を確認し、イベント分岐をモックで検証した。&lt;code&gt;up&lt;/code&gt;と&lt;code&gt;vpn-up&lt;/code&gt;では稼働中の場合だけタイマーを操作し、停止中や対象外のイベントでは操作しないことを確認した。&lt;/p&gt;
&lt;p&gt;Codexの隔離環境ではsystem busへの接続やソケット設定が制限され、現在のサービス状態の取得と&lt;code&gt;systemd-analyze verify&lt;/code&gt;は失敗した。モック検証は、実際のsystemdやサスペンド復帰を使った検証ではない。実機へのインストールは済んだ。手動再起動後のDNSの実応答は自分で確認したが、接続イベントによる自動再起動と、その後の名前解決の回復は未確認だ。&lt;/p&gt;
&lt;p&gt;次回のサスペンド復帰後には、自分で次のコマンドを実行し、ログと名前解決を確認する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;journalctl -b -u nextdns-reconnect.service -u nextdns.service --since &lt;span style="color:#e6db74"&gt;&amp;#39;-10 min&amp;#39;&lt;/span&gt; --no-pager
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dig @127.0.0.1 example.org +time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; +tries&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;getent ahosts example.org&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;dig&lt;/code&gt;の例は、NextDNSが&lt;code&gt;127.0.0.1:53&lt;/code&gt;で待ち受ける場合の直接問い合わせだ。待受先が異なる場合は、アドレスとポートを設定に合わせる。&lt;code&gt;getent&lt;/code&gt;ではOSの通常の名前解決を確認する。&lt;/p&gt;
&lt;p&gt;確認したいのは、接続後に自動再起動したログが残り、名前解決も成功することだ。サービスが&lt;code&gt;active&lt;/code&gt;というだけでは、今回の症状が解消したとは判断しない。&lt;/p&gt;
&lt;h2 id="アンインストール"&gt;アンインストール
&lt;/h2&gt;&lt;p&gt;仕組みをアンインストールするときは、ファイルを保存したディレクトリから次を実行する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo sh ./uninstall.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;アンインストールスクリプトは配置済みファイルと元の実装を比較し、変更されている場合は削除しない。NextDNS本体の設定は変更しない。&lt;/p&gt;</description></item><item><title>EmacsでCodexを使う環境を整え、関連書籍を買った日</title><link>https://sonohen.net/posts/2026/10/10/</link><pubDate>Sat, 10 Oct 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/10/10/</guid><description>&lt;p&gt;今日は、EmacsからCodexを使うための環境を整えていた。CLIのインストールから始めたのだが、ターミナルと日本語入力、Docker、権限の設定まで、思ったより作業が増えた。&lt;/p&gt;
&lt;h2 id="codexをインストールする"&gt;Codexをインストールする
&lt;/h2&gt;&lt;p&gt;まず、Codexをコマンドラインから使えるようにした。今日の環境では、次のコマンドでインストールしている。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo npm install -g @openai/codex
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;which codex&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;which codex&lt;/code&gt;の結果は&lt;code&gt;/usr/local/bin/codex&lt;/code&gt;だった。&lt;/p&gt;
&lt;h2 id="emacsではvtermを使うことにした"&gt;Emacsではvtermを使うことにした
&lt;/h2&gt;&lt;p&gt;Codexをインストールしたものの、Emacsのシェルではうまく動かなかった。そこで、vtermを使うためのパッケージを入れた。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt install -y cmake libvterm-dev libtool-bin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ところが、今回の環境ではvterm上でDDSKKによる日本語入力ができなかった。別のターミナルならどうかと思い、Eatも試してみた。&lt;/p&gt;
&lt;p&gt;NonGNU ELPAをパッケージの取得先に追加し、leafで次のように設定した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Emacs Lisp&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-elisp" data-lang="elisp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(leaf eat
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; :ensure &lt;span style="color:#66d9ef"&gt;t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; :bind (&lt;span style="color:#e6db74"&gt;&amp;#34;C-c v&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;.&lt;/span&gt; eat-project-other-window))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Eatでも日本語入力ができず、動作も安定しなかったため、今回はvtermを使うことにした。DDSKKで入力するという当初の希望は、ひとまず保留にした。これは今日の自分の環境での結果であり、ほかの環境でも同じとは限らない。&lt;/p&gt;
&lt;h2 id="codex用のdocker環境を作る"&gt;Codex用のDocker環境を作る
&lt;/h2&gt;&lt;p&gt;次に、CodexをDockerで動かすための環境を作った。Dockerの導入は&lt;a class="link" href="https://docs.docker.com/engine/install/ubuntu/" target="_blank" rel="noopener"
 &gt;公式のUbuntu向けインストール手順&lt;/a&gt;を参考にした。&lt;/p&gt;
&lt;p&gt;インストール後、次のコマンドで確認した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo docker run hello-world&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Hello from Docker!&lt;/code&gt;と表示されたので、続いてCodex用のDockerfileと起動スクリプトを用意した。&lt;/p&gt;
&lt;p&gt;当日の作業メモに残した初期構成では、イメージのベースに&lt;code&gt;node:22-bookworm-slim&lt;/code&gt;を使い、Git、ripgrep、PythonなどとCodex CLIをインストールする。コンテナ内では一般ユーザーの&lt;code&gt;node&lt;/code&gt;で実行し、作業ディレクトリを&lt;code&gt;/workspace&lt;/code&gt;にした。&lt;/p&gt;
&lt;p&gt;起動スクリプトでは、ホスト側の共有ディレクトリを&lt;code&gt;/workspace&lt;/code&gt;にマウントし、Codexのホームには名前付きボリュームを使った。当日のメモに残した初期のスクリプトを以下に示す。Dockerfileと起動スクリプトはその後も変更しているため、以下は初期構成の記録として読む。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set -eu
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;shared_dir&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/home/sonohen/dockershared
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir -p &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$shared_dir&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;exec docker run --rm -it --init &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -e TERM &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -v codex-home:/home/node/.codex &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --mount &lt;span style="color:#e6db74"&gt;&amp;#34;type=bind,src=&lt;/span&gt;$shared_dir&lt;span style="color:#e6db74"&gt;,dst=/workspace&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; codex-cli &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$@&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;shared_dir&lt;/code&gt;は自分の環境のパスなので、別の環境で使う場合は変更する。コンテナから共有ディレクトリ内のファイルは変更できるため、何を共有するかは意識しておきたい。&lt;/p&gt;
&lt;p&gt;イメージの作成と起動には、次のコマンドを使った。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker build -t codex-cli -f Dockerfile .
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./run-codex.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="bubblewrapとapparmorの設定で悩む"&gt;bubblewrapとAppArmorの設定で悩む
&lt;/h2&gt;&lt;p&gt;環境を整える途中で、bubblewrapが新しいnamespaceを作成できないというメッセージにも遭遇した。作業メモに残した原文は次のとおりだ。単語間の空白も記録どおりに示す。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bwrap:No permissions tocreate a new namespace,likely because the kerneldoes not allow non-privileged user namespaces.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;メッセージには、非特権ユーザーによるnamespaceの作成がカーネルで許可されていない可能性が示されていた。そこで、UbuntuのAppArmor設定を調べた。&lt;/p&gt;
&lt;p&gt;まず、次の設定値を確認した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sysctl kernel.apparmor_restrict_unprivileged_userns&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;結果は次のとおりだった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kernel.apparmor_restrict_unprivileged_userns = 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;この値を確認したうえで、&lt;code&gt;/usr/bin/bwrap&lt;/code&gt;に&lt;code&gt;userns&lt;/code&gt;を許可するAppArmorプロファイルを作った。管理者権限で次のコマンドを実行し、&lt;code&gt;apparmor_parser&lt;/code&gt;で読み込んだ。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo install -m &lt;span style="color:#ae81ff"&gt;644&lt;/span&gt; /dev/stdin /etc/apparmor.d/bwrap &lt;span style="color:#e6db74"&gt;&amp;lt;&amp;lt;&amp;#39;EOF&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;abi &amp;lt;abi/4.0&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;include &amp;lt;tunables/global&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;profile bwrap /usr/bin/bwrap flags=(unconfined) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; userns,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; include if exists &amp;lt;local/bwrap&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apparmor_parser -r /etc/apparmor.d/bwrap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;この設定後、私が使っている範囲ではbubblewrap関連のエラーは出なくなった。すべての実行条件を検証したわけではないため、今回確認できた範囲での結果として記録しておく。&lt;/p&gt;
&lt;p&gt;また、Codexの&lt;code&gt;config.toml&lt;/code&gt;には次の設定を追加した。これは今回の環境で追加した内容の記録なので、末尾のパスはインストール先に合わせる必要がある。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;TOML&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;default_permissions&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;project-edit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;permissions&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;project-edit&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;filesystem&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;:minimal&amp;#34;&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;read&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/usr/local/lib/node_modules/@openai/codex&amp;#34;&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;read&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a class="link" href="https://learn.chatgpt.com/docs/sandboxing?surface=app#app-prerequisites" target="_blank" rel="noopener"
 &gt;OpenAIのサンドボックスの説明&lt;/a&gt;にも、Linuxで必要になるbubblewrapと、UbuntuでのAppArmor設定について記載がある。Ubuntuのバージョンによって扱いが異なるため、同じメッセージが出た場合も、自分の環境に合う手順を確認したい。&lt;/p&gt;
&lt;h2 id="ubuntuで行ったほかの作業"&gt;Ubuntuで行ったほかの作業
&lt;/h2&gt;&lt;h3 id="aptの段階的な更新を知った"&gt;aptの段階的な更新を知った
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;sudo apt upgrade&lt;/code&gt;を実行したところ、&lt;code&gt;Not upgrading yet due to phasing&lt;/code&gt;と表示され、20個のパッケージが更新されなかった。&lt;/p&gt;
&lt;p&gt;作業メモから、表示の冒頭と更新件数を抜粋する。途中のパッケージ一覧は省略した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Not upgrading yet due to phasing:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;（パッケージ一覧を省略）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Summary:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Upgrading: 0, Installing: 0, Removing: 0, Not Upgrading: 20&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;調べると、Ubuntuには更新を一度に全員へ配布せず、対象を段階的に広げる仕組みがある。&lt;a class="link" href="https://ubuntu.com/project/docs/how-ubuntu-is-made/concepts/phased-updates/" target="_blank" rel="noopener"
 &gt;Phased updatesの公式説明&lt;/a&gt;によると、不具合が見つかった際の影響を小さくするためのものだ。今回の表示は、その段階的な配布に関係していた。&lt;/p&gt;
&lt;h3 id="localsearchを一時的に止めた"&gt;localsearchを一時的に止めた
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;localsearch-extractor-3&lt;/code&gt;の動作が気になったので、ひとまず次のコマンドでサービスを停止し、起動を抑止した。原因はまだ分かっていない。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemctl --user mask --now localsearch-3.service&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;実行すると、すぐにプロセスが停止した。元に戻すときのコマンドも記録しておく。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemctl --user unmask localsearch-3.service
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemctl --user start localsearch-3.service&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="ibus-skkを入れた"&gt;ibus-skkを入れた
&lt;/h3&gt;&lt;p&gt;vtermではDDSKKによる日本語入力ができなかったので、ibus-skkと辞書もインストールした。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt install ibus-skk skkdic&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ところが、vtermとの組み合わせでは変換した文字が消えてしまうなどの問題があり、ibus-skkは使わないことにした。今回の環境では、vterm上の日本語入力はUbuntuのMozcに頼るしかなさそうだ。&lt;/p&gt;
&lt;h2 id="codexの本を買った"&gt;Codexの本を買った
&lt;/h2&gt;&lt;p&gt;本屋で『Codexではじめるエージェンティックコーディング』を見かけ、タイトルが気になったので購入した。&lt;/p&gt;
&lt;p&gt;初版ということもあり、少し誤植が気になる。今後の修正に期待しつつ、読書メモを残しているところだ。&lt;/p&gt;
&lt;h3 id="指示に目標と完了条件を書く"&gt;指示に目標と完了条件を書く
&lt;/h3&gt;&lt;p&gt;読書メモには、Mini Codexテンプレートとして、指示に含める4つの項目を整理した。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Goal：達成したい目標を書く。&lt;/li&gt;
&lt;li&gt;Context Pointers：既存の実装や仕様など、参照してほしい情報の場所を示す。&lt;/li&gt;
&lt;li&gt;Constraints：変更してはいけない仕様や、守るべき規約を書く。&lt;/li&gt;
&lt;li&gt;Done When：作業が完了したと判断する条件を書く。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;AIに必要な情報を渡さなければ、推論や一般的な情報で補われてしまう。自分の作業に必要な文脈を、指示の中に具体的に含めることが大切だと受け取った。&lt;/p&gt;
&lt;p&gt;特に完了条件は、実行や確認によって判定できる形にしたい。「きれいなコードにする」よりも、「lintエラーが0件」「既存テストがすべてpassする」のように書く。&lt;/p&gt;
&lt;h3 id="plan-modeを使う場面を考える"&gt;Plan modeを使う場面を考える
&lt;/h3&gt;&lt;p&gt;Plan modeについては、方向性は決まっていても、詳細を相談しないと完成形が決まらない作業に向いているとメモした。タイプミスの修正や、単一ファイルの文言変更なら、計画を作る手間との釣り合いを考えたい。&lt;/p&gt;
&lt;p&gt;計画を確認するときは、目標、参照情報、制約、完了条件に加え、変更の範囲と順序も見る。変更が広がりすぎていないか、戻しやすい単位になっているかを確認する。&lt;/p&gt;
&lt;p&gt;また、調査やテスト、小さな変更を先に置き、影響の大きい変更を後にできるかも考える。タスクの分け方を判断するときには、複数の観点で検証できるかを確認したい。&lt;/p&gt;
&lt;p&gt;今日はCodexをEmacsから使う準備に多くの時間を使った。vtermを使う方針が決まり、使っている範囲ではbubblewrapのエラーも出なくなった。日本語入力はDDSKKとibus-skkを試したものの、Mozcに頼る方向で考えている。次は、用意した環境で実際の作業を続けながら使い勝手を見ていきたい。&lt;/p&gt;</description></item><item><title>オクトパスエナジーに切り替えた</title><link>https://sonohen.net/posts/2026/10/05/</link><pubDate>Mon, 05 Oct 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/10/05/</guid><description>&lt;h2 id="契約切り替えの経緯"&gt;契約切り替えの経緯
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://octopusenergy.co.jp/" target="_blank" rel="noopener"
 &gt;オクトパスエナジー&lt;/a&gt;という新興電力会社に切り替えた。&lt;/p&gt;
&lt;p&gt;その前は&lt;a class="link" href="https://denki.idemitsu.com/" target="_blank" rel="noopener"
 &gt;idemitsuでんき&lt;/a&gt;と契約していた。車に乗っていること、近くのガソリンスタンドが出光であること、単価が東京電力よりも若干割安であること、の3つの理由から契約していたのだが、わたしの使い方(日中の在宅が多く、割安な深夜時間帯にはエコキュートくらいしか稼動していない)では、割高な時間帯に電気を使うという矛盾した構図になるのだった。&lt;/p&gt;
&lt;p&gt;そんな折、日中(9:00-15:00)に割安になるオクトパスエナジーを知り、idemitsuでんきのウェブサイトから確認できる電力使用量を元にシミュレーションをし、若干割安になる可能性があることから、契約した。&lt;/p&gt;
&lt;h2 id="現在までの感想"&gt;現在までの感想
&lt;/h2&gt;&lt;p&gt;つい先日切り替わったばかりなので電気代については何とも言えないが、今のところの感想としては次の通りである。&lt;/p&gt;
&lt;h3 id="比較的-割安な時間帯に寄せやすい"&gt;比較的、割安な時間帯に寄せやすい
&lt;/h3&gt;&lt;p&gt;きちんとシミュレーションをしていたので当然といえば当然であるが、日常で使う電力を割安な時間帯(9:00-15:00)に寄せやすい。普通に生活をしていれば自然と寄っていくし、エコキュートも8時間、時間設定をずらした。&lt;/p&gt;
&lt;p&gt;どういうことかというと、元々、我が家のエコキュートは、電力会社が設定する割安な時間帯(1:00-6:00)に湯沸しをするように設定していた。オクトパスエナジーの割安な時間帯とは8時間の時差があることから、エコキュートの日時設定を-8時間して調整したのである。&lt;/p&gt;
&lt;p&gt;いままでは深夜に沸かしていたのが日中になったのだから違和感があったが、そんなのは最初の2日もすれば慣れるものである。&lt;/p&gt;
&lt;p&gt;どの程度の差があるのかは分からないが、深夜よりも日中のほうが外気温が高いのだから、沸かすのにかかるエネルギーも多少は少なくて済むのではないかと思っている。&lt;/p&gt;
&lt;h3 id="apiが便利"&gt;APIが便利
&lt;/h3&gt;&lt;p&gt;オクトパスエナジーは外向けにAPIを公開している。実際に、&lt;a class="link" href="https://qiita.com/tsubasa_k0814/items/d7346d19529ca2315fe3" target="_blank" rel="noopener"
 &gt;LINE Messaging APIで電力使用量を通知している開発者の方&lt;/a&gt;がいらっしゃる。&lt;/p&gt;
&lt;p&gt;例にもれず、私もこのAPIを使い、電力使用量と、当月の電力使用状況から月末時点での電気代をシミュレーションするPebbleのアプリケーションを開発し、今、試験しているところである。&lt;/p&gt;
&lt;p&gt;idemitsuでんきも過去の電力使用量を表示する契約者専用ページがあるが、APIは公開されていない。オクトパスエナジーは、電力使用量をもとにプログラムを作ることができる点で、開発者にとっては便利である。&lt;/p&gt;
&lt;p&gt;今、冷静に考えてみると、何もスマートウォッチで電気代のシミュレーションを見ることもないだろうとは思うものの、せっかくあるわけですし&amp;hellip;。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;電気代が安くなるかは正直微妙なところではあるが、最後に書いたAPIは結構遊びがいがありそうなので、しばらく様子を見たいと思う。&lt;/p&gt;
&lt;p&gt;ちなみに、オクトパスエナジーの契約を考えている人に向けて、&lt;a class="link" href="https://octopusenergy.co.jp/friend/stone-swing-182" target="_blank" rel="noopener"
 &gt;電気代が8,000円割引になる紹介URL&lt;/a&gt;をお伝えします。&lt;/p&gt;</description></item><item><title>Ubuntuの通信がNextDNSを経由せずにハマった話</title><link>https://sonohen.net/posts/2026/10/04/</link><pubDate>Sun, 04 Oct 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/10/04/</guid><description>&lt;p&gt;&lt;a class="link" href="https://test.nextdns.io/" target="_blank" rel="noopener"
 &gt;NextDNSの接続チェックサイト&lt;/a&gt;を参照したところ、以下のようなレスポンスが返ってきました。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;JavaScript&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;unconfigured&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;resolver&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;14.0.9.43&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;srcIP&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;xxx&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;server&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;zepto-tyo-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;NextDNSの起動状況等を確認するも、正常に起動している模様。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% nextdns status&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;running&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% nextdns config&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mdns all
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bogus-priv true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;setup-router false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;auto-activate true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;listen localhost:53
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;max-inflight-requests 256
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;profile 5d5e67
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cache-size 10MB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;max-ttl 5s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hardened-privacy false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;debug false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;control /var/run/nextdns.sock
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;log-queries false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cache-metrics false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cache-max-age 0s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;detect-captive-portals false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;use-hosts true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;timeout 5s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;report-client-info true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;discovery-dns&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% systemctl status nextdns&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;● nextdns.service - NextDNS DNS53 to DoH proxy.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Loaded: loaded (/etc/systemd/system/nextdns.service; enabled; preset: enabled)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Active: active (running) since Sun 2026-10-04 20:13:02 JST; 12min ago
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Invocation: 4981df20fedf4c4da23cb644af1c17ca
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Main PID: 57539 (nextdns)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tasks: 16 (limit: 22939)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Memory: 6.8M (peak: 9M)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; CPU: 227ms
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; CGroup: /system.slice/nextdns.service
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └─57539 /usr/bin/nextdns run
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;10月 04 20:13:02 thinkpad-e14-g3 systemd[1]: Started nextdns.service - NextDNS DNS53 to DoH proxy..
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;10月 04 20:13:02 thinkpad-e14-g3 nextdns[57539]: Starting NextDNS 1.47.3/linux on localhost:53
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;10月 04 20:13:02 thinkpad-e14-g3 nextdns[57539]: Listening on TCP/127.0.0.1:53
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;10月 04 20:13:02 thinkpad-e14-g3 nextdns[57539]: Listening on UDP/127.0.0.1:53
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;10月 04 20:13:07 thinkpad-e14-g3 nextdns[57539]: Activating
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;10月 04 20:13:07 thinkpad-e14-g3 nextdns[57539]: Connected [2a07:a8c1::]:443 (con=7ms tls=27ms, TCP, TLS13)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;10月 04 20:13:07 thinkpad-e14-g3 nextdns[57539]: Connected [2a0b:4341:b02:166:5054:ff:fe53:ab1]:443 (con=9ms tls=23ms, TCP, TLS13)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;10月 04 20:13:07 thinkpad-e14-g3 nextdns[57539]: Switching endpoint: https://dns.nextdns.io#167.179.109.118,103.170.232.254,2001:19f0:7001:5e19:5400:2ff:fec8:7b5a,2a0b:4341:b02:166:5054:ff:fe53:ab1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;/etc/resolv.conf&lt;/code&gt; は以下の通り。ローカルに向いている&amp;hellip;。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% cat /etc/resolv.conf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8).
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Do not edit.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# This file might be symlinked as /etc/resolv.conf. If you&amp;#39;re looking at
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# /etc/resolv.conf and seeing this text, you have followed the symlink.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# This is a dynamic resolv.conf file for connecting local clients to the
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# internal DNS stub resolver of systemd-resolved. This file lists all
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# configured search domains.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Run &amp;#34;resolvectl status&amp;#34; to see details about the uplink DNS servers
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# currently in use.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Third party programs should typically not access this file directly, but only
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# through the symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# different way, replace this symlink by a static file or a different symlink.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# See man:systemd-resolved.service(8) for details about the supported modes of
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# operation for /etc/resolv.conf.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nameserver 127.0.0.53
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;options edns0 trust-ad
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;search .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;これはもう間違いなくネットワークインタフェースにバインドされているDNSサーバ設定の問題だよなぁと思って調べたところビンゴで、 &lt;code&gt;192.168.10.1&lt;/code&gt; (デフォルトゲートウェイ)に向いていました。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% resolvctl status&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Global
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resolv.conf mode: stub
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DNS Servers: 127.0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Link 2 (enp2s0)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Current Scopes: none
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Protocols: -DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DNS Servers: 127.0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Default Route: no
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Link 3 (wlp3s0)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Current Scopes: DNS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DNS Servers: 192.168.10.1 2409:11:4680:100:8222:a7ff:feb8:e34a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Default Route: yes&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ということで、以下のコマンドを実行してDNS設定を変更しました。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% sudo nmcli connection modify &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;SSID&amp;gt;&amp;#34;&lt;/span&gt; ipv4.ignore-auto-dns yes ipv6.ignore-auto-dns yes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% sudo resolvectl dns wlp3s0 127.0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% sudo resolvectl domain wlp3s0 &lt;span style="color:#e6db74"&gt;&amp;#39;~.&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;これで無事、NextDNSに向いてくれました。&lt;/p&gt;</description></item><item><title>Pebbleで「あと何歩？」を確認する、Let's Walkingというアプリを開発しました</title><link>https://sonohen.net/posts/2026/10/03/</link><pubDate>Sat, 03 Oct 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/10/03/</guid><description>&lt;p&gt;目標までの残り歩数と、折り返しまでの残り歩数を同じ画面に表示する、シンプルなウォーキングアプリです。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://sonohen.net/ox-hugo/2026-10-03.Pebble.letswalking.png"
 alt="Figure 1: Let&amp;rsquo;s Walkingのウォーキング画面。GOAL LEFTとTURN INを同時に表示"&gt;&lt;figcaption&gt;
 &lt;p&gt;&lt;!-- raw HTML omitted --&gt;Figure 1: &lt;!-- raw HTML omitted --&gt;Let&amp;rsquo;s Walkingのウォーキング画面。GOAL LEFTとTURN INを同時に表示&lt;/p&gt;
 &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="今日の目標に足りない分を歩く"&gt;今日の目標に足りない分を歩く
&lt;/h2&gt;&lt;p&gt;設定する目標は、その日の累積歩数です。今回の散歩だけで歩く数ではありません。&lt;/p&gt;
&lt;p&gt;例えば、今日すでに3,000歩歩いていて、目標を8,000歩にすると、開始時の残りは5,000歩。その半分の2,500歩を、折り返しの目安にします。半分が端数になる場合は切り上げます。&lt;/p&gt;
&lt;p&gt;画面の &lt;strong&gt;&lt;strong&gt;GOAL LEFT&lt;/strong&gt;&lt;/strong&gt; は目標まで、 &lt;strong&gt;&lt;strong&gt;TURN IN&lt;/strong&gt;&lt;/strong&gt; は折り返しまでの残り歩数です。この例で1,000歩歩くと、表示はそれぞれ4,000歩と1,500歩になります。折り返し地点は開始時に決まるため、TURN INは、現在のGOAL LEFTを半分にした値ではありません。&lt;/p&gt;
&lt;p&gt;折り返しに達すると、一度だけ3回振動し、表示が &lt;strong&gt;&lt;strong&gt;TURN NOW&lt;/strong&gt;&lt;/strong&gt; に変わります。歩数に基づく目安なので、経路や帰り道を案内する機能はありません。&lt;/p&gt;
&lt;h2 id="目標を設定して-上ボタンで出発"&gt;目標を設定して、上ボタンで出発
&lt;/h2&gt;&lt;p&gt;アプリを起動したら、右側中央の選択ボタンで目標設定を開きます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上ボタン：100歩増やす&lt;/li&gt;
&lt;li&gt;下ボタン：100歩減らす&lt;/li&gt;
&lt;li&gt;選択ボタン：保存する&lt;/li&gt;
&lt;li&gt;左側の戻るボタン：変更を取り消す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上下のボタンは、押し続けると連続で変更できます。離すと止まり、設定範囲の100〜100,000歩を超えることはありません。初回の目標は8,000歩で、次回からは前回保存した値を使います。&lt;/p&gt;
&lt;p&gt;設定を終えたら、開始前の画面で上ボタンを押してウォーキングを開始します。すでに本日の目標を達成している場合は開始せず、 &lt;strong&gt;&lt;strong&gt;ALREADY MET&lt;/strong&gt;&lt;/strong&gt; と表示します。さらに歩きたいときは、目標を上げてください。&lt;/p&gt;
&lt;h2 id="休憩は選択ボタン-終了は下ボタン"&gt;休憩は選択ボタン、終了は下ボタン
&lt;/h2&gt;&lt;p&gt;歩いている途中で選択ボタンを押すと、中断して &lt;strong&gt;PAUSED&lt;/strong&gt; を表示します。もう一度押すと再開します。中断中に増えた歩数は、このウォーキングの進捗から除外します。&lt;/p&gt;
&lt;p&gt;目標までの残りが0になると、 &lt;strong&gt;&lt;strong&gt;GOAL MET&lt;/strong&gt;&lt;/strong&gt; に変わり、折り返しとは別に、一度だけ3回振動します。自動では終了しないので、歩き終えたら下ボタンを押してください。その時点の残り歩数で達成を判定し、結果画面に歩いた歩数と残り歩数を表示します。結果画面で選択ボタンを押すと、次のウォーキングの準備に戻れます。戻るボタンでアプリを閉じます。&lt;/p&gt;
&lt;p&gt;日付をまたいでも、開始時を基準にウォーキングは継続します。&lt;/p&gt;
&lt;h2 id="利用にあたって"&gt;利用にあたって
&lt;/h2&gt;&lt;p&gt;Pebble Healthから歩数を取得できる端末が対象で、初代PebbleとPebble Steelは対象外です。画面は英語表示ですが、主な操作は右側のアイコンでも確認できます。&lt;/p&gt;
&lt;p&gt;歩数の反映には遅延があり、表示や振動が歩いた瞬間と一致するとは限りません。歩数を取得できない場合は &lt;strong&gt;&lt;strong&gt;NO DATA&lt;/strong&gt;&lt;/strong&gt; 、そのまま終了した結果は &lt;strong&gt;&lt;strong&gt;UNKNOWN&lt;/strong&gt;&lt;/strong&gt; （判定不明）と表示します。また、進行中のウォーキングは、アプリの強制終了や端末の再起動後には復元しません。&lt;/p&gt;
&lt;p&gt;まずは一日の目標を決めて、残り歩数を見ながら、いつもの散歩に使ってみてください。&lt;/p&gt;
&lt;h2 id="ソースコード"&gt;ソースコード
&lt;/h2&gt;&lt;p&gt;MITライセンスで公開しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/sonohen/pebble-lets-walking" target="_blank" rel="noopener"
 &gt;pebble-lets-walking&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>PebbleOS v4.38.2が公開されました</title><link>https://sonohen.net/posts/2026/09/28/</link><pubDate>Mon, 28 Sep 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/09/28/</guid><description>&lt;p&gt;&lt;a class="link" href="https://github.com/coredevices/PebbleOS/releases/tag/v4.38.2" target="_blank" rel="noopener"
 &gt;Pebble OS v4.38.3が2026年9月24日に公開&lt;/a&gt;されました。&lt;a class="link" href="https://ndocs.repebble.com/pebbleos-changelog" target="_blank" rel="noopener"
 &gt;ChangeLog&lt;/a&gt;から変更点を確認することができます。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://sonohen.net/ox-hugo/2026-09-28.PebbleMobileApp.Update.png"
 alt="Figure 1: アップデート中の様子" width="250px"&gt;&lt;figcaption&gt;
 &lt;p&gt;&lt;!-- raw HTML omitted --&gt;Figure 1: &lt;!-- raw HTML omitted --&gt;アップデート中の様子&lt;/p&gt;
 &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;個人的に気になる点は次の3点です。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Initial support for blood oxygen (SpO2) monitoring. Not enabled in Pebble mobile app yet.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Larger timeline cards. Sports scores and calendar events make better use of the larger displayes.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Translations are now managed in a community project, making it easier to contribute and keep laguages up to date. Additional languages are delivered as language packs through the mobile app.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Emacs 31にしてからの設定見直し</title><link>https://sonohen.net/posts/2026/09/23/</link><pubDate>Wed, 23 Sep 2026 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2026/09/23/</guid><description>&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;brew install emacs-app --casks&lt;/code&gt; でインストールした &lt;code&gt;emacs&lt;/code&gt; を使用している。自分でコンパイルはしていない。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;emacs --version&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GNU Emacs 31.1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Development version fac653279dcb on HEAD branch; build date 2026-08-24.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Copyright (C) 2026 Free Software Foundation, Inc.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GNU Emacs comes with ABSOLUTELY NO WARRANTY.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;You may redistribute copies of GNU Emacs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;under the terms of the GNU General Public License.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;For more information about these matters, see the file named COPYING.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;過去の &lt;code&gt;.emacs&lt;/code&gt; を引っ張り出してきて使おうとしたところ、久し振り過ぎて色々なところで躓いたので、そのときの記録を残すことにした。&lt;/p&gt;
&lt;h2 id="libgccjit-dot-so-が見つからない"&gt;&lt;code&gt;libgccjit.so&lt;/code&gt; が見つからない
&lt;/h2&gt;&lt;h3 id="警告内容"&gt;警告内容
&lt;/h3&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plaintext" data-lang="plaintext"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;⛔ Warning (native-compiler): libgccjit.so: error: error invoking gcc driver&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="原因"&gt;原因
&lt;/h3&gt;&lt;p&gt;macOSの &lt;code&gt;gcc&lt;/code&gt; を参照しているため。ネイティブコードにコンパイルするときに &lt;code&gt;gcc&lt;/code&gt; が &lt;code&gt;libgccjit&lt;/code&gt; を参照できずにエラーになっている模様。&lt;/p&gt;
&lt;h3 id="対処"&gt;対処
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;brew&lt;/code&gt; で &lt;code&gt;gcc&lt;/code&gt; と &lt;code&gt;libgccjit&lt;/code&gt; をインストールした。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% brew install gcc libgccjit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;その上で &lt;code&gt;~/.emacs&lt;/code&gt; に以下の記述を追加し &lt;code&gt;brew&lt;/code&gt; でインストールした &lt;code&gt;gcc&lt;/code&gt; を呼び出すようにした。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Emacs Lisp&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-emacs-lisp" data-lang="emacs-lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(when (&lt;span style="color:#a6e22e"&gt;eq&lt;/span&gt; system-type &lt;span style="color:#e6db74"&gt;&amp;#39;darwin&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (setenv &lt;span style="color:#e6db74"&gt;&amp;#34;MACOSX_DEPLOYMENT_TARGET&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;27.0&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (let ((brew-prefix &lt;span style="color:#e6db74"&gt;&amp;#34;/opt/homebrew&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (setenv &lt;span style="color:#e6db74"&gt;&amp;#34;PATH&amp;#34;&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;concat&lt;/span&gt; brew-prefix &lt;span style="color:#e6db74"&gt;&amp;#34;/bin:&amp;#34;&lt;/span&gt; (getenv &lt;span style="color:#e6db74"&gt;&amp;#34;PATH&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (setq native-comp-compiler-path (&lt;span style="color:#a6e22e"&gt;concat&lt;/span&gt; brew-prefix &lt;span style="color:#e6db74"&gt;&amp;#34;/bin/gcc-16&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (setenv &lt;span style="color:#e6db74"&gt;&amp;#34;LIBRARY_PATH&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#a6e22e"&gt;concat&lt;/span&gt; brew-prefix &lt;span style="color:#e6db74"&gt;&amp;#34;/lib/gcc/16:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (getenv &lt;span style="color:#e6db74"&gt;&amp;#34;LIBRARY_PATH&amp;#34;&lt;/span&gt;)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="missing-lexical-binding-cookie-という警告が出力される"&gt;&lt;code&gt;Missing 'lexical-binding' cookie&lt;/code&gt; という警告が出力される
&lt;/h2&gt;&lt;h3 id="警告内容"&gt;警告内容
&lt;/h3&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plaintext" data-lang="plaintext"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;⛔ Warning (files): Missing ‘lexical-binding’ cookie in &amp;#34;~/.emacs.d/elpa/ddskk-20260329.1317/skk-cursor.el&amp;#34;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;You can add one with ‘M-x elisp-enable-lexical-binding RET’.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;See ‘(elisp)Selecting Lisp Dialect’ and ‘(elisp)Converting to Lexical Binding’
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;for more information.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="原因"&gt;原因
&lt;/h3&gt;&lt;p&gt;実装による。&lt;/p&gt;
&lt;h3 id="対処"&gt;対処
&lt;/h3&gt;&lt;p&gt;暫定対処となるが、以下の記述を &lt;code&gt;~/.emacs&lt;/code&gt; に追記する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Emacs Lisp&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-emacs-lisp" data-lang="emacs-lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(when (require &lt;span style="color:#e6db74"&gt;&amp;#39;warnings&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;t&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (add-to-list &lt;span style="color:#e6db74"&gt;&amp;#39;warning-suppress-log-types&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#39;&lt;/span&gt;(files missing-lexbind-cookie)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Pebbleの輸送追跡結果と、最初に開発したアプリケーション</title><link>https://sonohen.net/posts/2026/09/22/</link><pubDate>Tue, 22 Sep 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/09/22/</guid><description>&lt;p&gt;液晶に差し込む光が強ければ強いほど視認性が高まり、バッテリーは1ヶ月近く持つPebble Time 2*。前々から気にはなっていたのだが、途中で消えたこともあり、その後はあまり探していなかった。&lt;/p&gt;
&lt;p&gt;先日、何かをきっかけに検索したPebble Time 2*が在庫あり・2営業日以内に出荷すると書かれていたので、この円安の最中、注文した。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="../../../2026/09/13/" &gt;到着前にPebbleのアプリ開発のチュートリアルを実施した時の記録はこちら&lt;/a&gt;から参照ください。&lt;/p&gt;
&lt;h2 id="購入価格"&gt;購入価格
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;合計&lt;/strong&gt;: 269.52 USD (1 USD = 160.59 JPY計算で、43,281 JPY)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;本体 (Pebble Time 2 - Silver/Grey)&lt;/strong&gt;: 225.00 USD&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;輸送費 (DHL EXPRESS WORLDWIDE)&lt;/strong&gt;: 18.00 USD&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;諸税&lt;/strong&gt;: 26.52 USD&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="追跡"&gt;追跡
&lt;/h2&gt;&lt;p&gt;特に記載がない限り日本標準時(UTC +09:00)。&lt;/p&gt;
&lt;h3 id="912土"&gt;9/12（土）
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;11:44 注文&lt;/li&gt;
&lt;li&gt;11:47 注文確認（色など）完了&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="914月---1営業日目"&gt;9/14（月） - 1営業日目
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;16:42 発送した旨の連絡がPebbleから来る。この時に、DHLの追跡番号も送られてきた。&lt;/li&gt;
&lt;li&gt;16:47 Pebbleから、「A shipment from order #PBL-XXXXXXX is on the way」というメールが届く。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="915火---2営業日目"&gt;9/15（火） - 2営業日目
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;17:13 (UTC +08:00) 荷物集荷@香港&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="916水---3営業日目"&gt;9/16（水） - 3営業日目
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;00:25 (UTC +08:00) DHL仕分け施設に到着@香港&lt;/li&gt;
&lt;li&gt;03:23 (UTC +08:00) 輸送手配中@香港&lt;/li&gt;
&lt;li&gt;03:36 (UTC +08:00) DHL施設を出発@香港&lt;/li&gt;
&lt;li&gt;05:44 通関情報の更新(荷受国到着前に通関手続きを開始する可能性)@成田&lt;/li&gt;
&lt;li&gt;09:01 次のDHL施設に輸送中@成田&lt;/li&gt;
&lt;li&gt;09:20 通関情報の更新(荷受国到着前に通関手続きを開始する可能性)@東京(おそらく新木場)&lt;/li&gt;
&lt;li&gt;10:37 DHL仕分け施設に到着@東京(おそらく新木場)&lt;/li&gt;
&lt;li&gt;10:55 通関手続き完了@東京(おそらく新木場)&lt;/li&gt;
&lt;li&gt;11:14 DHL施設にて輸送手配中@東京&lt;/li&gt;
&lt;li&gt;11:15 DHL施設を出発@東京&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以降、最寄りのDHL配送施設に到着し、9/16（水）に荷物を受け取った。&lt;/p&gt;
&lt;p&gt;香港→成田間は、時間を考えると恐らくLD208便（3:25香港発・8:40成田着のAir Hong Kongによる運行便）で輸送されたものと思われる。ちなみにこの日は、3:36発・8:21着であった。&lt;/p&gt;
&lt;h2 id="到着後"&gt;到着後
&lt;/h2&gt;&lt;p&gt;色々な方が写真を載せられているので、私が特に気になった箇所だけ写真を載せたいと思う。&lt;/p&gt;
&lt;h3 id="紙マーク"&gt;紙マーク
&lt;/h3&gt;&lt;p&gt;外国製品なのに、嬉しいものです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2026/09/22/images/IMG_0486.jpeg"
	width="4032"
	height="3024"
	loading="lazy"
	
		alt="紙マーク"
	
	
		class="gallery-image" 
		data-flex-grow="133"
		data-flex-basis="320px"
	
&gt;&lt;/p&gt;
&lt;h3 id="充電器は極めて小さい"&gt;充電器は極めて小さい
&lt;/h3&gt;&lt;p&gt;充電時には、充電器にUSB-Cケーブルを差し込み、Pebble Time 2*本体には磁石で取り付ける。この充電器は極めて小さく、また、先に述べた通り充電はひと月に一回か二回程度であるから、よくよく気をつけて保管しておかないと、充電したい時に充電器を紛失している恐れがある。幸い、磁石がついているので、私は机の脚につけている。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2026/09/22/images/IMG_0494.jpeg"
	width="4032"
	height="3024"
	loading="lazy"
	
		alt="充電器"
	
	
		class="gallery-image" 
		data-flex-grow="133"
		data-flex-basis="320px"
	
&gt;&lt;/p&gt;
&lt;h2 id="最初に開発したアプリケーション"&gt;最初に開発したアプリケーション
&lt;/h2&gt;&lt;p&gt;Swarmにチェックインするアプリケーション「Pebblewarm」を開発した。Pebble向けにSwarmの公式アプリケーションが登録されていたのだが、10年以上前に更新が途絶えておりうまく動かなかったためである。&lt;/p&gt;
&lt;p&gt;Apple WatchでもSwarmアプリを使っていたのだが、Pebbleにしてからチェックインまでの時間がより短くなったし、Timeline Pinにも登録するようにしているので、何時にどこにチェックインしたのかも分かりやすくなっている。&lt;/p&gt;
&lt;p&gt;ちなみに、私はこのようなフローで動かしている。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;下ボタンの長押しに、Pebblewarmを割り当て&lt;/li&gt;
&lt;li&gt;場所が表示されたら、選択ボタン長押しでチェックイン&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/sonohen/pebblewarm" target="_blank" rel="noopener"
 &gt;仕様、ソースコードはMITライセンスで公開&lt;/a&gt;している。&lt;a class="link" href="https://ja.foursquare.com/developers/home" target="_blank" rel="noopener"
 &gt;Foursquare Developer Console&lt;/a&gt;でプロジェクトを作成してClient ID、Client Secretを入手し、Callback用のページをどこかに配置すれば、それらを使って動かすことができる。興味があればコンパイルして、インストールして動かしてみてほしい。詳細は、&lt;code&gt;src/README.md&lt;/code&gt;を参照いただきたい。&lt;/p&gt;
&lt;p&gt;Pebble Time 2*自体の性能が高くないので、アプリケーションを開発するにあたっても、Pebble本体とスマートフォンそれぞれの役割を考えなければならないなど、制約の中で設計するのはなかなか面白い。いくつか作ってみたいアプリケーションのアイデアがあるので、どんどん設計して実装していきたいと思っている。&lt;/p&gt;</description></item><item><title>Pebbleのアプリケーション作成のチュートリアルを実施してみた</title><link>https://sonohen.net/posts/2026/09/13/</link><pubDate>Sun, 13 Sep 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/09/13/</guid><description>&lt;p&gt;Pebble Time 2*を購入した。結構前に職場の上司から「自分でスマートウォッチのアプリケーションを開発できるから面白い」と紹介を受け気にはなっていたのだが、その後名前を消していたのであまり調べてもいなかった。とあるサイトを見ていたところPebbleが再度発売されているというのを知り、在庫もありそうだったので購入した。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="../../../2026/09/22/" &gt;発送から到着までのタイムラインと、到着後に作ったアプリケーションについてはこちら&lt;/a&gt;を参照ください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pebble Time 2*: $225.00&lt;/li&gt;
&lt;li&gt;Shipping: $18.00&lt;/li&gt;
&lt;li&gt;Taxes: $26.52&lt;/li&gt;
&lt;li&gt;Total: $269.52 USD&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これをビューカードで支払ったところ、日本円でおよそ43,281円（1USD = 160.59 JPY）という金額になった。随分と高い。&lt;/p&gt;
&lt;p&gt;Pebbleといえば、Cloud Pebbleを使うことで、コンピュータに色々なものをインストールしなくてもJavaScriptさえ書ければアプリケーションを作って配布することができる。それくらいの手軽さということもあり、コミュニティでは多くのアプリケーションやウォッチフェイスが配布されている。&lt;/p&gt;
&lt;p&gt;どんな感じで作るのか商品が届く前に知りたいと思い、&lt;a class="link" href="https://developer.repebble.com/tutorials/alloy-watchface-tutorial/part1/" target="_blank" rel="noopener"
 &gt;チュートリアル&lt;/a&gt;を実施した。&lt;/p&gt;
&lt;p&gt;最初はCloud Pebbleを使って試していたのだが、エディタの使い勝手があまり良くなく、結局MacBook上で開発環境を構築した。&lt;/p&gt;
&lt;p&gt;感想は以下のような形になる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;開発環境の構築が非常に簡単にできる。やろうと思ってから15分もかからないのは大きなメリットと言える。&lt;/li&gt;
&lt;li&gt;ドット単位で画面デザインを決めていくのは、非常にわかりやすい。CSSで1px単位でズレないように作ったりしていた経験がある人にはわかると思う。&lt;/li&gt;
&lt;li&gt;（チュートリアルレベルではあるが）比較的、理解しやすい。どういう仕組みで動くのか、1日もあれば分かる気がする。（ま、多分「完全に理解した」レベルではあるとは思うが）&lt;/li&gt;
&lt;li&gt;今作ろうと思っているアプリケーション（電力会社のAPIを叩いて利用状況をグラフにするのと、料金計算するのと）は、チュートリアルに少し毛が生えた程度で実装できそうなので、Pebble向けにアプリケーションを作ろうと思えている。つまり、チュートリアルが非常に実践的（私にとって）であると言える。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/sonohen/pebble_helloworld" target="_blank" rel="noopener"
 &gt;sonohen / pebble_helloworld&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/sonohen/pebble_helloworld/blob/master/tutorial.md" target="_blank" rel="noopener"
 &gt;チュートリアルを実施しながら書いたメモ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>市場はあなたを特別扱いしない</title><link>https://sonohen.net/posts/2026/07/12/</link><pubDate>Sun, 12 Jul 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/07/12/</guid><description>&lt;h2 id="出資--相手にとっては資金調達7という資金コストを負担してまで資金調達する必要性はどこにあるのだろうか"&gt;出資 = 相手にとっては資金調達。7%という資金コストを負担してまで資金調達する必要性はどこにあるのだろうか。
&lt;/h2&gt;&lt;p&gt;あなたとっての「出資」とは、相手にとっての「資金調達」なのである。あなたが7%の利回りを得るということは、相手は7%の資金調達コストを支払うことに他ならない。&lt;/p&gt;
&lt;p&gt;日本の信用力の高い企業であれば、まず7%の金利で資金調達をするケースは無い。銀行からの資金調達で1%台の金利、株式市場からの調達で2-3%の資金調達コストで調達できるからである。米国であっても、投資適格企業は5%台だが、7%はジャンク債（投機的格付け）の金利である。つまり、それだけ安価に調達できる資金をわざわざ7%の資金調達コストを支払ってでも得ようとする企業は、市場ではその程度のリスクが織り込まれている企業の可能性があるということだ。&lt;/p&gt;
&lt;p&gt;分かりやすい他の例も出すとするなら、住宅ローンである。契約者一人ひとりの信用によって借りられる金額、金利、期間は変わる。信用が高ければ金利は低く、信用がなければ金利は高くなる。&lt;/p&gt;
&lt;p&gt;金利の高低は、借り手の信用に依存する。7%という利回りということは、それだけのリスクを織り込んでいるということであり、やはり市場はあなたを特別扱いしない。&lt;/p&gt;
&lt;h2 id="7という利回りはどういうことか"&gt;7%という利回りはどういうことか
&lt;/h2&gt;&lt;p&gt;全世界株式に分散するインデックス投資では過去30年で均した利回りが5-6%。S&amp;amp;P500では過去100年で均した利回りが7%（いずれもインフレ調整後）。世界が戦争・リーマンショックなどの恐慌を経て、でっこみ引っ込みありながら、リスクを取った場合の歴史的な利回りの上限値であるといえる。&lt;/p&gt;
&lt;p&gt;不動産投資の場合、都内・新築で2-3%、郊外・築古で8-12%（いずれも実質利回りで幅があるが全てを網羅することはできない）。&lt;/p&gt;
&lt;p&gt;これらを見ると、7%という利回りがどれだけリスクを織り込んでいる数値かが分かる。&lt;/p&gt;
&lt;h2 id="インバウンド需要は増えているが成田に限った話ではない"&gt;インバウンド需要は増えているが、成田に限った話ではない
&lt;/h2&gt;&lt;p&gt;まず、近隣の空港と比べてみる。（数字は2024年度のもの）&lt;/p&gt;
&lt;p&gt;総旅客数は、羽田が約8,800万人、成田が3,980万人。国内線でみれば羽田は約6,400万人、成田はほぼ無し。つまり、成田はインバウンドの玄関口になっている。&lt;/p&gt;
&lt;p&gt;次に年間発着枠であるが、羽田が約45万回、成田が約30万回である。インバウンドの旅行客数は、コロナを経て、また円安になっていることから増加傾向にあり、羽田も成田の年間発着枠は不足気味にあると言われている。そのため、両者とも増強計画がなされている状況にある。&lt;/p&gt;
&lt;p&gt;つまり、インバウンド需要が高まっているのは成田に限らない話である。&lt;/p&gt;
&lt;h2 id="成田空港周辺が発展するイメージが沸かない"&gt;成田空港周辺が発展するイメージが沸かない
&lt;/h2&gt;&lt;p&gt;空港周辺にあるのは、利用客向けのホテルか、あるいはゴルフ場、物流施設などが中心である。&lt;/p&gt;
&lt;p&gt;また、東京都心まで出るためにかかる時間（ここでは東京駅としよう）を考えると、成田は約1時間（成田エクスプレス利用）、羽田は約31分（京急利用）。&lt;/p&gt;
&lt;p&gt;また、成田周辺の地価は羽田周辺に比べ1/10、周辺に存在する主な事業者は物流・倉庫業等。人口規模も違う。それらを見れば、インバウンド観光客が楽しめるところがどれくらいあり、今後もどれくらいの需要が見込まれるか、十分な収益が生まれる具体的なイメージを持つことができなかった。つまり、私にとって7%の想定利回りというのは、市場の高い成長性を反映したものというより、事業者が負担する資金調達コストとして理解するほうが自然に思えたのである。&lt;/p&gt;
&lt;h2 id="まとめると"&gt;まとめると
&lt;/h2&gt;&lt;p&gt;資金調達としては高い金利（利回り）であり、インバウンド需要が膨らんでいるのは成田に限った話でもなく、成田周辺が発展する好材料も無い中、このプロジェクトに出資する判断材料が揃わず、ゆえに当時の判断は慎重であるべきであったと考えている。&lt;/p&gt;
&lt;p&gt;資金調達コストというのは、市場がその案件に対してどれだけのリスクを見込んでいるかの一つのシグナルである。高い利回りには、それに見合う理由がある。市場は誰か一人だけを特別扱いしてくれるわけではない。そう考えることが、投資判断では重要なのだと思う。まあ、市場というのが一体何なのかという話ではあるが。&lt;/p&gt;</description></item><item><title>オンライン診療は、既往歴があったり、症状を定量的に説明できる場合には便利だが、そうでない場合はイマイチかもしれない</title><link>https://sonohen.net/posts/2026/07/0501/</link><pubDate>Sun, 05 Jul 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/07/0501/</guid><description>&lt;p&gt;7月5日（日）朝、足に違和感が出た。痛風の既往歴がある私は「これは発作が来るかも？」と思い、日曜日でもあったことからオンライン診療を試してみた。&lt;/p&gt;
&lt;p&gt;既往歴があったり、症状を定量的に説明できたりする場合にはオンライン診療は使いやすいと思うが、そうでない場合には使いづらい仕組みだなと思う。これは事業者や医師の責任というよりも「オンライン」という特性によるものかなと思う。対面診療であれば血液検査・X線検査・MRI検査などができるが、オンラインの場合は物理的にできないから、患者による説明スキルが対面診療よりも求められる。&lt;/p&gt;
&lt;h2 id="今回オンライン診療を選択した理由"&gt;今回、オンライン診療を選択した理由
&lt;/h2&gt;&lt;p&gt;既往歴と、直近の血液検査の結果があったため、オンライン診療を選択した。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;約1か月前に血液検査を実施しており、その時に尿酸値が基準値を超えていた。&lt;/li&gt;
&lt;li&gt;約1年前にも痛風発作の前兆があり、近所の医師からコルヒチンを処方してもらっていた。
&lt;ul&gt;
&lt;li&gt;普段なら領収書と薬の情報をスキャンしているのだが、今回は残っていなかった。&lt;/li&gt;
&lt;li&gt;マイナンバーカードを使って診察・処方を受けているので、マイナポータルから記録を辿った。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回出た症状が初めてで、直近の血液検査の結果もなければ、整形外科なのか内科なのかすら判断がつかなかった可能性がある。&lt;/p&gt;
&lt;h2 id="予約から診察までの時系列"&gt;予約から診察までの時系列
&lt;/h2&gt;&lt;p&gt;着替えて、病院に歩いて行って、待って、終わって、薬局で薬をもらって、歩いて家に帰って、とかやっているよりかは時間は掛かっていないので、便利ではある。&lt;/p&gt;
&lt;p&gt;痛風発作が出ているときには歩くのもままならず、薬を受け取りにいけない可能性もあるので使いにくいケースがあるかもしれない。その場合に取れる選択肢は3つで、代理人に受け取りを依頼するか、2日程度待って宅配される薬を受け取るか、タクシーを使うなりなんなりして自力で取りに行くかである。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;7月5日（日）
&lt;ul&gt;
&lt;li&gt;08:05　オンライン診療の予約完了。&lt;/li&gt;
&lt;li&gt;08:41　おくすり手帳の登録のお願いがSMSで届く→持っていない旨を回答&lt;/li&gt;
&lt;li&gt;08:53　ファストドクターより架電も出れず&lt;/li&gt;
&lt;li&gt;09:05　一度目の折り返し電話（自動音声）&lt;/li&gt;
&lt;li&gt;09:14　二度目の折り返し電話（自動音声）&lt;/li&gt;
&lt;li&gt;09:22　ファストドクターより架電。おくすり手帳の有無を確認&lt;/li&gt;
&lt;li&gt;09:43　診察開始&lt;/li&gt;
&lt;li&gt;09:47　診察終了&lt;/li&gt;
&lt;li&gt;10:24　処方箋を薬局へ送付した旨、SMSで連絡&lt;/li&gt;
&lt;li&gt;10:52　薬局より電話。医師へ確認事項があり、時間がかかっているとのこと&lt;/li&gt;
&lt;li&gt;11:56　薬局より電話。調剤が完了したとのこと&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="反省点"&gt;反省点
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;おくすり手帳は持っておいたほうがよい。マイナンバーカードで過去の診療情報を辿れるはずなのだが、どうにも浸透していなさそうであり、こういう場合に必要になる。&lt;/li&gt;
&lt;li&gt;電話やSMSでちょくちょく連絡が来るので、Apple Watch（Pixel Watch等でもいいが）に通知が来るようにしておいたほうがいい。今回の場合、1回電話に出れずに30分ロスしているし、ファストドクターに折り返すと自動音声対応しかない（と思われる）ので、本当に手続きが進んでいるのか不安になる。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="改善をお願いしたいところ"&gt;改善をお願いしたいところ
&lt;/h2&gt;&lt;h3 id="toファストドクター"&gt;to　ファストドクター
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;診察画面のステータスに「電話の折り返しを待ってるからはよ電話してこいや」とか、「折り返しの電話を準備してるから待っとれ」とか、なんかしら分かるようにしておいてほしい。初めてだと、何がどうなってるのかさっぱり分からん。&lt;/li&gt;
&lt;li&gt;マイナンバーカードを「写真としてスキャンして送る」のではなく、「チップをスキャンして送る」方式に変えてほしい。住所変更があると、印字されている新住所が小さく、写真にすると見えにくくなるケースがあるため。&lt;/li&gt;
&lt;li&gt;画面共有をできるようにしてほしい。過去の血液検査の結果や処方歴などを画面共有しながら医師に見せることで、説明しやすくなるため。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="toデジタル庁"&gt;to　デジタル庁
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;「医療保険の資格情報」が、マイナポータルからファストドクターに自動接続されるようになると便利なんだけれども、できないもんでしょうか。これは事業者の実装次第なのかな？&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="次に向けて"&gt;次に向けて
&lt;/h2&gt;&lt;p&gt;24時間対応の看護師・医師への相談窓口（私が入っている医療保険に付いている）に相談し、そこで得た情報をもとにオンライン診療か対面診療かどちらがよいのかを判断するのも手かもしれない。&lt;/p&gt;
&lt;p&gt;いずれにせよ、選択肢が増えるというのはよいことであるので、今後はオンライン診療とうまく付き合っていきたいと思う。&lt;/p&gt;
&lt;h2 id="医療費"&gt;医療費
&lt;/h2&gt;&lt;p&gt;今回の自己負担は、合計で2,810円でした。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ファストドクターからの請求　2,330円&lt;/li&gt;
&lt;li&gt;薬代　480円&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="その後"&gt;その後
&lt;/h2&gt;&lt;p&gt;処方されたコルヒチンを2日ほど飲み、足の違和感は消え、痛風発作には至らなかった。よかったよかった。&lt;/p&gt;</description></item><item><title>旅行荷物、行きは宿泊先、帰りは自宅に送ってしまったほうがよい</title><link>https://sonohen.net/posts/2026/07/0502/</link><pubDate>Sun, 05 Jul 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/07/0502/</guid><description>&lt;p&gt;最近、旅行の荷物を宿泊先に予め送り、帰りも送るということをやっている。そのメリットが3つほどあるかなと整理がついたのでブログに書くことにした。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;移動時間を身軽に過ごせるので、あちこちに立ち寄ることができる&lt;/li&gt;
&lt;li&gt;「いつもの道具」を使うことができる&lt;/li&gt;
&lt;li&gt;そもそも、荷物棚を使えない場合への対策が必要である&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="移動時間を身軽に過ごせるのであちこちに立ち寄ることができる"&gt;移動時間を身軽に過ごせるので、あちこちに立ち寄ることができる
&lt;/h2&gt;&lt;p&gt;荷物が大きかったり、嵩張ったりすると、人は移動が億劫になる。例えば、昼食を摂り終え、新幹線まであと30分あるという場合、荷物が多いと待合室かホームに移動し、座って待っていようとなりがちである。そして、往々にして待合室は満席、ホームに椅子が少ないといった状況に見舞われるのがオチである。一方で荷物が軽ければ、店を見て回るとか、少し外に出てみるといった選択肢が広がるのである。私は荷物を軽くした分で、いろいろな店を見て回り、土産を買ったり、電車内での酒やつまみを入手したりするのが好きである。&lt;/p&gt;
&lt;h2 id="いつもの道具を使うことができる"&gt;「いつもの道具」を使うことができる
&lt;/h2&gt;&lt;p&gt;旅行に必要な荷物は、必ず必要なものと、あればよいと思うものに分けられると思われる。荷物の選別とは、これらのバランスをどのように取るかということになるのだが、必ずしも必要なものは減らしにくい。なぜなら減らすには、現地で調達するか、あるいはコインランドリーを利用するか等という選択肢を取る必要があり、前者の場合には帰着時に荷物の総量が増えるので論外、後者はコインランドリーが空いていなかったら元も子もない。そうなるとどうしても、あればよいと思うものを減らさざるを得ない。&lt;/p&gt;
&lt;p&gt;私にとってあればよいものとは「いつもの道具」である。それは、寝間着、歯磨きセット、ボディタオル、ドライヤーである。宿泊先のアメニティを使うのが王道なのだろうが、今までの経験からこうした類を持ち込むか持ち込まないかでは、宿泊先での快適さが違うのである。ただ、これらを移動中に持ち歩きたくない。だから私は宿泊先に送ってしまう。これにより、移動中の身軽さと、宿泊中の快適さを両立させることができる。&lt;/p&gt;
&lt;h2 id="そもそも荷物棚を使えない場合への対策が必要である"&gt;そもそも、荷物棚を使えない場合への対策が必要である
&lt;/h2&gt;&lt;p&gt;最近は、航空機にせよ新幹線にせよ、荷物棚に荷物が入り切らないケースがある。航空機の場合には、手荷物として入れてしまったからには座席下に入れるか、他の場所の空いている荷物棚に入れるしかない。前者は一向に構わない（特にさっさと出たい場合には、入口近くの通路側座席で荷物を座席下に入れるのが常套手段）のだが、後者は悲惨である。&lt;/p&gt;
&lt;p&gt;また、新幹線も旅行客で荷物棚がいっぱいになっているケースも珍しくは無く、サイズによっては座席に置くこともできず扱いに困る。&lt;/p&gt;
&lt;p&gt;こうしたことを考えると、やはり荷物というものは少なければ少ないに越したことはなく、こんなことを考えるくらいなら送ってしまったほうが楽である。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="荷物の配送料をどう見るか"&gt;荷物の配送料をどう見るか
&lt;/h2&gt;&lt;p&gt;荷物の発送元・到着先、重さやサイズにもよるだろうが、私の場合は高くとも片道分で3,000円を超えたことは無い。つまり往復で6,000円以下になる場合が多いのだが、これを高いとみるか安いとみるかは、時と場合によるだろう。私の場合は以下のように決めている。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;公共交通機関を使う場合、または出張の場合には荷物を送る。&lt;/li&gt;
&lt;li&gt;自家用車を使う場合には荷物は送らない。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;つまり基本は送ることを前提に考えるようにしている。&lt;/p&gt;
&lt;h2 id="そうするとどうなるか"&gt;そうするとどうなるか
&lt;/h2&gt;&lt;p&gt;こうして基本を送ることを前提にすると、旅行中の持ち物は最小限で済む。私の場合は、スマホ + Apple Watch + 現金 + 鍵 + ハンカチを持ち運べばよいことになるので、サコッシュ程度の荷物で十分間に合うのである。特に勝手を知っている旅行先であれば、現金すら不要かもしれない。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="補足旅が終わってからも旅ができる"&gt;（補足）旅が終わってからも旅ができる
&lt;/h2&gt;&lt;p&gt;荷物にAirTagを入れておくことで、荷物の現在地の目安が分かる。いつ、どのように荷物が送られるのかを見ることで、旅が終わったあとにも旅が続いているような感覚を持つことができるので、おすすめである。&lt;/p&gt;</description></item><item><title>Apple Fitness+はジム、オンラインレッスンのデメリットを動画配信で潰してきた</title><link>https://sonohen.net/posts/2026/06/27/</link><pubDate>Sat, 27 Jun 2026 21:32:50 +0900</pubDate><guid>https://sonohen.net/posts/2026/06/27/</guid><description>&lt;p&gt;最近、スマホを2台持ちしている。1台がGoogle Pixelで、もう1台がiPhoneである。&lt;/p&gt;
&lt;p&gt;ということで遅ればせながらApple Fitness+が日本でも使えるようになったということを知り、ここ2週間ほどお試しをしているのだが、どうしてこれがなかなかよいのである。&lt;/p&gt;
&lt;h2 id="始めるまでのハードルが低い"&gt;始めるまでのハードルが低い
&lt;/h2&gt;&lt;p&gt;ある程度の空間があればできるので取り組みやすく、Fitnessアプリを起動すればすぐにできるので、運動することに対するハードルが低い。出張先でヨガを試してみて失敗したと思ったのは、道具（ヨガの場合ヨガマット）が必要なものは出先ではやりづらい。しかし、どうしてもヨガをやりたければヨガマットを持ち歩けばよいし、そうでなければ道具を使わないワークアウトを選べばどこでもできるのが便利である。&lt;/p&gt;
&lt;h2 id="同じワークアウトを何度でもできる"&gt;「同じ」ワークアウトを何度でもできる
&lt;/h2&gt;&lt;p&gt;Fitness+のワークアウトは動画で配信されているので、同じ内容を何回も繰り返しできる。ジムのレッスン配信とは異なり毎回同じであるので、2回目、3回目と慣れるに従って負荷を上げていくことができる。逆に言えば手の抜きどころが分かるという話ではある。&lt;/p&gt;
&lt;h2 id="バッジがもらえる"&gt;バッジがもらえる
&lt;/h2&gt;&lt;p&gt;例えば、初めてHIITに取り組むともらえる「初めてのFitness+のHIITワークアウト」や、Fitness+のワークアウトを10回行うともらえる「Fitness+セッション10回」などがある。ワークアウト自体は最短で5分のものを選べるので、回数を稼ぎやすくバッジも取りやすいのかなと思う。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;費用は、月額払いで980円/月、年額払いで7,800円/年（650円/月）。iCloudファミリーでサブスクリプションを共有できるので、使う家族の人数によってはお手頃感があるのではないかと思う。&lt;/p&gt;
&lt;p&gt;以前、住友生命のVitalityプログラムに登録していたときはルネサンスのオンラインレッスンに参加しており、確かに費用は安かった（220円/月で受け放題）のであるが、レッスンは時間指定があるのでどうにも使いづらかった。1週間、1日に何回もあるレッスンは都合をつけやすいのだが、週に1度しかないようなレッスンの場合、都合が合わなかったらまた来週になってしまう。それに比べればFitness+は費用は若干高く、またレッスンの数もルネサンスほど多くはないものの、動画でワークアウトができるという点はメリットと言えそうである。&lt;/p&gt;
&lt;p&gt;ちょうど運動不足が続いていたところでもあるので、しばらくFitness+を試してみようと思う。&lt;/p&gt;</description></item><item><title>Google Pixelのデスクトップモードでブログを書いてみるテスト</title><link>https://sonohen.net/posts/2026/04/12/</link><pubDate>Sun, 12 Apr 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/04/12/</guid><description>&lt;p&gt;私のスマートフォンは、Google Pixel 10 Pro Foldです。USB-C HDMIケーブルで外部モニタに接続すると、あたかもパソコンかのように使うことができます。今はこの機能を使い、かつ外部キーボード（MOBO Keyboard 2）とマウス（Logicool MX Vertical）を使用してこの記事を執筆しています。&lt;/p&gt;
&lt;p&gt;また、このブログはHugoで作成されており、その元ネタはすべてGitHubに保存されています。つまり、ブラウザでGitHub Codespacesにアクセスして記事を書きコミットすれば、自動的に公開されるのです。&lt;/p&gt;
&lt;p&gt;執筆中の画面はこんな感じです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2026/04/12/images/Screenshot_20260412-124716.png"
	width="2076"
	height="1750"
	loading="lazy"
	
		alt="編集中の画像イメージ"
	
	
		class="gallery-image" 
		data-flex-grow="118"
		data-flex-basis="284px"
	
&gt;&lt;/p&gt;
&lt;p&gt;この仕組みをうまく使えば、外出先からでも気軽にブログ記事を書くことができるので便利です。&lt;/p&gt;</description></item><item><title>Claude CodeでオウンドメディアのAI編集部を立ち上げてみた</title><link>https://sonohen.net/posts/2026/02/23/</link><pubDate>Mon, 23 Feb 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/02/23/</guid><description>&lt;p&gt;※ この記事は、誤字脱字、表現の冗長さ・曖昧さのチェックのためにClaude Codeを利用しています。&lt;/p&gt;
&lt;h2 id="tldr"&gt;TL;DR
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Claude Codeの &lt;code&gt;SKILL&lt;/code&gt; と &lt;code&gt;AGENTS&lt;/code&gt; を使い「マネーブログ　AI編集部」（オウンドメディアの編集部、うまくいけばアフィリエイトでお金儲けしようとした）を構築した。人間が事業計画・役割・ワークフローを定義し、Claude Codeがそれを実装するという役割分担で立ち上げた。&lt;/li&gt;
&lt;li&gt;編集長AIに課した承認条件が厳しすぎ、編集者AIが指摘を受けては記事を修正するループが止まらず、コンテキストを食い潰した。これは承認条件を緩和し、完走できるようになった。&lt;/li&gt;
&lt;li&gt;しかし、執筆された記事はいかにもAIが書いたような文体になってしまった。どのような文体で表現して欲しいのかを明確に定義しておく必要があったと考えている。&lt;/li&gt;
&lt;li&gt;「事業計画を定義し、その評価基準でAIの成果物を評価する」という構造設計は成立した。ただし、今回はコンテキストの消費量が多く、セッションの中で何度もフィードバックループを回すと言うことができなかった。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="なぜai編集部を作ろうとしたのか"&gt;なぜAI編集部を作ろうとしたのか
&lt;/h2&gt;&lt;p&gt;オウンドメディアで記事を継続的に発信するのは、手間がかかる。テーマ選定、調査、執筆、校正、ペルソナによるレビューなどを一人でやり続けることには限界がある。Claude Codeを日常的に使っていると、「この一連のワークフローをAIに任せられないか」と考えるのは自然な流れだった。&lt;/p&gt;
&lt;p&gt;ただし、やみくもにAIに任せるだけでは成果物の品質が担保できない。AIに何かを評価させるためには、事前に評価基準を定義しておく必要がある。これは前回の『&lt;a class="link" href="../../../2026/02/14/" &gt;ローカルLLMでSpec Driven Developmentは、まだ難しかった&lt;/a&gt;』での経験とも重なる。&lt;strong&gt;人間が最初にゴールを定義し、AIがそれに基づいて実装する&lt;/strong&gt; というSpec Drivenな構造がなければ、AIの出力物を評価し、修正を行うと言う一連のフィードバックループが成立しない。&lt;/p&gt;
&lt;h2 id="claudeの構成"&gt;&lt;code&gt;.claude&lt;/code&gt;の構成
&lt;/h2&gt;&lt;p&gt;今回の &lt;code&gt;.claude&lt;/code&gt; のディレクトリ構造は次のとおりである。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.claude
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── agents # 編集長・編集部員・ペルソナ等のエージェント定義
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── docs # オウンドメディアの設計ドキュメント
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── 01_Business-Model
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── 01_Concepts
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── 02_Design
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── 03_Personas
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── 04_Value-Proposition-Canvas
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── 05_Market-Analysis
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── 06_Business-Model-Canvas
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── 07_RoadMap
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── 02_Roles-and-Workflow # 組織構造・編集ルール等
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── skills
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └── article-workflow # 記事作成〜品質保証〜最終承認のワークフロー定義&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;docs&lt;/code&gt; には、人間が定義した事業計画を置く。&lt;code&gt;agents&lt;/code&gt; と &lt;code&gt;skills&lt;/code&gt; には、その事業計画を元にAIが実装した編集部の構成要素を置く。&lt;/p&gt;
&lt;h2 id="人間が定義するもの"&gt;人間が定義するもの
&lt;/h2&gt;&lt;p&gt;まず、Claudeと議論しながら事業計画を立案・策定した。具体的には以下である。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ビジネスモデルの定義&lt;/strong&gt;: エレベーターピッチを起点に、ペルソナ、バリュープロポジションキャンバス、市場分析などを一通り整備した。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ロールと役割の定義&lt;/strong&gt;: チーム構成、各メンバーの役割と責任、ワークフロー、編集ルール、ペルソナを定義した。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらがAIの成果物（今回でいうとオウンドメディアの記事）を評価する拠り所になる。評価基準が曖昧なままエージェントを動かしても、その成果物を正しく評価することはできない。&lt;/p&gt;
&lt;h2 id="aiが実装したもの"&gt;AIが実装したもの
&lt;/h2&gt;&lt;p&gt;Claude Codeに対して事業計画等の資料一式を渡したところ、Claude Codeは &lt;code&gt;SKILL&lt;/code&gt; と &lt;code&gt;AGENTS&lt;/code&gt; を自力で設計・実装した。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SKILLの決定&lt;/strong&gt;: 記事作成から品質保証・最終承認までの一連のワークフローを &lt;code&gt;article-workflow&lt;/code&gt; として定義した。実は、事業計画の中で記事の承認基準や差し戻し基準を明示的に定義していなかったが、私が渡した情報をもとにClaudeが適切に補完した。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AGENTSの決定&lt;/strong&gt;: 編集長、編集部員、ペルソナ（4名）を定義した。エージェントが達成すべき役割だけでなく、エージェント間でどのような情報を受け渡しするかというインターフェースも、ここで定義されている。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;実装自体はMarkdownを書くだけなので、手間は大きくない。ただし今回は、&lt;code&gt;SKILL&lt;/code&gt; や &lt;code&gt;AGENTS&lt;/code&gt; の分割や、どのように書いた方が効果的なのかはClaudeの方が理解しているだろうと判断し、すべてClaudeに任せた。&lt;/p&gt;
&lt;p&gt;問題は、Claudeの成果物のレビューである。「編集部の作業内容」と言う一次情報を持ち合わせていなかったため、Claudeの成果物にハルシネーションが含まれているかどうかの判断が難しかった。今回は常識的な範囲で荒いレビューを行った。未知の分野でAIを使った場合、ハルシネーションを見抜くのは非常に難しいため、AI時代においても一次情報の重要性は変わらないか、より増すものと考えられる。&lt;/p&gt;
&lt;h2 id="実際のところどうだったか"&gt;実際のところ、どうだったか
&lt;/h2&gt;&lt;h3 id="問題1-編集長の承認条件が厳しすぎてコンテキストを食い潰した"&gt;問題1: 編集長の承認条件が厳しすぎてコンテキストを食い潰した
&lt;/h3&gt;&lt;p&gt;最初に設定した承認条件はこうだった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;markdown&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;- [ ]&lt;/span&gt; ペルソナAI（4名中3名）が「推奨」している
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;- [ ]&lt;/span&gt; 編集長AIの「重要な」指摘事項が0件である
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;- [ ]&lt;/span&gt; ビジネスモデルとの整合性が星4つ以上
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- [ ] 読者に与える価値が星4つ以上&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;良かれと思ってペルソナの属性や性格が被らないように設計した結果、3名全員の「推奨」を取り付けることはほぼ不可能だった。編集長AIの重要指摘事項0件もほとんど達成できない水準だった。これにより、編集者AIが修正 → 編集長AIとペルソナAI4名がレビュー → 指摘に基づいて編集者AIが修正 → &amp;hellip;となってコンテキストを食い潰し、&lt;code&gt;article-workflow&lt;/code&gt; がセッション内で完走できないケースが続いた。&lt;/p&gt;
&lt;p&gt;そこで、承認条件を緩和した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;markdown&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;- [ ]&lt;/span&gt; ペルソナAI（4名中2名）が「推奨」している
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;- [ ]&lt;/span&gt; 編集長AIの「重要な」指摘事項が1件以下である
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;- [ ]&lt;/span&gt; ビジネスモデルとの整合性が星4つ以上
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- [ ] 読者に与える価値が星4つ以上&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ペルソナAIの推奨人数を4名中3名から4名中2名に下げ、また、編集長AIの重要な指摘事項を0件まで落としたことでワークフローが通せるようになった。ローカルLLMであれば &lt;code&gt;seed&lt;/code&gt; や &lt;code&gt;temperature&lt;/code&gt; 等のパラメータを設定できるので修正指示も一貫する可能性があるが、Claudeの場合はユーザが制御できないようになっており「発散する可能性」を制御できず、修正指示が収束しない可能性を考慮した結果である。つまり、AIの決定性・非決定性は、ワークフロー設計の前提条件になると言うことである。&lt;/p&gt;
&lt;p&gt;また、星4つ以上の条件は据え置いた。オウンドメディアと事業戦略の整合性を維持しなければ、記事と記事の間に矛盾が生じるため、ここは緩めなかった。結果として、セッション内で3記事程度は作れるようになった。&lt;/p&gt;
&lt;p&gt;エージェントを利用する際、チェックの基準を厳しくしすぎると修正ループが発生し、コンテキストを消耗する。実際の挙動を見ながら調整していく必要がある。&lt;/p&gt;
&lt;h3 id="問題2-執筆された記事が似非マーケターが書いたような内容になった"&gt;問題2: 執筆された記事が似非マーケターが書いたような内容になった
&lt;/h3&gt;&lt;p&gt;出力された記事は、如何にもAIが書いたような文体になってしまった。原因は明確だ。編集者AIがどのような文体で執筆すべきかを、最初に定義しなかったからだ。コンテキストの消費量を改善しても依然として大量のコンテキストを使うため、そのうちに面倒になり、この改善には手をつけなかった。&lt;/p&gt;
&lt;h4 id="実際に出力された記事"&gt;実際に出力された記事
&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;「貯蓄分はないもの」を本気で実感するには、時間差が必要だった&lt;/p&gt;
&lt;p&gt;「給料が入ったら、先に貯蓄分を別の口座に移しておく」&lt;/p&gt;
&lt;p&gt;これは先取り貯蓄の基本として、よく言われることです。私も何度か試しました。けれど、正直に言うと、しばらくすると元に戻してしまうことが多かったんです。&lt;/p&gt;
&lt;p&gt;なぜかというと、銀行口座から別の口座に振り込んでも、どちらも「自分の口座」であることに変わりはなく、心のどこかで「いざとなれば戻せる」と感じていたからだと思います。貯蓄口座に移したはずのお金が、結局「予備財布」のような感覚になっていました。&lt;/p&gt;
&lt;p&gt;そんな私が、1年間で50万円を貯められるようになったのは、**自動引き落としの「時間差」**を使うようになってからです。&lt;/p&gt;
&lt;p&gt;この記事では、なぜ手動の振込より自動引き落としの方が続きやすかったのか、その心理的な仕組みと、私が実際にやっている方法をお伝えします。あなたにとっての「続く仕組み」を考えるヒントになれば嬉しいです。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="学んだこと"&gt;学んだこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;構造設計としての有効性&lt;/strong&gt;: 「事業計画を定義し、その評価基準でAIがAIの成果物を評価する」という構造そのものは成立した。ルールとして明確に定義するものと、その範囲内で目的達成方法をAIに考えさせるという分業は機能した。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一次情報の重要性&lt;/strong&gt;: 人間とAIの関係を構造設計する際、一次情報をどれだけ知っているかが重要になる。今回の場合、実際の編集部がどのように機能しているかを知らなければ、AIの成果物を厳密にレビューすることは難しい。「知らないことをAIに尋ねるのはよいが、それを評価するのは至難の業」という問題は今回も残った。未知の分野でAIを使った場合、ハルシネーションを見抜くのは非常に難しいため、AI時代においても一次情報の重要性は変わらないか、より増すものと考えられる。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;コンテキスト管理の設計&lt;/strong&gt;: コンテキストの消費量が多いと、改善のフィードバックループが回しにくくなる。今回は &lt;code&gt;CLAUDE.md&lt;/code&gt; を活用せずに進めたが、コンテキストの使用効率を高める手段を積極的に取り入れるべきだった。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;インデックスの必要性&lt;/strong&gt;: ZettelkastenにおけるStructured Noteのようなインデックスが、AIのコンテキスト展開を段階的に制御するために重要だと気づいた。AIに何をどこまで読み込ませるかを決めるには、インデックス情報が必要になる。これは前回の『&lt;a class="link" href="../../../2026/02/22/" &gt;ZettelkastenをRAGの情報源として有効活用するには、ノート間のリンクに「意味ラベル」をつけ、型付きのエッジを持たなければならない&lt;/a&gt;』での考察とも合致する。今回利用した &lt;code&gt;SKILL&lt;/code&gt; や &lt;code&gt;AGENTS&lt;/code&gt; では、このインデックス情報はうまく活用しきれていない。そのため、&lt;code&gt;CLAUDE.md&lt;/code&gt; を使うことはこの文脈において有効な手段であると考えている。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="次にaiエージェントを立ち上げるときに考えておきたいこと"&gt;次にAIエージェントを立ち上げるときに考えておきたいこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt; のように、コンテキストの使用効率を高める方法を最初から組み込む。&lt;/li&gt;
&lt;li&gt;コンテキスト消費量とフィードバックループの速度はトレードオフになる。いかに効率を高めながらループを回すかが設計の肝になる。&lt;/li&gt;
&lt;li&gt;文体や表現スタイルは、事業計画と同じタイミングで定義しておく。後からでは手遅れになる可能性が高い。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Claude Codeの &lt;code&gt;SKILL&lt;/code&gt; と &lt;code&gt;AGENTS&lt;/code&gt; を使ったAI編集部は、形として動かすことはできた。人間が事業計画・役割・ワークフローを定義し、AIが実装するという構造設計は機能した。また、その定義が「AIエージェント間」での拠り所にもなっている様子が見てとれた。&lt;/li&gt;
&lt;li&gt;承認条件の設計ミス（?）によるコンテキスト枯渇と、文体定義をしなかったことによる記事の品質低下という、二つの失敗が発生した。いずれも設計段階での考慮不足が原因であり、実装後に気づいても取り返しにくい。&lt;/li&gt;
&lt;li&gt;コンテキストの消費量を管理しながらフィードバックループを回す設計が、AIエージェント活用の中心的な課題になる。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ZettelkastenをRAGの情報源として有効活用するには、ノート間のリンクに型付きエッジを持たなければならない</title><link>https://sonohen.net/posts/2026/02/22/</link><pubDate>Sun, 22 Feb 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/02/22/</guid><description>&lt;p&gt;※ この記事は、誤字脱字、表現の冗長さ・曖昧さのチェックのためにClaude Codeを利用している。&lt;/p&gt;
&lt;h2 id="tldr"&gt;TL;DR
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;本記事で提案する「手動による型付きエッジの付与による運用」は、GraphRAGやNeo4j RAGとは異なり、型付きエッジを手動で付与する。これにより、Zettelkastenの探索を人間の手によって制御し、かつインフラの運用コストを抑えることができる点に差別化要素がある。&lt;/li&gt;
&lt;li&gt;ZettelkastenをRAGの情報源として使う場合、&lt;strong&gt;ノート間のリンクに型付きエッジを付与しなければ、AIはグラフを無限に辿ってコンテキストが膨張する&lt;/strong&gt; 。&lt;/li&gt;
&lt;li&gt;人間はリンクの意味をノートの文脈から推測できるが、AIにはその判断ができない。これは「人間にとってわかりやすいリンクはAIにとって分からない」という構造的な非対称性である。&lt;/li&gt;
&lt;li&gt;データの意味付けを軽視してきた歴史（セマンティックウェブ、ビッグデータ、企業RAG）は、同じ失敗パターンの繰り返しだと解釈できる。&lt;/li&gt;
&lt;li&gt;付与する型付きエッジとして &lt;code&gt;supports →&lt;/code&gt; / &lt;code&gt;contradicts →&lt;/code&gt; / &lt;code&gt;refines →&lt;/code&gt; / &lt;code&gt;depends_on →&lt;/code&gt; の4種を提案する。&lt;/li&gt;
&lt;li&gt;コンテキストが膨張するとOOMによるクラッシュ（MLX）や推論崩壊（llama.cpp）が起きる。これは設計の問題であり、パラメーター調整で解決できるものではない。&lt;/li&gt;
&lt;li&gt;実際に計測したところ、型付きエッジによる制約付きグラフ探索（constrained graph traversal）でトークン使用量を約70%削減（556,006 → 163,782トークン）しながら、回答品質をほぼ維持できることを確認した。&lt;/li&gt;
&lt;li&gt;ただし、リンクに対する型付きエッジの付与だけが解決策ではない。どこを意味付けし、どこをしないかという全体設計が必要である。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="なぜノート間リンクの関係を自動抽出ではなく手動で行うのかはじめに"&gt;なぜ、ノート間（リンク）の関係を自動抽出ではなく手動で行うのか（はじめに）
&lt;/h2&gt;&lt;p&gt;GraphRAG&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; や、Neo4j RAGのような手法では、異なる2つのエンティティ間の関係を自動抽出し、型付きエッジを持つグラフを構築する。本記事の提案は、これらと同じくグラフのトラバーサルを意味的に制御するものであるが、設計の前提が異なる。&lt;/p&gt;
&lt;p&gt;第一に、ZettelkastenのAI（Claude）による自動操作はすでに試みており、失敗している。AIにノートの作成・メタデータ付与・構造操作を任せた結果、ノイズが混入し、知的生産の基盤としての機能を失った（詳細は『&lt;a class="link" href="../../../2026/01/25/" &gt;Zettelkastenを機能させ、また形骸化させないために、何でもかんでも入れるべきではない&lt;/a&gt;』を参照）。Zettelkastenは自分の思考の蓄積であり、AIによる自動操作とは相容れない。&lt;/p&gt;
&lt;p&gt;第二に、インフラコストの問題がある。GraphRAG/Neo4j RAGはグラフDBや埋め込みモデルの常時稼働を前提とし、個人が複数台の端末間で使い回すには重すぎる。本記事の設計は、ObsidianのMarkdownファイルとClaude(MCP)のみで完結し、端末を問わず持ち運べることを条件としている。&lt;/p&gt;
&lt;p&gt;つまり、手動による型付きエッジの付与を選んだのは、自動化の限界を実体験した結果と、軽量・ポータブルであるという制約条件の両方によるものである。この選択におけるGraphRAGとの差分は「自動か手動か」だけでなく、「運用環境の重さ」と「Zettelkastenの思想との整合性」にある。&lt;/p&gt;
&lt;h2 id="きっかけ"&gt;きっかけ
&lt;/h2&gt;&lt;p&gt;『&lt;a class="link" href="../../../2026/02/14/" &gt;ローカルLLMでSpec Driven Developmentは、まだ難しかった&lt;/a&gt;』という記事を書きながら、「自分のZettelkastenをRAGの情報源として接続すれば、自分の思考を元にした回答が得られるのではないか」という考えが浮かんだ。&lt;/p&gt;
&lt;p&gt;ただし、この設計を考えるにあたって、1つの前提がある。過去にAIにノート操作を任せた結果、Zettelkastenがノイズだらけになるという失敗を経験している（『&lt;a class="link" href="../../../2026/01/25/" &gt;Zettelkastenで管理する情報は何で、どう管理すべきなのか&lt;/a&gt;』、『&lt;a class="link" href="../../../2026/01/31/" &gt;Zettelkastenを機能させ、また形骸化させないために、何でもかんでも入れるべきではない。&lt;/a&gt;』）。その経験から、「AIはZettelkastenを読むことはできるが書いてはいけない」という原則をすでに確立している。今回の設計はその原則の上に成り立っている。&lt;/p&gt;
&lt;p&gt;しかし、実際に試そうとした瞬間、問題が見えてきた。Zettelkastenのノートはネットワーク型の構造になっており、ノート間には無数のリンクが張り巡らされている。RAGとして使うということは、AIがそのネットワークを辿ってコンテキストを組み立てることになるが、「どのリンクをどこまで辿るか」という制御をどうするかが難しい。&lt;/p&gt;
&lt;p&gt;そこで少し考えてみると、問題の本質は「ノート間に型付きエッジが付与されていない」ことだということに気がついた。&lt;/p&gt;
&lt;h2 id="zettelkastenとragの相性問題"&gt;ZettelkastenとRAGの相性問題
&lt;/h2&gt;&lt;p&gt;そもそもRAGとは何かを整理しておく。RAGは、LLMが一般的な訓練データから回答を生成するのではなく、特定のドキュメント群（情報源）を参照しながら回答する仕組みだ。ハルシネーションの影響範囲を限定し、特定ドメインに閉じた回答を得るための構造設計の方法論として使われる。具体的には、Zettelkastenとの組み合わせで期待できるのは、「自分の思考・知識を格納したナレッジベースを、AIが参照しながら回答できるようになること」だ。&lt;/p&gt;
&lt;p&gt;ところが、ZettelkastenをそのままRAGとして活用すると問題が起きる。Zettelkastenのノートはそれぞれが他のノートへのリンクを持っており、関連するノートをどんどん参照する構造になっている。AIがネットワークを辿り始めると、関連ノートをすべて読み込もうとしてしまい、コンテキストが際限なく膨張する。&lt;/p&gt;
&lt;p&gt;これは設計の問題だ。&lt;strong&gt;RAGという文脈においては、どのリンクをどこまで辿るかを制御する「制約付きグラフ探索」がなければ、Zettelkastenは有用な情報源にならない&lt;/strong&gt; のである。&lt;/p&gt;
&lt;h2 id="リンクの意味は人間は理解できaiには理解できない"&gt;リンクの「意味」は、人間は理解でき、AIには理解できない
&lt;/h2&gt;&lt;p&gt;リンクの制約付きグラフ探索の問題は、「このリンクは辿るべきか、辿らなくてよいか」をどう判断するか、である。&lt;/p&gt;
&lt;p&gt;人間はノートを読みながら、リンクの意味を文脈から推測できる。「このリンクは根拠として貼ったもの」「このリンクは反論の候補として貼ったもの」「このリンクは前提知識として必要なもの」といった区別を、リンクを貼った瞬間に理解している。&lt;/p&gt;
&lt;p&gt;しかし、AIにはそれが分からない。リンクはただの接続であり、その接続が「支持」なのか「反論」なのか「依存」なのかを、ただのリンクから読み解くことはできないのである。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[人間の場合]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ノートA ──リンク──&amp;gt; ノートB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↑
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 「これは根拠ノートだ」と文脈から判断できる
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[AIの場合]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ノートA ──リンク──&amp;gt; ノートB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↑
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 意味が分からない。全部辿るしかない。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;これは「人間にとってわかりやすいリンクはAIにとって分からない」という構造的な非対称性だ。この非対称性を放置したまま「ZettelkastenをRAGに使う」という設計は、機能しない。本質的には『&lt;a class="link" href="../../../2026/02/1503/" &gt;「顧客はわかっていない」を構造的に再解釈する&lt;/a&gt;』で議論した内容と同じである。&lt;/p&gt;
&lt;h2 id="データの意味付けを後回しにしてきた歴史"&gt;データの意味付けを後回しにしてきた歴史
&lt;/h2&gt;&lt;p&gt;この問題は、実は繰り返されてきた「うまくいかない」パターンと同じ構造を持っている。&lt;/p&gt;
&lt;h3 id="1-セマンティックウェブ"&gt;(1) セマンティックウェブ
&lt;/h3&gt;&lt;p&gt;Web 2.0の台頭で、膨大な個人メディアがウェブに溢れたとき、ティム・バーナーズ・リーは、RDFやOWLといったメタデータ技術によって情報に意味を付与する「セマンティックウェブ」を提唱した。機械が情報の意味を解釈し、より賢い検索・統合ができるようにするというビジョンだった。&lt;/p&gt;
&lt;p&gt;しかし、広くは普及しなかった。既存の膨大なデータにメタデータを付与するコストが、得られるメリットに見合わなかったからだ。現在はベクトル検索との共存という形で、その理念が部分的に受け継がれている。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2026/02/22/images/20260222111045.png"
	width="1352"
	height="398"
	loading="lazy"
	
		alt="メタデータを活用している例"
	
	
		class="gallery-image" 
		data-flex-grow="339"
		data-flex-basis="815px"
	
&gt;&lt;/p&gt;
&lt;h3 id="2-ビッグデータ"&gt;(2) ビッグデータ
&lt;/h3&gt;&lt;p&gt;Hadoopなどのデータ分析基盤が「大量のデータに価値がある」という前提で作られた時代、データの意味付けはないがしろにされた。データが何を意味しているのかが分からない状態で分析を行い、期待通りの洞察は得られなかった。&lt;/p&gt;
&lt;h3 id="3-企業におけるrag活用"&gt;(3) 企業におけるRAG活用
&lt;/h3&gt;&lt;p&gt;現在も同じパターンが繰り返されている。企業内に存在するExcelやPowerPointといった非定型データをRAGに登録しても、望む回答精度が得られないという課題がある。原因は単純で、ドキュメント内の要素がどのような文脈でどのような意味を持つのかを、AIが理解できないからだ。意味付けのない情報をいくら積み上げても、AIはそれを有効に活用できない。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;情報の蓄積に価値があるという幻想と、意味付けのコストを軽視してきた結果が、この繰り返しである&lt;/strong&gt; と私は考えている。この課題を解決しようとしている企業が多く存在していることからも、今回は同じ繰り返しをしないようにしていると考えられる。&lt;/p&gt;
&lt;h2 id="型付きエッジを付与したリンクの提案"&gt;型付きエッジを付与したリンクの提案
&lt;/h2&gt;&lt;p&gt;この構造的な非対称性を解消するために、リンクに「型付きエッジを付与する」設計を考えた。リンクの種類を以下の4つに分類し、リンクを貼る際に明示的に意味付けを行う。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;型&lt;/th&gt;
 &lt;th&gt;意味&lt;/th&gt;
 &lt;th&gt;用途&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;supports →&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;このノートの根拠&lt;/td&gt;
 &lt;td&gt;主張の根拠を支えるノートへのリンク&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;contradicts →&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;このノートへの反論&lt;/td&gt;
 &lt;td&gt;反論・対立する視点へのリンク&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;refines →&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;このノートの洗練・具体化&lt;/td&gt;
 &lt;td&gt;上位・下位概念の関係、より詳細な説明へのリンク&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;depends_on →&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;このノートの前提条件&lt;/td&gt;
 &lt;td&gt;読む前に理解すべき前提知識へのリンク&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;実際の記述例はこうなる。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;markdown&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## 主張
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ZettelkastenをRAGの情報源として有効活用するには、ノート間のリンクには型付きエッジを付与する必要がある。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;-&lt;/span&gt; supports → [[人間にとってわかりやすいリンクは、AIにとっては分からない]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;-&lt;/span&gt; context: 人間はリンクの意味を文脈から推測できるが、AIはできない。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;-&lt;/span&gt; depends_on → [[Zettelkastenのノート間のリンクは型付きエッジによって意味づけしておくことが重要]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - context: 型付きエッジがなければ、AIはグラフを無限に探索してしまう。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;この設計をすることで、制約付きグラフ探索が可能になる。たとえば「&lt;code&gt;supports&lt;/code&gt;リンクだけを辿る」「&lt;code&gt;depends_on&lt;/code&gt;は1ホップまで」といったルールをクエリ時に適用できるようになる。&lt;/p&gt;
&lt;p&gt;なお、&lt;code&gt;contradicts&lt;/code&gt;リンクが多いノートは、未解決の領域あるいは思考の臨界点を示していることになる。これはAIへの指示の文脈だけでなく、ノートを管理する人間にとっても有用な情報になる。&lt;/p&gt;
&lt;p&gt;ただし、この方法には、型付きエッジを後から付与するためのコストが爆発的に増えるという課題がある。&lt;/p&gt;
&lt;h2 id="制約付きグラフ探索の効果を計測する"&gt;制約付きグラフ探索の効果を計測する
&lt;/h2&gt;&lt;p&gt;提案している設計の効果を確認するために、実際にトークン使用量を計測した。170ノート・41,370文字・207リンクで構成されたZettelkastenを対象に、「生成AIにおけるRAGの現状と課題」を調査するタスクをClaude Codeに依頼し、制約付きグラフ探索によってどれほど差が出るかを比較した。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;条件&lt;/th&gt;
 &lt;th&gt;サブエージェント実行数&lt;/th&gt;
 &lt;th&gt;トークン使用量&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;制約付きグラフ探索なし&lt;/td&gt;
 &lt;td&gt;12回&lt;/td&gt;
 &lt;td&gt;556,006トークン&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;制約付きグラフ探索あり&lt;/td&gt;
 &lt;td&gt;4回（約67%削減）&lt;/td&gt;
 &lt;td&gt;163,782トークン（約70%削減）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;なしの場合、AIはすべてのリンクを辿るために12のサブエージェントを起動し、55万トークン超を消費した。ありの場合は、型付きエッジをもとに必要なノードに絞り込み、4エージェント・16万トークン強で完了した。&lt;/p&gt;
&lt;p&gt;回答品質についても比較した。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;回答事項&lt;/th&gt;
 &lt;th&gt;制約付きグラフ探索あり&lt;/th&gt;
 &lt;th&gt;制約付きグラフ探索なし&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;1. RAGの本質的な役割（Vaultが示す再定義）&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2. 実装アーキテクチャの変遷（実体験ベース）&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;3. AI Engineer ／ Application Developer の責任境界&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;4. ベクトル検索とメタデータの共存&lt;/td&gt;
 &lt;td&gt;&lt;em&gt;回答なし&lt;/em&gt; &lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;課題1：データ意味付けの困難さ（最重要課題）&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;課題2：コンテキスト長の膨張と推論エンジンへの影響&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;課題3：リンク意味の不透明性&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;課題4：AI／人間の判断境界設計&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;課題5：データ更新・削除の複雑性&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;課題6：机上設計と実装の乖離&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;課題7：歴史的失敗の反復リスク&lt;/td&gt;
 &lt;td&gt;&lt;em&gt;回答なし&lt;/em&gt; &lt;sup id="fnref1:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
 &lt;td&gt;回答あり&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;ありで「ベクトル検索とメタデータの共存」「歴史的失敗の反復リスク」の2項目が未回答となったが、これは型付きエッジによって選ばれたノード群が中心的な問いに絞り込まれた結果であり、カバレッジの欠落ではなく焦点化の結果と解釈している。&lt;/p&gt;
&lt;p&gt;トークン使用量を約70%削減しながら回答品質をほぼ維持できたことは、制約付きグラフ探索の有効性を裏付けている。また、データを絞ることでAIが中心的な問いにフォーカスするという副作用も確認できた。コンテキストの膨張は「情報量が多ければ回答の質が上がる」という直感に反し、むしろ回答品質を下げる可能性があることを示唆している。&lt;/p&gt;
&lt;h2 id="コンテキスト膨張は実害を生む"&gt;コンテキスト膨張は実害を生む
&lt;/h2&gt;&lt;p&gt;これは概念的な話ではなく、『&lt;a class="link" href="../../../2026/02/14/" &gt;ローカルLLMでSpec Driven Developmentは、まだ難しかった&lt;/a&gt;』で身をもって経験した実害でもある。コンテキストが膨張すると、推論エンジンはOOM（Out of Memory）に陥る。その挙動はエンジンによって異なる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MLX（mlx_lm）&lt;/strong&gt;: OOMが発生した時点でクラッシュする。これ以降の推論崩壊を防ぐための設計だが、処理が中断される。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;llama.cpp&lt;/strong&gt;: OOM後も &lt;code&gt;ctx_pos&lt;/code&gt; / &lt;code&gt;n_past&lt;/code&gt; が進み続け、初期化が保証されていないKV Cacheを参照しながら推論を続けてしまう。結果として推論崩壊が起きる。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;どちらが良い悪いではなく、設計思想のトレードオフだ。しかし、いずれにしてもコンテキストを膨張させないことが根本的な解決策であり、制約付きグラフ探索はその手段の1つになる。&lt;/p&gt;
&lt;h2 id="課題"&gt;課題
&lt;/h2&gt;&lt;p&gt;制約付きグラフ探索は1つの解だが、リンクだけを整備すれば十分というわけではない。ノート内のどの部分がAIにとって「文脈」として有効なのか、何をZettelkastenにおけるメタデータに含めるべきか、ノート自体にどのようなメタデータを持たせるかといった設計の問いは、リンクに対して型付きエッジを付与した後にも残る。&lt;strong&gt;型付きエッジの付与は「設計行為」であり、どこを付与し、どこをしないかという全体像を先に決めなければ、部分最適に終わる&lt;/strong&gt; という考えである。&lt;/p&gt;
&lt;p&gt;また、既存の大量のノートに型付きエッジを後から付与するコストも現実的な障壁だ。セマンティックウェブが普及しなかった理由の1つが「既存データへのメタデータ付与コスト」だったこと、GraphRAGが自動で検出を試みていることの2つを考えると、新規ノートから型付きエッジを付け始めて様子を見るスモールスタートが現実的だろうと考えている。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ZettelkastenをRAGの情報源として接続するには、ノート間のリンクに型付きエッジが必要である。型付きエッジがなければ、AIがグラフを無限にトラバースしてコンテキストが膨張する。実際の計測では、型付きエッジをもとにした制約付きグラフ探索なしで556,006トークン・12エージェントだったのに対し、ありでは163,782トークン・4エージェントに抑制できた（それぞれ約70%・約67%の削減）。&lt;/li&gt;
&lt;li&gt;これはデータに対する型付きエッジの付与を軽視してきた歴史（セマンティックウェブ、ビッグデータ、企業RAG）と同じ構造である。情報の蓄積には価値があるが、意味付けなき蓄積は、AIがそれを有効活用できないという点で、「何を蓄積するか」以上に重要な論点になる。&lt;/li&gt;
&lt;li&gt;Zettelkastenのノート間のリンクに意味付けを行うという点においては、&lt;code&gt;supports →&lt;/code&gt; / &lt;code&gt;contradicts →&lt;/code&gt; / &lt;code&gt;refines →&lt;/code&gt; / &lt;code&gt;depends_on →&lt;/code&gt; の4種の型付きエッジを提案する。これにより制約付きグラフ探索が可能になると考えている。&lt;/li&gt;
&lt;li&gt;コンテキスト膨張はOOMクラッシュや推論崩壊という実害を生む。これはパラメーター調整ではなく、設計で解決すべき問題である。&lt;/li&gt;
&lt;li&gt;リンクの型付きエッジは解決策の一部であり、全体の意味付け設計と合わせて考える必要がある。
&lt;ul&gt;
&lt;li&gt;リンクの型付きエッジは、双方向リンクに対しては爆発的にコストが大きくなる。片方向だけで十分かどうかも含めて検討する必要がある。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Edge, Darren, Ha Trinh, Newman Cheng, ほか. 「From Local to Global: A Graph RAG Approach to Query-Focused Summarization」. arXiv:2404.16130. 査読前原稿, arXiv, 2025年2月19日. &lt;a class="link" href="https://doi.org/10.48550/arXiv.2404.16130" target="_blank" rel="noopener"
 &gt;https://doi.org/10.48550/arXiv.2404.16130&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;制約付きグラフ探索ありで「回答なし」となった項目は、型付きエッジによって選ばれたノート群が中心的な問いに絞り込まれた結果、AIが回答対象として設定しなかったものである。カバレッジの欠落ではなく、焦点化の結果と解釈している。&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref1:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>「顧客はわかっていない」を構造的に再解釈する</title><link>https://sonohen.net/posts/2026/02/1503/</link><pubDate>Sun, 15 Feb 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/02/1503/</guid><description>&lt;h2 id="tldr"&gt;TL;DR
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;「顧客はわかっていない」という感覚は &lt;strong&gt;お互いの思考限界がズレている&lt;/strong&gt; ことを示しているに過ぎない。&lt;/li&gt;
&lt;li&gt;顧客は技術的制約を思考限界の外に置き、技術者はビジネス文脈を思考限界の外に置く。この非対称性が衝突を生む。&lt;/li&gt;
&lt;li&gt;優れたアーキテクトは、思考限界を動的にずらしながら、顧客・技術者・システムの三者間をコーディネートする。この能力を &lt;strong&gt;構造設計能力&lt;/strong&gt; と呼ぶ。&lt;/li&gt;
&lt;li&gt;AIとの協働においても、まったく同じ構造が成立する。「AIに何をさせ、何をさせないか」の設計と、「顧客と何を共有し、何を委ねるか」の設計は、同じ問いの別バージョンである。&lt;/li&gt;
&lt;li&gt;「顧客はわかっていない」という思考は未熟である。問うべきは「どの思考限界をどこへずらすか」である。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="きっかけ"&gt;きっかけ
&lt;/h2&gt;&lt;p&gt;顧客との打ち合わせのあと、「あの人は技術的なことが全くわかっていないから、好き勝手なことを言う」と感じることがある。おそらく多くのエンジニアが、一度はそう思ったことがあるはずだ。&lt;/p&gt;
&lt;p&gt;一方で、最近AIを使った開発を進める中で、ある気づきがあった。AIに対して「なんでこんなことをするんだ」「指示通りにやってくれない」と感じる場面が増えてきた。これは、顧客に対して感じることと、構造的にとても似ている。&lt;/p&gt;
&lt;p&gt;では、「顧客はわかっていない」という感覚は、本当に正しいのか。逆に顧客の立場から見たらどうなのか。AIとの対比を通じて、この問題を構造的に整理してみたい。&lt;/p&gt;
&lt;h2 id="思考限界というフレームワーク"&gt;思考限界というフレームワーク
&lt;/h2&gt;&lt;p&gt;まず、「思考限界」という概念を導入する。&lt;/p&gt;
&lt;p&gt;人は誰でも、自分が認識できる範囲に「限界」を持っている。業務を知り尽くしている顧客は、システムがどう実装されているかを必ずしも知らない。逆に、技術者はシステムを構築できるが、その業務がなぜ今の形になっているのか、歴史的・組織的な文脈を把握していないことが多い。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[顧客の思考]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;思考限界の内側: 業務知識・経営判断・ユーザー体験
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;思考限界の外側: 技術的制約・実装コスト・インフラ構造 ← まだ見えていない
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[技術者の思考]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;思考限界の内側: 技術スタック・実装難易度・パフォーマンス特性
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;思考限界の外側: 業務フロー・組織の意思決定構造・顧客の顧客の要求 ← まだ見えていない&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;「顧客はわかっていない」という発言は、技術者の思考限界の内側にある情報を、顧客が持っていないことへの苛立ちである。しかし同時に、顧客の思考限界の内側にある情報を、技術者も持っていない。この非対称性は、どちらかが「わかっていない」という話ではなく、 &lt;strong&gt;互いに相手の思考限界の外側に重要な情報を持っている&lt;/strong&gt; という構造の問題だ。&lt;/p&gt;
&lt;h2 id="アーキテクトの役割思考限界をずらす"&gt;アーキテクトの役割：思考限界をずらす
&lt;/h2&gt;&lt;p&gt;では、どうすればよいのか。ここで登場するのが「思考限界を動的にずらす」という設計行為だ。&lt;/p&gt;
&lt;p&gt;たとえば、顧客が「膨大なデータを、リアルタイムで全件表示したい」と要求してきたとする。技術者は「100万件を毎秒描画するのは不可能だ」と思う。この時点で衝突が生まれる。しかし、ここで優れたアーキテクトが行うのは、「それは無理です」というのではなく、自身が持つ技術知識をもとに、顧客の思考を分解して考え、思考限界を技術的制約の側に一歩ずらすことである。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[初期状態]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;顧客の思考限界の内側: 「全件リアルタイム表示」
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;↓ アーキテクトが制約を可視化
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[目的達成可能な状態]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;顧客の思考限界の内側: 「集計ビュー + 閾値超過時のアラート」← 移動させる
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;顧客の思考限界の外側: 描画コストの詳細（もはや意識不要）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;顧客が本当に欲しかったのは「全件表示」ではなく、「意思決定に必要な情報をタイムリーに得ること」だったかもしれない。このように、思考限界をずらすことで、本来の目的に辿り着ける。これが構造設計能力の本質だと考えている。このとき、制約は「できないことの証明」ではなく、 &lt;strong&gt;目的へ向かうための設計上の道具&lt;/strong&gt; として機能する。制約を設けることでトレードオフが生まれ、そのトレードオフを顧客と共有することで、はじめて合意形成ができる。&lt;/p&gt;
&lt;h2 id="aiとの協働に見る同じ構造"&gt;AIとの協働に見る、同じ構造
&lt;/h2&gt;&lt;p&gt;最近、AIを使った開発を進める中でまったく同じ構造を感じるようになった。AIに対して自由さを与えると、出力が発散する。逆に、過度に細かい制約を与えると、AIは制約の範囲でしか動けず、本来解けるはずの問題も解けなくなる。&lt;/p&gt;
&lt;p&gt;AIに「思考させる範囲」と「人間が判断すべき範囲」を設計することは、顧客の思考限界と技術者の思考限界の境界を設計することと、構造が同じだ。&lt;/p&gt;
&lt;p&gt;Vibe-Codingが崩壊するのも、この制約の設計が欠如しているからだと理解している。RAG、Spec Driven Development、エージェント設計といった手法は、すべてAIの思考限界を設計的に制御する試みであり、「AIに何をわからせ、何は人間が持つか」を明示化するアプローチだ。&lt;/p&gt;
&lt;p&gt;対顧客も対AIも、 &lt;strong&gt;思考限界の境界を設計することが、問題解決の核心&lt;/strong&gt; にあると考えている。&lt;/p&gt;
&lt;h2 id="思考限界を動的にずらすことに成功した例"&gt;思考限界を動的にずらすことに成功した例
&lt;/h2&gt;&lt;h3 id="openshift-強制という制約が自由をもたらす"&gt;OpenShift： 「強制」という制約が自由をもたらす
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="../../../2026/02/1502/" &gt;以前調べたRed Hat OpenShift&lt;/a&gt;が良い事例だと感じた。OpenShiftはGit・OCI・Kubernetesという業界標準を &lt;strong&gt;強制&lt;/strong&gt; することで、開発者の思考限界を「何を使うか」から「どう使うか」にずらしている。&lt;/p&gt;
&lt;p&gt;AWS（サービスの集合体）は設計の自由度が高い反面、「何を選ぶか」という判断コストが利用者に集中する。OpenShiftは、その選択の余地をあえて削ることで、350人規模の開発チームでもオンボーディングコストを下げることに成功した。&lt;/p&gt;
&lt;p&gt;「強制」という制約が、実は「自由に動ける範囲」を明確にしていた。これはまさに思考限界をずらす設計の実例だ。&lt;/p&gt;
&lt;h3 id="porsche-informatik-枠が組織のしがらみを溶かす"&gt;Porsche Informatik： 「枠」が組織のしがらみを溶かす
&lt;/h3&gt;&lt;p&gt;Porsche InformatikがプライベートクラウドからOpenShiftに移行した際、6週間で移行を完了し、350人超の開発者が常時利用する環境を実現した。「枠」という制約を設けることで、オープンソースの自由さと、組織の標準化要求という相反する要件を両立している。&lt;/p&gt;
&lt;p&gt;これは、顧客（経営層・開発チーム）の思考限界に「標準化された開発プラットフォーム」という概念を移植した結果だと言える。&lt;/p&gt;
&lt;h2 id="構造設計能力という自己研鑽の方向性"&gt;「構造設計能力」という自己研鑽の方向性
&lt;/h2&gt;&lt;p&gt;ここまでを整理すると、技術者に求められる能力は次のように言い換えられる。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;「自分の思考限界がどこにあるかを把握し、顧客や技術者の思考限界を動的にずらしながら、目的達成へコーディネートする能力」&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;これを構造設計能力と呼ぶことにしている。技術者の自己研鑽とは、何かの技術を追い続けることによって、「自分の思考限界がどこにあるかを探究し続けること」だと思っている。技術書を読む、新しいフレームワークを触る、顧客の業務フローを深く学ぶ、これらはすべて「自分の思考限界を広げる」行為だ。&lt;/p&gt;
&lt;p&gt;ただし、もうひとつ重要なことがある。&lt;strong&gt;思考限界を広げるだけでなく、どこに境界を置くかを設計する能力&lt;/strong&gt; も同時に必要だということだ。自分が何でも知っていようとすることは、「何でもできるノートパソコン」と同じで、帯に短し、襷に長しになりかねない。何を知っていて、何を知らないのかを具体化し続けることが重要なのではないだろうか（難しい話だが）。&lt;/p&gt;
&lt;p&gt;構造設計能力とは、知識の総量ではなく、&lt;strong&gt;知識の境界を設計する力&lt;/strong&gt; だと今は考えている。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;「顧客はわかっていない」は、思考限界の非対称性を正確に言い表した言葉ではあるが、それ止まりでは未熟な認識である。&lt;/li&gt;
&lt;li&gt;問うべきは「どの思考限界を、どこへ、どうずらすか」であり、この設計行為がアーキテクトの核心的な仕事だと考えている。&lt;/li&gt;
&lt;li&gt;AIとの協働においても、この構造はまったく同じだ。「AIに何をわからせるか」の設計と、「顧客に何を共有するか」の設計は、同じ問いの異なる文脈での現れである。&lt;/li&gt;
&lt;li&gt;思考限界の自己研鑽は終わりのない旅だが、その方向性は「限界を広げること」と「限界の境界を設計すること」の両輪で成り立つ。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Red Hat OpenShiftのDeveloper SandboxをAWSと比較しながら触ってみた</title><link>https://sonohen.net/posts/2026/02/1502/</link><pubDate>Sun, 15 Feb 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/02/1502/</guid><description>&lt;h2 id="tldr"&gt;TL;DR
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;AWS は多数のサービスを組み合わせて使う &lt;em&gt;Service&lt;/em&gt; の集合体であり、自由度が高い反面、設計・統合の責任は利用者側にある。&lt;/li&gt;
&lt;li&gt;Red Hat OpenShift は業界標準（Git / OCI / Kubernetes）を &lt;strong&gt;強制&lt;/strong&gt; する &lt;em&gt;Platform as a Product&lt;/em&gt; として設計されており、最初から統合された開発・運用体験を提供することを目的としている。&lt;/li&gt;
&lt;li&gt;Developer Sandboxでは以下の点から、迷わず進める体験が強く印象に残った。
&lt;ul&gt;
&lt;li&gt;Gitリポジトリ指定だけでビルド〜デプロイまで完結する。&lt;/li&gt;
&lt;li&gt;Podログ・ターミナル・リソース使用量が1画面で確認可能である。&lt;/li&gt;
&lt;li&gt;AIアシスタント Lightspeed により学習コストが低減している。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Developer Sandboxの基盤はAWS EC2上で動作しているが、実体はROSA(Redhat OpenShift Service on AWS) 上のOpenShiftであり、マルチクラウドで動作することをログレベルで体感した。&lt;/li&gt;
&lt;li&gt;閉域網要件やオンプレ併用が求められる企業システムでは、OpenShiftのマルチクラウド設計が大きな強みになる。また、上記の理由から組織の習熟度やスキルに応じて、選択肢の幅を広げていることにもつながる。&lt;/li&gt;
&lt;li&gt;結論として、AWSは“自由を最大化するプラットフォーム”、OpenShiftは“標準化で速度と再現性を出すプロダクト”であり、優劣ではなく設計思想の違いが現れているのだと実感した。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="きっかけ"&gt;きっかけ
&lt;/h2&gt;&lt;p&gt;普段の仕事では、AWSを使う機会が多い。ECS/Fargate、CodeBuild、Lambdaなど、サービスを組み合わせて作ること、その考え方には慣れてきたが、一方でその「組み合わせる責任」を、常にアーキテクトが負っていることは感じていた。「追いかけ続けるのは大変だ」と思う今日この頃です。&lt;/p&gt;
&lt;p&gt;そこで、とあることがきっかけとなりRed Hat OpenShiftが &lt;em&gt;Platform as a Product&lt;/em&gt; という考え方で設計されていると知り、それがAWSとどう違うのかを自分の手で確かめてみたくなり、無料で使える &lt;em&gt;Developer Sandbox&lt;/em&gt; があると知り、週末を使って触ってみた。&lt;/p&gt;
&lt;h2 id="platform-as-a-service-vs-platform-as-a-product"&gt;Platform as a Service vs Platform as a Product
&lt;/h2&gt;&lt;p&gt;AWSを一言で表すとすれば &lt;strong&gt;サービスの集合体&lt;/strong&gt; だろう。EC2、RDS、Lambda、ECSなど、数百に及ぶサービスが並んでおり、利用者はその中から自分のユースケースに合ったものを選び、組み合わせて使う。自由度は極めて高い。&lt;/p&gt;
&lt;p&gt;しかし裏を返せば、&lt;strong&gt;どのサービスをどう組み合わせるかの設計責任はすべて利用者にある&lt;/strong&gt; ということだ。CI/CDパイプラインを1本作るにも、CodeCommit → CodeBuild → Amazon ECR → Amazon ECSという工程を整え、IAMロール、セキュリティグループなど、自分で判断、設計しなければならない。熟練者には自由だが、習熟の浅いエンジニアには高い壁になる。&lt;/p&gt;
&lt;p&gt;それに対して、OpenShiftのアプローチは対照的だ。Git、OCI（ Open Container Initiative、コンテナ規格）、Kubernetesといった業界標準を &lt;strong&gt;強制&lt;/strong&gt; することで、開発者が最初からある一定の土台の上に立てる設計になっている。何でもできる、のではなく、標準という枠に沿ってできる、というわけだ。&lt;/p&gt;
&lt;p&gt;この「強制」はベンダーロックインの回避にも繋がっている。OpenShiftはAWS/Azure/オンプレミス等で動作する。アプリケーションコードはどの環境でも同じように動く。AWSのマネージドサービスに依存した設計と違い、インフラの切り替えコストが低い。&lt;/p&gt;
&lt;h2 id="developer-sandboxで試したこと"&gt;Developer Sandboxで試したこと
&lt;/h2&gt;&lt;h3 id="lightspeedとの統合"&gt;Lightspeedとの統合
&lt;/h3&gt;&lt;p&gt;OpenShiftはコンソールにAIアシスタント &lt;strong&gt;Lightspeed&lt;/strong&gt; が統合されている。試したのは、Podが起動していない状態でどうアクセスすればよいかを尋ねる場面だ。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;私&lt;/strong&gt;: The pods are not running so I cannot connect via ssh. If the pods are running, I can connect to these pods via console from anywhere?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lightspeed&lt;/strong&gt;: Yes, if the pods are running, you can connect to them using the OpenShift console or CLI from anywhere, provided you have network access to the cluster and the necessary permissions. Here&amp;rsquo;s how you can do it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;OpenShift Console&lt;/strong&gt;: Access the OpenShift web console using your browser. Navigate to the specific project and pod, and use the terminal feature to open a shell inside the pod.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenShift CLI&lt;/strong&gt;: Use the &lt;code&gt;oc&lt;/code&gt; command-line tool to interact with the pods. You can start a remote shell session with the following command: &amp;hellip;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2026/02/1502/images/20260214191743.png"
	width="1322"
	height="762"
	loading="lazy"
	
	
		class="gallery-image" 
		data-flex-grow="173"
		data-flex-basis="416px"
	
&gt;&lt;/p&gt;
&lt;p&gt;KubernetesやOpenShiftの概念を前提とした回答が返ってくるため、独自ドキュメントを読み漁る前に「なぜこうなっているのか」の文脈を掴める。経験の浅いエンジニアでも自己解決までの距離が縮まる、という点でこの統合は意味が大きいと思う。&lt;/p&gt;
&lt;h3 id="gitからのデプロイ"&gt;Gitからのデプロイ
&lt;/h3&gt;&lt;p&gt;まず試したのが、Gitリポジトリからのデプロイである。Developer Sandboxの画面からGitリポジトリのURLを指定するだけで、コンテナのビルドからPod・Serviceの生成まで自動で行われる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2026/02/1502/images/20260214192631.png"
	width="1296"
	height="742"
	loading="lazy"
	
	
		class="gallery-image" 
		data-flex-grow="174"
		data-flex-basis="419px"
	
&gt;&lt;/p&gt;
&lt;p&gt;GitHubのリポジトリに限らず、自前のGitサーバ、CodeCommitなど、名前解決できる場所にあれば何でも使える。&lt;/p&gt;
&lt;p&gt;AWSで同じことをしようとすると、CodeCommit（またはGitHubとの連携）→ CodeBuild（ビルド設定・buildspec.yml）→ Amazon ECR（イメージ登録）→ Amazon ECS（タスク定義・サービス設定）という順を踏まなければならない。それぞれのサービスの設定と試行錯誤で1日潰れることも珍しくない。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;パイプラインは難しい&lt;/em&gt; と感じる習熟レベルの人でも、OpenShiftなら最初のデプロイまで数分で到達できる。この体験の差は大きい。&lt;/p&gt;
&lt;h3 id="ログとターミナルの統合"&gt;ログとターミナルの統合
&lt;/h3&gt;&lt;p&gt;デプロイ後、ログをコンソールから確認してみた。PodのログはOpenShift ConsoleからPod単位でリアルタイムにストリーミングされる。&lt;/p&gt;
&lt;p&gt;ログを眺めていると、気になる行が目に入った。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Successfully assigned ***-dev/code-with-quarkus-665467cf97-9rcdb to ip-10-0-86-229.ec2.internal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;ec2.internal&lt;/code&gt; が示すように、Developer Sandbox自体のバックエンドはAWS EC2上で動いている。実際には、Red HatがAWS上でマネージド提供するROSA（Red Hat OpenShift Service on AWS）を基盤としており、その上にOpenShiftクラスタが構成されている。このログを通じて、OpenShiftが特定のインフラに依存しないプラットフォームであることを実感した。&lt;/p&gt;
&lt;p&gt;AWSでアプリケーションのログを確認しようとすると、CloudWatch Logs → ロググループ → ログストリームという階層を辿らなければならず、慣れていないとどこを見れば良いか迷う。OpenShiftはPodを選べばそのままログが見える。この一体感は確かに違う。&lt;/p&gt;
&lt;p&gt;Podへの接続は、コンソールから直接できる。また、OpenShift CLI（&lt;code&gt;oc&lt;/code&gt;）を使えば、普段使っているターミナルから一時認証情報を使ってPodにアクセスできる。&lt;/p&gt;
&lt;h3 id="リソースの可視化"&gt;リソースの可視化
&lt;/h3&gt;&lt;p&gt;CPU・メモリ・ファイルシステムの使用状況が時系列グラフでコンソールに表示される。CloudWatchでこれを実現しようとすると、CloudWatch Agentをインストールする必要がある。OpenShiftはデプロイ直後からリソースの状況が一画面で見える。&lt;/p&gt;
&lt;h2 id="awsとの比較-閉域網要件"&gt;AWSとの比較: 閉域網要件
&lt;/h2&gt;&lt;p&gt;企業システムでよく要件に上がるのが「インターネットに通信を出したくない」という閉域網の要求だ。&lt;/p&gt;
&lt;p&gt;AWSで閉域運用を実現しようとすると、VPC Endpoint（各サービスごとに作成が必要）、Route53 Private Hosted Zone（DNS解決の制御）などを組み合わせる必要がある。設定が複雑になるうえ、VPC Endpointによって課金ポイントも増える。予算の制約とのバランスをとることも難しい。&lt;/p&gt;
&lt;p&gt;OpenShiftはインフラを抽象化しているため、完全閉域が必要ならオンプレミス、柔軟性が必要ならクラウドという配置場所の変更が、アプリケーションの変更なしに実現できる。組織のクラウド習熟度や用途に応じて、オンプレとクラウドを使い分ける選択肢があり、さらにそれらの移動が比較的容易であると言える。&lt;/p&gt;
&lt;p&gt;セキュリティ要件の厳しい業界（金融・公共）への提案を考えると、この柔軟性は大きな差別化点になる。&lt;/p&gt;
&lt;h2 id="導入事例から読み解く"&gt;導入事例から読み解く
&lt;/h2&gt;&lt;h3 id="porsche-informatik6週間でのレガシー移行"&gt;Porsche Informatik：6週間でのレガシー移行
&lt;/h3&gt;&lt;p&gt;市場への投入スピードを競うPorsche Informatikは、プライベートクラウドで動作していたアプリケーションをOpenShiftへ移行した。所要期間は6週間。現在は350人を超える開発者が常時利用しており、Market-inまでの時間を90%向上させたという。&lt;/p&gt;
&lt;p&gt;スピードで語られることの多い事例だが、「350人が常時利用」という点も注目に値する。OpenShiftが「強制」する標準的な作法が、大規模な開発組織でのオンボーディングコストを下げていると考えられる。&lt;/p&gt;
&lt;p&gt;参考: &lt;a class="link" href="https://www.redhat.com/ja/resources/porsche-informatik-partner-case-study" target="_blank" rel="noopener"
 &gt;Porsche Informatik、Red Hat OpenShift でユーザーエクスペリエンスを促進&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="jra日本中央競馬会5000万pvの動的スケーリング"&gt;JRA（日本中央競馬会）：5000万PVの動的スケーリング
&lt;/h3&gt;&lt;p&gt;JRAは土日に1日に5,000万PV、平日はそれ以下という極端なトラフィックの波を抱えている。従来のプライベートクラウド基盤で静的にリソースを確保するのではなく、OpenShiftへ移行してHPA（Horizontal Pod Autoscaler）によるPod数の動的な増減で対応しているようだ。&lt;/p&gt;
&lt;p&gt;成果として以下のようなものが得られているようである。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;脆弱性対応の頻度が6ヶ月→2ヶ月に短縮&lt;/li&gt;
&lt;li&gt;本番リリース作業が5時間→1時間に短縮&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;脆弱性対応の短縮はローリングアップデートによるOpenShiftコントロールプレーンの更新速度と、DevOpsによるアプリケーション側の対応高速化の両方が効いていると考えられる。本番リリース作業の短縮はBlue/Greenデプロイメントが機能していると思われる。現場の開発者/運用者にとっては非常に大きな改善であると言える。&lt;/p&gt;
&lt;p&gt;なお、スケーリング戦略としてHPAを使っているのは合理的だと感じた。もしVPA（Vertical Pod Autoscaler）を使うとPodの再起動が必要になり、複雑さが増す。リクエスト数の波に対してはPod数で柔軟に対応するHPAの方が向いている。&lt;/p&gt;
&lt;p&gt;参考: &lt;a class="link" href="https://www.redhat.com/ja/about/press-releases/jra-adopts-red-hat-openshift-for-its-official-website-platform" target="_blank" rel="noopener"
 &gt;日本中央競馬会が公式ウェブサイトのプラットフォームにRed Hat OpenShiftを採用&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;Developer Sandboxを触って感じたのは、自由度と使いやすさのトレードオフに対するRed Hatなりの答えだ。&lt;/p&gt;
&lt;p&gt;AWSは設計の自由度が高い反面、その自由を使いこなすための学習コストと、組み合わせの責任を利用者が負う。対するOpenShiftは、標準を &lt;strong&gt;強制&lt;/strong&gt; することで、誰が使っても一定の品質と速度でデプロイ・運用できる土台を提供している。&lt;/p&gt;
&lt;p&gt;Gitからのデプロイ、ログとターミナルの一体化、Lightspeedとの統合など、これらはどれも「開発者がやりたいことに集中できる環境」を実現するための設計であり、サービスを繋ぎ合わせて仕組みを作らせようとするAWSとは出発点が違う。（念のため、どちらが良い悪いではなく、思想の違いということです）&lt;/p&gt;
&lt;p&gt;閉域網要件や既存のオンプレ資産との共存が求められる企業システムにこそ、このプロダクトの価値が発揮される場面がありそうだと感じた。&lt;/p&gt;</description></item><item><title>ローカルLLMのtemperatureとseedを比較：FizzBuzzと俳句を各条件3回生成してみた</title><link>https://sonohen.net/posts/2026/02/1501/</link><pubDate>Sun, 15 Feb 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/02/1501/</guid><description>&lt;h2 id="先に結果"&gt;先に結果
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;LM Studioで &lt;code&gt;seed = 42&lt;/code&gt; とし、&lt;code&gt;temperature&lt;/code&gt; を0・0.3・1.2に変えて、FizzBuzzと俳句を各条件3回生成した。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;temperature = 0&lt;/code&gt; では、各タスクで3回とも同じ結果になった。最大スコアのトークンを選ぶ設定で、出力の再現性を確認できた。&lt;/li&gt;
&lt;li&gt;FizzBuzzでは、0で仕様に合う関数が得られた一方、0.3と1.2では不具合を含む回答もあった。少数の試行なので、不具合の発生率までは判断できない。&lt;/li&gt;
&lt;li&gt;俳句では、季節に合わない季語の説明や、指定した句数との不一致が見られた。プロンプト自体にも「5-7-5」と「破調を積極的に使用」という曖昧さがあった。&lt;/li&gt;
&lt;li&gt;表示された推論テキストの言語は条件や試行によって変わったが、言語が出力品質の原因であるかは、この実験では切り分けられていない。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="きっかけ"&gt;きっかけ
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://sonohen.net/posts/2026/02/14/" &gt;前回の記事&lt;/a&gt;でローカルLLMのクラッシュと推論崩壊に苦しめられた。Context Lengthの設定を見直すとともに、「そもそもパラメータをどう設定すれば望ましい生成結果が得られるのか」という疑問が湧いた。&lt;/p&gt;
&lt;p&gt;ここでは、&lt;code&gt;seed&lt;/code&gt;を固定して&lt;code&gt;temperature&lt;/code&gt;を変え、生成結果を比較した。&lt;code&gt;seed&lt;/code&gt;を固定しない場合も予備的に試したが、seed値を系統的に変える比較実験は行っていない。&lt;/p&gt;
&lt;h2 id="実験環境"&gt;実験環境
&lt;/h2&gt;&lt;h3 id="使用機材とソフトウェア"&gt;使用機材とソフトウェア
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;マシン&lt;/strong&gt;: MacBook M3 24GB RAM&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LM Studio&lt;/strong&gt;: バージョン0.4.2 (Build 2) / Metal llama.cpp v2.1.0&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;モデル&lt;/strong&gt;: Deepseek R1 0528 Qwen3 8B（GGUF、GPU Full Off-Load）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用モデルの&lt;a class="link" href="https://huggingface.co/deepseek-ai/DeepSeek-R1-0528-Qwen3-8B" target="_blank" rel="noopener"
 &gt;公式モデルカード&lt;/a&gt;によると、土台はQwen3-8B Baseである。DeepSeek-R1-0528の推論データを使って追加学習している。元のQwen3とはトークナイザー設定が異なり、公式カードではDeepSeek側の設定ファイルを使うよう案内している。&lt;/p&gt;
&lt;h3 id="パラメータ"&gt;パラメータ
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;temperature&lt;/code&gt;のみを変化させ、その他は以下のとおり固定した。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;パラメータ&lt;/th&gt;
 &lt;th&gt;値&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Context Length&lt;/td&gt;
 &lt;td&gt;8192&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;GPU Off-Load&lt;/td&gt;
 &lt;td&gt;36（Full Off-Load）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;repeat-penalty&lt;/td&gt;
 &lt;td&gt;1.0&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;top-p&lt;/td&gt;
 &lt;td&gt;0.8&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;seed&lt;/td&gt;
 &lt;td&gt;42（固定）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="temperatureとseedの役割"&gt;temperatureとseedの役割
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;temperature&lt;/code&gt;は、次のトークンを選ぶ際の確率分布を調整する値である。正の値では、一般に低くすると高スコアの候補に集中し、高くすると低スコアの候補も選ばれやすくなる。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;temperature = 0&lt;/code&gt;では、各ステップで最大スコアのトークンを選ぶ。&lt;/strong&gt; この方法をgreedy decodingと呼ぶ。モデル・入力・計算条件をそろえると、同じ入力から同じ続きを返す関数のように動く。今回も、この設定ではFizzBuzzと俳句のそれぞれで3回とも同じ結果が得られた。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;seed&lt;/code&gt;は、確率に従ってトークンを選択する際に使う擬似乱数の初期値である。モデルが計算したスコアをもとに、どの候補を選ぶかに関わる。サンプリングを使う条件でseedを固定すると、乱数列をそろえて比較できる。通常のgreedy decodingでは、最大スコアの候補が直接選ばれる。&lt;/p&gt;
&lt;p&gt;予備的な試行では、seedを固定せずに&lt;code&gt;temperature = 0&lt;/code&gt;で実行した際にも出力の違いが見られた。その後、seedを42に固定して比較したところ、各タスクで同じ結果が得られた。ここでは、そのときに使った設定と観察結果を記録している。&lt;/p&gt;
&lt;h3 id="比較条件と結果の一覧"&gt;比較条件と結果の一覧
&lt;/h3&gt;&lt;p&gt;seedを42に固定し、各タスク・各temperatureで3回ずつ生成した。temperatureが0のときは同一の回答になり、0.3と1.2では同じ設定でも回答に違いが見られた。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;タスク&lt;/th&gt;
 &lt;th style="text-align: right"&gt;temperature&lt;/th&gt;
 &lt;th style="text-align: right"&gt;試行数&lt;/th&gt;
 &lt;th&gt;記録された結果&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;FizzBuzz&lt;/td&gt;
 &lt;td style="text-align: right"&gt;0&lt;/td&gt;
 &lt;td style="text-align: right"&gt;3&lt;/td&gt;
 &lt;td&gt;同一の関数を生成。目視では仕様に合う実装&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;FizzBuzz&lt;/td&gt;
 &lt;td style="text-align: right"&gt;0.3&lt;/td&gt;
 &lt;td style="text-align: right"&gt;3&lt;/td&gt;
 &lt;td&gt;1・3回目は変数iを文字列として出力、2回目は0と同じ実装&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;FizzBuzz&lt;/td&gt;
 &lt;td style="text-align: right"&gt;1.2&lt;/td&gt;
 &lt;td style="text-align: right"&gt;3&lt;/td&gt;
 &lt;td&gt;実装の表現が変化。不具合を含む回答もあり、全件の合否内訳は未集計&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;俳句&lt;/td&gt;
 &lt;td style="text-align: right"&gt;0&lt;/td&gt;
 &lt;td style="text-align: right"&gt;3&lt;/td&gt;
 &lt;td&gt;同一の回答。表示された推論テキストは中国語&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;俳句&lt;/td&gt;
 &lt;td style="text-align: right"&gt;0.3&lt;/td&gt;
 &lt;td style="text-align: right"&gt;3&lt;/td&gt;
 &lt;td&gt;回答が変化。3回目は反復が続き、最後まで生成できず&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;俳句&lt;/td&gt;
 &lt;td style="text-align: right"&gt;1.2&lt;/td&gt;
 &lt;td style="text-align: right"&gt;3&lt;/td&gt;
 &lt;td&gt;回答が変化。2回目は日本語の推論テキストと6句を出力&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;以下では、生成されたコードの条件分岐と出力文字列、俳句の季語・句数・表現を見ていく。「推論言語」は、LM Studioに表示された推論テキストの言語を指す。&lt;/p&gt;
&lt;h2 id="実験プログラムコードを生成するfizzbuzz"&gt;実験①：プログラムコードを生成する（FizzBuzz）
&lt;/h2&gt;&lt;h3 id="プロンプト"&gt;プロンプト
&lt;/h3&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;あなたは以下のMain.javaを読んでいます。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;適切な形でfizzbuzz関数を実装してください。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;不必要に思考せず、簡潔に答えてください。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;java&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;FizzBuzz&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(String&lt;span style="color:#f92672"&gt;[]&lt;/span&gt; args) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 0; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; 50; i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fizzbuzz(i);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fizzbuzz&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// TODO: Implement here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Spec:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// - This function print:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// &amp;#34;i: fizz&amp;#34; if i is multiple of 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// &amp;#34;i: buzz&amp;#34; if i is multiple of 5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// &amp;#34;i: fizzbuzz&amp;#34; if i is multiple of both 3 and 5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// &amp;#34;i: -&amp;#34; if others&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// - Each line should be ended with break line.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="temperature--0の場合3回とも完全に同一のコードが生成される"&gt;temperature = 0の場合(3回とも完全に同一のコードが生成される)
&lt;/h3&gt;&lt;p&gt;3回とも完全に同一のコードが生成された。表示された推論テキストは英語だった。下記の関数は目視では仕様に合っている。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;java&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fizzbuzz&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; 15 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(i &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;: fizzbuzz&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; 3 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(i &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;: fizz&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; 5 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(i &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;: buzz&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(i &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;: -&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="temperature--03の場合-やや多様"&gt;temperature = 0.3の場合 （やや多様）
&lt;/h3&gt;&lt;p&gt;バグが混入した。&lt;code&gt;i&lt;/code&gt;を変数ではなく文字列リテラルとして出力してしまっている（1回目・3回目）。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;java&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 1回目・3回目（バグあり）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fizzbuzz&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; 15 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;i: fizzbuzz&amp;#34;&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// ← iではなく&amp;#34;i&amp;#34;になっている&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; 3 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;i: fizz&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;2回目はバグがなく、&lt;code&gt;temperature = 0&lt;/code&gt;のときと同じ実装が得られた。条件分岐の方針は3回とも同じだったが、出力文字列に違いが出た。この3回だけで、temperatureを上げると一般に精度が落ちるとは結論できないが、揺れが出ていることは観察できる。&lt;/p&gt;
&lt;h3 id="temperature--12-多様"&gt;temperature = 1.2 （多様）
&lt;/h3&gt;&lt;p&gt;FizzBuzzの条件判定が&lt;code&gt;if i % 15 == 0&lt;/code&gt;から&lt;code&gt;if i % 3 == 0 &amp;amp;&amp;amp; i % 5 == 0&lt;/code&gt;に変化するなど、より多様な実装が出た。引き続きバグを含む回答も混じった。&lt;/p&gt;
&lt;p&gt;3回目には &lt;strong&gt;推論過程が初めて日本語になった&lt;/strong&gt;（1・2回目は英語）。また、&lt;code&gt;fizzbuzz()&lt;/code&gt; メソッドのみを出力し、&lt;code&gt;main()&lt;/code&gt;を出力しないケースもあった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;java&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 3回目（temperature=1.2、推論が日本語になった回）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fizzbuzz&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; 15 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(i &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;: fizzbuzz&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; 3 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(i &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;: fizz&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (i &lt;span style="color:#f92672"&gt;%&lt;/span&gt; 5 &lt;span style="color:#f92672"&gt;==&lt;/span&gt; 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(i &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;: buzz&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(i &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;: -&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;なお、すべての試行を通じて、「&lt;code&gt;if i % 3 == 0&lt;/code&gt;を先に評価してしまうミス」は一度も発生しなかった。&lt;/p&gt;
&lt;h3 id="コード生成の観察まとめ"&gt;コード生成の観察まとめ
&lt;/h3&gt;&lt;p&gt;今回の3回ずつの比較では、temperatureが0のときに同一の関数が得られ、0.3と1.2では不具合を含む回答もあった。temperatureと不具合の発生傾向について、より確かな結論を得るには、試行数を増やしたり、入力するプロンプトや実装課題を変えたりして検証するとよいと考えられる。生成コードをコンパイルし、仕様に沿ったテストで評価すれば、条件ごとの違いも比較しやすくなる。&lt;/p&gt;
&lt;h2 id="実験俳句を生成する"&gt;実験②：俳句を生成する
&lt;/h2&gt;&lt;p&gt;以下のプロンプトを使った。「5-7-5」を指定しながら破調も積極的に求めており、形式の評価基準が曖昧だった。そのため、音数が5-7-5でないことだけを失敗とは判定しない。季節との整合性、指定した3句への対応、日本語の表現を分けて観察する。生成文に含まれる季語や音数の説明は、モデルの回答をそのまま引用したもので、正しい解説とは限らない。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2月の季語を使いながら俳句を生成してください。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- 形式は5-7-5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- 冬の終わりの静寂さとの別れを彷彿させる俳句
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- 破調（5-7-5の崩れ）も積極的に使用 // ← わざと揺れさせるように
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- 対比する句を3句作成（例：朝・昼・夜） // ← わざと揺れさせるように&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="temperature--0の場合-今回の3回は同一出力"&gt;temperature = 0の場合 （今回の3回は同一出力）
&lt;/h3&gt;&lt;p&gt;推論が &lt;strong&gt;中国語&lt;/strong&gt; で行われた。3回とも完全に同一の結果で、推論言語も変わらなかった。&lt;/p&gt;
&lt;p&gt;（推論の一部）&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;嗯，用户想要用2月的季语创作俳句，主题是冬末的静寂感和离别氛围，
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;还特别要求使用破调和对毎句。这个需求挺有意思的，看来用户对俳句有一定了解...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;出力された俳句は以下のとおり（全3回共通）。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;句1: 朝の雪が舞い散る窓&lt;/strong&gt;
静かに静かに静かだ
冬の終わりを告げる
この季節の美しさは憂いを帯びて&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;句2: 午後の枯枝が揺れる風&lt;/strong&gt;
冷たく冷たく冷たい
待ち続ける季語たちの
ささやく別れの言葉&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;句3: 夜の灯りが揺れる窓&lt;/strong&gt;
孤独に孤独に孤独だ
季節は去りゆくが
心はまだ冬の静寂に囚われて&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;想定していた短い句とは異なり、説明的な複数行の詩になった。繰り返しも目立つ。ただし、破調を許容した指示の影響と、推論テキストの言語が影響した可能性も考えられる。&lt;/p&gt;
&lt;h3 id="temperature--03の場合-やや多様-1"&gt;temperature = 0.3の場合 （やや多様）
&lt;/h3&gt;&lt;p&gt;引き続き推論は中国語で行われた。ただし &lt;code&gt;temperature=0&lt;/code&gt; と同一の推論過程ではなく、出力にも多様性が出た。&lt;/p&gt;
&lt;p&gt;1回目はプロンプトに答えていない句が出た。回答の一部には、中国語の簡体字を含む表記（&lt;code&gt;阴り&lt;/code&gt;）があった。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;句例1:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;窓の外の雪が融け出す&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;季語:&lt;/strong&gt; 雪が融け出す (雪解けの始まり)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;イメージ:&lt;/strong&gt; 冬の終わり、雪が消え始める静寂と、その過程での期待や寂しさを表現。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;句例2:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;さくらんぼの花が咲き出す&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;季語:&lt;/strong&gt; さくらんぼの花 (2月の梅の花、暁花)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;イメージ:&lt;/strong&gt; 別れを彷彿させる、美しいが儚い花の開く様子。破調（5-7-5）ではありますが、季語と題意を満たしています。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;句例3:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;日は阴り少なくなった&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;季語:&lt;/strong&gt; 日は阴り少なくなった (日陰が減った、日照時間が長くなった)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;イメージ:&lt;/strong&gt; 冬の厳しさが和らぎ、春に向かう静かな変化。別れの訪れを暗示。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;2回目は1回目と大きく変わり、異なる季語・構成になった（今回の例では、コードの条件分岐よりも文章の構成の違いが目立った）。&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;季語：立春&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;句：&lt;/strong&gt; 立春の木枯らぎ / さよなら雪 / 窓の外で待ち&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;説明：&lt;/strong&gt; 「立春」が季語、「木枯らぎ」（枯れ木）が2月の風景を表す。破調の6-7-5で始まり、冬の終わりの静寂と去りゆく雪、窓の外で待ち続ける情景を描く。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;季語：梅雨&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;句：&lt;/strong&gt; 梅雨の朝露 / かすかに春の匂い / うっかり吸い込む&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;説明：&lt;/strong&gt; 「梅雨」が季語、「朝露」が2月の季語風景。破調の5-7-5で、ほのかな春の匂いを帯びた湿った空気を、つい意識せずに吸い込む無邪気さを表現。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;季語：雫&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;句：&lt;/strong&gt; 雫の花蕾 / 未だ届けられぬ手紙 / 春待ちの季語&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;説明：&lt;/strong&gt; 「雫」（しぶき、滴）が季語、「花蕾」（芽）が春の訪れを象徴。破調の5-5-5で、まだ届いていない別れの手紙と、待ち続ける季語の重ね合わせを表現。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;3回目は &lt;strong&gt;反復が続き、俳句を最後まで生成できなかった&lt;/strong&gt;。このときは&lt;code&gt;repeat-penalty = 1.0&lt;/code&gt;で、繰り返しへのペナルティをかけない設定だった。次に試す際は、この値を上げて比較すると、反復の抑制にどの程度効果があるかを確認できると考えられる。&lt;/p&gt;
&lt;h3 id="temperature--12の場合-多様"&gt;temperature = 1.2の場合 （多様）
&lt;/h3&gt;&lt;p&gt;1回目は、短い表現になり、説明的な言葉が控えられている点に注目した。中国語で推論されていた。&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;朝霜降る 春待ちかな&lt;/li&gt;
&lt;li&gt;雪降り 山の間は 静かに&lt;/li&gt;
&lt;li&gt;夜の季語に 山は青し&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;2回目は &lt;strong&gt;日本語で推論&lt;/strong&gt; した。ただし、指定した3句に対して6句を出力し、「梅雨明け」など2月の指定に合わない語も含まれていた。日本語の推論テキストが表示された回でも、指示への不一致は残った。&lt;/p&gt;
&lt;p&gt;（2回目の推論）&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;まず、ユーザーのクエリを理解します。ユーザーは2月の季語を使って俳句を作成してほしいと要請しています。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;二月寒風、枯れ木そよぐ静かに、別れの訪れ&lt;/li&gt;
&lt;li&gt;梅雨明けの青空、雪の跡が消え行く、心のほろび&lt;/li&gt;
&lt;li&gt;古池の水面結晶、冬が終りを告げる、孤独な夜&lt;/li&gt;
&lt;li&gt;6-7-5の句：風雪舞う空庭、往く者もなしの別れ、季節の幕下り&lt;/li&gt;
&lt;li&gt;7-5-5の句：灯す街路灯一筋、静寂が二重に深まる、時の流れを想う&lt;/li&gt;
&lt;li&gt;5-8-5の句：窓の外白い霧、待ち続ける影たちが重なる、冬の最後の夢&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;3回目は、やや説明的な言葉が目立った。こちらも、表示された推論テキストは中国語だった。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;1. 朝：&lt;/strong&gt; 正月に雪かすがり、君はもう去りぬ
&lt;strong&gt;2. 昼：&lt;/strong&gt; 窓辺、霜枯らむ、そよ風立ち込める
&lt;strong&gt;3. 夜：&lt;/strong&gt; 長閑、月光の下、さよならの言葉響く&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="俳句生成のまとめ"&gt;俳句生成のまとめ
&lt;/h3&gt;&lt;p&gt;temperatureが0では、今回期待していた俳句は得られなかった。0.3は表現のバランスが比較的よいと感じたが、季語の誤った説明や生成が完了しない試行もあり、最適値と判断できる結果ではない。1.2では日本語の推論テキストが表示された回もあったが、句数や季節の指定は守られなかった。&lt;/p&gt;
&lt;p&gt;プロンプトで複数の要求を同時に与えたことが影響した可能性もある。そのため、まず「破調なしで5-7-5」と「破調を許容する創作」を別のプロンプトに分けるとよいと考えられる。音数、季語、句数、表現の好みを別々に評価すれば、設定の違いを比較しやすくなる。実行パラメータを調整するには、小さなタスクでの出力結果の比較検討が必要と思われる。&lt;/p&gt;
&lt;h2 id="表示された推論言語と品質の関係"&gt;表示された推論言語と品質の関係
&lt;/h2&gt;&lt;p&gt;今回、同じ日本語の依頼でも、表示された推論テキストには英語・中国語・日本語が現れた。これは興味深い観察だが、&lt;strong&gt;推論テキストの言語が品質の原因だとは言えない&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;俳句では、中国語の推論テキストが表示された回答に問題があった一方、日本語が表示された回答にも季節や句数の不一致があった。言語以外の生成内容も同時に変わっているため、言語だけの効果は比較できていない。&lt;/p&gt;
&lt;p&gt;また、この出力からモデルの訓練データの言語比率や、日本語俳句の知識量を推定できない。「中国語で考えたから俳句の形式を守れなかった」という説明は仮説にとどまる。&lt;/p&gt;
&lt;h2 id="さらに検証する場合の設定と確認方法"&gt;さらに検証する場合の設定と確認方法
&lt;/h2&gt;&lt;p&gt;コード生成では、モデルの公式推奨設定を比較の基準にし、必要に応じて低いtemperatureや、場合によってはtemperature = 0も試す。サンプリングを使う場合はseedも記録し、モデルのファイル・量子化方式・推論エンジン・プロンプト・会話履歴・その他の設定をそろえる。そのうえで、生成コードをコンパイルし、0・3・5・15のような分岐を通る値と、通常の値で出力を確認する。temperatureで出力の傾向を調整し、テストで正しさを確認する。&lt;/p&gt;
&lt;p&gt;俳句のような創作では、先に守るべき条件を明確にし、temperatureを変えた回答を複数回比較する。今回、比較的バランスがよいと感じた0.3を出発点に、モデルやタスクに合わせて値を調整すると、適した設定を探りやすくなると考えられる。&lt;/p&gt;
&lt;p&gt;反復が続く場合は、生成トークン数に上限を設けたうえで、繰り返しペナルティの値を変えて比較するとよいと考えられる。繰り返しペナルティは1.0で補正なしとなる。値を上げれば既出トークンへのペナルティが強くなるため、反復が続くときの調整候補になる。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;本比較では、seedを42に固定してtemperatureを0にすると、FizzBuzzと俳句のそれぞれで、各3回の出力が一致したことを確認した。一方、temperatureを上げた条件では、実装や表現に違いが見られた。俳句の指示への適合は、temperatureの変更だけでは改善しなかった。&lt;/p&gt;
&lt;p&gt;各条件3回の比較で、出力の再現性と指示への適合は別々に見る必要があると感じた。同じ回答が返っても、それが期待した回答とは限らない。モデルやタスクを変えて調整する際にも、この2つを分けて評価することが有効だと考えられる。&lt;/p&gt;
&lt;h2 id="追加検証の観点"&gt;追加検証の観点
&lt;/h2&gt;&lt;p&gt;より確かな結論を得るための検証として、次の方法が考えられる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;サンプリングを使う条件でseedの値を変え、出力の違いを比較する。&lt;/li&gt;
&lt;li&gt;俳句のプロンプトについて、小さなタスクに分解し、音数・季語・句数を別々に評価する。&lt;/li&gt;
&lt;li&gt;日本語の俳句生成に適したモデルでも同じ条件を試し、モデル間の違いを比較する。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ローカルLLMでSpec Driven Developmentは、まだ難しかった</title><link>https://sonohen.net/posts/2026/02/14/</link><pubDate>Sat, 14 Feb 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/02/14/</guid><description>&lt;h2 id="tl-dr"&gt;TL; DR
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ローカルLLM（LM Studio） + AiderでSpec Driven Development（SDD）を試したが、実用には至らなかった&lt;/li&gt;
&lt;li&gt;14Bクラスのモデルでは推論性能が不足し、以下のような問題が頻発した。
&lt;ul&gt;
&lt;li&gt;仕様外のファイル生成&lt;/li&gt;
&lt;li&gt;過剰修正&lt;/li&gt;
&lt;li&gt;英語/日本語のコード再生成ループ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;一方で、より大きなモデルは メモリ制約（MacBook M3 / 24GB）で動かせない&lt;/li&gt;
&lt;li&gt;Deepseek系モデルでは、エンジンの設計上のトレードオフに直面した
&lt;ul&gt;
&lt;li&gt;MLX：OOMで即クラッシュ&lt;/li&gt;
&lt;li&gt;llama.cpp：OOM後も動き続けるが推論崩壊が発生&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;推論性能が低いほど、開発者側に高度な仕様記述スキルが要求される
&lt;ul&gt;
&lt;li&gt;ローカルLLMでSDDをするには、SDDが不要なほどの知識と熟練が必要&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Context Lengthは後から調整するものではなく、KV Cacheとメモリ量を踏まえた事前の設計判断が必須&lt;/li&gt;
&lt;li&gt;ローカルLLMは「クラウドLLMの安価な代替」ではなく、オンプレAI基盤としての設計・運用能力を要求される計算基盤&lt;/li&gt;
&lt;li&gt;結論としては、現時点の個人環境では、ローカルLLMで実用的なSDDを行うのは現実的ではない。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="背景"&gt;背景
&lt;/h2&gt;&lt;p&gt;昨今、生成AI(クラウドLLM)に渡したくない情報をローカルLLMで処理したいという要望がある。一方で、Claude CodeのようなクラウドLLMと比較すると、(ローカルLLMを動かす環境にもよるが)処理性能やパラメータの設計に難点がある。&lt;/p&gt;
&lt;p&gt;また、個人的に &lt;em&gt;Spec Driven Development&lt;/em&gt; （SDD）を試してみたいと思っていた。クラウドLLMを使えばそのまま実践できるが、実験を何度も繰り返すにはコストが気になる。&lt;/p&gt;
&lt;p&gt;そこで今回は、一般的に入手し易いMacBook Air M3を使用してローカルLLMでSDDを実践することを通じて、ローカルLLMの難点を体感すると同時に、ローカルLLMでSDDがどこまで実践できるのかを実験してみることにした。具体的には「LM StudioのOpenAI互換APIにAiderのバックエンドを向け、ローカルLLMでSDDを実行する」ということである。&lt;/p&gt;
&lt;p&gt;ちなみにここでいうSDDとは、AIに対して厳密な仕様書（プロンプト）を与えることで実装を自律的に行わせる開発手法を指している。&lt;/p&gt;
&lt;p&gt;予め申し上げるが、この記事はあくまでMacBook Air M3(24GB RAM)の環境でできたことをまとめたものであって、ローカルLLM全般や、他の環境での実用性を評価したものではない。&lt;/p&gt;
&lt;h3 id="環境"&gt;環境
&lt;/h3&gt;&lt;p&gt;主に使用した環境を以下に示す。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;マシン: MacBook Air M3&lt;/li&gt;
&lt;li&gt;メモリ: 24GB&lt;/li&gt;
&lt;li&gt;モデル: &lt;code&gt;qwen/qwen2.5-coder-14b&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;LM Studio: 0.4.2+2&lt;/li&gt;
&lt;li&gt;Aider: 0.82.3&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="実装対象"&gt;実装対象
&lt;/h2&gt;&lt;p&gt;Kotlin製のAndroidアプリ「Habit Tracker」を実装することにした。SSoT(Single Source of Truth)な情報源として仕様書を作成し、以下のような内容を記述した。可能な限りトークン消費を減らすため、実際の仕様書には英語で記述した。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;習慣を作成、更新、削除できる。&lt;/li&gt;
&lt;li&gt;習慣の継続状況を記録する。回数ではなく、その日に実行したかどうかを記録する。&lt;/li&gt;
&lt;li&gt;習慣を削除したあとも、過去の継続状況を確認できる。&lt;/li&gt;
&lt;li&gt;最初のMVPでは、習慣の作成、更新、削除だけを実装する。&lt;/li&gt;
&lt;li&gt;MVP範囲外の機能や、指示していない改善を追加しない。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また上記の他に、パッケージ名、Kotlinを使用すること、Minimum SDK、ソースコードとテストの配置先(ディレクトリツリー)を指定した。&lt;/p&gt;
&lt;h2 id="試行の記録qwenqwen25-coder-14b"&gt;試行の記録(&lt;code&gt;qwen/qwen2.5-coder-14b&lt;/code&gt;)
&lt;/h2&gt;&lt;p&gt;仕様書を渡して実装を依頼すると、主に3つの問題が発生した。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;指定したディレクトリ以外にファイルが生成される。&lt;/li&gt;
&lt;li&gt;指示にない画面の文言修正が続く。&lt;/li&gt;
&lt;li&gt;同じコードを繰り返し生成する。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;一つずつ説明する。&lt;/p&gt;
&lt;h3 id="指定したディレクトリ以外にファイルが生成される"&gt;指定したディレクトリ以外にファイルが生成される。
&lt;/h3&gt;&lt;p&gt;仕様書には、ソースコードの配置先を記載していたが、実際には意図しないディレクトリにファイルが生成された。よって、人間がレビューする際に、どのディレクトリにファイルが生成されたのかを確認する必要があり、LLM単独では実行可能なバイナリ(APKパッケージ)を作成することができなかった。&lt;/p&gt;
&lt;h3 id="指示にない画面の文言修正が続く"&gt;指示にない画面の文言修正が続く。
&lt;/h3&gt;&lt;p&gt;機能の追加やバグを改修するように指示をしたところ、それとは無関係である画面の文言修正を繰り返した。そもそも生成に時間がかかることに加え、人間のレビューの負荷が高くなるほか、AIの作業のモニタリングに非常に苦労した。&lt;/p&gt;
&lt;h3 id="同じコードを繰り返し生成する"&gt;同じコードを繰り返し生成する。
&lt;/h3&gt;&lt;p&gt;仕様書は英語で記述していたことから、推論、コード生成も英語で行われた。それはよいのだが、問題は英語による処理が終わったあとに、日本語でも推論、コード生成を行う挙動が見られた。つまり、画面上に色々と出力はされるものの、実装が先に進まない状態であった。&lt;/p&gt;
&lt;p&gt;これらの結果から、必ずしも「14Bクラスのモデルには実装能力が足りない」とまでは言えない。モデルの能力に加え、ローカルLLMのパラメータ設定やAiderとの組合せ、渡した情報量、仕様の曖昧さなど、様々な要因が絡んでいると思われる。今回は、そこまでの切り分けを行わず、安易にモデルの変更を試した。&lt;/p&gt;
&lt;h2 id="deepseekへの変更と長い出力での問題"&gt;DeepSeekへの変更と、長い出力での問題
&lt;/h2&gt;&lt;p&gt;別のモデルでも試してみるべく &lt;code&gt;DeepSeek R1 0528 Qwen 3 8B&lt;/code&gt;に切り替えた。ちなみにこの判断は、このモデルのサイズであれば、24GBのメモリに完全オフロードできるからである。&lt;/p&gt;
&lt;p&gt;また、今回は、仕様書に沿った実装がうまく進むか進まない理由がモデルにあることを特定することを目的とはしなかった。他にどのような課題が出るかを知りたいという興味がでてきたからである。そのため、今回は &lt;code&gt;qwen2.5-coder-14b&lt;/code&gt; のときと同じパラメータを使うということはしていない。&lt;/p&gt;
&lt;p&gt;ここで生じた問題点は以下の2点であった。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;MLXでは生成途中にエラーが発生した。&lt;/li&gt;
&lt;li&gt;llama.cppエンジンに切り替えたところ、生成が続いたが、推論内容が乱れた。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ちなみに、MLXやllama.cppエンジンというのは、LM Studioでモデルを動作させるときに使用するためのバックエンドエンジンのことである。&lt;/p&gt;
&lt;p&gt;一つずつ説明する。&lt;/p&gt;
&lt;h3 id="mlxでは生成途中にエラーが発生した"&gt;MLXでは生成途中にエラーが発生した。
&lt;/h3&gt;&lt;p&gt;MLXでは、メモリ確保に失敗すると例外が発生する。LM StudioのMLXバックエンドは、生成中の例外を捕捉すると、進行中のリクエストへエラーを通知し、生成処理を終了する&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Python&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;litellm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;APIConnectionError: APIConnectionError: OpenAIException &lt;span style="color:#f92672"&gt;-&lt;/span&gt; Error &lt;span style="color:#f92672"&gt;in&lt;/span&gt; iterating prediction stream: &lt;span style="color:#a6e22e"&gt;Exception&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Encountered fatal exception &lt;span style="color:#f92672"&gt;in&lt;/span&gt; the backend scheduler: Traceback (most recent call last):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; File &lt;span style="color:#e6db74"&gt;&amp;#34;.../mlx_engine/model_kit/batched_model_kit.py&amp;#34;&lt;/span&gt;, line &lt;span style="color:#ae81ff"&gt;216&lt;/span&gt;, &lt;span style="color:#f92672"&gt;in&lt;/span&gt; _generate_with_exception_handling
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_generate()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; File &lt;span style="color:#e6db74"&gt;&amp;#34;.../mlx_engine/model_kit/batched_model_kit.py&amp;#34;&lt;/span&gt;, line &lt;span style="color:#ae81ff"&gt;338&lt;/span&gt;, &lt;span style="color:#f92672"&gt;in&lt;/span&gt; _generate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; responses &lt;span style="color:#f92672"&gt;=&lt;/span&gt; batch_generator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;next()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;^^^^^^^^^^^^^^^^^^^^^^&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; File &lt;span style="color:#e6db74"&gt;&amp;#34;.../mlx_lm/generate.py&amp;#34;&lt;/span&gt;, line &lt;span style="color:#ae81ff"&gt;1266&lt;/span&gt;, &lt;span style="color:#f92672"&gt;in&lt;/span&gt; next
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_next()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;今回の場合、生成されたトークンが11,000を超えたあたりでクラッシュしている。&lt;/p&gt;
&lt;h3 id="llamacppエンジンに切り替えたところ生成が続いたが推論内容が乱れた"&gt;llama.cppエンジンに切り替えたところ、生成が続いたが、推論内容が乱れた。
&lt;/h3&gt;&lt;p&gt;次にクラッシュを回避するため、DeepseekをMLXフォーマットからGGUFフォーマットに変更し、&lt;code&gt;llama.cpp&lt;/code&gt;バックエンドに切り替えたところ、11,000トークンを超えても回答を生成するようにはなった。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;しかし、今度は &lt;strong&gt;推論崩壊&lt;/strong&gt; が発生した。&lt;code&gt;llama-cli&lt;/code&gt;はOOMが発生しても&lt;code&gt;ctx_pos&lt;/code&gt; / &lt;code&gt;n_past&lt;/code&gt;が進み続ける設計であり、初期化が保証されていないKV Cacheを文脈として使い続けるため、推論が崩壊しながら処理を続けてしまうのだ。&lt;/p&gt;
&lt;p&gt;これは、両者の良し悪しではなく、設計思想によるトレードオフである。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;この表現は正確ではない可能性がある。過去に、Out of Memoryを検出する処理に不具合があり、不正な状態で処理が続いた可能性がある。従って、設計上の違いというよりも、不具合に影響を受けていた可能性がある。&lt;/p&gt;
&lt;h2 id="試してわかったこと"&gt;試してわかったこと
&lt;/h2&gt;&lt;h3 id="仕様書を渡した後にも確認と軌道修正が必要だった"&gt;仕様書を渡した後にも、確認と軌道修正が必要だった
&lt;/h3&gt;&lt;p&gt;今回の仕様書には、MVPの範囲や禁止事項を記載した。それでも、ファイルの配置、画面文言、生成の繰り返しを人間が確認し、修正を促す必要があった。&lt;/p&gt;
&lt;p&gt;一方で、仕様書自体にも改善の余地はある。例えば「習慣を作成・更新・削除する」という要件だけでは、画面構成、入力項目、保存方法、完了とみなす条件までは決まらない。記載していない部分をどう実装するか、モデルに判断を委ねていたことになる。&lt;/p&gt;
&lt;p&gt;モデルの挙動と仕様の不足を分けて考えるためにも、実装してほしい内容と、確認する基準を具体化する必要があると感じた。仕様書の具体化にあたっては、Planモードを使用し、AIから見た仕様書の不明点をつめていく工程が必要になると思われる。&lt;/p&gt;
&lt;h3 id="小さな単位で依頼する方法を試したい"&gt;小さな単位で依頼する方法を試したい
&lt;/h3&gt;&lt;p&gt;今回のように実装が進まなくなった場合は、画面、ファイル、関数などの単位に依頼を分け、それぞれの結果を確認する方法が考えられる。&lt;/p&gt;
&lt;p&gt;ただし、今回の試行では、タスクを分割した場合に、どの程度改善するかまでは検証していない。次に試すなら、まず小さな変更を依頼し、指定したファイルだけが変更されるか、必要な機能が動作するかを確認したい。&lt;/p&gt;
&lt;h3 id="メモリ容量だけでは実行条件を決められない"&gt;メモリ容量だけでは実行条件を決められない
&lt;/h3&gt;&lt;p&gt;ローカルLLMを使う際は、モデルのパラメータ数だけでなく、量子化方式、コンテキスト長、生成する長さ、同時に動かすアプリケーションも考慮する必要がある。&lt;/p&gt;
&lt;p&gt;今回のMacBookはメモリ24GBで、Android StudioやChromeも使う環境だった。ただし、試行時の使用量を記録していなかったことから、本当にメモリ不足であったのかを断定することはできない。(恐らく、メモリが不足していたんだろうとは思われるが)&lt;/p&gt;
&lt;p&gt;コンテキスト長も、最初から大きく設定すればよいわけではない。必要な入力と出力が収まる設定から始め、メモリ使用量や生成結果を確認しながら調整する必要がある。&lt;/p&gt;
&lt;h3 id="ローカルllmでは推論環境の管理も作業になる"&gt;ローカルLLMでは、推論環境の管理も作業になる
&lt;/h3&gt;&lt;p&gt;今回はアプリの実装よりも、ローカルLLM環境の設定、調整に時間を要した。ローカルLLMを選ぶ際は、手元で動かせる利点とともに、この作業を引き受けられるかも考える必要があると感じる。&lt;/p&gt;
&lt;p&gt;業務利用であれば尚のことである。オンプレミスで生成AIを動作させる場合には、データの扱いに関する要件に加えて、必要な生成品質を維持するための検証・運用体制を考える必要がある。それに時間を使うことができない、あるいはそのための人材がいない場合には、クラウドLLMを第一に検討したほうがよいと考えられる。&lt;/p&gt;
&lt;h3 id="ローカルllmを使うにはオンプレミスのインフラ設計で求められるような設計を開発者に要求する"&gt;ローカルLLMを使うには、オンプレミスのインフラ設計で求められるような設計を開発者に要求する
&lt;/h3&gt;&lt;p&gt;今回最も印象に残ったのは、「ローカルLLMはクラウドLLMの手軽な代替ではない」という認識だ。ローカルLLMはマシンスペックさえあれば手軽に試せるという文脈で紹介されがちであるが、実際に使おうと思うとかなり難しい。しかし、クラウドで提供される生成AIであればインフラのことを意識しなくて済む。しかしローカルLLMでは、モデルの選定・量子化方式・推論エンジンの選択・Context Lengthとメモリの関係など、これらをオンプレミス環境のサーバ運用と同等の感覚で設計する必要がある。&lt;/p&gt;
&lt;p&gt;仕事では「セキュリティを要求する顧客にはオンプレの生成AIを提供すべきではないか」という議論が時たま起こるが、決してそんな単純な判断軸ではないと体感した。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;LM StudioとAiderを組み合わせ、ローカルLLMに仕様書からAndroidアプリを実装させようとした。しかし、今回の環境と依頼方法では、意図しない修正や生成の繰り返し、長い出力でのエラーに直面し、実用的に進められる状態には至らなかった。&lt;/p&gt;
&lt;p&gt;この経験から、ローカルLLMを使用する際には、少なくとも以下の点を考慮しながら、実用化に向けたトライエラーが必要になると考える。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;モデルの配布元、量子化方式、コンテキスト長、生成パラメータ&lt;/li&gt;
&lt;li&gt;入力と出力の長さ、実行時のメモリ使用量&lt;/li&gt;
&lt;li&gt;依頼した作業と、その完了を判断する基準&lt;/li&gt;
&lt;li&gt;発生したエラーと、条件を変えたときの結果&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、それらによって設計したローカルLLMを使用する際は、その特性によってタスクを実行可能な単位まで落とすなども検討する必要がある。&lt;/p&gt;
&lt;h2 id="次の記事"&gt;次の記事
&lt;/h2&gt;&lt;p&gt;「&lt;a class="link" href="https://sonohen.net/posts/2026/02/1501/" &gt;ローカルLLMのtemperatureとseedが生成品質に与える影響と『推論言語』の関係&lt;/a&gt;」 では、生成パラメータを変えながら、コードや俳句の出力を観察した記録をまとめている。&lt;/p&gt;</description></item><item><title>Slackと連携するチャットボットをOpenSearch + Bedrockで構築するまでの設計変遷と気づき</title><link>https://sonohen.net/posts/2026/02/08/</link><pubDate>Sun, 08 Feb 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/02/08/</guid><description>&lt;h2 id="きっかけ"&gt;きっかけ
&lt;/h2&gt;&lt;p&gt;社内で周囲の人がGPU搭載のマシンでLLMを動かしているのを見ていた。それ自体は良いのだが、「今時サーバレスだろjk」という思いもあり（当時Chromebook使ってましたし）、オンプレ前提の風潮に違和感を覚えていた。&lt;/p&gt;
&lt;p&gt;実用性は度外視して、SLM（Small Language Model）であればAWS Lambdaの制約範囲内&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;で動作するのではないかと思った。ただ動かすだけでは面白くないので、当時使っていた「ひとりSlack」から使えるチャットボットを作ることにした。Slack Incoming Web-hook APIを使えば、複雑な認証なしで統合できることも決め手になった。&lt;/p&gt;
&lt;h2 id="但し書き"&gt;但し書き
&lt;/h2&gt;&lt;p&gt;この記事は、2024年頃に検証した時のメモをブログに書き起こしたものです。一部、アップデートがかかっている箇所もあります。&lt;/p&gt;
&lt;h2 id="試行錯誤の記録"&gt;試行錯誤の記録
&lt;/h2&gt;&lt;h3 id="初期の設計lambda--ecrでslmを動かす"&gt;初期の設計：Lambda + ECRでSLMを動かす
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://sonohen.net/posts/2026/02/08/images/20260208113342.png"
	width="4248"
	height="2092"
	loading="lazy"
	
		alt="初期の設計"
	
	
		class="gallery-image" 
		data-flex-grow="203"
		data-flex-basis="487px"
	
&gt;&lt;/p&gt;
&lt;p&gt;最初の設計では、SLM（llama-cli）をECRに格納したコンテナイメージに入れ、Lambda Container Image機能を使って10GBのメモリ制約内で動作させる構成にした。SlackのWeb-hook関連のシークレットはAWS Secrets Managerに格納し、Lambdaから読み込むことでセキュアな構成にしている。&lt;/p&gt;
&lt;p&gt;しかし、&lt;code&gt;llama-cli&lt;/code&gt;の呼び出し時にCore Dumpが発生した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR stderr: /bin/bash: line 1: 25 Illegal instruction (core dumped)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/packs/src/llama.cpp/build/bin/llama-cli -m /packs/models-gemma-2b-it-q4_0.gguf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;今思えば、&lt;code&gt;llama-cli&lt;/code&gt;のバイナリとLambdaの命令セット（CPU命令セット）の相違が原因ではないか？と思われるが、当時は原因の特定に至らなかった。（2週間くらい頭を悩ませた記憶）&lt;/p&gt;
&lt;p&gt;原因の特定に時間がかかりそうであったため、Bedrockを利用する方針に転換した。ただし、Bedrock単独では面白みに欠けると思われたため、DynamoDBを使ったRAG構成へと発展させることにした。&lt;/p&gt;
&lt;h3 id="2回目の設計dynamodbでragを構築する"&gt;2回目の設計：DynamoDBでRAGを構築する←？
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://sonohen.net/posts/2026/02/08/images/20260208114721.png"
	width="4848"
	height="2088"
	loading="lazy"
	
		alt="2回目の設計"
	
	
		class="gallery-image" 
		data-flex-grow="232"
		data-flex-basis="557px"
	
&gt;&lt;/p&gt;
&lt;p&gt;Bedrockを採用し、エンベディングにはTitan Embeddingsモデルを使うことにした。Bedrockだけでは面白みに欠けるため、DynamoDBとOpenSearch Serviceのzero-ETL統合を読んで、DynamoDBを基盤としたRAGを構築することにした。&lt;/p&gt;
&lt;blockquote&gt;
 &lt;p&gt;&lt;p&gt;この zero-ETL 統合により、&lt;a class="link" href="https://aws.amazon.com/dynamodb" target="_blank" rel="noopener"
 &gt;Amazon DynamoDB&lt;/a&gt; を利用するお客様は、全文検索、あいまい検索、オートコンプリート、機械学習 (ML) 用のベクトル検索など、&lt;a class="link" href="https://aws.amazon.com/opensearch-service/" target="_blank" rel="noopener"
 &gt;Amazon OpenSearch Service&lt;/a&gt; の強力な検索機能を使用して、ユーザーエンゲージメントを高め、アプリケーションに対する満足度を向上させる新しいエクスペリエンスを提供できるようになりました。&lt;/p&gt;
&lt;p&gt;この zero-ETL 統合では、&lt;a class="link" href="https://aws.amazon.com/opensearch-service/features/ingestion/" target="_blank" rel="noopener"
 &gt;Amazon OpenSearch Ingestion&lt;/a&gt; を使用して、Amazon DynamoDB と Amazon OpenSearch Serviceの間でデータを同期します。データを同期する必要がある DynamoDB テーブルを選択すると、Amazon OpenSearch Ingestion は、データが使用可能になってから数秒以内に Amazon OpenSearch マネージドクラスターまたはサーバーレスコレクションにデータを同期します。&lt;/p&gt;
&lt;p&gt;また、インデックスマッピングテンプレートを指定して、Amazon DynamoDB フィールドが Amazon OpenSearch Service インデックスの正しいフィールドにマップされるようにすることもできます。また、複数の DynamoDB テーブルのデータを 1 つの Amazon OpenSearch Service マネージドクラスターまたはサーバーレスコレクションに同期して、複数のアプリケーションにわたる総合的なインサイトを得ることができます。&lt;/p&gt;
&lt;/p&gt;&lt;span class="cite"&gt;&lt;span&gt;― &lt;/span&gt;&lt;span&gt;Shuhei Fukami, &lt;/span&gt;&lt;a href="https://aws.amazon.com/jp/blogs/news/amazon-dynamodb-zero-etl-integration-with-amazon-opensearch-service-is-now-generally-available/"&gt;&lt;cite&gt;Amazon DynamoDB の Amazon OpenSearch Service とのゼロ ETL 統合が利用可能になりました&lt;/cite&gt;&lt;/a&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;しかし、ここで（自身の読解力の）基本的な問題に気がついた。DynamoDBはKey-ValueのNoSQLデータベースであり、単独ではベクトル検索に対応していない。RAGに必須のセマンティック検索を実現するためには、ベクトルDBの機能が必要である。この記事に明確に書いてあるのは、OpenSearchとの統合をすることで、ベクトル検索などができるようになると記載されているが、その部分を見落としていたのである。（ここでまた1週間くらい時間を使った）&lt;/p&gt;
&lt;p&gt;よって、zero-ETLを利用してOpenSearch Serviceとの統合が必要という結論に至り、設計を見直した。&lt;/p&gt;
&lt;h3 id="3回目の設計opensearch-serviceを中核に据える"&gt;3回目の設計：OpenSearch Serviceを中核に据える
&lt;/h3&gt;&lt;p&gt;3回目の設計では、OpenSearch Ingestionを使いDynamoDBとOpenSearch Serviceをzero-ETLで統合した。テキストエンベディングとセマンティック検索はBedrockに集約し、サービスごとの役割分担を明確にすることができた。&lt;/p&gt;
&lt;p&gt;実際にSlackから動作確認を行うと、ベクトル検索が機能していることが確認できた。大したデータを登録していないため回答の精度はまだまだだが、DynamoDBに登録したデータを元に回答を生成しようとしていることは確認できた。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2026/02/08/images/20260208112211.png"
	width="1944"
	height="760"
	loading="lazy"
	
		alt="動作イメージ。72トークンで回答を作っていること、OpenSearchからスコア0.34のデータを引っ張り、それを利用して回答を生成していることがわかる"
	
	
		class="gallery-image" 
		data-flex-grow="255"
		data-flex-basis="613px"
	
&gt;&lt;/p&gt;
&lt;h4 id="出力テキスト"&gt;出力テキスト
&lt;/h4&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;JSON&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;query&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;@AWS Bedrock こんにちは&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;prompt&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ユーザーからの質問: @AWS Bedrock こんにちは\n\n関連する情報：\n1. この文章はDynamoDBに登録するサンプルデータです。DynamoDBはAmazon Web Servicesが提供する完全マネージド型のNoSQLデータベースであり、高速で柔軟なスキーマを特徴としています。この文章には200文字程度の内容が含まれています。サンプルとして登録される内容は、主に日本語のテキストデータを取り扱います。(スコア: 0.34)\n\nこれらの情報を基に、質問に回答してください。&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;answer&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;tokenCount&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;72&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;outputText&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;\n200文字程度の内容が含まれています。サンプルとして登録される内容は、主に日本語のテキストデータを取り扱います。\nこの文章はDynamoDBに登録するサンプルデータです。DynamoDBはAmazon Web Servicesが提供する完全マネージド型のNoSQLデータベースであり、高速で柔軟なスキーマを特徴としています。&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;completionReason&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;FINISH&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ただし、この構成にはDynamoDBを不必要に残してしまっている点がある。DynamoDBストリームの検証をしたかったので問題はないが、OpenSearch単独で使う方法も検証する必要がありそうである。&lt;/p&gt;
&lt;h2 id="今回の検証で得たもの"&gt;今回の検証で得たもの
&lt;/h2&gt;&lt;h3 id="ragの本質は回答精度の向上ではない"&gt;RAGの本質は「回答精度の向上」ではない
&lt;/h3&gt;&lt;p&gt;今回の構築を通じて、RAGに対する理解が変わった。&lt;/p&gt;
&lt;p&gt;RAGは、生成AIの回答精度を向上させるものではなく、生成AIが利用できる情報に制限を加えるものと理解した方が良い。これにより、回答が一般論に限定されたり、ハルシネーションによる影響範囲を制御できる。&lt;/p&gt;
&lt;p&gt;生成AIは既に大量の情報を持っている。そして、我々だけが持つデータも、徐々に活用できるようになってきている。だからこそ重要なのは、「どこまでをAIに考えさせ、どこからが人間がルールに基づいて判断するのか」を設計する仕組みである。&lt;/p&gt;
&lt;p&gt;機械的に判断するもの、つまりルールが厳密に定義できるものには、生成AIを使ってはならない。この線引きの設計こそが、RAGの構築においても中心的な課題になる。&lt;/p&gt;
&lt;h3 id="opensearchを中核に据えることの本質的なメリット"&gt;OpenSearchを中核に据えることの本質的なメリット
&lt;/h3&gt;&lt;p&gt;Bedrock単独でもRAG機能は「Amazon Bedrock Knowledge Bases」として統合されている。では、なぜあえてOpenSearch Serviceを中核に据えたのか。&lt;/p&gt;
&lt;p&gt;構築し、中の仕組みを理解してようやく分かりつつあるので結果論だが、AI技術者とアプリケーション開発者の責任境界を明確に分離できることにある。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2026/02/08/images/20260208122214.png"
	width="4644"
	height="3080"
	loading="lazy"
	
		alt="OpenSearchの中の仕組み"
	
	
		class="gallery-image" 
		data-flex-grow="150"
		data-flex-basis="361px"
	
&gt;&lt;/p&gt;
&lt;p&gt;OpenSearch ServiceはConnectorを介してBedrockと統合している。この構成では、以下のように役割を分けることができる。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI技術者の役割：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OpenSearch ServiceとBedrockの統合&lt;/li&gt;
&lt;li&gt;利用するモデルの選定&lt;/li&gt;
&lt;li&gt;内部で動作するPipeline（検索、RAG、推論フロー）の設計&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;アプリケーション開発者の役割：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;データの登録&lt;/li&gt;
&lt;li&gt;推論・検索結果の取得&lt;/li&gt;
&lt;li&gt;アプリケーションロジックの実装&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bedrock単独構成では、この責任境界を明確に引くことが難しい。これはBedrockが悪いという話ではなく、「アプリケーションとAIを一体で設計する思想」に近いためである。OpenSearchを挟むことで、AI側とアプリケーション側がそれぞれ独立して開発・改善できるレイヤ構造が実現できるのである。&lt;/p&gt;
&lt;h2 id="ユースケースの例"&gt;ユースケースの例
&lt;/h2&gt;&lt;p&gt;今回の構成を応用したユースケースを2つ紹介する。&lt;/p&gt;
&lt;h3 id="faqチャットボット"&gt;FAQチャットボット
&lt;/h3&gt;&lt;p&gt;社外に公開しているFAQの情報をクロールし、DynamoDBに格納する。DynamoDB Streams経由でOpenSearch Ingestionのエンベディング処理を通し、OpenSearch Serviceにデータを流す。API GatewayからLambda関数を呼び出し、Search Pipelineを介してOpenSearch/Bedrockで処理したデータをクライアントに返却する構成である。&lt;/p&gt;
&lt;p&gt;ポイントは、DynamoDBの中で &lt;code&gt;role&lt;/code&gt; のようなキー属性を定義しておくことで、Ingest Pipelineでフィルタをかけ、indexに保存するデータを制御できることである。この構成であれば、複数のデータソースを権限に応じて同様のインタフェースで使い回すことができる。&lt;/p&gt;
&lt;h3 id="ログ解析とメディエーション"&gt;ログ解析とメディエーション
&lt;/h3&gt;&lt;p&gt;WebサーバのアクセスログをCloudWatch Logsに集約し、Kinesis Data StreamsでDynamoDBに転送する。CloudWatch Contributor InsightsでHTTPレスポンスコードがエラーのトップ10を分析し、特に対応が必要なものをLambda経由でOpenSearch/Bedrockにエラーメッセージと原因を解析させる。&lt;/p&gt;
&lt;p&gt;ここでも設計のポイントは明確である。機械的に分析しなければいけないもの（エラーのトップ10の抽出）と、AIに分析させなければいけないもの（エラー原因の推論）を分け、AIが扱うデータの境界線をシステム上も運用上も明確にしている。AIが分析すべきデータを絞ることで、トークンの無駄遣いによるコスト増やハルシネーションの影響範囲を抑えることができる。&lt;/p&gt;
&lt;h2 id="生成ai時代に求められる構造設計能力と試行錯誤の重要性"&gt;生成AI時代に求められる「構造設計能力」と試行錯誤の重要性
&lt;/h2&gt;&lt;p&gt;今回の構築を通じて、改めて感じたことがある。&lt;/p&gt;
&lt;p&gt;生成AIは、人間の「構造設計能力」を強く要求する。人間が変数、あるいはデータや処理の範囲の設計を担い、その範囲での処理や思考はAIが行うという役割分担は機能する。しかし逆に言えば、人間がすべきこと、つまり人間が持つ考えに対しては、AIを介入させてはならないのである。&lt;/p&gt;
&lt;p&gt;また、机上の設計と実装は容易に分離する。机上の設計で動くと思っていても、実際に動かしてみるとCore Dumpしたり、そもそもAWSサービスをきちんと理解していなかったりすることで足元を掬われる。特にAWSなど日進月歩のサービスを使ったシステムでは、信頼できる情報を調べた上でPoCを必ず実施することが重要である。&lt;/p&gt;
&lt;p&gt;仮説を素早く検証し、実現可能な構成を見極めるスキルが、これからの時代には不可欠になる。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;Slack連携のRAGチャットボットをAWS上に構築する過程で、3回の設計見直しを行った。Lambda + ECRでのSLM実行、DynamoDBベースのRAG、そしてOpenSearch Serviceを中核としたRAGという変遷を経て、以下の知見を得た。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RAGは「回答精度の向上」ではなく「AIが利用できる情報の制御」と理解すべきである&lt;/li&gt;
&lt;li&gt;OpenSearchを中核に据えることで、AI技術者とアプリケーション開発者の責任境界を明確に分離できる&lt;/li&gt;
&lt;li&gt;机上の設計と実装は容易に乖離するため、PoCの実施が不可欠である&lt;/li&gt;
&lt;li&gt;生成AI時代において、人間に求められるのは「どこまでをAIに任せ、どこからを人間が判断するのか」を設計する構造設計能力である。つまり、「何をAIに渡さないか」を決める能力でもある。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今後の課題として、ECRでllama.cppが動作しなかった原因（CPU命令セットの相違）の検証と、SageMakerとの比較（開発者の責任境界の設け方の違い）を進めていく予定である。&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;メモリ10GB、エフェメラルストレージ10GB、上限処理時間15分&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>GitHub Pagesに独自ドメインを設定する方法（ムームードメイン + Hugo）</title><link>https://sonohen.net/posts/2026/02/07/</link><pubDate>Sat, 07 Feb 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/02/07/</guid><description>&lt;p&gt;GitHub Pagesでブログを公開していると、&lt;code&gt;sonohen.github.io&lt;/code&gt;のようなデフォルトのドメインではなく、独自ドメインでアクセスしたくなる。今回、ムームードメインで取得したドメインをGitHub Pagesに設定したので、その手順と遭遇したトラブルについてまとめる。&lt;/p&gt;
&lt;h2 id="全体の流れ"&gt;全体の流れ
&lt;/h2&gt;&lt;p&gt;独自ドメインの設定は、大きく以下の5つのステップで行う。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ムームードメインでのネームサーバ設定&lt;/li&gt;
&lt;li&gt;GitHub側でのドメイン認証&lt;/li&gt;
&lt;li&gt;CNAMEファイルの作成&lt;/li&gt;
&lt;li&gt;GitHub側でのDNS設定チェック&lt;/li&gt;
&lt;li&gt;HTTPS通信の強制&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;順番に説明していく。&lt;/p&gt;
&lt;h2 id="ムームードメインでのネームサーバ設定"&gt;ムームードメインでのネームサーバ設定
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://docs.github.com/ja/pages/configuring-a-custom-domain-for-your-github-pages-site/managing-a-custom-domain-for-your-github-pages-site#about-custom-domain-configuration" target="_blank" rel="noopener"
 &gt;GitHub公式ドキュメント&lt;/a&gt;を参考に、ムームーDNSで以下のレコードを設定する。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;サブドメイン&lt;/th&gt;
 &lt;th&gt;種別&lt;/th&gt;
 &lt;th&gt;内容&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;-&lt;/td&gt;
 &lt;td&gt;A&lt;/td&gt;
 &lt;td&gt;185.199.108.153&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;-&lt;/td&gt;
 &lt;td&gt;A&lt;/td&gt;
 &lt;td&gt;185.199.109.153&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;-&lt;/td&gt;
 &lt;td&gt;A&lt;/td&gt;
 &lt;td&gt;185.199.110.153&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;-&lt;/td&gt;
 &lt;td&gt;A&lt;/td&gt;
 &lt;td&gt;185.199.111.153&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;www&lt;/td&gt;
 &lt;td&gt;CNAME&lt;/td&gt;
 &lt;td&gt;sonohen.github.io&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Aレコード4つはApexドメイン（&lt;code&gt;sonohen.net&lt;/code&gt;）をGitHub PagesのIPアドレスに向けるためのもので、CNAMEレコードは&lt;code&gt;www&lt;/code&gt;サブドメインをGitHub Pagesに向けるためのものである。&lt;/p&gt;
&lt;h3 id="確認方法"&gt;確認方法
&lt;/h3&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% dig www.sonohen.net&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.10.6 &amp;lt;&amp;lt;&amp;gt;&amp;gt; sonohen.net
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; global options: +cmd
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; Got answer:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 46977
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; OPT PSEUDOSECTION:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;; EDNS: version: 0, flags:; udp: 512
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; QUESTION SECTION:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;sonohen.net. IN A
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; ANSWER SECTION:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sonohen.net. 3367 IN A 185.199.109.153
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sonohen.net. 3367 IN A 185.199.111.153
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sonohen.net. 3367 IN A 185.199.108.153
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sonohen.net. 3367 IN A 185.199.110.153
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; Query time: 19 msec
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; SERVER: 2400:4051:4682:c200:32be:3bff:fe4d:9964#53(2400:4051:4682:c200:32be:3bff:fe4d:9964)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; WHEN: Sat Feb 07 22:47:33 JST 2026
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; MSG SIZE  rcvd: 104&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="github側でのドメイン認証"&gt;GitHub側でのドメイン認証
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;GitHub &amp;gt; Profile &amp;gt; Code, planning and automation &amp;gt; Pages &amp;gt; Add a domain&lt;/code&gt;から、ドメインの認証を行う。指定されたTXTレコードをムームーDNSに登録し、認証を通す。&lt;/p&gt;
&lt;p&gt;この認証が行われないと、後続のDNSレコードチェックが失敗するため、必ず先に済ませておく。&lt;/p&gt;
&lt;h2 id="cnameファイルの作成"&gt;CNAMEファイルの作成
&lt;/h2&gt;&lt;p&gt;GitHub Pagesが独自ドメインを認識するために、CNAMEファイルをリポジトリに配置する必要がある。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;www.sonohen.net&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Hugoで&lt;code&gt;stack&lt;/code&gt;テーマを使っている場合は、&lt;code&gt;themes/stack/static/CNAME&lt;/code&gt;に配置する。こうすることで、ビルド時に公開ディレクトリのルートにCNAMEファイルが生成される。&lt;/p&gt;
&lt;h2 id="github側でのdns設定チェック"&gt;GitHub側でのDNS設定チェック
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;リポジトリ &amp;gt; Settings &amp;gt; Code and automation &amp;gt; Pages &amp;gt; Custom domain&lt;/code&gt;に独自ドメインを入力すると、GitHubがDNS設定をチェックしてくれる。&lt;/p&gt;
&lt;p&gt;このチェックが通るためには、事前に以下の3つが完了している必要がある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ネームサーバにA、TXT、CNAMEレコードが追加されていること&lt;/li&gt;
&lt;li&gt;CNAMEファイルが公開され、外部からアクセス可能であること&lt;/li&gt;
&lt;li&gt;GitHubでドメイン認証が完了していること&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="https通信の強制"&gt;HTTPS通信の強制
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;リポジトリ &amp;gt; Settings &amp;gt; Code and automation &amp;gt; Pages &amp;gt; Enforce HTTPS&lt;/code&gt;にチェックを入れることで、HTTP通信が無効になり、HTTPS通信が強制される。&lt;/p&gt;
&lt;h2 id="ハマったポイント"&gt;ハマったポイント
&lt;/h2&gt;&lt;p&gt;設定自体はシンプルだが、2つのトラブルに遭遇した。&lt;/p&gt;
&lt;h3 id="ドメイン認証が通らない"&gt;ドメイン認証が通らない
&lt;/h3&gt;&lt;p&gt;ムームーDNSでTXTレコードを作成する際、ホスト名に&lt;code&gt;_github-pages-challenge-sonohen.sonohen.net&lt;/code&gt;と入力していた。しかし、ムームーDNSでは&lt;code&gt;.sonohen.net&lt;/code&gt;が自動的に付与されるため、実際に作成されたホスト名は&lt;code&gt;_github-pages-challenge-sonohen.sonohen.net.sonohen.net&lt;/code&gt;になっていた。&lt;/p&gt;
&lt;p&gt;ホスト名を&lt;code&gt;_github-pages-challenge-sonohen&lt;/code&gt;に修正することで解決した。&lt;/p&gt;
&lt;h4 id="確認方法-1"&gt;確認方法
&lt;/h4&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% dig _github-pages-challenge-sonohen.sonohen.net +nostats +nocomments +nocmd TXT&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.10.6 &amp;lt;&amp;lt;&amp;gt;&amp;gt; _github-pages-challenge-sonohen.sonohen.net +nostats +nocomments +nocmd TXT
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;; global options: +cmd
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;;_github-pages-challenge-sonohen.sonohen.net. IN TXT
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;_github-pages-challenge-sonohen.sonohen.net. 3541 IN TXT &amp;#34;ひみつ（でもないが）&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="dnsチェックが通らない"&gt;DNSチェックが通らない
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Custom domain&lt;/code&gt;の認証が通らなかった原因は、GitHubが&lt;code&gt;http://www.sonohen.net/CNAME&lt;/code&gt;にアクセスできなかったためだった。&lt;/p&gt;
&lt;p&gt;CNAMEファイルには&lt;code&gt;www.sonohen.net&lt;/code&gt;を記載しておく必要があり、かつ外部からアクセス可能でなければならない。また、DNSチェックが通っていない時点ではHTTPS通信ができないため、HTTPでアクセスされる点にも注意が必要である。&lt;/p&gt;
&lt;p&gt;対処として、以下の手順を踏んだ。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;CNAMEファイルを作成し、&lt;code&gt;static/CNAME&lt;/code&gt;に配置&lt;/li&gt;
&lt;li&gt;サイトをリビルド&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://www.sonohen.net/CNAME&lt;/code&gt;にアクセスできることを確認&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;GitHub Pagesへの独自ドメイン設定は、DNS設定・ドメイン認証・CNAMEファイル配置・DNSチェック・HTTPS強制の5ステップで完了する。特にムームーDNSでは、ホスト名にドメインが自動付与される仕様に注意が必要だった。&lt;/p&gt;</description></item><item><title>Zettelkastenで管理する情報は何で、どう管理すべきなのか</title><link>https://sonohen.net/posts/2026/01/31/</link><pubDate>Sat, 31 Jan 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/01/31/</guid><description>&lt;p&gt;Zettelkastenに、何でもかんでも入れるべきではないという記事を書いた。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="../../01/25/" &gt;Zettelkastenを機能させ、また形骸化させないために、何でもかんでも入れるべきではない。&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;では、どのような情報を入れるべきなのか。この記事では、3つの論点に沿って考えたいと思う。&lt;/p&gt;
&lt;h2 id="全ての情報を管理してはいけない"&gt;全ての情報を管理してはいけない
&lt;/h2&gt;&lt;p&gt;まず「何でも出来る」と聞いて、皆さんが思い浮かべるものの特徴はなんであろうか。私は「帯に短し、襷に長し」という特徴を思い浮かべる。&lt;/p&gt;
&lt;p&gt;例えば、何でも出来るノートパソコンというのは、実に扱いに困る。グラフィックス性能が高く、ゲームができるとしよう。それでも、デスクトップ型のパソコンにグラフィックス性能は及ばず、また、バッテリーの持ちも悪くなる。何にしても中途半端になるのである。&lt;/p&gt;
&lt;p&gt;同じことがZettelkastenにも言える。「何でも入っている」というのは、情報を検索する際には便利であるが、こと知の再生産を考えると、扱いに困る。有象無象、玉石混合な情報からは、何かを生み出すことは難しいからである。&lt;/p&gt;
&lt;p&gt;例えば、十分に調査された内容と、街中を歩いていてふと閃いたアイデアが一つの場所にあるとして、それらを組み合わせて何かを生み出すことは難しい。アイデアを裏付ける情報があるのであれば、その情報と組み合わせて一定の見解を整理しておくことが重要であろう。&lt;/p&gt;
&lt;p&gt;このようにZettelkastenには、吟味や精査が「ある程度」完了した情報を入れておくことで、情報のレベルを整えておくことが重要なのである。&lt;/p&gt;
&lt;h2 id="自分の考え以外の情報を入れてはならない"&gt;自分の考え以外の情報を入れてはならない
&lt;/h2&gt;&lt;p&gt;Zettelkastenを「思考の再利用装置」と機能させるためには、中のノートが「自分の考えだけで構成されている」と信頼できる状態を維持し続けることが重要である。&lt;/p&gt;
&lt;p&gt;Zettelkastenの関連するノートとして、Fleeting Notes（ひらめきやアイデアのノート）、Literature Notes（文献ノート）がある。これらは、ZettelkastenのPermanent/ Structured/ Index Notesを生み出すための補助的な位置付けにある&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;。従って、走り書きや他者の意見をZettelkastenに入れるべきではない。&lt;/p&gt;
&lt;p&gt;ここまでに述べてきた2点は、「再利用時のノイズを減らし、思考を引き出しやすい状態を維持すること」が目的となる。&lt;/p&gt;
&lt;h2 id="ノートは見返されることを前提に作るべきである"&gt;ノートは、見返されることを前提に作るべきである
&lt;/h2&gt;&lt;p&gt;Zettelkastenの基本的な考え方は「ネットワーク型ノート」である。Webの世界と同じく、ノート間がキーワードによって繋げられ、ネットワークが作られる。関連を作り、辿り、新たな知を生み出していくという流れになる。&lt;/p&gt;
&lt;p&gt;このような仕組みにおいて、ノートは少なくとも3回は見直されると考えている。&lt;/p&gt;
&lt;p&gt;1回目は、ノートを作成するときである。まずは、ノートの内容を記述し、Structured Notesからリンクさせる。その上で、記述されている内容がAtomic Note（原子ノート）として成立しているか、再利用可能かという観点でチェックをし、必要に応じて見直す。&lt;/p&gt;
&lt;p&gt;2回目は、ノートが他のノートから新たにリンクされたときである。新たな関連が生まれ、また、別と思われていたノートから関連が辿られるといったときに、ノートの記載内容を見直すことがある。例えば、再利用性を高めるためにはある程度の抽象化が必要になるが、切り口を変えてみたときに抽象化が不十分であったりする場合には、ノートの再利用性を高めるために記述内容を見直す。&lt;/p&gt;
&lt;p&gt;3回目は、他のノートからリンクを辿って参照されたときである。何かしらの新しい、あるいは意外なつながりが生まれたときに見直される可能性が高い。また、共通項を抜き出した上で新たにノートを作り、関連を作っていくという場合である。&lt;/p&gt;
&lt;p&gt;こう考えると、ノートというのは見返されることを前提に作るべきなのである。つまりどういうことか。たとえいつのノートであっても、ノートに背景情報など理解に必要な情報を含め、理解可能な状態を維持し続けなければならないということである。&lt;/p&gt;
&lt;h2 id="では全てをネットワーク型ノートで管理したい場合にはどうすれば良いか"&gt;では、全てをネットワーク型ノートで管理したい場合にはどうすれば良いか
&lt;/h2&gt;&lt;p&gt;管理単位を厳密に分けることを推奨したい。例えば、私の場合はZettelkastenとLiterature NotesをObsidianで運用しているが、それぞれVaultを分割している。&lt;/p&gt;
&lt;p&gt;ObsidianはVault間のリンクをサポートしているため、Zettelkasten側からLiterature Noteにリンクを貼り、「自分の考えと文献」を分離しながら運用をしている。これにより、Zettelkastenの独立性は守られ、ノイズトなる情報は入り込まなくなる。また、Obsidianが持つネットワーク型ノートの利点を享受することもできるのだ。&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://jmatsuzaki.com/archives/28172" target="_blank" rel="noopener"
 &gt;Zettelkasten（ツェッテルカステン）で使うノートの種類と構成まとめ&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Zettelkastenを機能させ、また形骸化させないために、何でもかんでも入れるべきではない。</title><link>https://sonohen.net/posts/2026/01/25/</link><pubDate>Wed, 21 Jan 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/01/25/</guid><description>&lt;p&gt;日々接する情報のうち「これは」という情報は、Zettelkastenに入れている。自分が知っていること、記録していること（= 既知の情報）を組み合わせたり、文脈の転換を行なったりすることで、新たな視点や価値を生みだす活動（これを知的生産活動といっている）に興味を持っている。その過程を支える実践的な方法としてZettelkastenが有効であると考え、今、試行錯誤しているところである。&lt;/p&gt;
&lt;h2 id="zettelkastenの仕組みはネットワーク型ノートで実装すべきである"&gt;Zettelkastenの仕組みは、ネットワーク型ノートで実装すべきである
&lt;/h2&gt;&lt;p&gt;Zettelkastenに似た仕組みとして、京大式カード（&lt;a class="link" href="https://www.amazon.co.jp/dp/4004150930" target="_blank" rel="noopener"
 &gt;『知的生産の技術』（梅棹）&lt;/a&gt;）がある。&lt;/p&gt;
&lt;p&gt;詳しい説明は別の記事に譲るとして、これらに共通するのは、「原子的（Atomic）に書かれたノートや文脈の組み合わせを変えることで、新たな視点や価値を創造できることを目指している。」点にあると考えている。この文脈においては、ObsidianやScrapboxといった、いわゆる「ネットワーク型ノート」を使うことが望ましいと考えている。トップダウン型ノートでは実現が難しい。&lt;/p&gt;
&lt;h2 id="ネットワーク型ノートを使うメリットは知識の再構成によって新たな価値を創造できる点にある"&gt;ネットワーク型ノートを使うメリットは、知識の再構成によって新たな価値を創造できる点にある
&lt;/h2&gt;&lt;p&gt;では、ネットワーク型ノートを使うメリットはなんだろうか。&lt;/p&gt;
&lt;p&gt;それは、すべてのノートがリンクで繋がっており、また、それぞれのノートが原子的（Atomic）な単位で書かれているが故に再利用可能であることだと考えている。ノートには、複数のポイントは書かれず、そのノート自体がZettelkastenにおける部品である。&lt;/p&gt;
&lt;p&gt;例えば、レゴを思い出して欲しい。レゴは、部品であるブロックを組み合わせ、船や城などを作り上げることができる。これと同じことがネットワーク型ノートにも言えるのである。ノートの組み合わせによって、船でも城でも作り上げることができる。すなわち、知識を蓄積するだけでなく、再構成することによって新たな価値を創造できる点に、ネットワーク型ノートの本質的なメリットがあると言える。&lt;/p&gt;
&lt;h2 id="再構成に必要な条件は2つある"&gt;再構成に必要な条件は2つある
&lt;/h2&gt;&lt;p&gt;そこで問題になるのが、再構成をするために必要な条件とは何かである。私は、以下の2つの条件があると考えている。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Zettelkastenの中ですべての情報を管理してはいけない&lt;/li&gt;
&lt;li&gt;他者の情報（本の書き抜きや生成AIの生成物等）を含めてはいけない&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;まず「Zettelkastenの中ですべての情報を管理してはいけない」である。これは部屋の整理と同じである。有象無象の情報が混在してしまうと、再構成するにあたりどの情報があるのか、どれを使って良いのかが分からなくなってしまう。Zettelkastenの中には考えや経験など、あくまで自分の情報を入れておくことが重要なのである。&lt;/p&gt;
&lt;p&gt;次に「他者の情報（本の書き抜きや生成AIの生成物等）を含めてはいけない」である。私は当初、「生成AIが探してきた文献や文章」をZettelkastenの中に入れてしまっていた。これは「自分の意見や主張を裏付ける情報がZettelkastenの中に存在する」という点で非常に便利なように思えたが、そのうち、問題が徐々に明らかになっていった。例えば、1つのノートに複数のテーマが書かれていたり、非体系的なタグが付与されてしまっていたのである。つまり、Zettelkastenの中身はノイズだらけで、検索可能性も落ちてしまったのである。&lt;/p&gt;
&lt;p&gt;その後、私が取った手段は悪手であった。何をしたかというと、（その時に使っていたClaude Codeの）精度を高めようとしたのである。&lt;/p&gt;
&lt;p&gt;例えば、スキルを使ってガチガチに固めたルールでノートを作成させたり、サブエージェントを使ってノートの中身をレビューさせるなど、本来論的にはすべきではないところに時間と労力を割いた。その結果、何が起こったかというと、Claude Codeの利用量制限には引っかかり、出来上がったノートは多少マシになったものの、結果的に「他者の意見が入っている」という点は何ら改善できなかった。&lt;/p&gt;
&lt;p&gt;今は考えを改め、Zettelkastenには自分の考えしか入れておらず、心の平穏は保たれている。&lt;/p&gt;
&lt;h2 id="情報の出所と活用方法は厳密に管理すべきである"&gt;情報の出所と活用方法は、厳密に管理すべきである
&lt;/h2&gt;&lt;p&gt;こうして考えてみると、何か特定のテーマの論点を整理したり、文献の検索までをAIにやってもらうのは結構なことだとは思う。また、Zettelkastenの中身を検索して、思いもつかないようなインサイトを提示してもらうのも良いだろう。&lt;/p&gt;
&lt;p&gt;しかし、AIにノートを作成・校正させたり、メタデータ（タグなど）や構造を操作させてはならないと強く実感した。これをしてしまうと、それらのノートがノイズになってしまい、知的生産活動ができなくなってしまう。&lt;/p&gt;
&lt;p&gt;SNSを見ていると、個人の知的ノートと生成AI（Claude CodeやAntigravityがホットな話題のようだ）を組み合わせてコンテンツを量産するという記事、あるいは情報商材が出回っており、カオスな状態になっていると感じる。&lt;/p&gt;
&lt;p&gt;私も、こうした仕組みを試した結果をnoteに書いたのだが、実際にはその仕組みは機能しないと思っている。なぜなら、これを本当の意味で実現しようと思うと、相応の設計能力、それに沿った運用が求められるからである。それができる人が、果たしてどれだけいるだろうか。できなければ、何もない状態からAIにコンテンツを作らせるのと何ら変わらない結果となってしまうのは火を見るよりも明らかである。&lt;/p&gt;
&lt;p&gt;すなわち、例え生成AIが自由に使えるようになったとはいえ、それを使った知的生産活動には、AIの使い方だけではない「知識」の高度な運用能力が引き続き求められている点に留意する必要がある。&lt;/p&gt;
&lt;h2 id="参考記事"&gt;参考記事
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="../../../2025/03/24/" &gt;この3ヶ月で得た、仕事におけるAI活用と、人間の役割に関する重要な気づき&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>読み放題よりも、Kindle Unlimitedの本当の価値は別にあった</title><link>https://sonohen.net/posts/2026/01/21/</link><pubDate>Wed, 21 Jan 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/01/21/</guid><description>&lt;p&gt;正直に言うと、Kindle Unlimitedにはあまり期待していなかった。&lt;/p&gt;
&lt;p&gt;「月額980円で読み放題」と言われても、読みたい本なんてそんなにないだろうと思っていた。&lt;/p&gt;
&lt;p&gt;ところが、しばらく使ってみて気づいた。&lt;/p&gt;
&lt;p&gt;Kindle Unlimitedの本当の価値は、「読み放題」ではない。それは、自分の中にあった学びの心理的ハードルを壊してくれたことだった。&lt;/p&gt;
&lt;h2 id="同じテーマを複数の視点で学ぶことの重要性"&gt;同じテーマを複数の視点で学ぶことの重要性
&lt;/h2&gt;&lt;p&gt;あるテーマについて深く理解しようとする時、1冊の本だけでは不十分だと感じたことはないだろうか？&lt;/p&gt;
&lt;p&gt;例えば、行動経済学について学びたいとする。その時、以下のような異なる視点の本を読むと理解が深まる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NewsPicksのような実務寄りの本&lt;/li&gt;
&lt;li&gt;アマチュアが書いた入門書&lt;/li&gt;
&lt;li&gt;プロが書いた専門書&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こうした異なる水準や視点の3〜4冊を一気に読むことで、個別の事実ではなく、なんとなくの知識体系が頭の中に形成される。単一の本よりも、複数の視点を組み合わせることで、より堅牢で応用可能な理解が得られるのだ。&lt;/p&gt;
&lt;h2 id="でも複数冊買うのは心理的ハードルが高い"&gt;でも、複数冊買うのは心理的ハードルが高い
&lt;/h2&gt;&lt;p&gt;ここで問題がある。同じテーマの本を複数冊購入するのは、意外と心理的・経済的な障壁が高い。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;「もう1冊買っても本当に読むかな？」&lt;/li&gt;
&lt;li&gt;「さっき買った本で十分かもしれない」&lt;/li&gt;
&lt;li&gt;「3冊も買ったら数千円になる…」&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こうした躊躇が、学びの深さを制限してしまう。&lt;/p&gt;
&lt;h2 id="kindle-unlimitedが下げる学びの障壁"&gt;Kindle Unlimitedが下げる「学びの障壁」
&lt;/h2&gt;&lt;p&gt;ここでKindle Unlimitedの真価が発揮される。定額制なので、同じテーマの本を何冊読んでも追加コストがゼロだ。&lt;/p&gt;
&lt;p&gt;この「追加コストゼロ」という安心感が、複数の視点から学ぶという行動を後押ししてくれる。経済的な障壁がなくなることで、心理的な障壁も下がるのだ。&lt;/p&gt;
&lt;p&gt;「気になるテーマがあれば、関連する本を3〜4冊まとめて読んでみよう」という発想が自然と生まれる。これこそが、Kindle Unlimitedの本当の価値だ。&lt;/p&gt;
&lt;h2 id="さらに効率を上げる要約サービスとの組み合わせ"&gt;さらに効率を上げる：要約サービスとの組み合わせ
&lt;/h2&gt;&lt;p&gt;学びの効率をさらに高める方法がある。それは要約サービスを読書前の準備段階として活用することだ。&lt;/p&gt;
&lt;p&gt;具体的には以下の流れとなる。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;気になるテーマについて、Flierなどの要約サービスで概要を把握する&lt;/li&gt;
&lt;li&gt;基礎的な枠組みができた状態で、Kindle Unlimitedで本を読む&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;この段階的なアプローチにより、本を読む際に既に基礎的な枠組みが形成されているため、知識の定着に大きく活かせる。要約で全体像を把握してから詳細を読むことで、情報がより効果的に統合されるのだ。&lt;/p&gt;
&lt;h2 id="まとめkindle-unlimitedは学びの実験場"&gt;まとめ：Kindle Unlimitedは「学びの実験場」
&lt;/h2&gt;&lt;p&gt;Kindle Unlimitedの価値を「何冊読めるか」で測るのはもったいない。本当の価値は、同じ情報に角度を変えて何度も触れることの心理的障壁を下げていることにある。&lt;/p&gt;
&lt;p&gt;要約サービスと組み合わせれば、さらに効率的な学習サイクルが回せる。&lt;/p&gt;
&lt;p&gt;あなたはKindle Unlimitedをどう活用している？「読み放題」ではなく「学びの実験場」として使ってみると、新しい発見があるかもしれない。&lt;/p&gt;</description></item><item><title>画面を分けるだけで「学び」が変わる。Pixel 10 Pro Foldで実現する新しい読書術</title><link>https://sonohen.net/posts/2026/01/11/</link><pubDate>Sun, 11 Jan 2026 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2026/01/11/</guid><description>&lt;p&gt;これまでは、ノートパソコンを広げて読書をするのが私のスタイルでした。左側に電子書籍のKindle、右側にメモ用のアプリを開き、気づいたことを音声で入力していく。この「読み」ながら記録する流れが、知識を身につける一番の近道だったからです。&lt;/p&gt;
&lt;p&gt;しかし、自宅、あるいは外出先でパソコンを取り出すのは、どうしても手間がかかります。もっと手軽に、それでいて本格的に学びたい。そんな悩みを解決してくれたのが、画面を大きく広げられるスマートフォン「Google Pixel 10 Pro Fold」でした。&lt;/p&gt;
&lt;p&gt;このデバイスの最大の特徴は、一つの画面を二つに分割して、別々のアプリを同時に動かせることです。電子書籍で本を読みながら、もう片方でGoogle Keepを開く。パソコンで行っていた効率的な学習環境が、手のひらの上で完全に再現されました。&lt;/p&gt;
&lt;h2 id="驚くほどスムーズな声のメモが思考を止めない"&gt;驚くほどスムーズな「声のメモ」が、思考を止めない
&lt;/h2&gt;&lt;p&gt;特に驚いたのが、Gboardの音声入力の精度です。読み進める中で心に残ったフレーズを口に出すと、魔法のようにスラスラと文字に変わります。反応が非常に速いため、せっかく思い浮かんだアイデアを忘れる前に、確実に記録に残せるようになりました。&lt;/p&gt;
&lt;p&gt;以前は「スマホでメモをするのは面倒」という先入観がありましたが、今ではパソコンよりも快適に感じています。場所を選ばず、思い立った瞬間にアウトプットを開始できる。このスピード感こそが、忙しい日々の中で学びを継続する鍵になると実感しています。&lt;/p&gt;
&lt;p&gt;さらにこの仕組みは、本だけでなく動画での学習にも応用できます。画面の左側にYouTubeやオンライン講座を流しながら、大事なポイントを右側のGoogle Keepに音声入力で書き留める。ツールが連携して動く様子は、まるで自分専用の学習室を持ち歩いているような感覚です。&lt;/p&gt;
&lt;h2 id="androidユーザーなら今すぐその恩恵を受けられる"&gt;Androidユーザーなら、今すぐその恩恵を受けられる
&lt;/h2&gt;&lt;p&gt;とはいえ、Google Pixel 10 Pro Foldは決して安い買い物ではありません。その価格に、導入をためらってしまう方も多いでしょう。ですが、今回お伝えした「効率的な学習体験」の本質は、実は多くのAndroid端末で今すぐ体験できるものです。&lt;/p&gt;
&lt;p&gt;画面分割機能や、高精度な音声入力は、Androidが共通して持っている強みです。まずは手持ちのスマートフォンで、読書アプリとメモアプリを並べてみてください。そしてキーボードで打つ代わりに、マイクに向かって自分の考えを話してみてください。&lt;/p&gt;
&lt;p&gt;たとえ画面が少し小さくても、声でアウトプットする爽快感とスピードは十分に実感できるはずです。道具の良さを引き出す工夫一つで、いつものスマートフォンが強力な学習ツールへと進化します。これは試してみない手はありません。&lt;/p&gt;
&lt;h2 id="スマートフォン一台で未来の自分への投資を加速させる"&gt;スマートフォン一台で、未来の自分への投資を加速させる
&lt;/h2&gt;&lt;p&gt;これからの時代、スマートフォンは単に情報を眺めるだけの道具ではなく、自分を成長させるための「相棒」になっていくでしょう。高性能な機能が手元に凝縮されたことで、隙間時間はすべて、価値あるアウトプットの時間へと姿を変えます。&lt;/p&gt;
&lt;p&gt;「スマホだけで本当に勉強ができるのか」と疑問に思う方もいるかもしれません。しかし、道具を賢く組み合わせることで、私たちは場所や時間の制約から解放されます。まずは一歩、手元のデバイスで「読みながら話す」習慣を始めてみませんか。&lt;/p&gt;
&lt;p&gt;日々の小さなアウトプットの積み重ねが、いつか大きな成果となって自分を助けてくれるはずです。新しい道具を味方につけて、自分なりの学びのスタイルをアップデートしていく。そんな前向きな挑戦を、これからも楽しんでいきたいと思います。&lt;/p&gt;</description></item><item><title>Emacs + DDSKK on kittyな環境で日本語変換がバグる</title><link>https://sonohen.net/posts/2025/12/02/</link><pubDate>Tue, 02 Dec 2025 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2025/12/02/</guid><description>&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Arch Linux&lt;/li&gt;
&lt;li&gt;tmux 3.6&lt;/li&gt;
&lt;li&gt;GNU Emacs 30.2 + DDSKK&lt;/li&gt;
&lt;li&gt;kitty 0.44.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="事象"&gt;事象
&lt;/h2&gt;&lt;p&gt;以下のように入力すると、不正な文字列が入力される。&lt;/p&gt;
&lt;p&gt;KiGasuru -&amp;gt; 気gがする&lt;/p&gt;
&lt;h2 id="解消方法"&gt;解消方法
&lt;/h2&gt;&lt;p&gt;以下のようにすることで、完全な解消は難しいものの軽減はできた。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;~/.config/kitty/kitty.conf&lt;/code&gt;&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;cfg&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cfg" data-lang="cfg"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;kitty_keyboard_protocol no&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;~/.local/bin/emacs-noime&lt;/code&gt;&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/sh -e
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;unset GTK_IM_MODULE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;unset QT_IM_MODULE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;unset XMODIFIERS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;unset DefaultImModule
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;unset GLFW_IM_MODULE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;export NO_AT_BRIDGE&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;exec emacs -nw &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$@&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;今後は、 &lt;code&gt;~/.local/bin/emacs-noime&lt;/code&gt; を &lt;code&gt;kitty&lt;/code&gt; から呼びだすことで、不正な文字が極力残らないようにして作業を実施できるものと思われる(完全解消するためには、 &lt;code&gt;emacs -nw&lt;/code&gt; を止めるしかない)。&lt;/p&gt;
&lt;h2 id="その後の検証の結果"&gt;その後の検証の結果
&lt;/h2&gt;&lt;p&gt;結局、上記は効果がなかったとは言えないが、もっとも効果がありそうなのは以下の対策であった。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;~/.config/kitty/kitty.conf&lt;/code&gt;&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;cfg&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cfg" data-lang="cfg"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;programs.kitty.keybindings&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;ctrl+j&amp;#34; = &amp;#34;discard_event&amp;#34;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="その後の検証の結果--2"&gt;その後の検証の結果(2)
&lt;/h2&gt;&lt;p&gt;結局、劇的な効果が見込まれず &lt;code&gt;emacs -nw&lt;/code&gt; をtmuxの中で動かすことは止めにした。&lt;/p&gt;</description></item><item><title>qutebrowserがウェブサイトを描画しない</title><link>https://sonohen.net/posts/2025/11/23/</link><pubDate>Sun, 23 Nov 2025 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2025/11/23/</guid><description>&lt;p&gt;かつてよりLinux環境ではFirefoxを愛用していたのですが、最近ではもっぱら&lt;a class="link" href="https://www.qutebrowser.org" target="_blank" rel="noopener"
 &gt;qutebrowser&lt;/a&gt;を愛用しています。vimの操作方法を使えるのが便利で、マウスを使わずともほとんどの操作をキーボード主体でできることから、i3-wmとも非常に相性が良いです。&lt;/p&gt;
&lt;p&gt;しかし、そのqutebrowserをArchLinuxにインストールしたところ、どうにもまともに動かない状況で、2-3日ハマりました。結論は、Xorgのドライバーをきちんとインストールしていなかったことでした。解決に至るまでの状況と教訓をまとめておきます。&lt;/p&gt;
&lt;h2 id="起こっていたこと"&gt;起こっていたこと
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;スタートアップに指定しているDuckDuckGoのページが表示されない。ロードが終わっていることはステータスバーから分かるものの、画面は真っ白の状態。まれに画面がちらつき、アヒルのロゴが表示される状況。&lt;/li&gt;
&lt;li&gt;操作がまともに出来ない。コマンドを受け付けない。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="調査--1--qutebrowser-qtwebkitのバージョンによる不具合の有無"&gt;調査(1) qutebrowser/qtwebkitのバージョンによる不具合の有無
&lt;/h2&gt;&lt;p&gt;まず最初に疑ったのが、ArchLinuxにインストールされている &lt;code&gt;qutebrowser&lt;/code&gt; と、それが利用している &lt;code&gt;QtWebEngine&lt;/code&gt; のバージョンによる不具合の有無です。私の環境では、2025年11月21日現在で以下のバージョンがインストールされていました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;qutebrowser&lt;/strong&gt; v3.6.1&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PyQt&lt;/strong&gt; 6.10.0&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PyQt6.QtWebEngineCore&lt;/strong&gt; 6.10.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらのバージョンは、正常に動作しているSlackware -current on ThinkPadと同じであったので、インストールされているバージョンに不具合があるというわけではなさそうだ、という結論に到達しました。(一応、ChatGPTにも調査させ、不具合がでていないことは調べました。)&lt;/p&gt;
&lt;h2 id="調査--2--ドライバの問題"&gt;調査(2) ドライバの問題
&lt;/h2&gt;&lt;p&gt;次に疑ったのがグラフィックドライバの問題です。疑った根拠は以下の2つです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Xorgの設定をまともにしていなかったと思い出したこと&lt;/li&gt;
&lt;li&gt;&lt;code&gt;qutebrowser --version&lt;/code&gt; の出力結果を眺めていたところ、qutebrowserの内部ではChromiumをベースとしたQtWebEngineが動作していることに気が付いたこと&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;利用している端末はHP EliteBook 630 (G9)で、これには12世代のIntel CPU(12th Gen Intel(R) Core(TM) i5-1235U)が搭載されています。使用しているグラフィックボードはオンボード(統合チップセット)で、Intel Iris Xe Graphicsです。&lt;a class="link" href="https://wiki.archlinux.jp/index.php/Xorg" target="_blank" rel="noopener"
 &gt;Xorg - ArchWiki&lt;/a&gt;によると、この世代のチップには &lt;code&gt;xf86-video-intel&lt;/code&gt; を使うのではなく、代わりに &lt;code&gt;mesa&lt;/code&gt; を使うように記載があります。&lt;/p&gt;
&lt;p&gt;なるほどと思い &lt;code&gt;/var/log/pacman.log&lt;/code&gt; を調べると、 &lt;code&gt;extra/mesa&lt;/code&gt; がインストールされていないことが判明しました。 &lt;code&gt;extra/x86-video-intel&lt;/code&gt; を削除したのち、 &lt;code&gt;extra/mesa&lt;/code&gt; をインストールして端末を再起動したころ、qutebrowserが正常に動作するようになりました。&lt;/p&gt;
&lt;h2 id="教訓"&gt;教訓
&lt;/h2&gt;&lt;p&gt;当たり前のことですが、ソフトウェアの動作環境はきちんと確認するようにすべきでした。今回の場合、 &lt;code&gt;qutebrowser --verion&lt;/code&gt; を実行すれば、どのバージョンのソフトウェアが動作しており、かつqutebrowserに認識されているのかを確認することができます。その中で、OpenGLがどのドライバーによって動作するのかも知ることができるので、最初から丹念に確認しておけば今回の調査期間を短縮できたはずです。今回気が付いたのは3日目でした。&lt;/p&gt;
&lt;p&gt;また、Slackwareでqutebrowserを特に何も気にすることなく使えていたのは、あらかじめ必要なドライバーがインストールされており、それが自動検出によって使われていたお陰であろうと思います。ArchLinuxはカスタマイズ性が高いのですが、それはすなわち全てを自分で管理しなければいけないということにあるので、まずはきちんと設定をする、というところを怠るべきではありませんでした。(最近のLinuxの自動検出/自動設定に甘えていました)&lt;/p&gt;
&lt;p&gt;今回のこの件を機に、自分のスキルはまだまだだなと思いつつ、利用者の目線からするとある意味ではシンプルに動作している点がさすがLinuxだと思ったので、今後も精進していこうと思います。&lt;/p&gt;</description></item><item><title>SlackwareでThinkPadの液晶の明るさを変える</title><link>https://sonohen.net/posts/2025/11/02/</link><pubDate>Sun, 02 Nov 2025 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2025/11/02/</guid><description>&lt;p&gt;&lt;a class="link" href="https://x.com/sonohenv0/" target="_blank" rel="noopener"
 &gt;X.com&lt;/a&gt;でもいくつかポストしていますが、先日からSlackwareでi3を使用しています。環境構築作業のなかで最も優先度が低かったのが液晶の明るさを変更するための仕組みであったのですが、今日、ようやく実装しました。&lt;/p&gt;
&lt;p&gt;何かツールを入れるのもなぁと思っていたところ、 &lt;code&gt;/sys/class/backlight/amdgpu_bl0/brightness&lt;/code&gt; を書き換えればよいということがわかり、以下のようなスクリプトを作っておきました。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/sh -e
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Usage:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# brightness.sh 1000 (for Brighter)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# brightness.sh -1000 (for Darker)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;FILE&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/sys/class/backlight/amdgpu_bl0/brightness
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CURRENT_BRIGHTNESS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;cat $FILE&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TARGET_BRIGHTNESS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$((&lt;/span&gt; $CURRENT_BRIGHTNESS &lt;span style="color:#f92672"&gt;+&lt;/span&gt; $1 &lt;span style="color:#66d9ef"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo $TARGET_BRIGHTNESS &amp;gt; $FILE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;これを、以下のように設定することでキーボードから呼び出すようにしました。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plaintext" data-lang="plaintext"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bindsym XF86MonBrightnessUp exec --no-startup-id sudo ~/.local/bin/brightness.sh 4000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bindsym XF86MonBrightnessDown exec --no-startup-id sudo ~/.local/bin/brightness.sh -4000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;私だけしか使っていないシステムなので、 &lt;code&gt;sudo&lt;/code&gt; は NOPASSWD で実行できるようにしています。&lt;/p&gt;
&lt;p&gt;これで、設定を再読み込みすれば、キーボードから液晶の明るさを調整することができるようになります。&lt;/p&gt;</description></item><item><title>Slackware -currentでHEIC対応のdigiKamを動かす</title><link>https://sonohen.net/posts/2025/10/20/</link><pubDate>Mon, 20 Oct 2025 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2025/10/20/</guid><description>&lt;h2 id="tl-dr"&gt;TL;DR
&lt;/h2&gt;&lt;p&gt;Slackware -currentのImageMagick (7.1.2-7)は &lt;code&gt;--with-heic=yes&lt;/code&gt; でコンパイルされていないため、それを使っているdigiKamでもHEIC/HEIFフォーマットの画像を扱うことができない。同じ理由で、Gwenviewでも扱うことができない。&lt;/p&gt;
&lt;h2 id="そもそもの発端"&gt;そもそもの発端
&lt;/h2&gt;&lt;p&gt;つい最近までDebian GNU/Linuxを使っていたのですが、思うところがありここ数日でSlackware -currentに環境を移行しました。kernel/gcc/emacsを自前でコンパイルし、色々な試行錯誤を繰り返しながら、なんとか必要な作業ができるようになってきたことから、本格的にデータを移行することにしました。&lt;/p&gt;
&lt;p&gt;これといった理由は特に無いのですが、趣味の写真をさっさと再開できるようにということで、まずは写真のデータをSlackwareに移行することにしました。&lt;/p&gt;
&lt;h2 id="heicフォーマットの画像がdigikamに表示されない"&gt;HEICフォーマットの画像がdigiKamに表示されない
&lt;/h2&gt;&lt;p&gt;HEICフォーマットはiPhone等で使われる形式で、同程度の視覚品質を得るためにはJPEGの50-60%程度のファイルサイズで済むといわれています。つまり、容量に制約のあるスマートフォンや、クラウドサービスの容量を節約したい場合にHEICを使うことが良いのではないかと思われます。私も、iPhoneでHEICが使われるようになってからというもの、iPhoneで撮る写真はすべてHEIC形式になりました。&lt;/p&gt;
&lt;p&gt;それらの写真をdigiKamに取り込もうとした時に、サムネイルもプレビューも表示されないので「どうなってんだ？」と思い調査したところ、まず判ったのは &lt;code&gt;libheif&lt;/code&gt; がシステムにインストールされていないことでした。&lt;/p&gt;
&lt;h2 id="libheif-をインストールする"&gt;&lt;code&gt;libheif&lt;/code&gt; をインストールする
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;libheif&lt;/code&gt; は &lt;code&gt;libaom&lt;/code&gt; と &lt;code&gt;libde265&lt;/code&gt; に依存している。まずはそれらをシステムにインストールする必要があるので、準備する。 &lt;code&gt;libaom&lt;/code&gt; は&lt;a class="link" href="https://github.com/darkskygit/libaom" target="_blank" rel="noopener"
 &gt;darkskygit / libaom&lt;/a&gt;から入手することができる。また &lt;code&gt;libde265&lt;/code&gt; は&lt;a class="link" href="https://github.com/strukturag/libde265" target="_blank" rel="noopener"
 &gt;structurag / libde265&lt;/a&gt;から入手できるので、それぞれREADMEを参考にコンパイルしてパッケージを作り &lt;code&gt;installpkg&lt;/code&gt; でインストールしておく。&lt;/p&gt;
&lt;p&gt;次に &lt;code&gt;libheif&lt;/code&gt; をインストールする。 &lt;code&gt;libheif&lt;/code&gt; は&lt;a class="link" href="https://github.com/strukturag/libheif" target="_blank" rel="noopener"
 &gt;structurag / libheif&lt;/a&gt;から入手できるので、こちらもREADMEを参考にコンパイルしてパッケージを作り &lt;code&gt;installpkg&lt;/code&gt; でインストールしておく。途中 &lt;code&gt;/usr/lib64/libaom.a&lt;/code&gt; が見付からないというエラーが出るので &lt;code&gt;ln -s /usr/lib64/libaom.a /usr/local/lib64/libaom.a&lt;/code&gt; としてsymlinkを張っておく。&lt;/p&gt;
&lt;p&gt;ここまで実施してdigiKamを起動しても状況は変わらなかった。なぜだと考え、調べているうちに、どうやらdigiKamはバックエンドにImageMagickを使っていそうだということがわかり、では、ImageMagickでHEIC/HEIFは有効になっているのだろうかと調べたところ有効になっていなかったのであった。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick -list format | grep HEIC &lt;span style="color:#75715e"&gt;# 結果は何も表示されなかった =&amp;gt; 無効&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ magick -list format | grep HEIF &lt;span style="color:#75715e"&gt;# 結果は何も表示されなかった =&amp;gt; 無効&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="imagemagickを-with-heic-yes-つきでインストールする"&gt;ImageMagickを &lt;code&gt;--with-heic=yes&lt;/code&gt; つきでインストールする
&lt;/h2&gt;&lt;p&gt;ImageMagicは、&lt;a class="link" href="https://mirrors.slackware.com/slackware/slackware-current/source/l/imagemagick/" target="_blank" rel="noopener"
 &gt;currentのソースコード&lt;/a&gt;をもとにコンパイルする。 &lt;code&gt;imagemagic.SlackBuild&lt;/code&gt; の中に記載されている &lt;code&gt;./configure&lt;/code&gt; に対し &lt;code&gt;--with-heic=yes&lt;/code&gt; を指定したうえでパッケージを作成し、インストールする。&lt;/p&gt;
&lt;p&gt;ここまで実施した上でdigiKamを開くと、HEICフォーマットの画像が表示されるようになっているはずである。&lt;/p&gt;
&lt;h2 id="dolphinとgwenviewでもheicを扱いたい場合は-kimageformatsをheicサポートつきでコンパイルし-インストールする必要がある"&gt;DolphinとGwenviewでもHEICを扱いたい場合は、KImageFormatsをHEICサポートつきでコンパイルし、インストールする必要がある
&lt;/h2&gt;&lt;p&gt;ここまで実施しても、まだDolphinやGwenviewでHEICを表示することはできない。それらでHEICを扱うためには、KImageFormatsをHEICサポートつきでコンパイルし、インストールする必要がある。 &lt;code&gt;cmake&lt;/code&gt; の引数に &lt;code&gt;-DKIMAGEFORMATS_HEIF=on&lt;/code&gt; を指定してコンパイルし、パッケージを作成、インストールする。&lt;/p&gt;
&lt;p&gt;こうして無事、私の写真ライブラリはSlackwareマシンに移行されたのでした。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;こうしてまとめてしまうと何てことのない作業なのですが、実際にはログを見たり、インターネットで調査したり、横道に逸れたりしながら調査して、結構時間を喰ったように思います。が、まずはHEICがきちんと取り扱える環境になってめでたし、めでたし。&lt;/p&gt;
&lt;p&gt;こういう調査は知識を身に付けるよい機会であるので、きちんと記録を取りながら対応し、知識を整理していきたい。今回は、作業ログをChangeLogのフォーマットで記録しておいたので、それを参考にしながらこの記事を書きました。&lt;/p&gt;</description></item><item><title>Debian GNU/Linux 13 (trixie)の4K出力が安定しない件を解決する</title><link>https://sonohen.net/posts/2025/10/13/</link><pubDate>Mon, 13 Oct 2025 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2025/10/13/</guid><description>&lt;p&gt;私は普段、Debian GNU/Linux 13 (trixie)をThinkPad E14 (Gen 3)で運用しており、外付けモニターとしてJapanNextの4Kモニターを使用しています。4K出力に対応しておりながら安価である点が気に入っています。&lt;/p&gt;
&lt;p&gt;さて、その環境も、HDMI出力が安定せず、画面が表示されたりされなかったりで作業にならない状況が続いていました。どうもXがEDIDをモニターから取得するまでのタイムラグが原因のように思えましたので、環境決め打ちになってしまうのが気にはなりますが、以下のように対処をしました。&lt;/p&gt;
&lt;p&gt;ここに記述している内容はX向けの設定ですが、結果的にXWayland経由で設定が反映されていることになります。&lt;/p&gt;
&lt;h2 id="問題の切り分け"&gt;問題の切り分け
&lt;/h2&gt;&lt;p&gt;まずは物理的な問題を除外しました。&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;モニター自体は正常か？&lt;/dt&gt;
&lt;dd&gt;手元にあるMacBookを使ったところ正常に4K出力できたので、問題は無いと判断した。&lt;/dd&gt;
&lt;dt&gt;HDMIケーブル自体は正常か？&lt;/dt&gt;
&lt;dd&gt;手元にあるMacBookに接続してみたところ正常に4K出力できたので、問題は無いと判断した。&lt;/dd&gt;
&lt;dt&gt;ThinkPadのHDMIポートに問題は無いか？&lt;/dt&gt;
&lt;dd&gt;手元にある他のモニター(FullHD)に接続してみたところ正常に出力できたので、問題は無いと判断した。&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;この結果、物理的なハードウェアの問題ではなく、モニターとThinkPadの間の通信(ネゴシエーション)がうまくいかない場合がある、という仮説にいたりました。&lt;/p&gt;
&lt;h2 id="ネゴシエーションの肝となる-edid--extended-display-identification-data-拡張ディスプレイ識別データ"&gt;ネゴシエーションの肝となる &lt;code&gt;EDID (Extended Display Identification Data: 拡張ディスプレイ識別データ)&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;EDIDは、モニターが自分自身の仕様をコンピュータに伝えるデータです。具体的には以下の情報を含みます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;対応解像度(例：1920x1080、3840x2160)&lt;/li&gt;
&lt;li&gt;リフレッシュレート(例：60hz)&lt;/li&gt;
&lt;li&gt;色深度やカラーフォーマット&lt;/li&gt;
&lt;li&gt;製造情報&lt;/li&gt;
&lt;li&gt;タイミング情報(垂直/水平同期)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;通常、コンピュータはEDIDを参照して自動的に最適な解像度やリフレッシュレートを設定します。EDIDのやり取りが失敗すると、画面が表示されなかったり、 &lt;code&gt;xrandr&lt;/code&gt; が &lt;code&gt;BadMatch&lt;/code&gt; エラーを返したりします(追記：これは、Waylandで実行すると出るエラーです)。&lt;/p&gt;
&lt;h2 id="モニターから取得したedid情報をxwayland経由で読み込む"&gt;モニターから取得したEDID情報をXWayland経由で読み込む
&lt;/h2&gt;&lt;p&gt;つまり、モニターとやり取りをして解像度等を決定するのではなく、あらかじめEDIDを取得しておき、それをXから読み取るようにしておけば、ネゴシエーションに失敗する可能性は低いわけです。ただ問題は、EDIDを取得するためにはきちんと画面出力されている必要があるということで、そこまではなんとかする必要があるということです。全く表示されない場合には、この手段は使えないと思います。&lt;/p&gt;
&lt;h3 id="edidを取得する"&gt;EDIDを取得する
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;/sys/class/drm/card0-HDMI-A-1/edid&lt;/code&gt; からダンプしておきます。ここは環境に依存しますので、どのパスからダンプすればよいのかは &lt;code&gt;xrandr&lt;/code&gt; の情報を参考にして決めてください。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo mkdir -p /etc/X11/edid/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo cat /sys/class/drm/card0-HDMI-A-1/edid &amp;gt; /etc/X11/edid/JAPANNEXT_JN-280IPS4KR.bin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="xの設定"&gt;Xの設定
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;/etc/X11/xorg.conf.d/10-monitor.conf&lt;/code&gt; を編集します。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Section &amp;#34;Monitor&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Identifier &amp;#34;HDMI-1&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Option &amp;#34;CustomEDID&amp;#34; &amp;#34;HDMI-1:/etc/X11/edid/JAPANNEXT_JN-280IPS4KR.bin&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;EndSection&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="ゴミデータの削除"&gt;ゴミデータの削除
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;~/.config/monitors.xml&lt;/code&gt; が悪さをする可能性があるので、消しておきます。&lt;/p&gt;
&lt;h3 id="waylandを再起動"&gt;Waylandを再起動
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;sudo systemctl restart display-manager&lt;/code&gt; によりWaylandを再起動し、正常に画面出力されることを確認します。また、HDMIケーブルを何回か抜き差ししても、毎回、安定して画面出力されるかを確認します。&lt;/p&gt;
&lt;h2 id="制約"&gt;制約
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;この方法を使うと、HDMI接続時に毎回、JapanNextのEDIDを参照することになるので、他のモニターによっては出力できなくなる可能性があります。環境がある程度固定的であればこの方法は有効ですが、そうでない場合(持ち歩き用途など)では使えない可能性もあります。&lt;/li&gt;
&lt;li&gt;画面が全く表示されない場合にはEDIDが取得できないため、この方法は使えません。&lt;/li&gt;
&lt;li&gt;サスペンドからの復旧時には、HDMIケーブルを抜線後にログインし、HDMIケーブルを差し込んだあと &lt;code&gt;display-manager&lt;/code&gt; を再起動する必要があります。 &lt;code&gt;sudo systemctl restart display-manager&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Debian GNU/Linux 13 (trixie)でSwiftを動かす</title><link>https://sonohen.net/posts/2025/10/12/</link><pubDate>Sun, 12 Oct 2025 00:00:00 +0000</pubDate><guid>https://sonohen.net/posts/2025/10/12/</guid><description>&lt;p&gt;&lt;code&gt;Swift&lt;/code&gt; は、Apple社が開発をしているプログラミング言語で、主にApple製品で動作させるソフトウェアを開発するために使用されるものですが、オープンソース化されてからというもの、Linuxなどサーバサイドで動作するソフトウェアの開発にも使われているようです。&lt;/p&gt;
&lt;p&gt;今回は、たまたま目新しいということで、インストールしてみました。&lt;/p&gt;
&lt;h2 id="swiftをインストールする"&gt;Swiftをインストールする
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://www.swift.org/install/linux/" target="_blank" rel="noopener"
 &gt;Install Swift&lt;/a&gt;を参考にすればインストール自体は簡単にできます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cd
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ mkdir swiftly
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cd swiftly
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ curl -O https://download.swift.org/swiftly/linux/swiftly-&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;uname -m&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ tar xvzf swiftly-&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;uname -m&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo ./swiftly init --quiet-shell-followup
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo apt install libstdc++-12-dev &lt;span style="color:#75715e"&gt;# Swiftlyからインストールを求められた場合のみ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ . &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;SWIFTLY_HOME_DIR&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;$HOME/.local/share/swiftly&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/env.sh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ hash -r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;~/.bashrc&lt;/code&gt; にも、以下を追記しておきます。&lt;/p&gt;
&lt;p&gt;&lt;!-- raw HTML omitted --&gt;&lt;!-- raw HTML omitted --&gt;&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;. &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;SWIFTLY_HOME_DIR&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;$HOME/.local/share/swiftly&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/env.sh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hash -r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="hello-world-してみる"&gt;&lt;code&gt;Hello World&lt;/code&gt; してみる
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;swift&lt;/code&gt; にパスが通っていることを前提に、以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ mkdir helloworld
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cd helloworld
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ swift package init --name HelloWorld --type executable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ swift run HelloWorld&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;すると、以下のように実行されます。初回はとにかく遅く、Hello Worldだけにも関わらず約5秒の処理時間が掛っていました。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Building for debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[8/8] Linking HelloWorld
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Build of product &amp;#39;HelloWorld&amp;#39; complete! (4.99s)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Hello, world!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;2回目は以下のようにキャッシュが効いているのか、速くはなってはいますが、それにしても遅いですね。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[1/1] Planning build
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Building for debugging...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[1/1] Write swift-version-3F9C5CDD8FC5382D.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Build of product &amp;#39;HelloWorld&amp;#39; complete! (0.20s)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Hello, world!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="emacsでswiftを使ってみる"&gt;EmacsでSwiftを使ってみる
&lt;/h2&gt;&lt;p&gt;当然、EmacsでもSwiftを使うことができます。私の場合、現時点でSwiftで本格的にプログラムを書く予定はなく、 &lt;code&gt;org-babel&lt;/code&gt; で少し勉強したいと思っている程度なので、 &lt;code&gt;ob-swift&lt;/code&gt; と &lt;code&gt;swift-mode&lt;/code&gt; を導入することにしました。&lt;/p&gt;
&lt;h3 id="pathを通す"&gt;PATHを通す
&lt;/h3&gt;&lt;p&gt;以下のような設定を &lt;code&gt;~/.emacs&lt;/code&gt; に入れることにより、Emacsを起動した際にShellの設定ファイルを読んでパスを通してくれます。事前に、 &lt;code&gt;M-x package-install&lt;/code&gt; で &lt;code&gt;exec-path-from-shell&lt;/code&gt; をインストールしておく必要があります。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Emacs Lisp&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-emacs-lisp" data-lang="emacs-lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(when (&lt;span style="color:#a6e22e"&gt;memq&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;window-system&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#39;&lt;/span&gt;(mac ns x))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (exec-path-from-shell-initialize))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="ob-swift-と-swift-mode-をインストールする"&gt;&lt;code&gt;ob-swift&lt;/code&gt; と &lt;code&gt;swift-mode&lt;/code&gt; をインストールする
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;M-x package-install&lt;/code&gt; から &lt;code&gt;ob-swift&lt;/code&gt; と &lt;code&gt;swift-mode&lt;/code&gt; をインストールしておきます。前者は &lt;code&gt;org-babel&lt;/code&gt; でSwiftを実行するために必要、後者はシンタックスハイライトをするために必要となります。&lt;/p&gt;
&lt;h3 id="org-babel-でswiftを有効化する"&gt;&lt;code&gt;org-babel&lt;/code&gt; でSwiftを有効化する
&lt;/h3&gt;&lt;p&gt;以下のような設定を &lt;code&gt;~/.emacs&lt;/code&gt; に入れることにより &lt;code&gt;org-babel&lt;/code&gt; でSwiftが実行できるようになる。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Emacs Lisp&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-emacs-lisp" data-lang="emacs-lisp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(org-babel-do-load-languages
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;org-babel-load-languages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#39;&lt;/span&gt;((swift &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;t&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (emacs-lisp &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;t&lt;/span&gt;)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;この例では、SwiftとEmacs Lispを有効化しています。Emacs Lispについては、あえて記述しなくとも最初から有効になっているため、書く必要はありません。&lt;/p&gt;
&lt;h3 id="org-babel-でswiftを実行する"&gt;&lt;code&gt;org-babel&lt;/code&gt; でSwiftを実行する
&lt;/h3&gt;&lt;p&gt;ここまでの設定を終えていれば、以下のように書くことで &lt;code&gt;org-babel&lt;/code&gt; でSwiftを実行できます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#+begin_src swift
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;let a: Int = 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(a)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#+end_src
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#+RESULTS:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;: 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;実際にiPhone等で動作するアプリケーションを開発するためにはMacbookが必要になりますが、Swiftの基本的な文法は、Linux上でも十分に試すことができますし、 &lt;code&gt;org-babel&lt;/code&gt; で気軽に試しながら勉強できるというのは大きなメリットになる人もいると思います。&lt;/p&gt;
&lt;p&gt;少なくとも、私の場合には &lt;code&gt;org-babel&lt;/code&gt; が使えるということと、Xcode Playgroundsよりも気軽に試すことができるということはメリットでありますので、しばらくこの環境で勉強しつつ、軌道に乗ってきたらMacbookで実際の開発作業に取り掛かってみようかと思います。&lt;/p&gt;</description></item><item><title>Git Submoduleを使っている環境で、 upload-pack: not our refエラーが発生した場合の修復方法</title><link>https://sonohen.net/posts/2025/10/08/</link><pubDate>Wed, 08 Oct 2025 13:39:47 +0900</pubDate><guid>https://sonohen.net/posts/2025/10/08/</guid><description>&lt;h1 id="概要"&gt;概要
&lt;/h1&gt;&lt;p&gt;このブログは、&lt;a class="link" href="https://gohugo.io/" target="_blank" rel="noopener"
 &gt;Hugo&lt;/a&gt;で構築している。
ブログを構成する資材は全て&lt;a class="link" href="https://github.com/" target="_blank" rel="noopener"
 &gt;GitHub&lt;/a&gt;に保存しており、以下のような構成になっていた。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plaintext" data-lang="plaintext"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;blog &amp;lt;--- Hugoの親リポジトリ(非公開)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; `--- public &amp;lt;--- 公開用資材のリポジトリ(公開、サブモジュール)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;この構成により、通常の運用の流れは以下になるはずであった。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;blogで記事を書き、チェック&lt;/li&gt;
&lt;li&gt;publicに公開用資材を作成&lt;/li&gt;
&lt;li&gt;public、blogの両方に対して &lt;code&gt;git commit&lt;/code&gt; 、&lt;code&gt;git push&lt;/code&gt; を実行&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ところが、前回、別のマシンで作業したときに、3.でpublicに対する &lt;code&gt;git commit&lt;/code&gt; は実行したものの、&lt;code&gt;git push&lt;/code&gt;の実行を忘れた状態で、blogに対しても &lt;code&gt;git commit&lt;/code&gt; 、&lt;code&gt;git push&lt;/code&gt; したのである。
そのため、以下のような状態になってしまっていた。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plaintext" data-lang="plaintext"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;blog public(submodule)のCommit Hashは BBB であると認識
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;`--- public(旧マシン) Commit Hash: BBBをCommit済、未push
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;`--- public(リモート) Commit Hash: AAAまでしか存在しない&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;blogは、publicがcommitされた状態(= Commit Hash: BBB)でGitHubのリポジトリに登録されている。
一方で、publicについて、リモート(GitHub)のリポジトリにはCommit Hash: BBBが反映されていない。
つまり、リモートでは、親リポジトリとサブモジュールで一世代分、ずれていたのである。&lt;/p&gt;
&lt;p&gt;そのため今回、新マシンで &lt;code&gt;git submodule update&lt;/code&gt; をしようとしたときに、Commit Hash: BBBのpublicが見付からないということで、&lt;code&gt;fatal: remote error: upload-pack: not our ref&lt;/code&gt;エラーが発生した。&lt;/p&gt;
&lt;h1 id="再現手順"&gt;再現手順
&lt;/h1&gt;&lt;ol&gt;
&lt;li&gt;サブモジュール(public)に変更を加え、&lt;code&gt;git commit&lt;/code&gt;する(&lt;code&gt;git push&lt;/code&gt;はしない)。&lt;/li&gt;
&lt;li&gt;親リポジトリ(blog)に戻り、サブモジュールを追加(&lt;code&gt;git add public&lt;/code&gt;)する。&lt;/li&gt;
&lt;li&gt;親リポジトリで、&lt;code&gt;git commit&lt;/code&gt;、&lt;code&gt;git push&lt;/code&gt;する。&lt;/li&gt;
&lt;li&gt;その後、別マシンにクローンしてから、以下のコマンドを実行する。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git submodule update --init&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;すると、以下のようなエラーが出力される。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Cloning into &amp;#39;/home/sonohen/work/blog/blog/public&amp;#39;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fatal: remote error: upload-pack: not our ref 35b4c8b0165369c2f92485e2b384bfc78827c75f
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fatal: Fetched in submodule path &amp;#39;./&amp;#39;, but it did not contain 35b4c8b0165369c2f92485e2b384bfc78827c75f. Direct fetching of that commit failed.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id="対処方法"&gt;対処方法
&lt;/h1&gt;&lt;p&gt;一世代分の変更を失うことになるが、参照可能なpublicのCommit Hashに戻すことで対応した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cd public
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git fetch
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git checkout 696fc9d1917dbab6789042c72e0b9b904aeb5e6a &lt;span style="color:#75715e"&gt;# GitHubに存在する最後のCommit Hashを指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cd ../
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git add public
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git commit -m &lt;span style="color:#e6db74"&gt;&amp;#34;Update submodule ref to valid commit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git push&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id="今後に向けて"&gt;今後に向けて
&lt;/h1&gt;&lt;p&gt;以下のような &lt;code&gt;deploy.sh&lt;/code&gt; を書いておくことで、サブモジュール側での &lt;code&gt;commit&lt;/code&gt;、&lt;code&gt;push&lt;/code&gt; し忘れを防止するようにした。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set -e
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# build site&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hugo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# commit using git&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd public
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;msg&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Rebuilding site `date`&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git add -A
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git commit -m &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$msg&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git push origin master
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd ../
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# upload all site settings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git add -A
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git commit -m &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$msg&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git push origin master&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>クレカで貯金体質に！賢い利用で未来を変える３つの秘訣</title><link>https://sonohen.net/posts/2025/09/28/</link><pubDate>Sun, 28 Sep 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/09/28/</guid><description>&lt;h2 id="この記事の背景と目的"&gt;この記事の背景と目的
&lt;/h2&gt;&lt;p&gt;前回、&lt;a class="link" href="../../09/06/" &gt;キャッシュレス決済を賢く使い、資産を増やす方法について私が実践している内容を記載&lt;/a&gt;しました。まだの方は、この記事よりも前に、こちらを読んでみてください。&lt;/p&gt;
&lt;p&gt;その中で、以下に示すような費用は、クレジットカードで支払いをしているということを記載しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;水道光熱費&lt;/li&gt;
&lt;li&gt;自動車税&lt;/li&gt;
&lt;li&gt;NHK受信料&lt;/li&gt;
&lt;li&gt;火災・地震保険&lt;/li&gt;
&lt;li&gt;ガソリン（※現在は近隣のガソリンスタンドがSuica支払いに対応したため、都度払いに移行）&lt;/li&gt;
&lt;li&gt;高速（ETCカード）&lt;/li&gt;
&lt;li&gt;高額決済（おおむね2万円以上）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;この記事では、これらの支払いにクレジットカードを使っても、「支払いの都度、残高が減るという現金払いと同じメリットと、利便性というキャッシュレスのメリット」を適用するために、私が実践している内容をご紹介します。&lt;/p&gt;
&lt;h2 id="使ったらその日のうちに現金を取り分ける"&gt;使ったら、その日のうちに現金を取り分ける
&lt;/h2&gt;&lt;p&gt;使ったら、その日のうちに現金を取り分けておきます。つまり、使えるお金の中から、クレジットカードで支払った分だけを別にしておくということです。&lt;/p&gt;
&lt;p&gt;ここで活用したいのが、「クレジットカードの利用通知」と、住信SBIネット銀行の「目的別口座」の2つです。&lt;/p&gt;
&lt;p&gt;まず、クレジットカードの利用通知ですが、支払い先と金額がメールで送られてくるので、これは必ず使いましょう。不正利用の早期発見にもつながります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.jcb.co.jp/security/my-anshin/usage-notice/index.html" target="_blank" rel="noopener"
 &gt;カードご利用通知｜クレジットカードなら、JCBカード&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;次に「目的別口座」です。これは、クレジットカードで支払った分を、別の口座に取り分けておくために使います。私の場合は、普段使うお金は普通口座に入れておき、クレジットカードで使ったお金は、その日のうちに目的別口座（クレジットカード支出分口座）に移しています。その際、いくら移せば良いのかを決めるのに見ているのが、「クレジットカードの利用通知」です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.netbk.co.jp/contents/lineup/purpose/" target="_blank" rel="noopener"
 &gt;目的別口座 | 商品・サービス | NEOBANK 住信SBIネット銀行&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;私が参考にさせていただいている方の中には、封筒で取り分けているという方もいらっしゃいますので、お好きな方法を使えば良いのではないかと思います。&lt;/p&gt;
&lt;p&gt;いずれにせよ、「使った分は、その日のうちに取り分けておく」というルールにより、現金払いのように使えるお金が減りつつ、キャッシュレスの利便性を享受することができます。&lt;/p&gt;
&lt;h2 id="1週間に1回確定した残高を繰上げ返済する"&gt;1週間に1回、確定した残高を繰上げ返済する
&lt;/h2&gt;&lt;p&gt;クレジットカードによっては、確定した明細を繰上げ返済することができるサービスがあります。私が知る限り、JCBカードと三井住友カードは、繰上げ返済の手続きをインターネットで実施できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://j-faq.jcb.co.jp/faq/show/514?site_domain=default" target="_blank" rel="noopener"
 &gt;カード利用分の繰上返済方法を教えてください。 | よくあるご質問（個人・法人のお客様）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.smbc-card.com/mem/oshiharai/rinji.jsp" target="_blank" rel="noopener"
 &gt;お振込みによる臨時のお支払い｜クレジットカードの三井住友VISAカード&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これを活用し、1週間に1回、確定した明細分の支払いを、先ほど述べた「目的別口座」から繰上げ返済してしまいます。&lt;/p&gt;
&lt;p&gt;私がこのようにしている理由は2つあります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;普通口座と目的別口座は、容易に資金の移動ができてしまう。つまり、普通残高が苦しくなってきた時に、目的別口座のお金を使い込んでしまう可能性が高くなる。1週間に1回でもカード会社にお金を支払ってしまえば、目的別口座の残高は少なくなるはずなので、使い込む金額は少なくて済む。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;クレジットカードの残高が多いのは、プレッシャーになる可能性がある。クレジットカードの残高 = 借金であり、残高が少ければ少ないほど良いと考えているため、1週間に1回、前払いすることで残高を減らしたい（気分の問題）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;クレジットカードでも、現金払いの良さとキャッシュレスの利便性を両立させることができます。その際に使うのは、「クレジットカードの利用通知」、「目的別口座を使った現金の取り分け」、「繰上げ返済」の3つです。&lt;/p&gt;
&lt;p&gt;2回にわたって、キャッシュレスの利便性を求めながら、現金払いの良さも両立させることで資産を増やす方法として、私が実践していることを記事にしました。&lt;/p&gt;
&lt;p&gt;基本は、デビットカードを基軸にした支払い方法を使いつつ、高額な支払いなどはクレジットカードを使って定期的に繰上げ返済するということで、私は賢く、キャッシュレス社会を生き抜こうとしています。&lt;/p&gt;
&lt;p&gt;日々、よりよい方法を考えているところではあるので、今後もアップデートがあれば記事にしていきたいと思います。ご覧いただいてありがとうございました。&lt;/p&gt;</description></item><item><title>キャッシュレス決済の賢い使い方 ～支出管理と資産形成のコツ～</title><link>https://sonohen.net/posts/2025/09/06/</link><pubDate>Sat, 06 Sep 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/09/06/</guid><description>&lt;h2 id="要約"&gt;要約
&lt;/h2&gt;&lt;p&gt;キャッシュレス決済は便利ですが、使い方を間違えるとつい無駄遣いし、資産が増えにくくなることもあります。以下のポイントを参考にすると、利便性を享受しつつ資産を守ることができます。&lt;/p&gt;
&lt;h2 id="主なキャッシュレス決済の種類"&gt;主なキャッシュレス決済の種類
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;クレジットカード（後払い型）&lt;/strong&gt;:　支払は月単位でまとまり、後日まとめて銀行口座から引き落とされます。便利ですが、使いすぎやすい面があります。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;デビットカード（即時払い型）&lt;/strong&gt;:　使った直後に銀行口座から即時引き落とし。支出管理がしやすく、現金感覚に近いのが特徴です。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;チャージ式電子マネー&lt;/strong&gt;:　あらかじめチャージした金額内での利用なので、使いすぎの心配がありません。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="賢い使い分けの実例"&gt;賢い使い分けの実例
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;高額決済や生活インフラの支払いには、クレジットカード&lt;/li&gt;
&lt;li&gt;日常的な買い物や交通費、サブスクなどは、デビットカードや電子マネー&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こうすることで、無駄遣いの抑制・日々の資産把握・家計の見える化を実現できます。&lt;/p&gt;
&lt;h2 id="キャッシュレスをめぐる日本の最新動向"&gt;キャッシュレスをめぐる日本の最新動向
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;2024年のキャッシュレス決済比率は42.8%。デビットカードは3.1％と伸びていますが、全体ではまだ少数派です。&lt;/li&gt;
&lt;li&gt;補償面ではクレジットカードの方が手厚い傾向がありますが、デビットカードもセキュリティや銀行ごとの工夫が広がっています。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;私はキャッシュレス決済の使い分けにより、増えも減りもしなかった資産を、1年間で190万円近く増やすことに成功しました。この記事では、そのことを記載したいと思います。&lt;/p&gt;
&lt;h2 id="キャッシュレス決済の種類"&gt;キャッシュレス決済の種類
&lt;/h2&gt;&lt;p&gt;主なキャッシュレス決済には、以下の4つの種類があります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;後払い（例：クレジットカード）&lt;/strong&gt;:　ある期間に使った金額を、決められた日にクレジットカード会社に支払う方法。請求をまとめられるメリットがあるものの、使いすぎる傾向にある。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;都度払い③（例：デビットカード）&lt;/strong&gt;:　支払いの都度、デビットカードに紐づけられている銀行口座から即時引き落としされる支払い方法。（即時引き落としされない場合もありますが、話が複雑になるため割愛）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;都度払い④（例：モバイルSuica）&lt;/strong&gt;:　支払いの都度、電子マネーの残高から即時引き落としされる支払い方法。クレジットカードやデビットカード、銀行口座、ATMや券売機などで電子マネーの残高にお金を入れ、その範囲内で使用できる。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;後払い②（例：ペイディ）&lt;/strong&gt;:　ある期間に使った金額を、決められた日に金融会社に支払う方法。クレジットカードと違う点は、与信審査が簡易であったり、利用限度額が一般にクレジットカードよりも低額に抑えられている点などです。「即買って、支払いは後日（Buy Now, Pay Later）」と表現されることもあり、別名、BNPLとも言われます。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;この記事では、1〜3を「キャッシュレス決済」と扱います。&lt;/p&gt;
&lt;p&gt;参考情報として、キャッシュレスの場合、現金に比べて支出が1.7倍程度増えるという調査結果があります。&lt;/p&gt;
&lt;p&gt;キャッシュレスは、「お金を使いすぎてしまう」って本当？
キャッシュレスは、「お金を使いすぎてしまう」って本当？｜ベネッセ教育情報サイト
【ベネッセ｜教育費】消費税増税をきっかけに、キャッシュレス決済への流れが大きく加速しています。政府は2025年の大阪・関西
benesse.jp&lt;/p&gt;
&lt;blockquote&gt;
 &lt;p&gt;&lt;p&gt;日本クレジットカード協会の調査(2017年度)によると、支払いをクレジットカードで行う人は現金で行う人より1.7倍多く使うという結果でした。&lt;/p&gt;
&lt;p&gt;使ってしまいがちな場面は、「衣料品専門店」「雑貨・文具」「タクシー」の支払いで、現金の２倍以上と高くなっています。共通するのは少し特別感のある消費場面です。&lt;/p&gt;
&lt;/p&gt;&lt;span class="cite"&gt;&lt;span&gt;― &lt;/span&gt;&lt;span&gt;ベネッセ, &lt;/span&gt;&lt;a href="https://benesse.jp/kyouiku/201912/20191210-1.html"&gt;&lt;cite&gt;キャッシュレスは、「お金を使いすぎてしまう」って本当？&lt;/cite&gt;&lt;/a&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;h2 id="before---何でもかんでも後払い"&gt;Before - 何でもかんでも、後払い
&lt;/h2&gt;&lt;p&gt;水道光熱費やサブスクリプションなどの固定費、食料品や飲食の立替などの変動費。全ての支払いを後払いで支払っていました。後払いでは支払った実感のない私は、常にクレジットカードの請求額が大きな金額になっており、給与や副業収入のほとんどがクレジットカードの支払いに回っている状態でした。何に金を使っているのかもよく分からない状態で、資産が増えることはありませんでした。&lt;/p&gt;
&lt;p&gt;今思えば、クレジットカード会社の思う壺というか、いいカモだったと思います。便利で、ポイントも貯まるということで、わずかなポイントのために、大きな金額を浪費していたのです。&lt;/p&gt;
&lt;h2 id="after---後払いと都度払いをうまく使い分ける"&gt;After - 後払いと都度払いをうまく使い分ける
&lt;/h2&gt;&lt;p&gt;今はどうしているかというと、以下のようにキャッシュレス決済の方法を使い分けています。ほぼ、現金主義と同じです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;水道光熱費、自動車税、NHK受信料、火災・地震保険、ガソリン、高速（ETCカード）、高額決済（おおむね2万円以上）は、後払い（クレジットカード；JCBカード）。&lt;/li&gt;
&lt;li&gt;通勤や日常の移動に使っているモバイルSuicaは、都度払い（デビットカード；住信SBIネット銀行プラチナデビットカード）からチャージして利用。&lt;/li&gt;
&lt;li&gt;サブスクリプションや、その他の日常的な決済は、都度払い（デビットカード、またはiD；住信SBIネット銀行プラチナデビットカード）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こうすることのメリットはいくつもあります。要するに、「支払いの都度、残高が減るという現金払いのメリットと、利便性というキャッシュレスのメリットを両立できる」ということです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;常に現金が手元に残る&lt;/strong&gt;:　私の場合、後払いの金額が（高額になったとしても）月に10万円を超えることはなく、クレジットカードの引き落としが終わっても、常に手元に現金が残る。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;無駄遣いをしなくなる&lt;/strong&gt;:　支払いのたびに銀行口座の残高がリアルタイムに減っていくため、その範囲内で支払いを考えるようになって無駄遣いをしなくなる。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;資産の増減を日々確認できる&lt;/strong&gt;:　支払いの大半を都度払いで行うことで、家計簿に使っているMoneyForwardというアプリで、ほぼリアルタイムに家計簿が作られる。後払い（クレジットカード）の場合には、利用から明細が上がるまでのタイムラグがあり、リアルタイムというわけにはいかない。これにより、資産の増減を毎日見ることになるので、無駄遣いをやめようという気持ちがより強くなる。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="キャッシュレスの利点を損なうことはない"&gt;キャッシュレスの利点を損なうことはない
&lt;/h2&gt;&lt;p&gt;キャッシュレス決済のメリットの1つである迅速な支払いは保たれたまま、資産は増えていく。ポイント還元も、私が使っている住信SBIネット銀行のプラチナデビットカードであれば1.25%と、そこまで低くはありません。また、同カードは、ポイントが大体翌月の15日前後に付与され、設定次第では決済時にポイントが自動で充当されます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.netbk.co.jp/contents/lineup/debitcard/mastercard-platinum/" target="_blank" rel="noopener"
 &gt;住信SBIネット銀行 プラチナデビットカード(Mastercard)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://moneyforward.com/" target="_blank" rel="noopener"
 &gt;マネーフォワード｜家計簿アプリやクラウド会計ソフト&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;日本におけるキャッシュレス決済額のシェアは42.8%、そのうちデビットカードのシェアは2024年時点で3.1%（約4.4兆円）で、キャッシュレス決済額に占める割合としては少ないです。周りでも、不正利用があった場合の補償に不安があったり、そもそもデビットカードを認知していないケースがあったりします。&lt;/p&gt;
&lt;p&gt;クレジットカードでうまく家計ができている人にとって、デビットカードを使うメリットはあまり多くないかもしれませんが、私のように「使った感覚が薄く、つい無駄遣いしがち」という人にとっては、デビットカードも含めたキャッシュレス決済方法の使い分けは、資産を増やす上で重要な考え方になるかもしれません。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://sonohen.net/posts/2025/09/28/" &gt;クレジットカードとの上手な付き合い方&lt;/a&gt;もご紹介しています。ぜひ、本記事と合わせてご覧ください。&lt;/p&gt;</description></item><item><title>Apple Watch Ultra 2の先入観に惑わされながら、バンドの最適解がスポーツバンドであることを見落としていた日々</title><link>https://sonohen.net/posts/2025/09/05/</link><pubDate>Fri, 05 Sep 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/09/05/</guid><description>&lt;h2 id="apple-storeでは3種類のバンドがapple-watch-ultra-2用として販売されている"&gt;Apple Storeでは、3種類のバンドがApple Watch Ultra 2用として販売されている
&lt;/h2&gt;&lt;p&gt;私の「変な先入観」は、ここから始まったーー。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.apple.com/jp/shop/watch/bands/apple-watch-ultra" target="_blank" rel="noopener"
 &gt;Apple Watch Ultra 2 Apple Watchのバンドを購入&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Apple Watch Ultra 2を購入した際に付属していたのはブルーオーシャンバンド。その後、服装に合わせナチュラルチタニウムミナレーゼループ（長い……）を追加で購入しました。&lt;/p&gt;
&lt;h2 id="バンドの質はいいんだけどどこか着けづらい"&gt;バンドの質はいいんだけど、どこか着けづらい
&lt;/h2&gt;&lt;p&gt;あくまで「冒険する人のためのウォッチ」なので、バンドもそれに合わせて、外れにくいように、頑丈に作られているのです。ま、要は着けづらいということです。&lt;/p&gt;
&lt;p&gt;オーシャンバンドは留め具がキツく作られているし、ミナレーゼループは幅広でジャキジャキする。買ったこともつけたこともないですが、アルパインループも着けづらいというレビューを見たことがあります（慣れ次第とも言われてました）。&lt;/p&gt;
&lt;p&gt;「普段遣い」には、どうも適さないように思えていたのですが、先の先入観から別のバンドを試そうともあまり思わなかったのです。&lt;/p&gt;
&lt;h2 id="スポーツバンドはどうだろう"&gt;スポーツバンドはどうだろう？
&lt;/h2&gt;&lt;p&gt;Apple Watch Journalのこちらの動画。Apple Watch Ultra 2にスポーツバンドをつけているのです。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/esgz4DbtlOI" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;この動画を見たときに、「あれ、Ultra 2にスポーツバンドいけるんじゃない？」と思い、ナチュラルチタニウムミナレーゼループを、自宅にあるApple Watch 10のスポーツバンドに換装したところ、&lt;/p&gt;
&lt;p&gt;これは着けやすく、着け心地も快適だぞ！&lt;/p&gt;
&lt;p&gt;となったのです。&lt;/p&gt;
&lt;h2 id="割とこういうことは多いのではないか"&gt;割とこういうことは多いのではないか
&lt;/h2&gt;&lt;p&gt;変な先入観ってあると思います。色々な人がどのように使われているのかを見聞きすることで、それがきっかけで自分の考え方や行動が変わるのかもなあと思った経験でした。&lt;/p&gt;
&lt;p&gt;私はITエンジニアですが、この出来事から色々な勉強会に出て見識を広げるのも重要だなと考えました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="../../02/09/" &gt;NIFTY Tech Day 2025で思ったことと職場への持ち帰り&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Fitbit Charge 6から、結局Apple Watch Ultra 2に戻った話</title><link>https://sonohen.net/posts/2025/08/24/</link><pubDate>Sun, 24 Aug 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/08/24/</guid><description>&lt;p&gt;&lt;a class="link" href="../../05/25/" &gt;前回&lt;/a&gt;、Apple Watch Ultra 2を使うのをやめて、Fitbit Charge 6に移行した話を書きました。&lt;/p&gt;
&lt;p&gt;それから2ヶ月経ち、今、腕に巻いているのはApple Watch Ultra 2なのでした。&lt;/p&gt;
&lt;h2 id="戻った理由-スマホ無しで持ち出せるセルラーモデルはなんだかんだで便利"&gt;戻った理由① スマホ無しで持ち出せるセルラーモデルは、なんだかんだで便利
&lt;/h2&gt;&lt;p&gt;ウォーキングが趣味で、多い時には週7日、少ない時でも週3日は時間をとって歩くようにしています。&lt;/p&gt;
&lt;p&gt;その時に、スマホや家の鍵を持ち出すのは面倒だな、と思っています。&lt;/p&gt;
&lt;p&gt;そこで活躍するのが、Apple Watchの中でも通信機能を持つセルラーモデルです。それなら、外にいても通信できます。音楽を聴くのも、家族に位置情報を知らせるのも、家の鍵を開け閉めするのもApple Watch単体でできるので、スマホも家の鍵も持ち出す必要はありません。&lt;/p&gt;
&lt;p&gt;ウォーキング中におすすめなのが、Audible、Radiko、Apple Musicです。時間が溶けますよ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://apps.apple.com/jp/app/amazon%E3%82%AA%E3%83%BC%E3%83%87%E3%82%A3%E3%82%AA%E3%83%96%E3%83%83%E3%82%AF-%E3%82%AA%E3%83%BC%E3%83%87%E3%82%A3%E3%83%96%E3%83%AB/id379693831" target="_blank" rel="noopener"
 &gt;Audible&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://apps.apple.com/jp/app/radiko-for-watch/id1479983134" target="_blank" rel="noopener"
 &gt;radiko for watch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="戻った理由-アプリによるカスタマイズが便利"&gt;戻った理由② アプリによるカスタマイズが便利
&lt;/h2&gt;&lt;p&gt;先に挙げたAudibleやRadikoもですが、Apple Watchはアプリによって自分好みにすることができます。&lt;/p&gt;
&lt;p&gt;例えば、外出先でポイントカードを求められた時を思い浮かべます。財布を持っていなければ、ポイントを取り損ねます。&lt;/p&gt;
&lt;p&gt;ですが、Apple WatchにMembership Widgetというアプリを入れ、事前に設定しておけば、財布がなくてもポイントを貯めることができるのです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://apps.apple.com/jp/app/membership-widget/id1009897703" target="_blank" rel="noopener"
 &gt;Membership widget&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;私は他にも、天気系（Yahooの天気、防災速報アプリ）、楽天Pay、日経、StepsApp（歩数をわかりやすく見せるアプリ）を入れています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://apps.apple.com/jp/app/yahoo-%E5%A4%A9%E6%B0%97/id521974902" target="_blank" rel="noopener"
 &gt;Yahoo!天気&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://apps.apple.com/jp/app/yahoo-%E9%98%B2%E7%81%BD%E9%80%9F%E5%A0%B1/id481914139" target="_blank" rel="noopener"
 &gt;Yahoo!防災速報&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://apps.apple.com/jp/app/%E6%97%A5%E6%9C%AC%E7%B5%8C%E6%B8%88%E6%96%B0%E8%81%9E-%E9%9B%BB%E5%AD%90%E7%89%88/id396855834" target="_blank" rel="noopener"
 &gt;日本経済新聞電子版&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://apps.apple.com/jp/app/stepsapp-%E6%AD%A9%E6%95%B0%E8%A8%88/id1037595083" target="_blank" rel="noopener"
 &gt;StepsApp 歩数計&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特に楽天Payは、楽天ポイントカードとQRコード決済の両方をApple Watchでできるようになったので便利です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://apps.apple.com/jp/app/%E6%A5%BD%E5%A4%A9%E3%83%9A%E3%82%A4-%E6%A5%BD%E5%A4%A9%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%82%AB%E3%83%BC%E3%83%89%E3%82%82%E5%88%A9%E7%94%A8%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%B9%E3%83%9E%E3%83%9B%E6%B1%BA%E6%B8%88%E3%82%A2%E3%83%97%E3%83%AA/id1139755229" target="_blank" rel="noopener"
 &gt;楽天ペイ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また数ヶ月後、Fitbitに戻ってたり、はたまた違うスマートウォッチに変えていたりするかもしれませんが、その時はその時でまた理由づけをしようと思います（笑）。&lt;/p&gt;</description></item><item><title>Apple Watch Ultra 2をやめて、Fitbit Charge 6にした話（前編 - 背景編）</title><link>https://sonohen.net/posts/2025/05/25/</link><pubDate>Sun, 25 May 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/05/25/</guid><description>&lt;p&gt;&lt;a class="link" href="../../02/23/" &gt;先日、Apple Watch Ultra 2を秘書がわりに使っているということを記事にしました&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;Apple Watch Ultra 2は快適に使っていましたが、先日困ったことがありました。ゴルフの練習中に、グローブとボタンが干渉してしまい、意図せず大量のスクリーンショットが撮影されてしまったのです。設定でスクリーンショットの生成を止められることは分かっていますが、場合によっては誤動作を引き起こす可能性もあり、少し不安を感じ始めました。&lt;/p&gt;
&lt;p&gt;この経験から、Apple Watch Ultra 2の完成度について疑問を持つようになりました。Appleは開発者向けに、ゴルフコンパニオンとしてのApple Watchの機能を開発するためのAPIを公開（iPhone Mania）しています。にもかかわらず、グローブを装着して手首を曲げた際にボタンが干渉してしまうのは、Apple Watch Ultra 2自体の完成度としてどうなのかと疑問に思いました。（期待しすぎだったのかもしれません。）&lt;/p&gt;
&lt;p&gt;Apple Watch Ultra 2の挙動とプロダクトの完成度に少し残念な思いをしたことで、以前のような熱量が冷めてしまったというのが正直なところです。&lt;/p&gt;
&lt;h2 id="そもそもapple-watch-ultra-2が必要だったのか問題"&gt;そもそも、Apple Watch Ultra 2が必要だったのか？問題
&lt;/h2&gt;&lt;p&gt;ガジェットは、必要性ももちろん大事ですが、ロマンはもっと大事だと思っていますので、買うときに必要性だけを考えないようにしている、というのが前提にあります。&lt;/p&gt;
&lt;p&gt;その上で少し冷静になって、本当にApple Watch Ultra 2が必要だったのかを考えてみました。&lt;/p&gt;
&lt;p&gt;私の主な用途は、以下の4つです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;予定とメッセージの通知&lt;/li&gt;
&lt;li&gt;音声メモの収集&lt;/li&gt;
&lt;li&gt;健康状態の収集&lt;/li&gt;
&lt;li&gt;決済（モバイルSuicaとデビットカード（住信SBIデビットプラチナカード））&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらのために本当にApple Watch Ultra 2が必要なのか？と考えると、結構疑問なところがあります。音声メモの収集を除いて、他のスマートウォッチあるいはアクティビティトラッカーでできるからです。&lt;/p&gt;
&lt;p&gt;また、Apple Watch Ultra 2は単独で4G通信ができます。iPhoneを持ち歩かなくても通信ができるので、極端な話、Apple Watch Ultra 2だけで外出してもなんとかなりそうな気さえします。が、実際に私が出歩く限りはiPhoneを持ち歩かないということはほとんどない（近所のコンビニに行く時くらい）なので、あってもなくてもどちらでもいいや、というくらいの価値です。&lt;/p&gt;
&lt;p&gt;…さすがにApple Watch Ultra 2は高いのでは？と思い始めました。&lt;/p&gt;
&lt;h2 id="音声メモをどうするか"&gt;音声メモをどうするか？
&lt;/h2&gt;&lt;p&gt;私が音声メモを取りたいと思うのは、手が離せない状況ではなく、思いつきをそのまま言葉として記録しておきたい場面です。つまり、言語化がうまくできるかどうかは分からないが、そのもどかしさも含めて記録しておきたい場面、です。&lt;/p&gt;
&lt;p&gt;Apple Watch Ultra 2は、ほぼ24時間装着できた（充電の時間は除く）ので、ほぼ全てのそうした場面をカバーできていました。ゆえに、Apple Watch Ultra 2がなくなると困る場面は多々出てきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;トイレ&lt;/li&gt;
&lt;li&gt;風呂&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;といっても2つか……。これらの場面をどうやってカバーするかは、今後考えていかなければなりませんが、その他の場面においてはApple Watch Ultra 2が無くなっても問題はなさそうです。&lt;/p&gt;
&lt;h2 id="他のapple製品との連携をどう考えるか"&gt;他のApple製品との連携をどう考えるか？
&lt;/h2&gt;&lt;p&gt;Apple Watch Ultra 2と他のApple製品との連携で使われる（と思われる）のは、Handoff、AirPlayそしてiCloud連携です。そして、私が使っているのはAirPlay（AirPodsとの連携）と、iCloud連携（主にDrafts）です。&lt;/p&gt;
&lt;p&gt;前者（AirPlay）は、Apple Watch Ultra 2にダウンロードしたAudibleやApple Musicのデータを、Apple Watch単独で、iPhoneを持ち歩かずに視聴するために使っています。iPhoneを持ち歩かない場面は少ないため、Apple Watch Ultra 2単独でAirPlayが使えなくなる影響はほとんどないと考えています。&lt;/p&gt;
&lt;p&gt;後者（iCloud連携）は、Google Keepに移行すれば良いかなと思っています。Draftsをハブにしていろいろなアプリケーションにメモを飛ばす、というのがDraftsの目玉機能なのですが、私の場合は情報の一次収集場所くらいにしか使っていないので、Google Keepでも問題ないのです。&lt;/p&gt;
&lt;p&gt;ですので、この辺りも特に問題にはならなそうです。&lt;/p&gt;
&lt;h2 id="前編のまとめ"&gt;前編のまとめ
&lt;/h2&gt;&lt;p&gt;ゴルフの練習で感じたプロダクトとしての違和感で熱が冷め、冷静に用途を考えると、他のスマートウォッチ、アクティビティトラッカーでも十分代替できることがわかりました。&lt;/p&gt;
&lt;p&gt;次の記事では、Apple Watch Ultra 2の後任として、なぜFitbit Charge 6を選んだのかを執筆したいと思います。&lt;/p&gt;
&lt;h2 id="2025年8月24日追記"&gt;2025年8月24日追記
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="../../08/24/" &gt;結局、Apple Watch Ultra 2に戻りました&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id="2025年9月6日追記"&gt;2025年9月6日追記
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="../../09/05/" &gt;Apple Watch Ultra 2のバンドはスポーツバンドがいいよねという結論に至りました&lt;/a&gt;。&lt;/p&gt;</description></item><item><title>勉強会が仕事を変えてくれたという経験談</title><link>https://sonohen.net/posts/2025/04/29/</link><pubDate>Tue, 29 Apr 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/04/29/</guid><description>&lt;p&gt;&lt;a class="link" href="../../02/09/" &gt;今年の2月に、ニフティ社の勉強会に参加したことを記事にしました&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;この勉強会をきっかけに、社内勉強会への登壇回数を増やしました。その結果、予想以上の効果を実感したので共有します。&lt;/p&gt;
&lt;p&gt;なお、私はシステムエンジニアの端くれのため、テーマはIT関連（特にAIやクラウド設計）が多いです。&lt;/p&gt;
&lt;h2 id="効果1-アクティブラーニングによる理解促進定着"&gt;効果1 アクティブラーニングによる理解促進・定着
&lt;/h2&gt;&lt;p&gt;「テーマを決め、資料を作り、理解が足りない部分は補足し、他者へ教授する」という一連の過程で、理解が進み、定着する効果は大きいものがありました。&lt;/p&gt;
&lt;p&gt;例えば、「トランスフォーマーモデルの概要」をテーマにし、資料を作っている際に「自己注意機構（Self-attention mechanism）」というキーワードをきちんと説明できない自分がいました。一言で言えば、「文章における要素間の関係を捉えて文脈を理解するための仕組み」なのですが、これをわかるように平易に説明するのは難しいと感じています。&lt;/p&gt;
&lt;p&gt;なんとか形にして迎えた勉強会当日、説明した内容を全ての聴講者が理解したかは不明ですが、少なくとも自分で資料にして説明するという過程で、自分なりの理解が進み、定着したのではと思います。&lt;/p&gt;
&lt;h2 id="効果2-社内での認知度向上"&gt;効果2 社内での認知度向上
&lt;/h2&gt;&lt;p&gt;普段はプロジェクトに閉じた範囲で物事が完結することが多かった私ですが、プロジェクト外の活動である勉強会を通じて、社内での認知度が上がった（社内での交流関係の幅と深さが増した）ように思います。&lt;/p&gt;
&lt;p&gt;今まで接点のなかった人から「AI関連のプロジェクトで、AIも去ることながらクラウド設計の部分でも協力して欲しいことがあるんだけど」と声をかけていただいた（これをきっかけに仕事になりました）&lt;/p&gt;
&lt;p&gt;以前、同じプロジェクトを担当していた先輩から「当時は技術力があるなぁという印象はなかったけど、かなり深いところまでやってるんだね」と声をかけていただいた&lt;/p&gt;
&lt;p&gt;興味や腕に覚えのあることを自分から発信することで、社内での認知度が上がり、その結果として新しい仕事にチャレンジすることができていることを考えると、やはり自分から発信し、いろいろなチャンスを掴んでいくことが重要だなと認識しました。&lt;/p&gt;
&lt;h2 id="効果3-仕事の幅の広がり"&gt;効果3 仕事の幅の広がり
&lt;/h2&gt;&lt;p&gt;これはコツなのですが、勉強会では絶対に完璧を目指さない方が良いと思います。例えば、以下のような要素を残しておき、それを発表してしまう、ということです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ここまでは理解できたけど、ここから先はよくわからなかった&lt;/li&gt;
&lt;li&gt;この実装の課題はこうで、その解決策は思いついていない&lt;/li&gt;
&lt;li&gt;実装中にトラブってこんなエラーが出たけど、実は解決できなかった&lt;/li&gt;
&lt;li&gt;そもそも、自分に足りないところはこういうことだとわかった&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そうすると、わかる人が教えてくれたり、たまたま参加していた人が他の部署の人に繋いでくれたり、研修の機会を提供してくれたりします。そして、そこで得た知識やノウハウは、また別の機会の勉強会で発表をしたり、他部署と連名で発表したりするのです。&lt;/p&gt;
&lt;p&gt;私の場合は、当時の業務でできていないことを明確にしたことで、管理職が別部署に繋いでくれ、その部署の方にメンター役を担ってもらい業務をやり切っただけではなく、これから、その方と一緒に新しい仕事を始めようとしているところです。&lt;/p&gt;
&lt;p&gt;勉強会において、「わからない」「できていない」を残すことは、強力な武器になり得ることを理解して取り組むことが重要だなと、私は思います。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;勉強会に登壇するようになって仕事の幅も人脈も広がり、「会社って意外と面白いもんだな」と思うようになりました。余計忙しくなった気もしますが、その分充実しているということで、結果オーライだと思っています。&lt;/p&gt;
&lt;p&gt;そういう意味では、きっかけを与えてくださったニフティ社の方には感謝しています。&lt;/p&gt;
&lt;p&gt;今は社内での発表に閉じていますが、今後は社外への発表もしてみたいと思っているので、まずは社外の勉強会に今以上に積極的に出てみて、どんな雰囲気なのかを知り、どういうことができるのかを知りたいと思います。&lt;/p&gt;
&lt;p&gt;もし、私と同じような境遇を経た方で、今は社外に向けていろいろ発表してるよ、という方がいれば、どんなふうにして社外向け発表の最初の壁を乗り越えたのかなど、経験談を教えていただけると嬉しいです。&lt;/p&gt;</description></item><item><title>この3ヶ月で得た、仕事におけるAI活用と、人間の役割に関する重要な気づき</title><link>https://sonohen.net/posts/2025/03/24/</link><pubDate>Mon, 24 Mar 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/03/24/</guid><description>&lt;p&gt;この記事の内容は、あくまで私個人の見解であると同時に、仕事内容の詳細までを書くことはできないので、抽象的かつ意味不明な記載があると思いますが、悪しからずご了承ください。ただの仕事の感想文です。&lt;/p&gt;
&lt;p&gt;職業柄、数多のシステム開発プロジェクトに関わってきたが、それでも過去に扱ったことのない技術領域で、短期間でやり遂げなければならない仕事をやっていたのである。&lt;/p&gt;
&lt;p&gt;今回はシステム開発ではなく調査業務であり、キャッチアップ、課題設定、仮説設定・検証などを経て、成果をどうにか納めることができた。&lt;/p&gt;
&lt;p&gt;これができた理由は、以下の3つがあると考えている。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ピンポイントの技術の詳細は把握していないが、周辺に対する問題意識を常日頃から持っていた。&lt;/li&gt;
&lt;li&gt;色々な局面で使えるフレームワークを持っていた。&lt;/li&gt;
&lt;li&gt;AIエージェント（Perplexity.ai）が使える環境にあった。特に、初期のリサーチで大活躍した。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;こう考えた時に、1.と2.は人間だけができる仕事なのかなと思ったので整理しておくことにした。&lt;/p&gt;
&lt;h2 id="人間の役割"&gt;人間の役割
&lt;/h2&gt;&lt;h3 id="常日頃から問題意識を持つ"&gt;常日頃から問題意識を持つ
&lt;/h3&gt;&lt;p&gt;自分の周りの事柄に対して、「どうしてこういう仕組みになっているのだろうか？」、「なぜ、こうしたのか？」、「自分ならこうするのに」といった問題意識を持つ。そして、その事柄に対して興味を持ち、調べる。&lt;/p&gt;
&lt;p&gt;こうしたことの積み重ねが、「詳しくは知らないけれども、なんとなくわかる」ことの引き出しを増やすことに繋がっていく。引き出しは、いつの間にか他の引き出しと繋がり、これが独自性につながっていく。&lt;/p&gt;
&lt;p&gt;これにより、キャッチアップにかかる時間が短くなり、また、課題設定もどことなく的を射るようになってくる。要するに、仕事の成功率が高くなるのである。&lt;/p&gt;
&lt;h3 id="考えてaiエージェントを導く"&gt;考えてAIエージェントを導く
&lt;/h3&gt;&lt;p&gt;ただ考えるのではない。ある程度の縛り（枠）がないと考えることは難しい。例えば、「渋谷についてあなたの意見を述べてください」と言われても、ただただ困惑するのみではなかろうか。&lt;/p&gt;
&lt;p&gt;今までに、多くの頭の良い人たちが考えるための縛り（枠）を考えてきており、それらをフレームワークという。&lt;/p&gt;
&lt;p&gt;フレームワークのメリットには3つあると考えている。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;考える前段階で、考えるための枠をゼロから考える必要がない&lt;/li&gt;
&lt;li&gt;考え忘れが減る&lt;/li&gt;
&lt;li&gt;フレームワークを用途に合わせて組み合わせることで、より思考がクリアになる&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;まず、適当にAIエージェントに質問を投げる。そうすると、ディープリサーチを行い、回答を作ってくる。もっともらしい回答を作ってくるのだが、そこに偏りや検討漏れがないかを、フレームワークに当てはめて考えていく。&lt;/p&gt;
&lt;p&gt;偏りを補正しつつ、検討漏れの部分をさらに問うていく。この繰り返しで、生成された回答の質を高めていくのである。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;「生成AIを活用するには？」という言葉が散見されるように思う（私の周りだけ？）。やれ、動画作成にはXXだ、プレゼンテーション作成にはXXだ、といった具合である。&lt;/p&gt;
&lt;p&gt;今や色々なツールにAIが組み込まれており、適材適所で使えた方が良いということに反対するつもりはないのだが、ツールを使いこなすために必要な土台に考えを巡らせなければいけないのではないかと思ったので、この記事を書いた。&lt;/p&gt;</description></item><item><title>AWS SysOps Administrator - Associate合格記</title><link>https://sonohen.net/posts/2025/02/16/</link><pubDate>Sun, 16 Feb 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/02/16/</guid><description>&lt;p&gt;&lt;a class="link" href="../../01/26/" &gt;先月、AWS Certified Solutions Architect - Professionalに合格しました&lt;/a&gt;。こういうものは、連続して受験してしまうのが、記憶が新鮮なうちに対策ができるので有利なわけです。また、Solutions Architect - Professionalも余裕（844点）で合格していたので、Associate資格で残っているSysOps Administrator - Associate（以下SOA）は、それほど手こずらずに取得できると思ったのです。&lt;/p&gt;
&lt;p&gt;ところがどっこい、正直、過去一難しかったです。Solutions Architect - Professionalの時よりも感触が悪く、マジで落ちたと思った。&lt;/p&gt;
&lt;h2 id="受験前の状態"&gt;受験前の状態
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;CLF, SAA, DVA, SAPPro取得済み（SAProは844点）&lt;/li&gt;
&lt;li&gt;AWSが出しているサンプル問題は、SAPPro合格後、対策を始めた時点で100%正解。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="試験中の感想"&gt;試験中の感想
&lt;/h2&gt;&lt;p&gt;一問目から分からねぇ・・・。&lt;/p&gt;
&lt;h2 id="試験結果"&gt;試験結果
&lt;/h2&gt;&lt;p&gt;789点。以下の分野は「改善が必要」でした。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一分野：モニタリング、ロギング、および修復&lt;/li&gt;
&lt;li&gt;第四分野：セキュリティとコンプライアンス&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="何が良くなかったのか"&gt;何が良くなかったのか
&lt;/h2&gt;&lt;h3 id="最初から自信過剰になっていた"&gt;最初から自信過剰になっていた
&lt;/h3&gt;&lt;p&gt;AWSが出しているサンプル問題で、対策前に全問正解した時点で、正直「何もしなくても受かるかも」と自信過剰になっていました。SOAは特に難しいと聞いたことがあるので、その認識をきちんと持った対策をすべきでした。&lt;/p&gt;
&lt;h3 id="ハンズオンをしなかった"&gt;ハンズオンをしなかった
&lt;/h3&gt;&lt;p&gt;今回、問題集を使っていて分からないサービスがあった時には、ブラックベルトも読まず、ハンズオンもしませんでした。結果、理解があやふやなまま試験に突入しました。&lt;/p&gt;
&lt;h2 id="次どうしようか"&gt;次、どうしようか
&lt;/h2&gt;&lt;p&gt;Solutions Architect - Professionalまでは、自分なりに「AWSの裏側ってこんな感じになっているのかな」とかを調べながら勉強していたので理解が深まったように思えますし、それが点数にも繋がったのだと思います。&lt;/p&gt;
&lt;p&gt;SOAは、試験に合格するための勉強をしてしまいました。悪いことではないのですが、AWSを生業にしている人間としては、試験に合格することよりも試験勉強を通じてAWSを理解することを目的とすべきであって、その点においては同じ時間を使うにしてもだいぶ勿体無かった気がしていますし、点数もギリギリになってしまいました。&lt;/p&gt;
&lt;p&gt;次はDeveloper - Professionalを受験しようと思っていますが、少し時間を長めにとって、ハンズオンやブラックベルトを通してAWSの仕組みをもう少しきちんと理解するようにしてから試験に臨みたいと思いました。&lt;/p&gt;
&lt;h2 id="終わりに"&gt;終わりに
&lt;/h2&gt;&lt;p&gt;今回、半額になるバウチャーを使ったとはいえ、受験費用は11,000円でした。安くはない試験ですので、きちんと自信を持って取り組むことができるように準備はしたいものです。&lt;/p&gt;
&lt;p&gt;これで、以下の資格を取り終えました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AWS Certified Cloud Practitioner&lt;/li&gt;
&lt;li&gt;AWS Certified Solutions Architect - Associate&lt;/li&gt;
&lt;li&gt;AWS Certified Developer - Associate&lt;/li&gt;
&lt;li&gt;AWS Certified SysOps Administrator - Associate&lt;/li&gt;
&lt;li&gt;AWS Certified Solutions Architect - Professional&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>参加者として勉強会の定着率（学習効果）を最大化する方法を考えてみた</title><link>https://sonohen.net/posts/2025/02/11/</link><pubDate>Tue, 11 Feb 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/02/11/</guid><description>&lt;p&gt;先日、&lt;a class="link" href="../../02/09/" &gt;NIFTY Tech Day 2025に参加しました&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;その中で、学習方法によって定着率が変わるという「ラーニングピラミッド」の概念を知りました。せっかく参加した勉強会、定着率を上げたいと思いますよね？&lt;/p&gt;
&lt;p&gt;あまり時間をかけず、定着率を上げるための方法を検討してみたので、共有させてください。&lt;/p&gt;
&lt;h2 id="きっかけ"&gt;きっかけ
&lt;/h2&gt;&lt;p&gt;私は手書きでメモを取る派でした。いろいろな意見があると思いますが、私が考える手書きメモの最大のメリットは自由であることです。前後左右、自由に構造化できますし、関連を線で表現することもできます。&lt;/p&gt;
&lt;p&gt;その一方で、分からない言葉が出てくると、スマホや辞書などを使って調べて、調べた結果をメモに書くことになります。この方法では、分からない言葉が多発してくる場合に、いささか不便です。&lt;/p&gt;
&lt;p&gt;ふと思い浮かんだのは「マインドマップを使ってメモを取れば良いのでは？」というありきたりな考えです。手書きメモに近しい自由度で書くことができますし、分からない言葉はその場でAIに聞き、回答をマインドマップに反映することができます。&lt;/p&gt;
&lt;p&gt;今回、勉強会中のメモは手書き、勉強会後のまとめにはNotionを使いました。分からない言葉は手書きメモに印をつけておき、NotionでまとめるときにNotion AIに聞きながら整理しました。AIを勉強会中に使えばもっと効率的、効果的だったのでは、と思いましたが、手書きメモ、およびマインドマップとAIの組み合わせでは、どちらの方が定着率が高まるのかが分からない状況でした。&lt;/p&gt;
&lt;h2 id="定着率を高めるにはラーニングピラミッドによる他者への教授"&gt;定着率を高めるには（ラーニングピラミッドによる「他者への教授」）
&lt;/h2&gt;&lt;p&gt;そこで出てくるのがラーニングピラミッドです。学習方法によって定着率が変わるということを示すもので、定着率が低いもの、高いものにはそれぞれ以下があります（括弧内は定着率）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;定着率が低いもの　講義（5%）、読書（10%）、視聴覚（20%）&lt;/li&gt;
&lt;li&gt;定着率が高いもの　グループ討論（70%）、実践・体験（75%）、他者への教授（90%）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;勉強会は「講義」でしたので、これを「他者に教える」ところまで持っていくことが定着率を高める上で有効であると考えました。&lt;/p&gt;
&lt;h2 id="とはいえとはいえ時間がなければ機会もそう恵まれるものではない"&gt;とはいえとはいえ、時間がなければ機会もそう恵まれるものではない
&lt;/h2&gt;&lt;p&gt;とはいえとはいえ、の元ネタ。&lt;/p&gt;
&lt;p&gt;勉強会に出るところまでが精一杯で、その後、内容を整理して、その上、人に教えている時間まではない、というのがほとんどではないでしょうか。私は、過去に何回も勉強会に参加したことはありますが、その場でメモを取る程度で、勉強会の後に整理し、さらに人に教える、ということはやったことがありませんでした。そのメモも、どこへ行ったかわかりません。&lt;/p&gt;
&lt;p&gt;とはいえ、ラーニングピラミッドが示すように、人に教えるということの効果は無視できるものではありません。&lt;/p&gt;
&lt;p&gt;まず考えたのは、人に教えるということです。会社の勉強会はあるにはありますが、スケジュールが微妙な時があります。それに、そもそも適した勉強会がなかったりします。そこで、「noteでもどこでも良いので、勉強会の内容をシェアするということをやってみてはどうだろうか？」ということです。インターネットであれば、時間の制約なくいつでも見てもらえるので、「人に教える」ことの代替手段になるのではないかと考えました。&lt;/p&gt;
&lt;p&gt;ここでポイントになるのは、内容を整理するところにかかる時間をいかに短縮できるか、です。&lt;/p&gt;
&lt;p&gt;まず、人に教えるためには自分が理解していなければいけません。勉強会終了時点で、自分の頭の中が構造化されており、不明な言葉がない状態になっていることが理想です。そのために最も重要なのは「勉強会中に分からないことを解消しておく」ことです。常にAIに触れるようにしておき、分からない言葉が出てきたらAIに調べてもらうのです。それでも分からないことは質問してみましょう。勉強会が終わるまでに内容を理解しておくことが大切です。&lt;/p&gt;
&lt;p&gt;次に、すぐに共有できる状態にしておくということです。先ほど「noteでもどこでも良いので」と書きましたが、共有先はインターネットです。その際、扱いやすいデータは共有に使うプラットフォーム次第ではありますが、私の場合はnoteを使っているので、Markdown形式が最も扱いやすい形式です。note以外にも、NotionやGammaもMarkdownをサポートしています。&lt;/p&gt;
&lt;p&gt;人に教えられるように理解したトピックを、Markdownのように自分が扱いやすいデータにしておく。これが時短しながら内容を整理するために必要なことだと考えます。&lt;/p&gt;
&lt;h2 id="実例と改善点"&gt;実例と改善点
&lt;/h2&gt;&lt;h3 id="メモをメモ帳で取る--勉強会中"&gt;メモをメモ帳で取る @ 勉強会中
&lt;/h3&gt;&lt;h4 id="今回"&gt;今回
&lt;/h4&gt;&lt;p&gt;今回は、勉強会のメモを手書きで取りました。いくつか分からない言葉がありましたが、その言葉には後で調べられるように印をつけておきました。&lt;/p&gt;
&lt;h4 id="今後"&gt;今後
&lt;/h4&gt;&lt;p&gt;このプロセスは必要ありません。手書きでメモを取るということは、それをデジタル形式に変換する必要があるということで、その手間がかかります。今後は、はじめからマインドマップにメモを取ろうと考えています。これも後で整理する必要がある点で手書きメモと変わりませんが、コピペができる分、手間は省けます。&lt;/p&gt;
&lt;h3 id="整理しながらnotionに転記する--勉強会後"&gt;整理しながらNotionに転記する @ 勉強会後
&lt;/h3&gt;&lt;h4 id="今回-1"&gt;今回
&lt;/h4&gt;&lt;p&gt;勉強会が終わった後、メモ帳に書いたメモをNotionに転記しました。後から見返してもわかるように記述すること、先に印をつけた言葉を調べました。この時に、Notion AIが大活躍しました。時間にして約1時間程度はかかりました。&lt;/p&gt;
&lt;p&gt;復習にもなるので良いプロセスだとは思いますが、本質的には不要なプロセスです。なぜなら、メモを整形するという過程において定着率は上がらないからです。分かっているものを読んでも学習効果がないのと同じです。&lt;/p&gt;
&lt;h4 id="今後-1"&gt;今後
&lt;/h4&gt;&lt;p&gt;Miroのマインドマップでメモをとり、その裏で言葉をすぐに調べられるようにperplexity.aiでも動かすことにして、今後はこのプロセスは廃止したいと考えています。&lt;/p&gt;
&lt;h3 id="notionからnoteに転記する--勉強会後"&gt;Notionからnoteに転記する @ 勉強会後
&lt;/h3&gt;&lt;h4 id="今回-2"&gt;今回
&lt;/h4&gt;&lt;p&gt;勉強会の情報は、タイトル、開催日時、場所、そして先にまとめた勉強会の内容をNotionに集約しています。今後も、この取り組みは続けていきたいと思っています。&lt;/p&gt;
&lt;h4 id="今後-2"&gt;今後
&lt;/h4&gt;&lt;p&gt;今後は、勉強会ごとに作ったマインドマップをNotionに取り込んでおくことにしたいと思います。&lt;/p&gt;
&lt;p&gt;そして、マインドマップをもとにnoteに掲載する記事を執筆します。このプロセスは、自分用のメモから、人に教えるための記事を起こすことになるので、読みやすく、わかりやすく記載する必要があります。このプロセスは脳を活性化しますので、定着率の向上に貢献します。しかし、マインドマップであらかじめ視覚的に構造化していますので、まっさらな状態から記事を起こすよりも時間はかかりません。&lt;/p&gt;
&lt;p&gt;ここで書いた記事は、noteに掲載します。Notionにまとめている勉強会の情報には、noteのURLも記載しておきます。こうすることで、自分用のメモと、人への共有に使った記事の両方が勉強会の情報から参照できるようになります。&lt;/p&gt;
&lt;h3 id="notionからgammaに転記する--勉強会後"&gt;NotionからGammaに転記する @ 勉強会後
&lt;/h3&gt;&lt;h4 id="今回-3"&gt;今回
&lt;/h4&gt;&lt;p&gt;noteの記事をGammaにコピペすれば、ある程度の形になってプレゼンテーション用の資料が作られました。適当に手直しをし、保存しておきます。Gammaの共有リンクを、Notionに記録している勉強会の情報に追記しておきます。&lt;/p&gt;
&lt;h2 id="終わりに"&gt;終わりに
&lt;/h2&gt;&lt;p&gt;今回書いていて思いましたが、マインドマップでメモをとるということは、マインドマップの外にある情報（過去のマインドマップ）とリンクを直接的に取る方法がない、ということになります。この点、メモはトピックを超えて相互参照しやすいというメリットはありそうです。この点をどう運用するかは今後考えなくてはと思いました。&lt;/p&gt;
&lt;p&gt;そもそも思いましたが、勉強会中にパソコンを立ち上げていると、後ろの人から覗き見されて「そんなことメモしてるのかよ」と思われそうだなと思いました。&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;p&gt;&lt;img src="https://sonohen.net/posts/2025/02/11/images/tegaki.webp"
	width="1727"
	height="1266"
	loading="lazy"
	
		alt="勉強会中に書いた手書きメモの一部"
	
	
		class="gallery-image" 
		data-flex-grow="136"
		data-flex-basis="327px"
	
&gt;&lt;/p&gt;
&lt;p&gt;手書きメモの一部。これをMarkdownに変換するのは結構めんどい。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2025/02/11/images/mindmap.webp"
	width="1631"
	height="832"
	loading="lazy"
	
		alt="マインドマップ"
	
	
		class="gallery-image" 
		data-flex-grow="196"
		data-flex-basis="470px"
	
&gt;&lt;/p&gt;
&lt;p&gt;この記事のマインドマップ。このように構造化し、関連を線で表現すれば手書きメモ並の自由度は得られそう。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2025/02/11/images/gamma.webp"
	width="2400"
	height="1350"
	loading="lazy"
	
		alt="Gammaで生成したスライド"
	
	
		class="gallery-image" 
		data-flex-grow="177"
		data-flex-basis="426px"
	
&gt;&lt;/p&gt;
&lt;p&gt;手書きメモをMarkdownに変換し、それをGammaでスライドに変換したもの&lt;/p&gt;</description></item><item><title>NIFTY Tech Day 2025で思ったことと職場への持ち帰り</title><link>https://sonohen.net/posts/2025/02/09/</link><pubDate>Sun, 09 Feb 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/02/09/</guid><description>&lt;p&gt;2025年が始まってもう1ヶ月が経過しましたが、皆さんはもう勉強会やセミナーには参加していますか？&lt;/p&gt;
&lt;p&gt;私は年初に「個人として毎月1回以上、勉強会に参加する」という目標を立てました。そして、NIFTY Tech Day 2025が今年初めての参加でした。参加によって刺激を受け、インターネットに学んだことをアウトプットすることも目標に加わりました。&lt;/p&gt;
&lt;p&gt;ここでは私の感想と、職場への持ち帰りと実践をどう考えているかを記述したいと思います。&lt;/p&gt;
&lt;p&gt;勉強会の学習効果を高めるにはどうしたらよいかを考えてみました。こちらも参考にしていただけると嬉しいです。&lt;/p&gt;
&lt;p&gt;この勉強会を機に、自身も勉強会に登壇するようになりました。その結果、仕事が大きく変わったので、その経験談を書いてみました。こちらも参考にしていただけると嬉しいです。&lt;/p&gt;
&lt;h2 id="aiと協働する次世代開発スタイル---求められる新たなスキルと役割の変化"&gt;AIと協働する次世代開発スタイル - 求められる新たなスキルと役割の変化
&lt;/h2&gt;&lt;p&gt;AIと人間が協働するステージには3段階がありますが、現在最も高度とされるのは「エージェント型AIとの協働」です。エディタに生成AIが組み込まれるようになったことで、以下の3つの形態で進化してきました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文脈を理解し、適切なプログラムコードを補完する「自動補完型」&lt;/li&gt;
&lt;li&gt;プロンプトを通じて対話形式でコードを生成する「対話型」&lt;/li&gt;
&lt;li&gt;目的達成のために必要な作業を実行する「エージェント型」&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一部（社内）では「生成AIによってシステムエンジニアの仕事が減少する」という意見もありますが、私はむしろ「やるべきことが増え、専門性が一層求められるようになった」と考えています。その理由は、生成AIの性能向上に伴い、人間がAIの生成物をレビュー・承認する作業の難易度が高まっているからです。このプロセスでは、必ず人間がボトルネックになります。&lt;/p&gt;
&lt;p&gt;生成AIを効果的に活用するためには、レビューしやすい出力を得られるようAIをコントロールするスキルが求められます。また、レビューには知識が必要であり、そのためにカバーすべき領域が広がることや、チームで協力して対応する重要性も増しています。&lt;/p&gt;
&lt;p&gt;こうした状況を踏まえると、「オープンソースの知識を深く持つ優秀な人材がチームに加わり、その生成能力で他メンバーに影響を与えている」という現実を、いかにコントロールして良い方向へ導くかが課題になると感じており、対応が必要だと認識しています。&lt;/p&gt;
&lt;p&gt;さらに、「インナーソース」という概念は初めて知りました。これは企業内でオープンソース活動を展開する取り組みです。生成AIがプロプライエタリなソースコードではなく、オープンソースコミュニティの成果物から学習しているという事実に基づくと、オープンソースコミュニティの流儀やスタンダードを組織内に取り入れるかどうかが、生産性向上の鍵となる可能性があります。&lt;/p&gt;
&lt;h2 id="エンジニアの殻を破るインナーソースと社外活動がもたらした成長"&gt;エンジニアの殻を破る：インナーソースと社外活動がもたらした成長
&lt;/h2&gt;&lt;p&gt;「インナーソース」をニフティ社内で展開した功労者の方による講演でした。この取り組みはエンジニアだけでなく、ビジネス部門も巻き込み、ビジネス部門のメンバーがシステム設定ファイルの一部をプルリクエストで更新できる仕組みも構築したとのことです。また、次のトピックでも触れられていましたが、「将来的にメリットが学習コストを上回るなら、学習してもらう」という姿勢は非常に参考になると感じました。&lt;/p&gt;
&lt;p&gt;特に印象的だったのは、「社外活動は話を聞くところから始めよう。社外の勉強会に参加し、アウトプットしていこう」というメッセージです。講演者自身も、インナーソースについては勉強会への参加からスタートし、人脈を広げていったと語っていました。この姿勢を見習い、自分も積極的に行動しなければと感じました。&lt;/p&gt;
&lt;h2 id="自社製cmsからの脱却10件のwebサイト再構築に学ぶ運用重視の技術選定"&gt;自社製CMSからの脱却：10件のWebサイト再構築に学ぶ運用重視の技術選定
&lt;/h2&gt;&lt;p&gt;レガシーシステムの更新を組織課題として捉え、将来を見据えたアーキテクチャ設計と必要な教育を実施した結果、過去に何度も失敗してきた切り替えに成功したとのことです。プロトタイプを作成しながら設計を改善し、最終的には運用面も含めて高評価を得る設計に仕上げたそうです。&lt;/p&gt;
&lt;p&gt;また、更新前のシステムと比較してリードタイムが短縮され、新規サイトの投入スピードも向上したため、IT部門とビジネス部門の双方にメリットがあったようです。&lt;/p&gt;
&lt;p&gt;さらに、コンポーネント名の統一によって、生成AIが設計意図を正確に理解し対応できるようになった点も興味深いポイントです。特に詳細設計では、明確な目的意識を持った設計が重要であることが改めて示されました。&lt;/p&gt;
&lt;h2 id="スクラムマスター入門者のための学習マップ-効果的な学びと実践"&gt;スクラムマスター入門者のための学習マップ 効果的な学びと実践
&lt;/h2&gt;&lt;p&gt;スクラム開発を経験したと口にしながらも、「複雑なものへの対応」の仕組みについては知らなかったことに改めて気づきました。私が経験したのは、仕様が明確に定まらないためにウォーターフォールではなくスクラムを採用したというケースでした。&lt;/p&gt;
&lt;p&gt;実際、スクラムには「技術・実装」「プロダクトとビジネス」「人と組織」「改善」の4つの象限が存在し、これらは独立しているのではなく互いに重なり合っています。それぞれ、開発者、スクラムマスター、プロダクトオーナーといった各役割が注目すべきポイントも異なります。&lt;/p&gt;
&lt;p&gt;これまで自分が抱いていたスクラムマスター像とは異なる面があり、より深く学ぶほどにその役割の奥深さと面白さに気付かされました。&lt;/p&gt;
&lt;p&gt;SCRUMMASTER THE BOOK 優れたスクラムマスターになるための極意――メタスキル、学習、心理、リーダーシップに書いてありますが「組織改革に立ち向かうあなたに知恵と勇気を与えます」とあるとおり、開発自体の話ではなく、もっと広い範囲の話であると認識しました。無知は恐ろしいと改めて思い、また興味があるのでもっと調べてみようと思います。と思っていたら、野中先生も本を書いていらっしゃる。アジャイル開発とスクラム 第2版 顧客・技術・経営をつなぐ協調的ソフトウェア開発マネジメント&lt;/p&gt;
&lt;h2 id="学びを文化に変えるニフティの内製研修と継続的成長の仕組み"&gt;学びを文化に変える〜ニフティの内製研修と継続的成長の仕組み〜
&lt;/h2&gt;&lt;p&gt;ラーニングピラミッドの中でも、学習定着率が高いとされるアクティブラーニング（「グループ討論」「実践・体験」「他者に教える」）を、ニフティ社内の内製研修で実践しているとのことです。特に興味深かったのは、研修の参加方式として「オプトアウト方式」を採用した点です。これは、研修を基本的に「参加」とし、「欠席」の場合のみ事務局に連絡する仕組みで、この変更により参加率が1割から7割にまで向上したそうです。&lt;/p&gt;
&lt;p&gt;私自身もアクティブラーニングを社内勉強会で活用してみたいと感じました。また、社内勉強会を高度化させることに抵抗がある人に向けては、社内ブログのようなプラットフォームを構築するのも面白いアイデアだと思いました。これにより、後から情報を検索しやすくなるだけでなく、講師役を避けたい人にも知識共有の選択肢を提供できるのではないかと考えています。&lt;/p&gt;
&lt;h2 id="社内seとしての進化aiツールを活かすネットワークエンジニアの新たな挑戦"&gt;社内SEとしての進化：AIツールを活かすネットワークエンジニアの新たな挑戦
&lt;/h2&gt;&lt;p&gt;エンジニア不足の話は私もよく耳にしますが、セシール社でも同様に人手が足りない中で、業務効率の低下やコミュニケーションの課題、セキュリティリスクの増加といった問題を抱えているとのことです。これらの課題に対して、情シス部門の規模に適した形で解決策を模索していく必要があると感じました。&lt;/p&gt;
&lt;p&gt;具体的には、ナレッジマネジメントを活用して「人に聞く頻度」を減らす効率化や、紙運用を削減するためのAI-OCR導入、さらにセキュリティログ監視へのAI活用などが挙げられていました。事業会社のIT部門にはこうした多岐にわたる取り組みが求められ、大きなやりがいがあると感じながらお話を拝聴しました。&lt;/p&gt;
&lt;h2 id="終わりに"&gt;終わりに
&lt;/h2&gt;&lt;p&gt;大変貴重なお話をお伺いさせていただいたと思っています。また来年も、ぜひ参加させていただければと思いました。&lt;/p&gt;
&lt;h2 id="後日追記"&gt;後日追記
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="../../02/11/" &gt;勉強会での学習効果を最大化する方法を考えました&lt;/a&gt;。&lt;/p&gt;</description></item><item><title>Apple Watch Ultra 2で思考と行動が整理できた話</title><link>https://sonohen.net/posts/2025/02/23/</link><pubDate>Sun, 26 Jan 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/02/23/</guid><description>&lt;p&gt;ある程度、Apple Watchの使い方に慣れている方を対象にしています。&lt;/p&gt;
&lt;h2 id="思考と行動の関係と本記事の結論"&gt;思考と行動の関係と本記事の結論
&lt;/h2&gt;&lt;p&gt;前提である「思考と行動の関係」を整理したいと思います。人それぞれ色々な考え方があると思いますが、私が考える思考と行動の理想的な関係は以下の図に示すものです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2025/02/23/images/outline.webp"
	width="2400"
	height="1488"
	loading="lazy"
	
		alt="思考から行動までの個人的な理想形"
	
	
		class="gallery-image" 
		data-flex-grow="161"
		data-flex-basis="387px"
	
&gt;&lt;/p&gt;
&lt;p&gt;このように「思考と行動の間に2つの袋を置くことで、思考と行動はスムーズに連係する」というのが私の考え方です。それぞれの袋をわかりやすく表現すると以下のようになります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;忘れないための袋&lt;/strong&gt;:　メモアプリ（Draftsなど）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;行動するための袋&lt;/strong&gt;:　カレンダーアプリ、リマインダーアプリなど&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本記事が最も言いたいことは、以下の3点です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2つの袋は、完全にデジタル化する。&lt;/li&gt;
&lt;li&gt;「忘れないための袋」はDraftで管理し、取りこぼしなく集約するために、Apple Watch Ultra 2から音声入力で情報を記録する。&lt;/li&gt;
&lt;li&gt;「行動するための袋」は、情報の種類に応じてカレンダー/リマインダー/Notion/今日の支出で管理し、「忘れない袋」を定期的に確認してそれらに移す。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下で詳細を示します。&lt;/p&gt;
&lt;h2 id="2つの袋は整理されていなかった"&gt;2つの袋は整理されていなかった
&lt;/h2&gt;&lt;p&gt;まず、2つの袋は管理されていませんでした。具体的には以下の状態でした。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;忘れないための袋　Moleskine、Onenote、Notion、付箋紙、iPhoneのメモ&lt;/li&gt;
&lt;li&gt;行動するための袋　Google Calendar、iCloud Calendar、紙のカレンダー、付箋紙、iPhoneのリマインダー、Todoist、Omni Focusなど&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こうした状況でも、仕事や日常生活に支障は出ていませんでした。散らばっていても、その様は本人が一番よくわかっているということです。一番の問題は、「やりたいことができなくなっていた」ことです。情報が散らばっていると、情報の格納と検索で脳が疲労状態になります。そうすると、何をすれば良いのかが段々とわからなくなってきます。夢やビジョン、趣味に向かって計画し、実行できている実感が薄れてきます。&lt;/p&gt;
&lt;p&gt;今まで、何度かこうした管理を徹底してきましたが、少し油断すると上記のような状態になってしまうのが常でした。改善しなければと考えていた時、Apple Watch Ultra 2のアクションボタンのことを思い出しました。「うまく活用できれば、思考と行動の理想形を実現できるのではないか」と考え、Apple Watch Ultra 2を購入し、改善に取り組みました。&lt;/p&gt;
&lt;h2 id="改善後"&gt;改善後
&lt;/h2&gt;&lt;p&gt;それぞれ、以下のように整理をしました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;忘れないための袋&lt;/strong&gt;:　Draftsに音声入力する。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;行動するための袋&lt;/strong&gt;:　Draftsに登録されたメモを識別・分類し、予定はGoogle Calendar、タスクはリマインダー、メモはNotion、支出は今日の予算に登録する。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="実現できた理由はapple-watch-ultra-2によるものが大きかった"&gt;実現できた理由はApple Watch Ultra 2によるものが大きかった
&lt;/h2&gt;&lt;p&gt;これが実現できた理由には、大きく直接的な理由と間接的な理由の2つがあります。&lt;/p&gt;
&lt;p&gt;まず、直接的な理由はApple Watch Ultra 2を購入したことです。画面サイズが大きく、処理性能が高いので、ショートカットやアプリを画面上に多く配置できたり、音声入力の精度やアプリの起動速度に不足はありません。&lt;/p&gt;
&lt;p&gt;次に、間接的な理由で、これには2つあります。&lt;/p&gt;
&lt;p&gt;1つがリモートワーク環境になったことです。これにより、仕事中でも音声入力ができるようになりました。同僚から予定が送られてきても、Draftsに音声で予定の情報を入れておけば良いのです。&lt;/p&gt;
&lt;p&gt;もう1つが、Siriやアプリを活用しやすくなったことです。これはApple Watch Ultra 2の画面サイズや処理性能の高さに関連するものですが、音声認識が速くなったことでSiriが使いやすくなっていますし、アプリに関しては文字が見やすくなったり、起動速度も申し分ありません。&lt;/p&gt;
&lt;p&gt;そして、Apple Watch Ultra 2のアクションボタンです。物理的なボタンが具備されており、それを押下すると、あらかじめ設定したアプリが起動します。私はこれにDraftsを起動するショートカットを割り当てています。起動する敷居が高いもの（ネガティブ感のあるもの：お金や体重管理など）をアクションボタンに割り当てると、そうしたものも管理しやすくなるかもしれません。私は、Apple Watch 10も所有していますが、物理ボタンの利便性は極めて高いです。&lt;/p&gt;
&lt;h2 id="ワークフロー"&gt;ワークフロー
&lt;/h2&gt;&lt;p&gt;ここでは、私が試し、改良しているワークフローを紹介します。&lt;/p&gt;
&lt;h3 id="思考で得た情報はまず1つの袋に入れる"&gt;思考で得た情報は、まず1つの袋に入れる
&lt;/h3&gt;&lt;h4 id="2つの重要なこと"&gt;2つの重要なこと
&lt;/h4&gt;&lt;p&gt;1つは、&lt;strong&gt;自分に降りかかってくる情報に対して、反応的な行動をしないこと&lt;/strong&gt;です。スマホを見ていると、通知が多く送られてきます。それに反応しているうちに1日が終わってしまった、ということもあるのではないかと思います。通知を受けて即、行動しなければならないものはほとんどなく、いちいち反応していては時間がいくらあっても足りません。まずは、情報を「忘れないための袋」に入れ、対応は後で考えるということを原則にした方が良いと考えています。&lt;/p&gt;
&lt;p&gt;もう1つは、&lt;strong&gt;分類しないこと&lt;/strong&gt;です。ここでの目的は、とにかく全ての情報を1つの袋に入れることです。情報の分類は脳の負担が大きい行為です。これをしてしまうと、1つの袋に情報を入れることが面倒になり、やらなくなります。そうして待っているのは、管理不能な状態で、日常に追われる毎日です。&lt;/p&gt;
&lt;h3 id="忘れないための袋に情報を格納する"&gt;「忘れないための袋」に情報を格納する
&lt;/h3&gt;&lt;p&gt;ここでは、Draftsというアプリを使います。このアプリのコンプリケーションをApple Watchのフェイス画面に設定します。そして、これをタップすると、すぐに音声入力ができる状態になります。&lt;/p&gt;
&lt;p&gt;使い方は以下のサイトに詳しく書いてありますので、ご参考になさってください。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://teineini.net/20191114-memo-drafts/" target="_blank" rel="noopener"
 &gt;すべてのメモの入り口を「Drafts」にすれば迷いがなくなる&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="忘れないための袋に入っている情報は定期的に識別分類し別の袋に移すか捨てる"&gt;「忘れないための袋」に入っている情報は、定期的に識別・分類し、別の袋に移すか捨てる
&lt;/h3&gt;&lt;p&gt;この時点で、「忘れないための袋」に入っている情報は玉石混合です。これらの情報が何なのかを識別し、適切な場所に移します。例えば、「2月25日17:00　山田さんと打ち合わせ」という情報が入っていたとすると、これは予定に分類できます。このほかに、私は以下の4つに分類しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;予定&lt;/li&gt;
&lt;li&gt;タスク&lt;/li&gt;
&lt;li&gt;残しておくべき価値のあるメモ&lt;/li&gt;
&lt;li&gt;支出&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;個人的な感覚として、これ以上増えると利用するツールが増えてしまうので、5つくらいまでに押さえておいた方が良いのではないかと思います。&lt;/p&gt;
&lt;p&gt;そして、分類ごとにツールを選びます。私の場合は、予定は「Google Calendar」、タスクの場合は「リマインダー」、残しておくべき価値のあるメモは「Notion」、支出は「今日の予算」で管理していますので、Draftsからそれぞれのツールに転記していきます。&lt;/p&gt;
&lt;p&gt;このように、全ての情報は「忘れないための袋」（Drafts）に格納した後、識別・分類し、予定/タスク/残しておくべき価値のあるメモ/支出は、「実行するための袋」（Google Calendar/リマインダー/Notion/今日の予算）に格納され、維持していくことが重要です。&lt;/p&gt;
&lt;p&gt;さらに、タスクについては、リマインダーの中にinboxという、何も整理されていないタスクを入れる場所を作っています。それらのタスクは、GTD（Getting Things Done）というメソッドを使って管理しています。詳細を知りたい方は以下のサイトを参考にするとわかりやすいと思います。&lt;/p&gt;
&lt;h2 id="コツ"&gt;コツ
&lt;/h2&gt;&lt;p&gt;「忘れないための袋」から「実行するための袋」に移す敷居を下げる　タスクの場合は「インボックス」など、何でも受け入れる袋を作っておくと、まずはそこに移せば良いことになるのでおすすめ。&lt;/p&gt;
&lt;p&gt;面倒でも毎日、袋分けをする　量が増えると手がつけにくくなり、管理不能になる。&lt;/p&gt;
&lt;p&gt;同時に複数のツールを使わない　例えば、カレンダーにGoogle Calendarを使うと決めたら、しばらくはそれを使い、他のカレンダーツールは使わない。どっちに書いたかわからなくなり、情報が分散してしまうため。完全に移行する場合なら大丈夫ですが、同種のツールを並行して使うのは絶対にやめた方が良いです。&lt;/p&gt;
&lt;p&gt;体系的に整理されたものを学ぶ　GTDは、結構前から整理されたタスクの管理手法なので、それを学ぶことで自分のやり方にカスタマイズしていくと運用がうまく回るようになる。&lt;/p&gt;
&lt;p&gt;後から検索できる、そしてApple Watchなどに通知されるツールを使う　可能な限りデジタル化することが望ましい。アナログの場合は、検索や通知の面でデジタルに劣るため。&lt;/p&gt;
&lt;p&gt;この結果、2025年にどのような成果を得たか&lt;/p&gt;
&lt;p&gt;2025年1月から2月23日までの成果です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;以下の資格を取得しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AWS Solutions Architect Professional - Professional（2025年1月）※2024年12月頃から勉強してました。2025年1月の勉強計画は、この記事の方法で対応したということで記載しています。&lt;/li&gt;
&lt;li&gt;AWS SysOps Administrator - Associate（2025年2月）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;18冊の本を読みました。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;縁あって、4月から念願だった大学院（MBA）に単科生として通うことになりました。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらは、日常のごちゃごちゃしたものを整理し、やりたいと思っていたことにリソースを使うことができるようになったからに他なりません。&lt;/p&gt;
&lt;h2 id="よかった点"&gt;よかった点
&lt;/h2&gt;&lt;p&gt;2つあります。&lt;/p&gt;
&lt;p&gt;1つは仕組み化ができたことにあります。これによって、情報の取りこぼしがなくなり、情報がどこに格納されているのかも把握された状態になるため、自信につながりました。また、物事を忘れなくなりました。厳密にいうと、自身の脳ではなく外部の脳が記憶し、後から探すことができる状態になっている、あるいは必要な時に通知される状態になっています。&lt;/p&gt;
&lt;p&gt;もう1つは、やらないことが増えた点です。思考は、「忘れないための袋」と「実行するための袋」を経て、実行されることになります。その過程で、意味不明なタスクやメモなどを消すようにしたため、残ったものは確実に実行できるもの、そして価値があるものになります。その結果として、1つのことに投下できる資源が増え、質が上がり、短時間でも大きな成果を出すことができたと考えています。&lt;/p&gt;
&lt;h2 id="改善したい点"&gt;改善したい点
&lt;/h2&gt;&lt;p&gt;3つあります。&lt;/p&gt;
&lt;p&gt;1つは、袋間の移動を手動にしている点を省力化したいと考えています。手作業で行うと、作業ステップが増えるため、間違えたり、そもそもが面倒になったりします。Draftsのプレミアムプランに申し込めば「アクション」というものが使えるため、それを使って省力化できないかと考えています。&lt;/p&gt;
&lt;p&gt;次に、音声入力できない場面での対応です。音声で入力できない局面はどうしてもあります（電車や職場など）。そうした場面で、効率よく、取りこぼしなくメモが取得できないかを考えたいと思っています。&lt;/p&gt;
&lt;p&gt;最後に、アナログとの統合です。以下の記事でも書きましたが、マインドマップを使う方法によっても、なおアナログの利点には敵わないと考えています。アナログメモをどう扱うかはよくよく検討する必要があります。&lt;/p&gt;</description></item><item><title>AWS Solutions Architect - Professional合格記</title><link>https://sonohen.net/posts/2025/01/26/</link><pubDate>Sun, 26 Jan 2025 00:00:00 +0900</pubDate><guid>https://sonohen.net/posts/2025/01/26/</guid><description>&lt;h2 id="対象としている読者の方"&gt;対象としている読者の方
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;受験対策中のITエンジニアの方で，私と同じく「何をどこまでやればよいのかが分からない状態」で，不安に思っている。&lt;/li&gt;
&lt;li&gt;自分が合格水準にあるのか，受験日を決めるために目安を知りたいと思っている。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="執筆者の経歴"&gt;執筆者の経歴
&lt;/h2&gt;&lt;p&gt;システムインテグレータ所属のSEです。AWS関連の認定は以下の通り受けています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AWS Certified Cloud Practitioner, 799点（2021年）&lt;/li&gt;
&lt;li&gt;AWS Certified Solutions Architect - Associate, 822点（2022年）&lt;/li&gt;
&lt;li&gt;AWS Certified Developer - Associate, 834点（2023年）&lt;/li&gt;
&lt;li&gt;AWS Certified Solutions Architect - Professional, 844点（2025年）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;実務ではAWSを検証に使用しており，また，個人プロジェクトでもAWSを使っています。&lt;/p&gt;
&lt;p&gt;好きなAWSサービスはAWS CDKです。&lt;/p&gt;
&lt;h2 id="免責事項"&gt;免責事項
&lt;/h2&gt;&lt;p&gt;この記事は，無償/有償部分問わず，私の経験や理解を記載したものであり，合格や正確性を保証するものではありません。最終的には，AWS公式ドキュメント等をご確認いただき，ご自身でご判断いただくようにお願いいたします。&lt;/p&gt;
&lt;h2 id="勉強の順番"&gt;勉強の順番
&lt;/h2&gt;&lt;p&gt;私は以下の順番で教材を勉強しました。どの教材も，受験にあたっては必須だと思いました。今回，Blackbeltは参照しませんでした（Associate試験のときにだいぶ読み込んだので、大丈夫だろうという驕りがありました）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;『AWS認定ソリューションアーキテクト－プロフェッショナル　試験特性から導き出した演習問題と詳細解説』&lt;/li&gt;
&lt;li&gt;AWS Certified Solutions Architect - Professional (SAP-C02) 試験問題サンプル&lt;/li&gt;
&lt;li&gt;AWS公式模擬試験&lt;/li&gt;
&lt;li&gt;問題集①「2024年版！最新のソリューションアーキテクトプロフェッショナル試験に対応した模擬問題集です。同じ出題形式の本番レベルの問題と，参考URLを含む詳細な解説で構成されており，効率的に確実合格を目指すことのできる問題集です」(Clouds Starterさま)&lt;/li&gt;
&lt;li&gt;問題集②「AWS認定ソリューションアーキテクト - プロフェッショナル(SAP-C02)試験対策の決定版！」(Maruchin Techさま）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="勉強方法"&gt;勉強方法
&lt;/h2&gt;&lt;h3 id="事前に"&gt;事前に
&lt;/h3&gt;&lt;p&gt;『科学的根拠に基づく最高の勉強法』（安川康介著，KADOKAWA）を読み，効率的な勉強方法を学ぶことをおすすめします。私の場合，この本の方法で暗記物は時短できました。&lt;/p&gt;
&lt;h4 id="本を2周し必要な知識をたたき込む"&gt;本を2周し，必要な知識をたたき込む
&lt;/h4&gt;&lt;p&gt;『AWS認定ソリューションアーキテクト－プロフェッショナル　試験特性から導き出した演習問題と詳細解説』を読み，章末問題，および模擬問題を解きます。章末問題，模擬問題は最低，2周は解きます（1周目は誤答の洗い出し，2周目は1周目の復習効果の確認）。&lt;/p&gt;
&lt;h4 id="現在の実力を知る"&gt;現在の実力を知る
&lt;/h4&gt;&lt;p&gt;現在の実力を把握しておきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;試験問題サンプル（5割を越えたら2週間後に試験日を設定）&lt;/li&gt;
&lt;li&gt;公式模擬試験（8割を越えたら1週間後に試験日を設定）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;勉強期間中に，定期的にこれらに取り組みます。私の場合は，1週間に1回取り組み，試験問題サンプルが5割を越えたら2週間後に，公式模擬試験で8割を越えたら1週間後に試験日を設定することにしました。&lt;/p&gt;
&lt;h4 id="演習と知識獲得"&gt;演習と知識獲得
&lt;/h4&gt;&lt;p&gt;ここからは，演習と知識獲得を繰り返します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;問題集①を1周する。間違えた問題を中心に復習する。&lt;/li&gt;
&lt;li&gt;問題集①を試験分野ごとに全問解き直す。この段階では，誤答が多いと思います。1問に時間がかかるので，1回あたりの負荷を減らすために試験分野ごとの解き直しをしました。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;試験分野ごとの正答率が7-8割に達したら，次に進みます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;問題集②Practice Test No.1とNo.2を2周する。間違えた問題を中心に復習する。復習後，間違えた問題のみ回答する。Udemyには間違えた問題のみを解答する機能は無いので，Excelで管理します。&lt;/li&gt;
&lt;li&gt;問題集②Practice Test No.3～No.5を1周する。間違えた問題を中心に復習する。復習後，間違えた問題のみ回答します。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;間違えた問題のなかで正答率が8割に達したら，次に進みます。&lt;/p&gt;
&lt;h4 id="試験問題サンプルを解く"&gt;試験問題サンプルを解く。
&lt;/h4&gt;&lt;p&gt;公式模擬試験を解く。両者とも8割に達していれば，合格を狙うことができる水準に達していると思います。&lt;/p&gt;
&lt;h2 id="重点的に学習した方がよいと思われるポイント"&gt;重点的に学習した方がよいと思われるポイント
&lt;/h2&gt;&lt;p&gt;特に重要なサービスについて，押さえておいたほうがいい部分やユースケースなどを考えながら覚えた箇所について，私の覚え方をご紹介します。&lt;/p&gt;
&lt;p&gt;ここまでの対策を行っていれば自ずと導き出されるポイントです。ご参考までに。&lt;/p&gt;
&lt;h3 id="超重要"&gt;★★★★★（超重要）
&lt;/h3&gt;&lt;p&gt;Solutions Architect - Professionalで頻出のサービスのため超重要であると考えています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PrivateLinkの構成サービス提供側の構成（リソース - NLB - エンドポイントサービス）と，それに接続する側の構成（リソース - インタフェース型VPCエンドポイント），および接続承認の方法（自動か手動）を把握しておきます。&lt;/li&gt;
&lt;li&gt;Transfer Familyの種類，接続方法，ストレージの種類オンプレミスで構築，運用しているSFTPサーバを，AWS Transfer Familyを使って移行する場合に，接続元の機器や運用に変更を与えないようにするためにはどのように構築したらよいかを考えます。AWSに自社のIPアドレス範囲を持ち込み（BYOIP），BYOIPプールからElastic IPを作るという方法を考える必要があります。&lt;/li&gt;
&lt;li&gt;Direct Connectの接続ルートと，仮想インタフェースの使い分けオンプレミスに設置するCustomer Gatewayから，Direct Connect LocationのCustomer Router，Direct Connect Routerを経てAWSに接続するルート，およびDirect Connect Routerから先のPrivate VIF(Virtual Interface)，Public VIF，Transit VIFのそれぞれの向き先を把握しておきます。関連して，Site-to-Site VPNでTransit GatewayやVPCに直接接続する方法も覚えておきます。これらは必ず絵に描けるようにしておくようにします。&lt;/li&gt;
&lt;li&gt;また，地味ですがオンプレミスからS3等にアクセスする際に，ゲートウェイ型VPCエンドポイントは利用できず，インタフェース型VPCエンドポイントが利用できるのはなぜだか確認しておいたほうがよいです。前者はトラフィックをルートテーブルで制御，後者はENIで制御しており，VPC内部の名前解決を利用しています。ですので，インタフェース型VPCエンドポイントのみ，オンプレミスからアクセスできるのです。また，オンプレミスからインタフェース型VPCエンドポイントを経由してS3等にアクセスする場合，VPCのEnableDNSHostNamesとEnableDNSSupportの有効化が必要です。実態はPrivate Linkなので，Private Linkを使う場合にもそれらのオプションを有効化しておく必要があります。&lt;/li&gt;
&lt;li&gt;VPC内のリソースからオンプレミスサーバの名前解決を行う方法，またその逆Route 53 ResolverによるDNSリクエストのフォワーディングルール，アウトバウンドエンドポイントの設置などを把握しておきます。これも絵を描けるようにしておきます。&lt;/li&gt;
&lt;li&gt;Active DirectoryまわりSimple AD，AD Connector，AWS Managed Microsoft ADのユースケースを押さえておきます。対応しているサービス，MFAの要否，シングル vs マルチドメイン，フォレスト構築の要否によって使い分けを行います。また，AD Connectorはサブネットに配置するので，冗長化構成を取る必要があるのかないのかをよく考える必要があります。&lt;/li&gt;
&lt;li&gt;移行系ツールの使い分けMigration Hub，Migration Evaluator，Application Discovery Serviceなど。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AWS Organizations周りについて、以下をよく把握しておきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SCPの目的と割り当て，タグポリシーの有効化，および必須タグをつけていないインスタンスをSCPで起動させないようにする方法&lt;/li&gt;
&lt;li&gt;OUを分割し，元々のOUにいたメンバを新しいOUに持って行く際のオペレーションの方法&lt;/li&gt;
&lt;li&gt;3つのガードレール（予防的・検知的・プロアクティブ）と実現方法（SCP・Config・CloudFormation Hooks）&lt;/li&gt;
&lt;li&gt;Reserved Instanceの共有をオフにする方法（各OUに購入を許可していても，共有設定は組織の管理アカウントで行う必要がある）&lt;/li&gt;
&lt;li&gt;AWS Resource Access Manager(RAM)で共有できるリソースには何があるか。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="重要"&gt;★★★（重要）
&lt;/h3&gt;&lt;p&gt;Solutions Architect - Associateでも問われる内容ですが，もう少し深い理解が求められます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Route 53のルーティングポリシー混乱せずに覚える必要があります。特に3つのルーティング方式（位置情報ルーティング/地理的近接性ルーティング/レイテンシルーティング）は，特性を覚え，使い分けができるようにしておくことが重要です。&lt;/li&gt;
&lt;li&gt;トラフィック課金の範囲リージョン間，AZ間，AWS内から外への通信は課金されますが，PrivateLinkとTransit Gatewayを使った同一リージョン内のAZ間通信の場合は，それぞれ時間単位料金とデータ処理料金の課金が行われます。&lt;/li&gt;
&lt;li&gt;CloudFrontを媒介してオリジンにアクセスする経路でLamdbaを使うパターンとCloudFront Functionsを使うパターンではどう違うかビューワーリクエスト，オリジンリクエスト，オリジンレスポンス，ビューワーレスポンス。CloudFront FunctionsではHTTPヘッダの書き換えが可能。Lambdaは，ユーザが送信した画像をリサイズしてS3に格納する場合などに使います。&lt;/li&gt;
&lt;li&gt;CloudFrontのフィールドレベル暗号化が必要になるユースケースと，RSA公開鍵・秘密鍵の紐付け先EKS等で，特定のPodのみがユーザから送信されたデータを参照できるようにするユースケースが想定されます。RSA公開鍵をCloudFrontに紐付け，公開鍵で暗号化。復号するオリジン側に秘密鍵を紐付けます。&lt;/li&gt;
&lt;li&gt;ELBのターゲットグループとしてのIPアドレスタイプのユースケースus-west-1にアプリケーションをデプロイしている。日本にサービスを展開するにあたって，ap-northeast-1に同じアプリケーションをデプロイせず，コストを削減したいとします。このような場合に，ELBへの着信トラフィックの向き先をus-west-1のELBに向けるのがIPアドレスタイプのユースケースの1つです。&lt;/li&gt;
&lt;li&gt;VPCまたはサブネットのCIDRが重複している場合の対応方法再設計，Private Linkを使って接続，NAT変換によって接続，セカンダリVPCを通す方法の4つがあります。&lt;/li&gt;
&lt;li&gt;フェイルオーバーの方式の違いCloudFrontのオリジンフェイルオーバー，Route53のフェイルオーバールーティング，ELBのフェイルオーバーのユースケースの違いを押さえておく必要があります。関連して，Elastic IPのスワップ，4つのDR戦略（バックアップ・リストア，パイロットライト，ウォームスタンバイ，マルチサイト）の違いも押さえたほうがよいです。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="そこそこ重要"&gt;★（そこそこ重要）
&lt;/h3&gt;&lt;p&gt;覚えればよいだけのものをここにまとめました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;クロスアカウントの実装方法&lt;/li&gt;
&lt;li&gt;EC2/Lambda/Fargate/SageMakerの割引プラン。Reserved InstanceとSavings Planの違い&lt;/li&gt;
&lt;li&gt;AppStream2.0のフリートの種類，インスタンスタイプ，スケーリングポリシー&lt;/li&gt;
&lt;li&gt;VPCプレフィックスのユースケース&lt;/li&gt;
&lt;li&gt;FSx for LustreとS3を組み合わせた遅延ローディングのユースケース&lt;/li&gt;
&lt;li&gt;API Gateway REST APIで連携可能なAWSサービス&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Grand Seikoを買った</title><link>https://sonohen.net/posts/2023/05/14/</link><pubDate>Sun, 14 May 2023 14:43:18 +0000</pubDate><guid>https://sonohen.net/posts/2023/05/14/</guid><description>&lt;h2 id="セイコー社を信頼している"&gt;セイコー社を信頼している
&lt;/h2&gt;&lt;p&gt;思えば、セイコー社との付き合いは長い。成人のときに購入してもらったセイコー5（7S26）、就職祝いに購入してもらったクロノグラフ（7T62）。いずれも10年以上使っている。&lt;/p&gt;
&lt;p&gt;さすがに調整もかねて修理に出さねばと思っていたが、どこに依頼するかとは思案のしどころであった。近所に時計店は無いうえ、節目節目での大事な時計であるがゆえ、大手家電量販店の時計修理に出すのも気が引ける。なぜなら、彼らは時計専門では無いからであり、結局取次だろう。どこに取り次がれるのか分からないあたり、聞けば教えてくれるのだろうが不安ではある。しからば、セイコー社に修理してもらおうと思った次第である。&lt;/p&gt;
&lt;p&gt;さすがに10年を過ぎた時計なので、修理ができないか、できるにしても高額になるだろうと予想していたが、それはいい意味で裏切られた。クロノグラフは全体的な修理・調整を依頼して約2万円。セイコー5は今、オーバーホールに出しているがバンドを新品に交換して約1万円。さすがにオーバーホールには時間がかかり、またバンドの手配に時間を要していることから2か月程度時間がかかっているが、クロノグラフのクォーツは2週間程度で修理・調整してくれた。10年を超えても、普通に修理してくれるあたりさすがだと思う。&lt;/p&gt;
&lt;p&gt;サンプル数2であるが、こういう経緯があって、私はセイコー社のアフターサービスを信頼している。ほかのメーカーも同じなのかも知れないが、私は修理までしてもらったことはないのでよくわからない。&lt;/p&gt;
&lt;h2 id="そしてgrand-seikoへ"&gt;そしてGrand Seikoへ
&lt;/h2&gt;&lt;p&gt;いずれ、「きちんとした」腕時計が欲しいと思っていた。「きちんとした」というのの私なりの定義はこんなところである。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3針であること。&lt;/li&gt;
&lt;li&gt;駆動方式は機械式であること。理想は、自動巻きではなく手巻きで、ノンデイトであること。&lt;/li&gt;
&lt;li&gt;煌びやかでなく、目立たないこと。&lt;/li&gt;
&lt;li&gt;製造工程が可視化されていること（工場を見ようと思えば見学できること）。&lt;/li&gt;
&lt;li&gt;修理の体制が整っていて、長く使えること。&lt;/li&gt;
&lt;li&gt;大きくとも直径40mm以内であること。&lt;/li&gt;
&lt;li&gt;国産であること。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;日本にはセイコー社のほかに、シチズン時計社やオリエント時計社といった時計メーカーがあるが、あいにくそれらのメーカーの時計を購入し、修理までを受けた経験はなかった。シチズン時計社のザ・シチズンや、オリエント時計社のメカニカルムーンフェイズ等は実に興味深いところであったが、上記の経験から、自分にとってはセイコー社しかなかった。なお、国産であることの理由は、単純に検討の選択肢を増やすのが面倒くさいということである。&lt;/p&gt;
&lt;p&gt;結局、購入したのは「SBGR315」というモデルである。私にとっての「きちんとした」を、手巻き・ノンデイトを除いて満たしている。妥協した理由は、店員から秒針加工技術の話を伺ったことと、金属バンドの装着感が良かったことである。革バンドのモデルもあったが、ちょうどこれから暑くなっていく時期でもあったので、外した。&lt;/p&gt;
&lt;h2 id="購入してから"&gt;購入してから
&lt;/h2&gt;&lt;p&gt;「この腕時計の何が良いのか？」と聞かれたときに、いろいろな答えが出るんだろうと思ったが、実際には答えられないというのが実感である。自分にとって「きちんとした」時計である、というのが答えになるかと思ったが、実際にオーナーになると、この時計に特筆すべき良さは無いと思う。だが、これが左腕に付いていないと、しっくりこないというか、違和感を感じてしまう。そういう意味で、自分にとっては時間に関するパートナーを得たようなものであるからして、パートナーの良し悪しを尋ねるのもナンセンスというものだし、そんなものに答えることは難しいことであるがゆえ、先の質問に答えが出ないのだろうと納得している。&lt;/p&gt;</description></item><item><title>AWS Certified Developer - Associate (DVA-C01)に合格した</title><link>https://sonohen.net/posts/2023/02/13/</link><pubDate>Mon, 13 Feb 2023 12:26:36 +0000</pubDate><guid>https://sonohen.net/posts/2023/02/13/</guid><description>&lt;p&gt;AWS Certified Developer - Associate (DVA-C01)に合格しましたので、その記録を書いておきます。&lt;/p&gt;
&lt;h2 id="好きなサービス"&gt;好きなサービス
&lt;/h2&gt;&lt;p&gt;とりあえず書いておきます。好きなサービスはAmazon S3です。&lt;/p&gt;
&lt;h2 id="遍歴"&gt;遍歴
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;2021年11月 AWS Certified Cloud Practitioner（CLF-C01）取得（799点）&lt;/li&gt;
&lt;li&gt;2022年04月 AWS Certified Solutions Architect - Associate（SAA-C02）取得（822点）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そして今回、AWS Certified Developer - Associate (DVA-C01)に合格しました（834点）。これでAWS資格3冠、アソシエイト資格2冠ということになります。&lt;/p&gt;
&lt;h2 id="勉強方法"&gt;勉強方法
&lt;/h2&gt;&lt;h3 id="使った資料"&gt;使った資料
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.amazon.co.jp/dp/4798063401/" target="_blank" rel="noopener"
 &gt;ポケットスタディ AWS認定 デベロッパーアソシエイト&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.udemy.com/course/aws-31955/" target="_blank" rel="noopener"
 &gt;AWS 認定デベロッパー アソシエイト模擬試験問題集（5回分325問）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Black Belt (X-Ray, KMS, Cognito, CodeStar &amp;amp; CodePipeline, CodeCommit &amp;amp; CodeArtifact, CodeBuild, CodeDeploy. Lambdaは見たかったけど量が多すぎてやめた)&lt;/li&gt;
&lt;li&gt;AWS公式ドキュメント&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://d1.awsstatic.com/ja_JP/training-and-certification/docs-dev-associate/AWS-Certified-Developer-Associate_Sample-Questions.pdf" target="_blank" rel="noopener"
 &gt;AWS Certified Developer - Associate サンプル問題&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS Certified Developer - Associate 公式練習問題集&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="流れ"&gt;流れ
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;ポケットスタディを一周する&lt;/li&gt;
&lt;li&gt;Udemyの演習テスト1～5までを解いて、解説を読む。最初の2セットは4割くらいの正答率だが、ちゃんと解説を理解すればこのタイミングで残りの3セットは6割くらいはとれるはず。&lt;/li&gt;
&lt;li&gt;弱点となったサービスを洗い出す&lt;/li&gt;
&lt;li&gt;Black BeltとAWS公式ドキュメントを使って重要なところを整理する&lt;/li&gt;
&lt;li&gt;Udemyの325問をもう一回解く（正答率は8割前後を目指す）&lt;/li&gt;
&lt;li&gt;サンプル問題と公式練習問題集を一通り解いておく&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ポケットスタディ自体は2023年1月13日に購入しましたが、実際に勉強を始めたのは1月22日からなので、概ね3週間くらいで準備したような感じです。&lt;/p&gt;
&lt;h2 id="udemyの問題集の難易度"&gt;Udemyの問題集の難易度
&lt;/h2&gt;&lt;p&gt;本番試験では、Udemyの問題集ほど複雑な問題は出てきませんが、それに回答するための要素1つ1つを聞いてくるような印象はありました。BlackBeltなどを使って、要素1つ1つをきちんと整理しておかないと合格は厳しいかなと思います。あと、解説が間違っている、あるいは雑な箇所がいくつかあります。解説を読んでいて「いやいやそうじゃないっしょ」と思いつつAWSの公式ドキュメントを読んで、自分の考え方のほうが正しいということを確認しながら進められるようになれば合格できると思います。そういう意味では、ただ解いて解説を読むことを繰り返すよりも、講師と問題集を通してコミュニケーションをするために知識武装するくらいのつもりでやったほうが面白いと思います。CLF、SAAとも同じですが、問題集を解いて、解説を読んで、だけだと合格は不安かなと。&lt;/p&gt;
&lt;p&gt;目安として、Udemyで6割だと合格ラインぎりぎり、7～8割だと余裕をもって合格できるかなという印象です。9割とれるようになるまでやる必要はないと思います。&lt;/p&gt;
&lt;h2 id="次のステップ"&gt;次のステップ
&lt;/h2&gt;&lt;p&gt;AWS Certified SysOps Administrator – Associate(SOA-C02)を3月に取得します。&lt;/p&gt;
&lt;p&gt;7月末までにSolutions Architect - Professional、9月末までにDevOps Engineer - Professionalを取得し、その後何か専門知識を取りたいというのが当面の目標です。&lt;/p&gt;
&lt;h2 id="追伸"&gt;追伸
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://aws.amazon.com/jp/blogs/news/taking_aws_certification/" target="_blank" rel="noopener"
 &gt;aws certifiedのステッカー&lt;/a&gt;をもらってきました。Foundamentals、Associateは取得したのでノートパソコンの天板にステッカーを貼っておきました。ProfessionalとSpecialityは、まだ取得していないので自粛しています。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/02/13/images/DSC00577.JPG"
	width="4912"
	height="3264"
	loading="lazy"
	
		alt="記念撮影？"
	
	
		class="gallery-image" 
		data-flex-grow="150"
		data-flex-basis="361px"
	
&gt;&lt;/p&gt;
&lt;p&gt;微妙にアピっていきます。では、また明日から頑張りましょう。&lt;/p&gt;</description></item><item><title>SAMを使ってみる</title><link>https://sonohen.net/posts/2023/01/23/</link><pubDate>Mon, 23 Jan 2023 10:50:30 +0000</pubDate><guid>https://sonohen.net/posts/2023/01/23/</guid><description>&lt;h2 id="samの使い方"&gt;SAMの使い方
&lt;/h2&gt;&lt;p&gt;大きな流れは以下の通りです。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;サーバレスアプリケーションの雛形作成（&lt;code&gt;sam init&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;コーディング&lt;/li&gt;
&lt;li&gt;ビルド（&lt;code&gt;sam build&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;ローカル環境でのテスト（&lt;code&gt;sam local start-api&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;デプロイ（&lt;code&gt;sam deploy&lt;/code&gt;）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="サーバレスアプリケーションの雛形作成"&gt;サーバレスアプリケーションの雛形作成
&lt;/h3&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sam init&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;今回は、以下のような構成を取りました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;テンプレートの種類&lt;/strong&gt;: AWS Quick Start Templates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用するテンプレート&lt;/strong&gt;: Serverless API&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ランタイム&lt;/strong&gt;: Node.js 16.x&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;X-Rayの使用有無&lt;/strong&gt;: No X-Ray&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;アプリケーション名&lt;/strong&gt;: sam-app&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sam init&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以下のとおり選択していきます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;You can preselect a particular runtime or package type when using the `sam init` experience.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Call `sam init --help` to learn more.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Which template source would you like to use?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1 - AWS Quick Start Templates
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 - Custom Template Location
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Choice: 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Choose an AWS Quick Start application template
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1 - Hello World Example
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 - Multi-step workflow
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3 - Serverless API
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4 - Scheduled task
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 5 - Standalone function
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 6 - Data processing
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 7 - Infrastructure event management
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 8 - Lambda EFS example
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 9 - Machine Learning
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Template: 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Which runtime would you like to use?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1 - dotnet6
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 - dotnetcore3.1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3 - nodejs16.x
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4 - nodejs14.x
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 5 - nodejs12.x
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Runtime: 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Based on your selections, the only Package type available is Zip.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;We will proceed to selecting the Package type as Zip.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Based on your selections, the only dependency manager available is npm.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;We will proceed copying the template using npm.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: N
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Project name [sam-app]: sam-app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -----------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Generating application:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -----------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Name: sam-app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Runtime: nodejs16.x
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Architectures: x86_64
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Dependency Manager: npm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Application Template: quick-start-web
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Output Directory: .
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Next steps can be found in the README file at ./sam-app/README.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Commands you can use next
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; =========================
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [*] Create pipeline: cd sam-app &amp;amp;&amp;amp; sam pipeline init --bootstrap
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [*] Validate SAM template: sam validate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SAM CLI update available (1.70.0); (1.57.0 installed)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;To download: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="コーディング"&gt;コーディング
&lt;/h3&gt;&lt;p&gt;ディレクトリ構成を確認しておきます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── buildspec.yml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── env.json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── events
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│   ├── event-get-all-items.json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│   ├── event-get-by-id.json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│   └── event-post-item.json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── package.json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── README.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── src
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│   └── handlers
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│   ├── get-all-items.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│   ├── get-by-id.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│   └── put-item.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── template.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── __tests__
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └── unit
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └── handlers
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ├── get-all-items.test.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ├── get-by-id.test.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └── put-item.test.js&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;buildspec.yml&lt;/code&gt;&lt;/strong&gt;: CodeBuildの動作を決めるための定義ファイルです。アーティファクトはS3にZIP形式で置かれるようです。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;src/handlers/*.js&lt;/code&gt;&lt;/strong&gt;: ソースコードの実体です。CFnの&lt;code&gt;template.yaml&lt;/code&gt;から参照されているとおり、このソースコードがLambda関数の実体になります。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;__tests__/unit/handlers/*.js&lt;/code&gt;&lt;/strong&gt;: テストコードです。&lt;code&gt;buildspec.yml&lt;/code&gt;で、&lt;code&gt;pre_build&lt;/code&gt;フェーズで実行されるようになっています。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;events/*.json&lt;/code&gt;&lt;/strong&gt;: Lambda関数を起動するときに使う起動イベントの定義です。&lt;em&gt;Invocation events that you can use to invoke the function.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;env.json&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;sam local invoke --env-vars env.json&lt;/code&gt;とすることで、&lt;code&gt;template.yaml&lt;/code&gt;に記載されている内容をオーバーライドできる仕組みのためのもののようです（&lt;a class="link" href="https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-using-invoke.html" target="_blank" rel="noopener"
 &gt;ローカルでの Lambda 関数の呼び出し&lt;/a&gt;）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ビルド"&gt;ビルド
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;cd sam-app; sam build&lt;/code&gt;で実行できます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd sam-app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sam build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以下のように出力されます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;アーティファクト&lt;/strong&gt;: &lt;code&gt;.aws-sam/build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ビルドに使用したテンプレート&lt;/strong&gt;: &lt;code&gt;.aws-sam/build/template.yaml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Building codeuri: /home/ec2-user/environment/sam-app runtime: nodejs16.x metadata: {} architecture: x86_64 functions: getAllItemsFunction, getByIdFunction, putItemFunction
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Running NodejsNpmBuilder:NpmPack
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Running NodejsNpmBuilder:CopyNpmrcAndLockfile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Running NodejsNpmBuilder:CopySource
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Running NodejsNpmBuilder:NpmInstall
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Running NodejsNpmBuilder:CleanUpNpmrc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Running NodejsNpmBuilder:LockfileCleanUp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Build Succeeded
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Built Artifacts : .aws-sam/build
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Built Template : .aws-sam/build/template.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Commands you can use next
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;=========================
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[*] Validate SAM template: sam validate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[*] Invoke Function: sam local invoke
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[*] Deploy: sam deploy --guided&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="ローカル環境でのテスト"&gt;ローカル環境でのテスト
&lt;/h3&gt;&lt;p&gt;以下のコマンドにより、ローカル環境でテストできるエンドポイントが提供されます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sam local start-api&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;template.yaml&lt;/code&gt;で定義された3つのハンドラーに対し、それぞれエンドポイントが提供されていることが分かります。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Mounting getAllItemsFunction at http://127.0.0.1:3000/ [GET]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Mounting getByIdFunction at http://127.0.0.1:3000/{id} [GET]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Mounting putItemFunction at http://127.0.0.1:3000/ [POST]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023-01-23 12:12:43 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ここで、Cloud9で別のターミナルを開き、&lt;code&gt;getAllItemsFunction&lt;/code&gt;を呼び出してみます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl http://localhost:3000/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;当然ですが、DynamoDBが適切にセットアップされていないのでエラーが返ってきます。また、一番最初に&lt;code&gt;getAllItemsFunction&lt;/code&gt;を呼び出すときには、Dockerコンテナイメージのダウンロードが行われるため、ややレスポンスが悪いです。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Invoking src/handlers/get-all-items.getAllItemsHandler (nodejs16.x)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Image was not found.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Removing rapid images for repo public.ecr.aws/sam/emulation-nodejs16.x
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Building image..............................................................................................................................
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Skip pulling image and use local one: public.ecr.aws/sam/emulation-nodejs16.x:rapid-1.57.0-x86_64.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Mounting /home/ec2-user/environment/sam-app/.aws-sam/build/getAllItemsFunction as /var/task:ro,delegated inside runtime container
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;START RequestId: b38fd596-3599-4c48-bb0b-c4fe0906b982 Version: $LATEST
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} version: &amp;#39;1.0&amp;#39;: null,&amp;#39;,4475962,12:42 +0000&amp;#39;,e9808e&amp;#39;,b-c4fe0906b982 INFO received: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023-01-23T12:15:21.803Z b38fd596-3599-4c48-bb0b-c4fe0906b982 INFO response from: / statusCode: 404 body: Unable to call DynamoDB. Table resource not found.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;END RequestId: b38fd596-3599-4c48-bb0b-c4fe0906b982
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;REPORT RequestId: b38fd596-3599-4c48-bb0b-c4fe0906b982 Init Duration: 1.49 ms Duration: 508.13 ms Billed Duration: 509 ms Memory Size: 128 MB Max Memory Used: 128 MB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;No Content-Type given. Defaulting to &amp;#39;application/json&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023-01-23 12:15:21 127.0.0.1 - - [23/Jan/2023 12:15:21] &amp;#34;GET / HTTP/1.1&amp;#34; 404 -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="デプロイ"&gt;デプロイ
&lt;/h3&gt;&lt;p&gt;なんとなく動いたことの確認ができたので、デプロイしてみます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sam deploy --guided&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;少々ログが長いので、&lt;a class="link" href="sam-deploy.log" &gt;sam-deploy.log&lt;/a&gt;に置いておきました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--guided&lt;/code&gt;をつけて&lt;code&gt;sam deploy&lt;/code&gt;を起動すると、スタック名やリージョン等が聞かれます。聞かれた内容は&lt;code&gt;samconfig.toml&lt;/code&gt;に記載され、今後は&lt;code&gt;sam deploy&lt;/code&gt;を実行するだけで自動的にデプロイされます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;TOML&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;version&lt;/span&gt; = &lt;span style="color:#ae81ff"&gt;0.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;default&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;default&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;deploy&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;default&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;deploy&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;parameters&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;stack_name&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;sam-app&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;s3_bucket&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;aws-sam-cli-managed-default-samclisourcebucket-1ae5e5y3ql961&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;s3_prefix&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;sam-app&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;region&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;ap-northeast-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;confirm_changeset&lt;/span&gt; = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;capabilities&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;CAPABILITY_IAM&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;disable_rollback&lt;/span&gt; = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;image_repositories&lt;/span&gt; = []&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="apiを叩いてみる"&gt;APIを叩いてみる
&lt;/h2&gt;&lt;h3 id="post"&gt;POST
&lt;/h3&gt;&lt;p&gt;実行コマンド&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -X POST -H &lt;span style="color:#e6db74"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; -d &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;id&amp;#34;:&amp;#34;1&amp;#34;, &amp;#34;name&amp;#34;:&amp;#34;sonohen&amp;#34;}&amp;#39;&lt;/span&gt; https://su7cqge7o3.execute-api.ap-northeast-1.amazonaws.com/Prod/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -X POST -H &lt;span style="color:#e6db74"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; -d &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;id&amp;#34;:&amp;#34;2&amp;#34;, &amp;#34;name&amp;#34;:&amp;#34;sonohen2&amp;#34;}&amp;#39;&lt;/span&gt; https://su7cqge7o3.execute-api.ap-northeast-1.amazonaws.com/Prod/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;戻り値&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;JSON&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;,&lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;sonohen&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;,&lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;sonohen2&amp;#34;&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="get-all-items"&gt;GET (All Items)
&lt;/h3&gt;&lt;p&gt;実行コマンド&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl https://su7cqge7o3.execute-api.ap-northeast-1.amazonaws.com/Prod/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;戻り値&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;JSON&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;sonohen2&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;sonohen&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="get-by-id"&gt;Get (By-Id)
&lt;/h3&gt;&lt;p&gt;実行コマンド&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl https://su7cqge7o3.execute-api.ap-northeast-1.amazonaws.com/Prod/1 &lt;span style="color:#75715e"&gt;# {&amp;#34;id&amp;#34;:&amp;#34;1&amp;#34;,&amp;#34;name&amp;#34;:&amp;#34;sonohen&amp;#34;} should be returned&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;戻り値&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;JSON&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{ &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;sonohen&amp;#34;&lt;/span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="環境の削除"&gt;環境の削除
&lt;/h2&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sam delete&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;出力例&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Are you sure you want to delete the stack sam-app in the region ap-northeast-1 ? [y/N]: y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Are you sure you want to delete the folder sam-app in S3 which contains the artifacts? [y/N]: y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - Deleting S3 object with key sam-app/11e6ad52d95b7ff61f7c5edee5989cc5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - Could not find and delete the S3 object with the key sam-app/11e6ad52d95b7ff61f7c5edee5989cc5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - Could not find and delete the S3 object with the key sam-app/11e6ad52d95b7ff61f7c5edee5989cc5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - Deleting S3 object with key sam-app/a4776539efacb8d6b52ef4f5bcf5a08e.template
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - Deleting Cloudformation stack sam-app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Deleted successfully&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="感想"&gt;感想
&lt;/h2&gt;&lt;p&gt;正直、SAMのハンズオンをやるかは、ものすごく悩んだ。DVAの教科書を見れば、コマンドの実行例とともにSAMの紹介がなされており、それを読めば十分だろうと思っていたからです。ただ実際にやってみると、SAMでHello Worldレベルのことをやるのに、このブログでメモを取りながらでも1時間くらいだし、最後、環境をきれいに削除してしまうのもCFnならではだなと思いました。実際に時間を使ってやってみると、自分の過去の似たような案件と比較してしまう&amp;hellip;いや、してしまうという残念な感じよりも、このプロセスそのものが次の案件に向けては重要なんだろうなと思いました。&lt;/p&gt;</description></item><item><title>Elastic Beanstalkを試してみる</title><link>https://sonohen.net/posts/2023/01/22/</link><pubDate>Sun, 22 Jan 2023 03:26:59 +0000</pubDate><guid>https://sonohen.net/posts/2023/01/22/</guid><description>&lt;h2 id="目標"&gt;目標
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Elastic Beanstalkを使って&amp;quot;Congratulations&amp;quot;してみる。&lt;/li&gt;
&lt;li&gt;Blue/Greenデプロイにより、サンプルプログラムの&amp;quot;Congratulations&amp;quot;を&amp;quot;Hello World&amp;quot;に変えてみる。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="今回の構成"&gt;今回の構成
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/22/images/ElasticBeanstalk_trial.drawio.png"
	width="1024"
	height="701"
	loading="lazy"
	
		alt="今回の構成"
	
	
		class="gallery-image" 
		data-flex-grow="146"
		data-flex-basis="350px"
	
&gt;&lt;/p&gt;
&lt;p&gt;※相変わらず分かりにくい図で申し訳ないです。&lt;/p&gt;
&lt;h2 id="elastic-beanstalkでcongratulationsしてみる"&gt;Elastic Beanstalkで&amp;quot;Congratulations&amp;quot;してみる。
&lt;/h2&gt;&lt;h3 id="アプリケーションの作成"&gt;アプリケーションの作成
&lt;/h3&gt;&lt;p&gt;Elastic Beanstalkは初めて使うため（AWS研修では使った経験あり）、&lt;code&gt;AWS Management Console&lt;/code&gt;から作成しました。&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;&lt;a class="link" href="https://aws.amazon.com/jp/corretto/" target="_blank" rel="noopener"
 &gt;Amazon Corretto&lt;/a&gt;とは、Amazonによる無料の長期サポートが提供されている、Java SE標準と互換性があると認定されているOpen JDKディストリビューションのことです。&lt;/p&gt;
&lt;p&gt;作成を開始すると、CloudFormationテンプレートによりスタックが作成されていきます。&lt;/p&gt;
&lt;h3 id="ハマリポイント1スタック作成でエラーが発生"&gt;ハマリポイント1　スタック作成でエラーが発生
&lt;/h3&gt;&lt;h4 id="エラー内容"&gt;エラー内容
&lt;/h4&gt;&lt;p&gt;次に、&lt;code&gt;CloudFormation &amp;gt; スタック &amp;gt; awseb-e-e7d8kvxdpq-stack&lt;/code&gt;を開き、&lt;code&gt;イベントタブ&lt;/code&gt;を開いたところ、以下のようなエラーが発生し、スタックのステータスは&lt;code&gt;CREATE_FAILED&lt;/code&gt;になっていました。この時、&lt;code&gt;ElasticBeanstalk &amp;gt; 環境 &amp;gt; Beanstalktrial-env-2&lt;/code&gt;の環境のヘルスは&lt;code&gt;保留中&lt;/code&gt;になっていました。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The following resource(s) failed to create: [AWSEBV2LoadBalancer, AWSEBAutoScalingGroup].&lt;/p&gt;
&lt;p&gt;You must use a valid fully-formed launch template. &lt;em&gt;No default subnet for availability zone: &amp;lsquo;ap-northeast-1c&amp;rsquo;&lt;/em&gt;. (Service: AmazonAutoScaling; Status Code: 400; Error Code: ValidationError; Request ID: 7d99081a-1554-487c-b265-38b01661aa2e; Proxy: null)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;このエラーの原因は、デフォルトサブネットが存在しないことです。過去にデフォルトVPCを削除した時に、一緒に削除されたのだと思います。そして、現在はデフォルトVPCのみ作成されている状況です。本来、デフォルトVPCは以下のような構成になっているのが正しいようです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/22/images/default-vpc.png"
	width="503"
	height="561"
	loading="lazy"
	
		alt="デフォルトVPCの構成"
	
	
		class="gallery-image" 
		data-flex-grow="89"
		data-flex-basis="215px"
	
&gt;&lt;/p&gt;
&lt;p&gt;そこで、以下の手順でデフォルトVPC、デフォルトサブネットを構成し直します。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Elastic Beanstalkの環境を削除し、アプリケーションを終了する&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/default-vpc.html#create-default-vpc" target="_blank" rel="noopener"
 &gt;デフォルトVPC&lt;/a&gt;の記載を参考に、&lt;code&gt;AWS CloudShell&lt;/code&gt;から以下のコマンドでデフォルトVPCとデフォルトサブネットを作成する&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="対応1elastic-beanstalkの環境を削除しアプリケーションを終了する"&gt;対応1　Elastic Beanstalkの環境を削除し、アプリケーションを終了する
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;Elastic Beanstalk &amp;gt; 環境&lt;/code&gt;から、環境を選択し、右にあるアクションから&lt;code&gt;環境の終了&lt;/code&gt;を選択し、環境を終了します。これにより、アプリケーションの公開も停止されます。&lt;/p&gt;
&lt;h4 id="対応2デフォルトvpcを作成する"&gt;対応2　デフォルトVPCを作成する
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;AWS Cloud Shell&lt;/code&gt;から以下のコマンドを実行します。実行しているコマンドの詳細は、&lt;a class="link" href="https://awscli.amazonaws.com/v2/documentation/api/latest/index.html" target="_blank" rel="noopener"
 &gt;AWS CLI Command Reference&lt;/a&gt;を参照してください。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws ec2 create-default-vpc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;出力例は以下です。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;An error occurred (DefaultVpcAlreadyExists) when calling the CreateDefaultVpc operation: A Default VPC already exists for this account in this region.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;既にデフォルトVPCが存在すると言われます。そこで、デフォルトVPCの&lt;code&gt;VpcId&lt;/code&gt;を調べます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws ec2 describe-vpcs --filter Name=is-default,Values=true --query &amp;#39;Vpcs[].[VpcId]&amp;#39; --output text&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;出力例は以下です。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vpc-0f48a5ddd72f1781f&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h4 id="既に存在するサブネットの削除"&gt;既に存在するサブネットの削除
&lt;/h4&gt;&lt;p&gt;今回は、既にデフォルトVPCが存在していました。その配下にあるサブネットがデフォルトサブネットか判断がつかなかった上、他で使っていなかったことから、デフォルトVPCにあるサブネットを削除しておきます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; target_subnet in &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;aws ec2 describe-subnets --filters Name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;vpc-id,Values&lt;span style="color:#f92672"&gt;=&lt;/span&gt;vpc-0f48a5ddd72f1781f --query &lt;span style="color:#e6db74"&gt;&amp;#39;Subnets[].[SubnetId]&amp;#39;&lt;/span&gt; --output text&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws ec2 delete-subnet --subnet-id $target_subnet
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以下のコマンドを実行し、出力結果が無いことを以てサブネットが削除されたことを確認します。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws ec2 describe-subnets \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --filters Name=vpc-id,Values=vpc-0f48a5ddd72f1781f \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --query &amp;#39;Subnets[].[SubnetId]&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --output text&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h4 id="デフォルトサブネットの作成"&gt;デフォルトサブネットの作成
&lt;/h4&gt;&lt;p&gt;以下のコマンドで、各AZにデフォルトサブネットを作成します。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;availabilityzones&lt;span style="color:#f92672"&gt;=(&lt;/span&gt;ap-northeast-1a ap-northeast-1c ap-northeast-1d&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; az in &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;availabilityzones[@]&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws ec2 create-default-subnet --availability-zone $az
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;unset availabilityzones&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;作成されたことを確認します。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws ec2 describe-subnets \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --filters Name=vpc-id,Values=vpc-0f48a5ddd72f1781f \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --filters Name=state,Values=available \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --query &amp;#39;Subnets[].[SubnetId,AvailabilityZone,CidrBlock]&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;出力例は以下です。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;JSON&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;subnet-090132d78642c5909&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;ap-northeast-1d&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;172.31.32.0/20&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;subnet-0a941d6e7b4ae578c&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;ap-northeast-1c&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;172.31.0.0/20&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;subnet-0374fa703f83f7ae1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;ap-northeast-1a&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;172.31.16.0/20&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ドキュメントによると、デフォルトサブネットのCIDRは&lt;code&gt;172.31.0.0/20, 172.31.16.0/20, 172.31.32.0/20&lt;/code&gt;の3つであるということなので、きちんと作成されたようです。&lt;/p&gt;
&lt;h4 id="インターネットゲートウェイの状況の確認"&gt;インターネットゲートウェイの状況の確認
&lt;/h4&gt;&lt;p&gt;まず、デフォルトVPCにアタッチされているインターネットゲートウェイの&lt;code&gt;InternetGatewayId&lt;/code&gt;を調べます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws ec2 describe-internet-gateways \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --filter Name=attachment.vpc-id,Values=vpc-0f48a5ddd72f1781f \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --filter Name=attachment.state,Values=available \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --query &amp;#39;InternetGateways[].[InternetGatewayId]&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --output text&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;出力例は以下です。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;igw-0adc27eae43d8714d&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;0.0.0.0/0&lt;/code&gt;宛の通信が上記のInternetGatewayを通るように設定されているか、ルートテーブルを確認します。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws ec2 describe-route-tables &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --filter Name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;vpc-id,Values&lt;span style="color:#f92672"&gt;=&lt;/span&gt;vpc-0f48a5ddd72f1781f &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --filter Name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;route.destination-cidr-block,Values&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0.0.0.0/0 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --filter Name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;route.gateway-id,Values&lt;span style="color:#f92672"&gt;=&lt;/span&gt;igw-0adc27eae43d8714d &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --output text&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;出力例は以下です。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;JSON&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="background-color:#3c3d38"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;/span&gt;&lt;span style="background-color:#3c3d38"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;/span&gt;&lt;span style="background-color:#3c3d38"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;/span&gt;&lt;span style="background-color:#3c3d38"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26
&lt;/span&gt;&lt;span style="background-color:#3c3d38"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27
&lt;/span&gt;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;RouteTables&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Associations&amp;#34;&lt;/span&gt;: [],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;PropagatingVgws&amp;#34;&lt;/span&gt;: [],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;RouteTableId&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;rtb-0ef8c99720a501497&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Routes&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;DestinationCidrBlock&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;172.31.0.0/16&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;GatewayId&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;local&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Origin&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;CreateRouteTable&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;State&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;active&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex; background-color:#3c3d38"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;DestinationCidrBlock&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;0.0.0.0/0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex; background-color:#3c3d38"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;GatewayId&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;igw-0adc27eae43d8714d&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex; background-color:#3c3d38"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Origin&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;CreateRoute&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex; background-color:#3c3d38"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;State&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;active&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Tags&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Key&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Value&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;default-public-rtb&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex; background-color:#3c3d38"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;VpcId&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;vpc-0f48a5ddd72f1781f&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;OwnerId&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;436589084651&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;0.0.0.0/0&lt;/code&gt;宛の通信が&lt;code&gt;igw-0adc27eae43d8714d&lt;/code&gt;を通るように設定されていることが確認できました。&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;ここまでで、以下の構成が作成されたことが確認できました（以下図は再掲）。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/22/images/default-vpc.png"
	width="503"
	height="561"
	loading="lazy"
	
		alt="デフォルトVPCの構成（再掲）"
	
	
		class="gallery-image" 
		data-flex-grow="89"
		data-flex-basis="215px"
	
&gt;&lt;/p&gt;
&lt;h4 id="elasticbeanstalkでアプリケーションを再作成する"&gt;ElasticBeanstalkでアプリケーションを再作成する
&lt;/h4&gt;&lt;p&gt;再度、ElasticBeanstalkのアプリケーションを作成します。アプリケーションの作成に成功すると、&lt;code&gt;Elastic Beanstalk &amp;gt; 環境&lt;/code&gt;にURLが表示されるので、それにアクセスします。すると、以下のように&amp;quot;Congratulations&amp;quot;と表示されるはずです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/22/images/ebeanstalk_bootstrap.png"
	width="1917"
	height="596"
	loading="lazy"
	
		alt="Bootstrap screen of Elastic Beanstalk"
	
	
		class="gallery-image" 
		data-flex-grow="321"
		data-flex-basis="771px"
	
&gt;&lt;/p&gt;
&lt;h4 id="ハマりポイント2"&gt;ハマりポイント2
&lt;/h4&gt;&lt;p&gt;私の場合、以前にデフォルトVPCを作成した時に、プライベートサブネット用のルートテーブル、およびパブリックサブネット用のルートテーブルの2つを作っており、デフォルトのルートテーブルは「プライベートサブネット用のルートテーブル」でした。その結果、Beanstalkのアプリケーションを作成した際に、EC2インスタンスは「プライベートサブネット」に配置されており、それが原因でヘルスチェックに失敗する、必要な情報がELB側で取得できない等の問題が発生しました。解決するため、Beanstalkが作ったEC2インスタンスが配置されているサブネットのルートテーブルを「パブリックサブネット用のルートテーブル」に関連付けし直し、環境を再構築しました。&lt;/p&gt;
&lt;h2 id="hello-worldの作成"&gt;Hello Worldの作成
&lt;/h2&gt;&lt;h3 id="cloud9環境の構築"&gt;Cloud9環境の構築
&lt;/h3&gt;&lt;p&gt;サクッと作っておきます。今回は、&lt;code&gt;ap-northeast-1d&lt;/code&gt;に配置しました。&lt;/p&gt;
&lt;h3 id="hello-worldの作成-1"&gt;Hello Worldの作成
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/RelatedResources.html?icmpid=docs_elasticbeanstalk_console" target="_blank" rel="noopener"
 &gt;Elastic Beanstalk resources&lt;/a&gt;に&lt;code&gt;corretto.zip&lt;/code&gt;があるので、Cloud9のターミナルを使ってダウンロードし、展開しておきます。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wget https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/samples/corretto.zip
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;unzip corretto.zip -d sample/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;続いて、&lt;code&gt;sample/src/main/resources/index.html&lt;/code&gt;を開き、以下のように編集します。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;HTML&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="background-color:#3c3d38"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="background-color:#3c3d38"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex; background-color:#3c3d38"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;title&lt;/span&gt;&amp;gt;Hello World&amp;lt;/&lt;span style="color:#f92672"&gt;title&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex; background-color:#3c3d38"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;h1&lt;/span&gt;&amp;gt;Hello World&amp;lt;/&lt;span style="color:#f92672"&gt;h1&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; This is a end of the Web as there are no links in this page. Hello World.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;アップロードできるよう、&lt;code&gt;cd sample; zip corretto-2.0.zip -r .&lt;/code&gt;で圧縮しておきます。&lt;/p&gt;
&lt;h2 id="bluegreenデプロイの実行"&gt;Blue/Greenデプロイの実行
&lt;/h2&gt;&lt;h3 id="環境のクローン"&gt;環境のクローン
&lt;/h3&gt;&lt;p&gt;現在動作している環境をクローンします。&lt;code&gt;Elastic Beanstalk &amp;gt; 環境&lt;/code&gt;を開き、ラジオボタンにチェックを入れ、アクションから&lt;code&gt;環境のクローンを作成&lt;/code&gt;を選択します。ひとまずはデフォルト設定のままクローンします。新しい環境の名前は「beanstalktrial-env-1」になりました。現時点で環境は2つあり、それぞれURLは以下の通りになっています。&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;1つ目、2つ目のURLにアクセスし、「Congratulations」が表示されていることを確認します。&lt;/p&gt;
&lt;h3 id="zipファイルのアップロードとデプロイ"&gt;ZIPファイルのアップロードとデプロイ
&lt;/h3&gt;&lt;p&gt;先ほど作成した&lt;code&gt;corretto-2.0.zip&lt;/code&gt;を、Green環境（Beanstalktrial-env-1）にアップロードし、デプロイします。&lt;code&gt;Elastic Beanstalk &amp;gt; 環境 &amp;gt; beanstalktrial-env-1&lt;/code&gt;を開き、&lt;code&gt;アップロードとデプロイ&lt;/code&gt;を選択します。ZIPファイルをアップロードし、デプロイが完了するのを待ちます。&lt;/p&gt;
&lt;p&gt;デプロイが完了した後、先ほどの2つ目のURLにアクセスし、「Hello World」が表示されていることを確認します。1つ目のURLは引き続き「Congratulations」になっていることを確認しておきます。&lt;/p&gt;
&lt;h3 id="blue環境とgreen環境の切り替え"&gt;Blue環境とGreen環境の切り替え
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Elastic Beanstalk &amp;gt; 環境&lt;/code&gt;を開き、Green環境（Beanstalktrial-env-1）を選択し、アクションから&lt;code&gt;環境URLのスワップ&lt;/code&gt;を選択します。次の画面で、スワップする環境の選択で、環境名に「Beanstalktrial-env」を選択し、&lt;code&gt;スワップ&lt;/code&gt;を押下します。&lt;code&gt;最近のイベント&lt;/code&gt;を確認すると、&lt;code&gt;Swapping CNAMEs for environments 'Beanstalktrial-env-1' and 'Beanstalktrial-env'.&lt;/code&gt;と記載がある通り、スワップはRoute 53のCNAMEレコードの変更によって実現されています。&lt;/p&gt;
&lt;p&gt;ここで、&lt;code&gt;Elastic Beanstalk &amp;gt; 環境&lt;/code&gt;を開き、2つの環境のURLがスワップされていることを確認します。&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;これでBlue/Greenデプロイが完了しました。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;非常に単純な操作によって、Blue/Greenデプロイが出来ることが分かりました（小並感）。&lt;/p&gt;
&lt;p&gt;Elastic Beanstalk自体は、AWS研修でもハンズオンを実施したことがありましたが、やはりそこは研修環境、トラブルなんて起こりません。今回は、自分のAWS環境を使って実行したので、デフォルトVPCやデフォルトサブネットが壊れていたこと、デフォルトルートテーブルがプライベート用になっていたことなど、ここに書いていないことも含めてハマりポイントがありました。過去xx年の経験によって、こういうハマりポイントを経て人は強くなっていくということを身を持って理解していますので、今後も用意された環境ではなく、自分の環境で色々と操作を試していきたいと思います。&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;起動する際、選択しているリージョンに注意してください。今回は、Elastic Beanstalkをap-northeast-1（東京リージョン）で起動したいので、それを指定した後、&lt;code&gt;AWS CloudShell&lt;/code&gt;を起動しました。&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;もう少し読み進めて頂くと分かりますが、この確認だけでは不十分です。このルートテーブルがデフォルトルートテーブルになっていることを確認するか、あるいはサブネットのルートテーブルの付け替えをしないといけません。&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Twitterをやめた</title><link>https://sonohen.net/posts/2023/01/09/</link><pubDate>Mon, 09 Jan 2023 12:15:31 +0000</pubDate><guid>https://sonohen.net/posts/2023/01/09/</guid><description>&lt;p&gt;もともと、Twitterは情報収集を目的に始めたものだった。その中で、自分が得た情報を発信し、何らかの反応が得られることを知ると、目的が人から反応を得ること、に徐々にすり替わった。つまり、反応を得るための情報収集、情報発信になっていったのだ。インフルエンサーでもなし、見ず知らずの人からリアクションが得られたところで何になるだろう？　そんなことを思うと、急にTwitterがくだらないと思ってしまったのだ。しかし、ふと第三者視点からTwitterに書き込む自分の姿を観察すると、承認欲求というものは厄介なもんだと思う。&lt;/p&gt;
&lt;p&gt;辞めるにあたって、ツイートしたものは全て自分の手で削除し、いいねしたものを全て自分の手で外し、フォロワーにも感謝しつつ外した。いいねを外しながら、当時の自分は何を思ってこの人のツイートにいいねをしたのかさっぱり思い出せなかった。「どうでもいいね」だったのかもしれない。&lt;/p&gt;
&lt;p&gt;面白いと思ってやっていたときもあるし、今この瞬間にも面白いと思って使っている人がいるんだろうから悪く言うつもりも無いが、思ってしまったことは思ってしまったことだし、過去にも何回か同じような理由で始めてはやめてきた経緯もあることから、とりあえずここに書いておくことにした。&lt;/p&gt;</description></item><item><title>Pixel Watchを買った</title><link>https://sonohen.net/posts/2023/01/06/</link><pubDate>Fri, 06 Jan 2023 08:10:00 +0000</pubDate><guid>https://sonohen.net/posts/2023/01/06/</guid><description>&lt;h2 id="買い方"&gt;買い方
&lt;/h2&gt;&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;アメリカン・エキスプレス・カード + メンバーシップ・リワード・プラスで購入したので、100円につき3ポイント（3%）の還元があり、実際に1,194ポイントの還元があった。このポイントを1ポイント1円として使うかどうかは自分次第ではあるが。&lt;/p&gt;
&lt;h2 id="写真"&gt;写真
&lt;/h2&gt;&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/06/images/DSC00557.JPG"
	width="4912"
	height="3264"
	loading="lazy"
	
		alt="箱"
	
	
		class="gallery-image" 
		data-flex-grow="150"
		data-flex-basis="361px"
	
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/06/images/DSC00561.JPG"
	width="4912"
	height="3264"
	loading="lazy"
	
		alt="液晶はきれい"
	
	
		class="gallery-image" 
		data-flex-grow="150"
		data-flex-basis="361px"
	
&gt;&lt;/p&gt;
&lt;h2 id="購入後にやったこと"&gt;購入後にやったこと。
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;バンドの装着順を交換した。普段は左手に装着するが、手首を曲げたときにリュウズが左手の甲に当たるため。&lt;/li&gt;
&lt;li&gt;Google KeepのアプリをPixel Watchに入れた。音声でメモが取れるのはやはり良い。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="よく分からないこと"&gt;よく分からないこと。
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;AnkerのSoundCore Libertyを使っているわけだが、これとPixel Watchのペアリングが必要なのか否か。どうもPixel Watchから、ペアリングしているスマートフォンを通して電話が掛けられるのだが、その音声をPixel Watchのスピーカーやマイクから垂れ流すというのはちょっとできない。&lt;/li&gt;
&lt;li&gt;Pixel Watch自体に何かファイルを入れたりはできないのか？というよりその辺の思想がよくわからない。Pixel Watchはスマホのインタフェースの1つに当たるのか、それともそれ単独で何かできるようになっているのか。&lt;/li&gt;
&lt;li&gt;Chromebook、Pixelスマホ、Pixel Watch、他Google製品との連携エコシステムはまだ良くわからないことが多い。このあたりはAppleがよくできていると思う。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="事前に気になっていたことと現在"&gt;事前に気になっていたことと現在
&lt;/h2&gt;&lt;p&gt;事前に調べていて気になった「バッテリーの持ち」は、「常時点灯」と「傾けて点灯」をOFFにしておけば、活動量計＋たまの通知確認程度の自分の用途では少なくとも日中は問題なく持つ。時間を確認するのに、いちいち画面タップが必要なのが面倒ではあるが。「傷の付きやすさ」については分からないが精密機器として丁重に扱っていればつきにくいとは思うがまだ良くわからない。&lt;/p&gt;
&lt;h2 id="最後に"&gt;最後に
&lt;/h2&gt;&lt;p&gt;こんなことを思いながら使っていると、Apple Watchの第2世代を使っていたときのことを思い出す。処理は遅い、バッテリーは持たない、傷は付きやすい。それに比べれば、初代としては完成度は高いのではないか。&lt;/p&gt;</description></item><item><title>GitHub Codespacesを試しつつ、Hugoへ移行する</title><link>https://sonohen.net/posts/2023/01/04/</link><pubDate>Wed, 04 Jan 2023 09:07:32 +0000</pubDate><guid>https://sonohen.net/posts/2023/01/04/</guid><description>&lt;h2 id="試す上での縛り"&gt;試す上での縛り
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Chromebookで全ての作業（このブログの執筆も含む）を完結させる&lt;/li&gt;
&lt;li&gt;ブラウザ（Chrome）だけで全ての作業（このブログの執筆も含む）を完結させる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="試す手順"&gt;試す手順
&lt;/h2&gt;&lt;h3 id="リポジトリの準備"&gt;リポジトリの準備
&lt;/h3&gt;&lt;p&gt;GitHub上で、プライベートなリポジトリ（ここでは「hugo-blog」とする）を作成しておく。あわせて「draft」という名前でブランチを作っておく。以降、全ての作業はこのdraftブランチを軸に行っていく。&lt;/p&gt;
&lt;h3 id="codespacesの起動"&gt;Codespacesの起動
&lt;/h3&gt;&lt;p&gt;「hugo-blog」リポジトリ、「draft」ブランチを選択してCodespacesを起動する。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/04/images/launch_codespace_from_repository.png"
	width="1042"
	height="499"
	loading="lazy"
	
		alt="ブランチからCodespaceを起動"
	
	
		class="gallery-image" 
		data-flex-grow="208"
		data-flex-basis="501px"
	
&gt;&lt;/p&gt;
&lt;p&gt;メニューバーの「Codespaces」を選択して起動する方法もある。[Codespaces] &amp;gt; [New codespace]の順に操作し、起動パラメータを以下の通り設定してもよい。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/04/images/launch_codespace_from_codespace.png"
	width="909"
	height="525"
	loading="lazy"
	
		alt="CodespaceからCodespaceを起動"
	
	
		class="gallery-image" 
		data-flex-grow="173"
		data-flex-basis="415px"
	
&gt;&lt;/p&gt;
&lt;p&gt;起動後の画面はWeb版VS Codeなり。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/04/images/codespace_launched.png"
	width="1920"
	height="1026"
	loading="lazy"
	
		alt="起動したCodespaceの画面"
	
	
		class="gallery-image" 
		data-flex-grow="187"
		data-flex-basis="449px"
	
&gt;&lt;/p&gt;
&lt;h3 id="hugoの最低限の設定"&gt;hugoの最低限の設定
&lt;/h3&gt;&lt;p&gt;初期状態で、hugoはインストールされている（パス：&lt;code&gt;/usr/local/hugo/bin/hugo&lt;/code&gt;）。hugoの&lt;a class="link" href="https://gohugo.io/getting-started/quick-start/#step-3-add-a-theme" target="_blank" rel="noopener"
 &gt;Quick Start&lt;/a&gt;に沿って作業を進める。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-Shell" data-lang="Shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ hugo new site . –force
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke themes/ananke
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ echo &lt;span style="color:#e6db74"&gt;&amp;#34;theme = &amp;#39;ananke&amp;#39;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; config.toml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ hugo server&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;そうすると、Codespaceの中で動作しているhugoのポートと、外部からアクセスできるアドレス（ローカルアドレス）のバインドが行われ、「ポート」タブに表示される。ローカルアドレスにアクセスすれば、Codespaceの中で動作しているhugoのサーバにアクセスできる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/04/images/codespace_launched.png"
	width="1920"
	height="1026"
	loading="lazy"
	
		alt="hugo server起動中のポートタブの状態"
	
	
		class="gallery-image" 
		data-flex-grow="187"
		data-flex-basis="449px"
	
&gt;&lt;/p&gt;
&lt;p&gt;アクセスすると、以下の通りhugoで作成したサイトが表示される。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/04/images/my_first_blog_in_hugo.png"
	width="1920"
	height="1026"
	loading="lazy"
	
		alt="Hugoで作成したサイトの初期表示"
	
	
		class="gallery-image" 
		data-flex-grow="187"
		data-flex-basis="449px"
	
&gt;&lt;/p&gt;
&lt;p&gt;一旦、ここまでの変更をコミットしておく。&lt;/p&gt;
&lt;h2 id="hexoからhugoへの移行"&gt;hexoからhugoへの移行
&lt;/h2&gt;&lt;p&gt;ここから先は、hexoからhugoへの移行の記録である。&lt;/p&gt;
&lt;h3 id="submoduleの削除"&gt;submoduleの削除
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;themes/ananke&lt;/code&gt;は使わないので削除しておく。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ git submodule deinit -f themes/ananke
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ rm -rf themes/ananke&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="テーマの選定"&gt;テーマの選定
&lt;/h3&gt;&lt;p&gt;今回はsimplenessというものにした。シンプルでヨシ。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ git submodule add https://github.com/RainerChiang/simpleness.git themes/simpleness&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="configtomlの変更"&gt;config.tomlの変更
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;config.toml&lt;/code&gt;を変更する。とりあえずはデフォルトで記載されている以下のパラメータを変更しておく。動けばヨシ。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;TOML&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;baseURL&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#39;https://sonohen.github.io/&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;languageCode&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#39;ja-jp&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;title&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#39;とあるエンジニアの備忘録&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;theme&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#39;simpleness&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="gitignoreの作成"&gt;.gitignoreの作成
&lt;/h3&gt;&lt;p&gt;以下を追加しておく。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/public/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/resources/_gen/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.hugo_build.lock&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="動作確認"&gt;動作確認
&lt;/h3&gt;&lt;p&gt;ここまでで動作するかを確認しておく。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ hugo server -D&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;theme/simpleness&lt;/code&gt;は、各種リソースを&lt;code&gt;localhost:1313&lt;/code&gt;から取得しようとしてしまうのでこれだと正しく動作しない。その場合は、以下のコマンドで対処する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ hugo server -D --baseUrl&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://sonohen-scaling-space-pancake-j4wxjgjq9r2qxxj-1313.preview.app.github.dev/&amp;#34;&lt;/span&gt; --appendPort&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;もう少し良いやり方があると思うが、とりあえずはこれで動いたのでヨシ。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/04/images/blog_in_simpleness.png"
	width="1920"
	height="1026"
	loading="lazy"
	
		alt="simplenessで表示したサイト"
	
	
		class="gallery-image" 
		data-flex-grow="187"
		data-flex-basis="449px"
	
&gt;&lt;/p&gt;
&lt;p&gt;ここで一旦、コミットしておく。&lt;/p&gt;
&lt;h3 id="記事静的ファイルの移行"&gt;記事・静的ファイルの移行
&lt;/h3&gt;&lt;p&gt;hugoの場合、&lt;code&gt;/content&lt;/code&gt;に記事本体（*.md）、&lt;code&gt;/static&lt;/code&gt;に静的ファイル（*.jpg等）を入れておけば良いらしい。また、hexoで書いていた記事は「hexo」という名前のリポジトリに保存してあるので、スマートではないがとりあえず以下の方法で移行する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 鍵の作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ ssh-keygen -t rsa
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ cat ~/.ssh/id_rsa.pub &lt;span style="color:#75715e"&gt;# 公開鍵をGitHubに登録する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 接続テスト&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ ssh -T git@github.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Hi sonohen! You&lt;span style="color:#ae81ff"&gt;\&amp;#39;&lt;/span&gt;ve successfully authenticated, but GitHub does not provide shell access.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 移行作業&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ mkdir content
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ cd ../
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/ $ git clone git@github.com:sonohen/hexo.git
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hexo/source &lt;span style="color:#f92672"&gt;(&lt;/span&gt;master&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ cp -Rp ./_posts/ /workspaces/hugo-blog/content/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hexo/source &lt;span style="color:#f92672"&gt;(&lt;/span&gt;master&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ cp -Rp ./images/ /workspaces/hugo-blog/static/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hexo/source &lt;span style="color:#f92672"&gt;(&lt;/span&gt;master&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ cd /workspaces/hugo-blog
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 動作確認&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/workspaces/hugo-blog &lt;span style="color:#f92672"&gt;(&lt;/span&gt;draft&lt;span style="color:#f92672"&gt;)&lt;/span&gt; $ hugo server -D --baseUrl&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://sonohen-scaling-space-pancake-j4wxjgjq9r2qxxj-1313.preview.app.github.dev/&amp;#34;&lt;/span&gt; --appendPort&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ここで以下のように表示されればうまく移行できたと思われる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/04/images/blog_after_migrated.png"
	width="1920"
	height="1026"
	loading="lazy"
	
		alt="simplenessで表示したサイト"
	
	
		class="gallery-image" 
		data-flex-grow="187"
		data-flex-basis="449px"
	
&gt;&lt;/p&gt;
&lt;h2 id="github-actionsを利用した自動デプロイ"&gt;GitHub Actionsを利用した自動デプロイ
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;/content/_posts/&lt;/code&gt;にMarkdownファイルを作成し、コミットしたら&lt;code&gt;sonohen.github.io&lt;/code&gt;に表示されるようにしたい。。&lt;/p&gt;
&lt;p&gt;そのためにはリポジトリを開き、[Settings] &amp;gt; [Build and deployment] &amp;gt; [Source]からGitHub Actionsを選択し、[Hugo] &amp;gt; [Configure]を選択し、次の画面でCommitすればよい。次のコミット分からGitHub Actionsで自動デプロイされる。&lt;/p&gt;</description></item><item><title>Amazon WorkSpacesの検証をやってみた</title><link>https://sonohen.net/posts/2023/01/03/</link><pubDate>Tue, 03 Jan 2023 09:37:30 +0000</pubDate><guid>https://sonohen.net/posts/2023/01/03/</guid><description>&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/03/images/top_image.png"
	width="1920"
	height="1080"
	loading="lazy"
	
		alt="表紙イメージ"
	
	
		class="gallery-image" 
		data-flex-grow="177"
		data-flex-basis="426px"
	
&gt;&lt;/p&gt;
&lt;h2 id="amazon-workspacesとは"&gt;Amazon WorkSpacesとは
&lt;/h2&gt;&lt;p&gt;VDI（Virtual Desktop Infrastructure：仮想デスクトップ基盤）の1つで、シンクライアントとも言われます。皆さんがお勤めの企業でも導入されているかもしれません。Windows等のOSがAWSのデータセンター上で動いており、そこにアクセスして作業します。&lt;/p&gt;
&lt;p&gt;個人の場合（例えば私の場合）、以下のユースケースがあるかなと思います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;日常的な作業の大半はChromebookで出来るが、一部の作業でWindowsが必要、だけどWindows端末は持ちたくない、という場合にスポットで利用&lt;/li&gt;
&lt;li&gt;特定の国からしかアクセスできないサイトにアクセスする場合に、その国に設置されているリージョンにAmazon WorkSpacesを設定し、アクセス（良く分からないVPNを経由してアクセスするよりもAmazon WorkSpacesのほうがセキュアな可能性があります）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="背景"&gt;背景
&lt;/h2&gt;&lt;p&gt;Amazon WorkSpacesを試してみようと思ったときに、以下の前提条件で最も費用が安くなるのが米国東部（バージニア北部：us-east-1）です。時間料金を選択すると、1ヶ月あたりの固定費用が9.75 USD/月（約1,227円/月）、利用時間ごとの変動費用が0.30 USD/時間（約40円/時間）です。例えば、月に40時間だけ使うという場合にAmazon WorkSpacesにかかる費用は、9.75 USD + 0.30 USD * 40h = 21.75 USD (約2,845円)です。&lt;/p&gt;
&lt;h3 id="前提条件"&gt;前提条件
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;リージョンは米国東部（us-east）&lt;/li&gt;
&lt;li&gt;Windowsバンドルオプション&lt;/li&gt;
&lt;li&gt;スタンダード（2 vCPU、4GBメモリ）&lt;/li&gt;
&lt;li&gt;ルートボリューム80GB、ユーザーボリューム50GB&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ただし、この場合にネックになるのがパフォーマンスです。Amazon WorkSpacesの管理ドキュメントによると以下のような記載があります。&lt;/p&gt;
&lt;blockquote&gt;
 &lt;p&gt;&lt;p&gt;PCoIP のパフォーマンスを最大限に高めるには、クライアントネットワークからWorkSpaces があるリージョンまでのラウンドトリップ時間 (RTT) が 100ms 未満でなければなりません。RTT が 100 ミリ秒から 200 ミリ秒の間にある場合、ユーザーはWorkSpace にアクセスできますが、パフォーマンスに影響します。RTT が 200 ミリ秒～375 ミリ秒の間にある場合、パフォーマンスは低下します。RTT が 375 ミリ秒を超えると、WorkSpacesクライアント接続は終了します。&lt;/p&gt;
&lt;p&gt;WorkSpaces Streaming Protocol (WSP) の最高のパフォーマンスのためには、クライアントのネットワークから WorkSpaces があるリージョンまでの RTT が 250 ミリ秒未満でなければなりません。RTT が 250 ミリ秒から 400 ミリ秒の間にある場合、ユーザーはWorkSpace にアクセスできますが、パフォーマンスは低下します。&lt;/p&gt;
&lt;/p&gt;&lt;span class="cite"&gt;&lt;span&gt;― &lt;/span&gt;&lt;span&gt;AWS, &lt;/span&gt;&lt;a href="https://docs.aws.amazon.com/ja_jp/workspaces/latest/adminguide/workspaces-network-requirements.html"&gt;&lt;cite&gt;Amazon WorkSpaces クライアントネットワークの要件&lt;/cite&gt;&lt;/a&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;Amazon WorkSpacesの&lt;a class="link" href="https://clients.amazonworkspaces.com/Health.html" target="_blank" rel="noopener"
 &gt;Connection Health Check&lt;/a&gt;を見ると、日本国内からアクセスしたときの米国東部までのラウンドトリップ時間（以下RTT）は380msと表示されており、上記の記載に照らし合わせるとWorkSpaceにアクセスできないことになります。しかし、実際にはアクセスし、操作できます。ここで確認できるRTTと、実際にWorkSpacesのクライアント（Android版）から確認できるRTTは大きく乖離している場合があるためで、クライアントから確認できるRTTは186msでした。よって、RTTを確認する際には、実機にクライアントを入れて確認するのが一番良いと思います。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/03/images/connection_health_check.png"
	width="1200"
	height="580"
	loading="lazy"
	
		alt="Connection Health Checkの結果"
	
	
		class="gallery-image" 
		data-flex-grow="206"
		data-flex-basis="496px"
	
&gt;&lt;/p&gt;
&lt;h2 id="目的"&gt;目的
&lt;/h2&gt;&lt;p&gt;以下の操作を行い、体感性能がどの程度であるのかを把握します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WorkSpacesにログインする&lt;/li&gt;
&lt;li&gt;ソフトウェア（Google Chrome）をインストールする&lt;/li&gt;
&lt;li&gt;Google Chromeで速度測定（speed.cloudflare.com）を行う&lt;/li&gt;
&lt;li&gt;タスクマネージャや設定画面を開く&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="環境"&gt;環境
&lt;/h2&gt;&lt;p&gt;見て分かる通り、private-subnet-(1a|1b)は不要です。なぜ作ったかというと、もともとSimple ADとAmazon WorkSpacesはprivate-subnet-(1a|1b)に配置する計画でしたが、その場合、public-subnetにNATゲートウェイを設置する必要があり、そのコストが勿体ないと気がついたのが、public-subnetの作成後だったからです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2023/01/03/images/WorkSpaces_overall_design.drawio.png"
	width="1007"
	height="750"
	loading="lazy"
	
		alt="全体像"
	
	
		class="gallery-image" 
		data-flex-grow="134"
		data-flex-basis="322px"
	
&gt;&lt;/p&gt;
&lt;h2 id="結果"&gt;結果
&lt;/h2&gt;&lt;p&gt;作業をしている時に撮影した動画をYouTubeにアップロードしました。&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/Or0luY0mWCQ" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;ポイントは以下のとおりです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RTTは178ms（2023年1月2日20:00〜20:02に撮影）であったが、軽い作業であればレスポンスが気になることは少ないと思われる&lt;/li&gt;
&lt;li&gt;Google Chromeをインストールし、Chromeで速度測定を行う程度であれば体感上、遅いと感じることはない。ただ、CloudFlareを開いたときの引っかかりはややあるかという程度（Intel Celeron N4020を搭載したChromebook HP 14aでCloudFlareを開いたときよりはマシという程度）&lt;/li&gt;
&lt;li&gt;OSはWindows Server 2016 Datacenter (1607)&lt;/li&gt;
&lt;li&gt;WorkSpaceとインターネット（CloudFlare）の間のダウンロード速度は1.10Gbps、アップロード速度は926Mbps。Ping値は低いがJitter値がやや高い&lt;/li&gt;
&lt;li&gt;何も作業していない状態で、メモリは51%が使用されており、CPU使用率は5%前後位を推移。割り当てられているCPUは「Intel Xeon Platinum 8259CL CPU 2.5Ghz (2vCPU)」、メモリは4GB&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="今後について"&gt;今後について
&lt;/h2&gt;&lt;p&gt;メインマシンをChromebookに置き換えたので、年賀状印刷（特に宛名印刷）だけのためにWindows端末が必要な状況です。WorkSpaceに筆王をインストールし、自宅にVPNで接続後、自宅に据え付けているネットワークプリンタ（DCP-J4140N）を使って宛名印刷が出来るようにしてみたいと思います。今どき、宛名印刷はネットで注文できるのでこのような手間をかける意味は無いですが。&lt;/p&gt;</description></item><item><title>ITエンジニアに求められる姿勢、または能力に関する私見</title><link>https://sonohen.net/posts/2023/01/01/</link><pubDate>Sun, 01 Jan 2023 09:51:59 +0000</pubDate><guid>https://sonohen.net/posts/2023/01/01/</guid><description>&lt;h2 id="はじめに"&gt;はじめに
&lt;/h2&gt;&lt;p&gt;「ITエンジニア」にも色々いますが、特に大手企業から受託してシステム・インテグレーションを行っている人々のことを想定しています。あまり関係ないかもしれません。&lt;/p&gt;
&lt;p&gt;私が思うITエンジニアに求められる姿勢、または能力には3つのものがあると思います。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自社の課題と、顧客企業の課題を捉え、または捉えようとし、それを解決し、または解決しようとする姿勢、能力&lt;/li&gt;
&lt;li&gt;常に身の回りに疑問を持ち続け、それを解決し、または解決しようとする姿勢、能力&lt;/li&gt;
&lt;li&gt;言語を正しく運用する能力&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ここでは、個々に対して私見を整理したいと思います。&lt;/p&gt;
&lt;h2 id="自社の課題と顧客企業の課題を捉えまたは捉えようとしそれを解決しまたは解決しようとする姿勢能力"&gt;自社の課題と、顧客企業の課題を捉え、または捉えようとし、それを解決し、または解決しようとする姿勢、能力
&lt;/h2&gt;&lt;p&gt;顧客がIT投資の意思決定を行う背景には、大なり小なり課題があります。何の課題もないところに投資を行う必要はないということです。そして顧客は、課題を解決してくれる（と期待する）ベンダーにシステム開発を委託します。委託された側は、顧客の課題を、自らが持つアセットを使って解決しようとします&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;。これらの流れが途中で断ち切られると、IT投資は必ず失敗に終わります。&lt;/p&gt;
&lt;p&gt;ここで、以下のような疑問が出てきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;顧客はベンダーに課題を正確に伝えてくるでしょうか。&lt;/li&gt;
&lt;li&gt;ベンダーは、「他社」のビジネスと課題を正確に理解できるでしょうか。&lt;/li&gt;
&lt;li&gt;自社が持つアセットと自社の課題（不十分なところ）を正確に理解しているでしょうか。&lt;/li&gt;
&lt;li&gt;顧客と自社のそれぞれが持つ課題は、現場とマネジメントで一致しているでしょうか。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まず、顧客がベンダーに課題を正確に伝えてくることは稀だと思います。それは、顧客自身が正確に認識していないこともあれば、ベンダーからすれば他社のビジネスにおける課題なわけで、言葉の使い方、ニュアンスや温度感などを取り違えるなんていうことはザラでもあるからです。ゆえに、顧客とベンダーは、様々な技法を用いて、ビジネスと課題を共通認識のもとに捉えていくことが求められます。技法には「ドメイン駆動設計」のようなものがあれば、「デザイン思考」といったものもあるかもしれません。いずれにしても、双方向の取り組みが必要になるということです。&lt;/p&gt;
&lt;p&gt;そして、ビジネスと課題を共通認識のものにできたら、ベンダーは課題を解決、または整理しなければなりません。ここでは解決すると決めた課題について書きます。業界には課題を解決するための技術が多くあり、その技術は更に「基本」と「応用」に分解できます。応用部分に対して、各社が持ち合わせているアセットやその深度は多種多様で、強みもあれば、弱みもあります。そして多くの場合、顧客の課題を解決するのは「応用の技術」です。したがって、自社の何が強みで、何が弱みなのか。それに対してどのように対応しようとしているのか。これが自社の課題であり、顧客と対峙するときには、常に正しく認識しておくことが重要です&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;。これは何も強みを活かして対応しましょうということではありません。強みを活かすことも大事ですが、顧客からの求めによっては、弱みを課題として認識して対処する必要があるということです。&lt;/p&gt;
&lt;h2 id="常に身の回りに疑問を持ち続けいくつかを課題と捉えそれを解決しまたは解決しようとする姿勢能力"&gt;常に身の回りに疑問を持ち続け、いくつかを課題と捉え、それを解決し、または解決しようとする姿勢、能力
&lt;/h2&gt;&lt;p&gt;1つ目の話は、いわばトップダウンの考え方です。ビジネスを理解し、課題を抽出し、自社の課題を踏まえて顧客課題の解決を目指す、という3段階の流れです。ここでは、ボトムアップの考え方を書きたいと思います。&lt;/p&gt;
&lt;p&gt;先に「基本」と「応用」という言葉を使いました。「基本」とは、長きにわたって変わらないもので、常に立ち戻ることができる地点のことを意図して書いています。これに対して「応用」とは、基本を土台と捉え、その土台の上に成り立つ概念を意図して書いています。あるいは、応用が土台となり、その土台の上に成り立つ概念でもあります。例えば、何かをしようとした時に、ある方法よりも正確に行える方法、効率が良い方法、安全性が高い方法などを意図しています。&lt;/p&gt;
&lt;p&gt;まず、何においても「基本と応用の技術」を習得・研鑽することが肝要で、どちらかといえば基本に注力することが大事です。この理由は2つあります。まず、基本に注力すべき理由ですが、基本は応用の土台であり、不安定な土台のうえに物は載らない、あるいは載ったとしても不安定であり、もっと言えば載った状態の再現性が低いからです。次に、技術の習得と研鑽が肝要であるとする理由ですが、人は知らないことに対して疑問を持つことができないからです。人が疑問を持つのは、自分が知っている道理に沿って物事が進まないときです。人は何かを知り、そこから外れたものに対して疑問を持ち、その疑問の一部は、自分に不足している基本や応用の技術で塗り替えられ、そうでないものはやがて課題に置き換わっていきます。課題とは何かを達成するための障壁です。だから、「基本と応用の技術」の習得・研鑽は重要なのです。&lt;/p&gt;
&lt;p&gt;私の仕事はチームで仕事をするので、ここで「チーム」という言葉を考えたいと思います。そもそもチームとは個人の集団であって、チームを組む理由（意味）は（1）個人ではなし得ないことをやり遂げること、または、（2）そのやり遂げる結果が、個々の成果の総和を超えること、にあると考えます。特に（2）を目指すなら、そこに集まる個人によってチームとしての「基本と応用の技術」の幅が広げられ、かつ深くなっている状態でなければなりません&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;。さらに、その多様性を発信し、また個々人が受け入れることができる土壌も必要です。”Diversity and Inclusion”（多様性の受け入れ）の意味の1つはこれにあるのではないでしょうか。&lt;/p&gt;
&lt;p&gt;その中で、個人が持つ「基本と応用の技術」の範囲で、常に身の回りに疑問を持ち続けることが大切です。具体的には、「自分と周りが正しい&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;ことをしているか」を問い続けることです。断面はいくつかあるでしょう。ビジネス理解、課題抽出、設計、実装、テスト。アーキテクチャ。マネジメント。もっと広くは組織。それぞれに対し、「基本と応用の技術」を当てはめたときに、個人が疑問を生み出すことができ、その一部を個人またはチームの課題と捉えられるかどうかが、チームとしての成果を生み出せるか否かに関わり、ひいては顧客の課題を解決できるかどうかにも関わるのだと思います。&lt;/p&gt;
&lt;h2 id="言語を正しく運用する能力"&gt;言語を正しく運用する能力
&lt;/h2&gt;&lt;p&gt;最後は、「言語」の話です。&lt;/p&gt;
&lt;p&gt;私の仕事の成果は、すべて「言語」で成り立っています。言葉には2つあり、1つは日本語や英語といった人間同士が使う言語（これを便宜上、会話言語とします）、もう1つはサーバやネットワーク等のインフラ、およびそれらの上で動作する各種ソフトウェアを開発または統合し、動作させるために必要な言語（あるいはパラメータ類）です。&lt;/p&gt;
&lt;p&gt;それを生産するプロセスは大きく3つに分けられると思います。1つ目は顧客のビジネスや課題を、会話言語を用いて言語化して共通認識の下に置くこと、2つ目は、その課題を解決するための方法を「基本と応用の技術」を用いて考えること、３つ目は、考えた解決策をコンピュータ等が理解できる形に変換することです。これらのすべてで言語が使われ、そして最終的に変換するということは、変換元となるものの解釈を誤ってはならないですし、変換も正確に行われなければなりません。それぞれの対象に適した言語を適切に運用しなければならないのです。&lt;/p&gt;
&lt;p&gt;よりよい（より伝わり易い）言い回しがないか、よりよい実装の仕方はないかを常に自分に問いながら、言語を正しく運用していきたいものです。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ
&lt;/h2&gt;&lt;p&gt;勘違いしないで頂きたいのは、あくまで上記は私見であり、また、自分が出来ていると思っているものでもないということです。また、人によって置かれた状況が異なるため、ITエンジニアに求められるものも人それぞれ、またはその時々によって変わるものと思います。&lt;/p&gt;
&lt;p&gt;ただ、現時点でITエンジニアに求められるものは、ここに書いた3つのことに帰結するのではと私は思っていますし、少なくとも2023年においても私とチームの課題でもあると思っていますので、ここに書いたことを念頭に置きながら仕事をしていきたいと考えています。&lt;/p&gt;
&lt;p&gt;では、よいお年を。&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;実際には、QCD等に代表される「制約」の範囲において、です。&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;一方で顧客は、そのベンダーの強みと弱みを理解し、課題を解決する道筋を立てられるか、その道筋に適合するかを自分たち、またはコンサルティングファームのコンサルタントと一緒に考え、自分たちの解を持っておくことが重要です。&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;マネジメントの要素もありますが、ここでは話を単純にするために書かないことにします。&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;「正しい」とは、あらゆるレベルで共有された目標・目的に向かって、まっすぐの方向へ推し進めようとする力のことです。&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>ブログ環境をGitHubからAWSに移行しました</title><link>https://sonohen.net/posts/2022/12/06/</link><pubDate>Tue, 06 Dec 2022 11:24:12 +0000</pubDate><guid>https://sonohen.net/posts/2022/12/06/</guid><description>&lt;h2 id="今までの構成"&gt;今までの構成
&lt;/h2&gt;&lt;p&gt;今までは、静的CMSである&lt;a class="link" href="https://hexo.io/" target="_blank" rel="noopener"
 &gt;Hexo&lt;/a&gt;を使ってローカル環境で各ページを生成し、生成されたページをGitHub Pagesで公開する、という構成を取っていました。&lt;/p&gt;
&lt;p&gt;この構成を取っていた理由は以下の2つです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ブログ記事をMarkdown形式で書くことができ、HTMLを作るために必要なテンプレートや設定ファイルを&lt;code&gt;git&lt;/code&gt;で管理できるため&lt;/li&gt;
&lt;li&gt;GitHub Pagesは、リポジトリに&lt;code&gt;git push&lt;/code&gt;さえすればページが公開され、かつ無料で気軽に使うことができるため&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;しかし思うところがあり、今回、この構成をAWSに移行することにしました。&lt;/p&gt;
&lt;h2 id="新たに構築した構成"&gt;新たに構築した構成
&lt;/h2&gt;&lt;p&gt;新たに構築した構成のイメージは以下の通りです。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sonohen.net/posts/2022/12/06/images/overall_image.png"
	width="692"
	height="340"
	loading="lazy"
	
		alt="構成イメージ"
	
	
		class="gallery-image" 
		data-flex-grow="203"
		data-flex-basis="488px"
	
&gt;&lt;/p&gt;
&lt;p&gt;ポイントは以下のとおりです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Chromebookで執筆した記事をCodeCommitに&lt;code&gt;git push&lt;/code&gt;すると、CloudWatch EventsがCodePipelineを起動する&lt;/li&gt;
&lt;li&gt;CodeBuildが、&lt;code&gt;/buildspec.yml&lt;/code&gt;に記載された内容に基づき、&lt;code&gt;hexo generate&lt;/code&gt;を実行する。そして、生成されたHTML（&lt;code&gt;./public/&lt;/code&gt;配下）をS3バケットと&lt;code&gt;aws s3 sync&lt;/code&gt;で同期する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これにより、（1）&lt;code&gt;source/_pages/&lt;/code&gt;にMarkdown形式で記事を書いた記事を保存する、（2）&lt;code&gt;git commit&lt;/code&gt;と&lt;code&gt;git push&lt;/code&gt;を実行する、だけで、自動的にブログ記事が公開されるわけです。&lt;/p&gt;
&lt;h2 id="ハマったポイント"&gt;ハマったポイント
&lt;/h2&gt;&lt;h3 id="git-clone-sshgit-codecommitap-northeast1-amazonawscomv1reposでpermission-denied-publickeyが発生しcloneに失敗する"&gt;&lt;code&gt;git clone ssh://git-codecommit.ap-northeast1-amazonaws.com/v1/repos/...&lt;/code&gt;で、&lt;code&gt;Permission denied (publickey).&lt;/code&gt;が発生し、cloneに失敗する
&lt;/h3&gt;&lt;p&gt;確認したポイントは以下です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.ssh/id_rsa&lt;/code&gt;（秘密鍵）のパーミッションが400になっていること&lt;/li&gt;
&lt;li&gt;Management Consoleの&lt;code&gt;IAM &amp;gt; ユーザー &amp;gt; 認証情報 &amp;gt; AWS CodeCommit の SSH キー&lt;/code&gt;に、&lt;code&gt;~/.ssh/id_rsa.pub&lt;/code&gt;の内容が正しく登録されていること&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これでもエラーが解消しなかったため、&lt;a class="link" href="https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/troubleshooting-ssh.html" target="_blank" rel="noopener"
 &gt;Troubleshooting SSH connections to AWS CodeCommit&lt;/a&gt;を参考に、&lt;code&gt;git clone ssh://[my-key-id]@git-codecommit.ap-northeast1-amazonaws.com/v1/repos/...&lt;/code&gt;を実行したところ、&lt;code&gt;git clone&lt;/code&gt;できるようになりました。&lt;code&gt;my-key-id&lt;/code&gt;は、IAMから確認できます。&lt;/p&gt;
&lt;h3 id="buildspecymlに記載したaws-s3-sync-src-destの実行がlistobjectsv2のaccess-deniedエラーで失敗する"&gt;&lt;code&gt;buildspec.yml&lt;/code&gt;に記載した&lt;code&gt;aws s3 sync [src] [dest]&lt;/code&gt;の実行が、&lt;code&gt;ListObjectsV2&lt;/code&gt;のAccess Deniedエラーで失敗する
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-access-denied-listobjects-sync/" target="_blank" rel="noopener"
 &gt;Amazon S3 バケットで sync コマンドを実行すると、ListObjectsV2 で Access Denied (アクセス拒否) エラーが表示されるのはなぜですか?&lt;/a&gt;によると、&lt;code&gt;ListObjectsV2&lt;/code&gt;の実行を許可するためには、IAMで&lt;code&gt;s3:ListBuckets&lt;/code&gt;の実行を許可する必要があります。&lt;/p&gt;
&lt;p&gt;と、ここまでは良いのですが、何を血迷ったのか、私は以下のように記載し、&lt;em&gt;&lt;code&gt;CodePipeline&lt;/code&gt;のサービスロール&lt;/em&gt;にアタッチして3時間ほど悩んでいました。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;YAML&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Effect&amp;#34;: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Allow&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Action&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;s3:ListBuckets&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;s3:PutObject&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;s3:GetObject&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;s3:DeleteObject&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Resource&amp;#34;: &lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;arn:aws:s3:::.../*&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;これをアタッチしてから何回もCodePipelineを実行しましたが、毎回毎回&lt;code&gt;ListObjectsV2&lt;/code&gt;起因のエラーでパイプラインが止まりました。深夜になっていたこともあり、一旦そこで作業を中断しましたが、翌日、CodePipelineではなく、CodeBuildのサービスロールにアタッチしなければ意味が無いことに気が付きました。（&lt;code&gt;aws s3 sync&lt;/code&gt;を呼び出すのはCodePipelineではなくCodeBuildのため）&lt;/p&gt;
&lt;h2 id="なぜawsに移行したのか"&gt;なぜAWSに移行したのか
&lt;/h2&gt;&lt;p&gt;昨年、Chromebook hp 14aを購入したのをきっかけに、日常作業のほぼ全てをクラウド環境に移行しました。Windows環境が必要なScanSnapを使った書類のスキャンと、開発作業のためにWindows端末を残しています。&lt;/p&gt;
&lt;p&gt;ただ、よくよく考えて見ると、Windows端末での作業もChromebookに移行できそうです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ScanSnapをWiFi対応のものに買い換えることで、クラウドストレージに直接スキャンデータを保存できるようになりそう&lt;/li&gt;
&lt;li&gt;Windowsで実施している開発も、AWSのサービスをうまく組み合わせればWindows環境なしでもいけそう。Cloud9 + なにか、で出来そう。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特に最近、開発に使っているPCのスペックが時代遅れになりつつあり、必要な時に必要なリソースが取れるクラウド環境での開発に興味が出始めています。開発環境をAWSに移行する際には、Codeシリーズの使い方を少しは知っておく必要があるので、研究を兼ねてAWSに移行しました。&lt;/p&gt;
&lt;h2 id="今後の構想"&gt;今後の構想
&lt;/h2&gt;&lt;p&gt;以下の5点を年内目処くらいでやっておきたいなと思っています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Slackからコマンドを投げると、自動的にPipelineが動作するようにする。&lt;/li&gt;
&lt;li&gt;CloudFrontを使った配信&lt;/li&gt;
&lt;li&gt;S3の非公開化&lt;/li&gt;
&lt;li&gt;独自ドメインを使ったアクセス&lt;/li&gt;
&lt;li&gt;開発環境の移行。色々やり方はありそう。EC2/ CodeCatalyst/ Cloud9/ WorkSpacesなど。WorkSpacesを使うなら、Wyseの端末を買ってシンクライアント化するのも面白そうではある&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ちなみに"&gt;ちなみに、
&lt;/h2&gt;&lt;p&gt;この記事は、&lt;a class="link" href="https://www.fmworld.net/fmv/cb/" target="_blank" rel="noopener"
 &gt;富士通のChromebook(14F)&lt;/a&gt;で、下書きは&lt;a class="link" href="https://dynalist.io/" target="_blank" rel="noopener"
 &gt;Dynalist&lt;/a&gt;を使って、最終的な整形と&lt;code&gt;git push&lt;/code&gt;はCloud9を使って書いています。また、構成イメージは&lt;a class="link" href="https://diagrams.net/" target="_blank" rel="noopener"
 &gt;diagrams.net&lt;/a&gt;で書きました。&lt;/p&gt;
&lt;h2 id="20230109追記"&gt;2023/01/09追記
&lt;/h2&gt;&lt;p&gt;結局、GitHub Pagesに戻しました。&lt;/p&gt;</description></item><item><title>AWS Certified Cloud Practitioner合格記</title><link>https://sonohen.net/posts/2021/12/16/</link><pubDate>Thu, 16 Dec 2021 00:24:12 +0000</pubDate><guid>https://sonohen.net/posts/2021/12/16/</guid><description>&lt;p&gt;AWS認定資格の登竜門である「AWS Cloud Practitioner」を受験し、合格したので記録として残します。&lt;/p&gt;
&lt;h2 id="バックグラウンド"&gt;バックグラウンド
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;SIerで、DCの物理配線〜アプリ開発、PMまで幅広く。オンプレも仮想基盤（プライベートクラウド）は利用した経験あり&lt;/li&gt;
&lt;li&gt;その後、コンサルファームに移籍&lt;/li&gt;
&lt;li&gt;プライベートでは広く浅く勉強するも、パブリッククラウドに対する疑心暗鬼は絶えず&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;とは言っても、今や猫も杓子もパブリッククラウド（また？）、内製！ローコード！の再燃（何回目や……）もあり、いよいよ勉強しなければと思いつつ、仕事でクラウドを使うこともなかったので、体系的に勉強するために勉強・受験しました。&lt;/p&gt;
&lt;h2 id="勉強方法"&gt;勉強方法
&lt;/h2&gt;&lt;p&gt;私は以下で勉強をしました。特にAWS Cloud Practitioner Essentialsは、AWSが何たるかを手っ取り早く掴むのに非常に分かりやすいリソースです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AWS Skill Builder - AWS Cloud Practitioner Essentials (Japanese)(日本語実写版)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.amazon.co.jp/dp/4797397403" target="_blank" rel="noopener"
 &gt;AWS認定資格試験テキスト AWS認定 クラウドプラクティショナー&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.udemy.com/course/aws-4260/" target="_blank" rel="noopener"
 &gt;【2022年版】この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（7回分455問）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;合格率は不明ですが（※公表されていない）、ネットの情報を見ていると簡単な資格と錯覚するケースがあるようです。ですが、勉強しないと普通に落ちます。ただし、勉強しても落ちます。何が問われるのかは、模擬試験問題などを見るとわかります。&lt;/p&gt;
&lt;h2 id="点数"&gt;点数
&lt;/h2&gt;&lt;p&gt;799点 / 1,000点（※ビミョー）&lt;/p&gt;
&lt;h2 id="今後"&gt;今後
&lt;/h2&gt;&lt;p&gt;以下を取得して、次の仕事を探したい。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AWS Certified Solutions Architect - Associate&lt;/li&gt;
&lt;li&gt;AWS Certified DevOps Engineer - Associate&lt;/li&gt;
&lt;li&gt;AWS Certified SysOps Administrator - Associate&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>dnfでRepository is listed more than once in the configurationが表示された場合の対応</title><link>https://sonohen.net/posts/2021/05/082/</link><pubDate>Sat, 08 May 2021 20:45:53 +0000</pubDate><guid>https://sonohen.net/posts/2021/05/082/</guid><description>&lt;p&gt;結論としては、&lt;code&gt;/etc/yum.repos.d/&lt;/code&gt;の配下に別名で、中身が（ほぼ同じ）ファイルが2つ存在したための警告メッセージであったため、重複しているものを無効にすることでメッセージの出力を抑制した。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ls -alh /etc/yum.repos.d/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;合計 60K
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;664&lt;/span&gt; 5月 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 19:48 .
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root 5.3K 5月 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 19:51 ..
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;190&lt;/span&gt; 4月 &lt;span style="color:#ae81ff"&gt;28&lt;/span&gt; 21:29 1password-beta.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;210&lt;/span&gt; 5月 &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; 01:01 1password.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;311&lt;/span&gt; 1月 &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; 14:48 _copr_phracek-PyCharm.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;728&lt;/span&gt; 4月 &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 02:31 fedora-cisco-openh264.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root 1.3K 4月 &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 02:31 fedora-modular.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root 1.4K 4月 &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 02:31 fedora-updates-modular.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root 1.4K 4月 &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 02:31 fedora-updates-testing-modular.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root 1.4K 4月 &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 02:31 fedora-updates-testing.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root 1.3K 4月 &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 02:31 fedora-updates.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root 1.3K 4月 &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 02:31 fedora.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;173&lt;/span&gt; 5月 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 19:48 google-chrome.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root 1.5K 1月 &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; 14:48 rpmfusion-nonfree-nvidia-driver.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root 1.4K 1月 &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; 14:48 rpmfusion-nonfree-steam.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;148&lt;/span&gt; 5月 &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; 21:00 skype-stable.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r--. &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;154&lt;/span&gt; 5月 &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; 21:02 teams.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;なぜか1passwordのrepoが2つ存在している。ので、これのうち一つをどこかに移してしまえば良さそう。というわけで、どちらを残すのか中身を確認してみる。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;diff&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ diff 1password.repo 1password-beta.repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;2,3c2,3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt; name=&amp;#34;1Password Beta Channel&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt; baseurl=https://downloads.1password.com/linux/rpm/beta/$basearch
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;&amp;gt; name=1Password
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;&amp;gt; baseurl=https://downloads.1password.com/linux/rpm/beta/x86_64
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;7c7
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt; gpgkey=&amp;#34;https://downloads.1password.com/linux/keys/1password.asc&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;&amp;gt; gpgkey=https://downloads.1password.com/linux/keys/1password.asc
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;細かい差分はさておき、注目すべき差分は &lt;code&gt;1password.repo&lt;/code&gt; の &lt;code&gt;$basearch&lt;/code&gt; である。 ここで、 &lt;code&gt;$basearch&lt;/code&gt; には &lt;code&gt;x86_64&lt;/code&gt; が入る（see &lt;a class="link" href="https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/deployment_guide/sec-using_yum_variables" target="_blank" rel="noopener"
 &gt;6.3.3 Yum 変数の使用&lt;/a&gt;) ということなので、つまり2つのファイルに差分は見受けられない。&lt;/p&gt;
&lt;p&gt;ゆえに、&lt;code&gt;1password for Linux&lt;/code&gt; はbeta版であるので、&lt;code&gt;/etc/yum.repos.d/1password-beta.repo&lt;/code&gt;を残す方針とする。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo mv 1password.repo 1password.repo.old
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo dnf update
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;メタデータの期限切れの最終確認: 1:56:41 時間前の 2021年05月08日 18時22分17秒 に実施しました。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;依存関係が解決しました。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;行うべきことはありません。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;完了しました!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ついでに、&lt;code&gt;/etc/yum.repos.d/google-chrome.repo&lt;/code&gt;も削除しておいた（Firefoxに移行したため）。&lt;/p&gt;</description></item><item><title>Rcloneの使い方</title><link>https://sonohen.net/posts/2021/05/081/</link><pubDate>Wed, 05 May 2021 21:56:43 +0000</pubDate><guid>https://sonohen.net/posts/2021/05/081/</guid><description>&lt;h2 id="rcloneとは"&gt;Rcloneとは
&lt;/h2&gt;&lt;blockquote&gt;
 &lt;p&gt;Rclone is a command line program to manage files on cloud storage. It is a feature rich alternative to cloud vendors&amp;rsquo; web storage interfaces. Over 40 cloud storage products support rclone including S3 object stores, business &amp;amp; consumer file storage services, as well as standard transfer protocols.&lt;/p&gt;&lt;span class="cite"&gt;&lt;span&gt;― &lt;/span&gt;&lt;span&gt;Rclone, &lt;/span&gt;&lt;a href="https://rclone.org/"&gt;&lt;cite&gt;Rclone&lt;/cite&gt;&lt;/a&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;つまるところ、Rcloneはクラウドストレージを操作するためのコマンドライン・インタフェースであり、40を超えるクラウドサービスに加え、標準的な転送プロトコル（SFTP等）もサポートしているというものです。&lt;/p&gt;
&lt;h2 id="使い方"&gt;使い方
&lt;/h2&gt;&lt;p&gt;使用する前に、設定を行う必要があります。ここでは、&lt;code&gt;onedrive&lt;/code&gt;を例に記載します。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;**&lt;/code&gt;に囲まれている箇所が入力する箇所です。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ rclone config
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021/05/05 21:34:53 NOTICE: Config file &lt;span style="color:#e6db74"&gt;&amp;#34;/home/sonohen/.config/rclone/rclone.conf&amp;#34;&lt;/span&gt; not found - using defaults
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;No remotes found - make a new one
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n&lt;span style="color:#f92672"&gt;)&lt;/span&gt; New remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;s&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Set configuration password
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;q&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Quit config
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n/s/q&amp;gt; n
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;name&amp;gt; **onedrive**
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Type of storage to configure.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Enter a string value. Press Enter &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; the default &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Choose a number from below, or type in your own value
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; / 1Fichier
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;fichier&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; / Alias &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; an existing remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;alias&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; / Amazon Drive
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;amazon cloud drive&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; / Amazon S3 Compliant Storage Providers including AWS, Alibaba, Ceph, Digital Ocean, Dreamhost, IBM COS, Minio, and Tencent COS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;s3&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; / Backblaze B2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;b2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; / Box
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;box&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; / Cache a remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;cache&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; / Citrix Sharefile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;sharefile&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; / Compress a remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;compress&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; / Dropbox
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;dropbox&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; / Encrypt/Decrypt a remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;crypt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;12&lt;/span&gt; / Enterprise File Fabric
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;filefabric&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; / FTP Connection
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ftp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; / Google Cloud Storage &lt;span style="color:#f92672"&gt;(&lt;/span&gt;this is not Google Drive&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;google cloud storage&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt; / Google Drive
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;drive&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; / Google Photos
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;google photos&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; / Hadoop distributed file system
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hdfs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt; / Hubic
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hubic&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; / In memory object storage system.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;memory&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; / Jottacloud
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;jottacloud&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt; / Koofr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;koofr&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; / Local Disk
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;local&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; / Mail.ru Cloud
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;mailru&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;24&lt;/span&gt; / Mega
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;mega&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;25&lt;/span&gt; / Microsoft Azure Blob Storage
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;azureblob&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; / Microsoft OneDrive
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;onedrive&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; / OpenDrive
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;opendrive&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;28&lt;/span&gt; / OpenStack Swift &lt;span style="color:#f92672"&gt;(&lt;/span&gt;Rackspace Cloud Files, Memset Memstore, OVH&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;swift&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; / Pcloud
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;pcloud&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; / Put.io
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;putio&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;31&lt;/span&gt; / QingCloud Object Storage
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;qingstor&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt; / SSH/SFTP Connection
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;sftp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;33&lt;/span&gt; / Sugarsync
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;sugarsync&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;34&lt;/span&gt; / Tardigrade Decentralized Cloud Storage
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;tardigrade&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;35&lt;/span&gt; / Transparently chunk/split large files
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;chunker&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;36&lt;/span&gt; / Union merges the contents of several upstream fs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;union&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;37&lt;/span&gt; / Webdav
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;webdav&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;38&lt;/span&gt; / Yandex Disk
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;yandex&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;39&lt;/span&gt; / Zoho
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;zoho&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;40&lt;/span&gt; / http Connection
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;41&lt;/span&gt; / premiumize.me
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;premiumizeme&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt; / seafile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;seafile&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Storage&amp;gt; **26**
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;*See help &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; onedrive backend at: https://rclone.org/onedrive/*
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;OAuth Client Id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Leave blank normally.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Enter a string value. Press Enter &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; the default &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;client_id&amp;gt;**&lt;span style="color:#f92672"&gt;[&lt;/span&gt;Blank&lt;span style="color:#f92672"&gt;]&lt;/span&gt;**
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;OAuth Client Secret
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Leave blank normally.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Enter a string value. Press Enter &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; the default &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;client_secret&amp;gt;**&lt;span style="color:#f92672"&gt;[&lt;/span&gt;Blank&lt;span style="color:#f92672"&gt;]&lt;/span&gt;**
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Choose national cloud region &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; OneDrive.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Enter a string value. Press Enter &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; the default &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;global&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Choose a number from below, or type in your own value
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; / Microsoft Cloud Global
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;global&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; / Microsoft Cloud &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; US Government
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;us&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; / Microsoft Cloud Germany
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;de&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; / Azure and Office &lt;span style="color:#ae81ff"&gt;365&lt;/span&gt; operated by 21Vianet in China
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;cn&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;region&amp;gt; **1**
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Edit advanced config? &lt;span style="color:#f92672"&gt;(&lt;/span&gt;y/n&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;y&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Yes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n&lt;span style="color:#f92672"&gt;)&lt;/span&gt; No &lt;span style="color:#f92672"&gt;(&lt;/span&gt;default&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;y/n&amp;gt; **n**
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Remote config
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Use auto config?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * Say Y &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; not sure
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * Say N &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; you are working on a remote or headless machine
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;y&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Yes &lt;span style="color:#f92672"&gt;(&lt;/span&gt;default&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n&lt;span style="color:#f92672"&gt;)&lt;/span&gt; No
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;y/n&amp;gt; **y**
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;If your browser doesn&lt;span style="color:#e6db74"&gt;&amp;#39;t open automatically go to the following link: http://127.0.0.1:53682/auth?state=xxx
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Log in and authorize rclone for access
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Waiting for code...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;**ここでブラウザが開くので、Microsoftアカウントでログインし、画面の指示に従う。**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Got code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Choose a number from below, or type in an existing value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 1 / OneDrive Personal or Business
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; \ &amp;#34;onedrive&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 2 / Root Sharepoint site
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; \ &amp;#34;sharepoint&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 3 / Sharepoint site name or URL (e.g. mysite or https://contoso.sharepoint.com/sites/mysite)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; \ &amp;#34;url&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 4 / Search for a Sharepoint site
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; \ &amp;#34;search&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 5 / Type in driveID (advanced)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; \ &amp;#34;driveid&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 6 / Type in SiteID (advanced)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; \ &amp;#34;siteid&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 7 / Sharepoint server-relative path (advanced, e.g. /teams/hr)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; \ &amp;#34;path&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Your choice&amp;gt; **1**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Found 1 drives, please select the one you want to use:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;0: (personal) id=xxx
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Chose drive to use:&amp;gt; **0**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Found drive &amp;#39;&lt;/span&gt;root&lt;span style="color:#e6db74"&gt;&amp;#39; of type &amp;#39;&lt;/span&gt;personal&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;, URL: https://onedrive.live.com/?cid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;xxx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Is that okay?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;y&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Yes &lt;span style="color:#f92672"&gt;(&lt;/span&gt;default&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n&lt;span style="color:#f92672"&gt;)&lt;/span&gt; No
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;y/n&amp;gt; **y**
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;onedrive&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;type &lt;span style="color:#f92672"&gt;=&lt;/span&gt; onedrive
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;region &lt;span style="color:#f92672"&gt;=&lt;/span&gt; global
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;token &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;access_token&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;token_type&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;Bearer&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;refresh_token&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;expiry&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;2021-05-05T22:36:16.565429024+09:00&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drive_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; xxx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drive_type &lt;span style="color:#f92672"&gt;=&lt;/span&gt; personal
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;y&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Yes this is OK &lt;span style="color:#f92672"&gt;(&lt;/span&gt;default&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;e&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Edit this remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;d&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Delete this remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;y/e/d&amp;gt; **y**
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Current remotes:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Name Type
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;====&lt;/span&gt; &lt;span style="color:#f92672"&gt;====&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;onedrive onedrive
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;e&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Edit existing remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;n&lt;span style="color:#f92672"&gt;)&lt;/span&gt; New remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;d&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Delete remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;r&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Rename remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;c&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Copy remote
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;s&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Set configuration password
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;q&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Quit config
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;e/n/d/r/c/s/q&amp;gt; **q**&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="使い方-1"&gt;使い方
&lt;/h2&gt;&lt;h3 id="リモート側のファイルを確認する"&gt;リモート側のファイルを確認する
&lt;/h3&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ rclone ls onedrive:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="リモートからファイルをダウンロードする"&gt;リモートからファイルをダウンロードする
&lt;/h3&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ rclone copy -P onedrive: /path/to/download&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;他のコマンドは、&lt;a class="link" href="https://rclone.org/docs/" target="_blank" rel="noopener"
 &gt;詳細&lt;/a&gt;を参照。&lt;/p&gt;</description></item><item><title>2021年のGWを振り返る</title><link>https://sonohen.net/posts/2021/05/05/</link><pubDate>Wed, 05 May 2021 20:27:56 +0000</pubDate><guid>https://sonohen.net/posts/2021/05/05/</guid><description>&lt;h2 id="2021年のgwの目標"&gt;2021年のGWの目標
&lt;/h2&gt;&lt;p&gt;以下の目標を立てていました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;自宅のレッツノートのFedora 33からFedora 34へのアップグレード&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;レッツノート&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;のスクロールをまともに動かすようにする&lt;/li&gt;
&lt;li&gt;OneDriveからの脱却のため、NAS（LANDISK）にファイルを移管する&lt;/li&gt;
&lt;li&gt;Emacsでeasy-hugo, wanderlust, org-agenda, org-capture, org-roamの設定&lt;/li&gt;
&lt;li&gt;GnuCashで使っているMySQLのバックアップ自動化&lt;/li&gt;
&lt;li&gt;「TCP/IPの絵本」の読了&lt;/li&gt;
&lt;li&gt;「ネットワークはなぜつながるのか」の読了&lt;/li&gt;
&lt;li&gt;「マスタリングTCP/IP」の読了&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="実績"&gt;実績
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;アップデート完了。不具合として認識しているのは、(1)Virt Managerを使った場合のUSB Redirectionの動作不良（&lt;a class="link" href="https://fedoraproject.org/wiki/Common_F34_bugs#USB_devices_forwarded_from_the_host_to_a_guest_aren.27t_recognized_in_a_libvirt_virtual_machine" target="_blank" rel="noopener"
 &gt;詳細&lt;/a&gt;）、(2) Pipewireがレッツノート上で機能しない（音が出ない）、の2点。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;systemd&lt;/code&gt;を使用し、サスペンドからレジュームした際に&lt;code&gt;i2c_hid&lt;/code&gt;を&lt;code&gt;modprove&lt;/code&gt;するようにした。これが実に快適。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Personal Valut&lt;/code&gt;のほかは、LANDISKに移行完了。同時に、自宅のネットワークに接続している場合、自動で&lt;code&gt;mount&lt;/code&gt;するように自動化した。&lt;/li&gt;
&lt;li&gt;いずれも設定完了。&lt;/li&gt;
&lt;li&gt;今週末対応予定。&lt;/li&gt;
&lt;li&gt;読了。&lt;/li&gt;
&lt;li&gt;途中まで読んだ（10%程度）。&lt;/li&gt;
&lt;li&gt;未着手。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="今後実施したいこと"&gt;今後実施したいこと
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;1passwordに月会費を支払っているので、bitwarden等に移行したい。&lt;/li&gt;
&lt;li&gt;低レベルプログラミングへの着手。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;毎年支払っているOffice 365の年間サブスクリプション（年額約1万3千円程度）を節約するため、徐々にMicrosoftから離れつつあります。&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;CF-SV9を使用中。サスペンドからレジュームした際に、タッチパッドの動作が非常に遅くなり、操作不能になります。&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>VS CodeからDebian on WSL2.0にアクセスできずに焦った話</title><link>https://sonohen.net/posts/2021/04/12/</link><pubDate>Mon, 12 Apr 2021 19:29:25 +0000</pubDate><guid>https://sonohen.net/posts/2021/04/12/</guid><description>&lt;h2 id="発生した問題"&gt;発生した問題
&lt;/h2&gt;&lt;p&gt;VS Codeが出力したエラーメッセージは次の通りでした。&lt;code&gt;VS Code Server for WSL closed unexpectedly.&lt;/code&gt;と表記されている通り、WSL向けのVS Code Serverへの接続が予期しない理由により切断された、ということです。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-Plain" data-lang="Plain"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.224] Resolving wsl+debian, resolveAttempt: 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.302] Starting VS Code Server inside WSL (Debian)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.302] Extension version: 0.54.6, Windows build: 19042. Multi distro support: available. WSL path support: enabled
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.302] No shell environment set or found for current distro.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.510] Probing if server is already installed: C:\Windows\System32\wsl.exe -d Debian -e sh -c &amp;#34;[ -d ~/.vscode-server/bin/08a217c4d27a02a5bcde898fd7981bda5b49391b ] &amp;amp;&amp;amp; printf found || ([ -f /etc/alpine-release ] &amp;amp;&amp;amp; printf alpine-; uname -m)&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.775] Probing result: found
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.775] Server install found in WSL
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.777] Launching C:\Windows\System32\wsl.exe -d Debian sh -c &amp;#39;&amp;#34;$VSCODE_WSL_EXT_LOCATION/scripts/wslServer.sh&amp;#34; 08a217c4d27a02a5bcde898fd7981bda5b49391b stable .vscode-server 0 &amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.968] sh: 1: /mnt/c/Users/sonohen/.vscode/extensions/ms-vscode-remote.remote-wsl-0.54.6/scripts/wslServer.sh: Input/output error
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.969] VS Code Server for WSL closed unexpectedly.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.969] For help with startup problems, go to
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.969] https://code.visualstudio.com/docs/remote/troubleshooting#_wsl-tips
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2021-04-12 10:24:41.981] WSL Daemon exited with code 0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="原因"&gt;原因
&lt;/h2&gt;&lt;p&gt;不明。この事象が発生している時に、Windows TerminalからDebian on WSL2.0にアクセスし、以下のコマンドを発行したところ、エラーが発生した。&lt;code&gt;cd&lt;/code&gt;の後に&lt;code&gt;ls&lt;/code&gt;が発行されているのは環境によるものである。&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Shell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;% cd /mnt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ls: &lt;span style="color:#e6db74"&gt;&amp;#39;c&amp;#39;&lt;/span&gt; にアクセスできません: 入力/出力エラーです&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="解決方法"&gt;解決方法
&lt;/h2&gt;&lt;p&gt;VS Codeを閉じた後、コマンドプロンプトで以下のコマンドを実行し、その後、再度VS Codeを起動する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;PowerShell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wsl --shutdown&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="参考にしたサイト"&gt;参考にしたサイト
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/microsoft/WSL/issues/6174" target="_blank" rel="noopener"
 &gt;WSL2 cannot access &amp;lsquo;c&amp;rsquo;: Input/output error&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;~/.zshrcに、&lt;code&gt;chpwd() { ls -ltr --color=auto }&lt;/code&gt;を登録しているため、cd直後にlsコマンドが発行されている。&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>WSL2で使っているソフトウェア</title><link>https://sonohen.net/posts/2020/06/02/</link><pubDate>Tue, 02 Jun 2020 01:08:36 +0000</pubDate><guid>https://sonohen.net/posts/2020/06/02/</guid><description>&lt;ul&gt;
&lt;li&gt;今のところ使っているアプリケーションは以下の通り。
&lt;ul&gt;
&lt;li&gt;GNU Emacs&lt;/li&gt;
&lt;li&gt;tmux&lt;/li&gt;
&lt;li&gt;tig: gitのクライアント&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;dotfilesの管理も始めた。&lt;/li&gt;
&lt;li&gt;Windows Terminalは，Alt+Enterでフルスクリーンになる。
&lt;ul&gt;
&lt;li&gt;上記の環境だと，もはやWindowsなのかLinuxなのか分からないですね。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>放送大学大学院の通信指導課題提出結果と今後の作戦について</title><link>https://sonohen.net/posts/2020/05/24/</link><pubDate>Sun, 24 May 2020 14:58:21 +0900</pubDate><guid>https://sonohen.net/posts/2020/05/24/</guid><description>&lt;p&gt;履修している科目は以下の通り。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;人的資源管理（&amp;lsquo;18）&lt;/li&gt;
&lt;li&gt;社会的協力論（&amp;lsquo;20）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;結果は，どちらも満点。人的資源管理については，一部（というか半分）の回答は，テキストを見ながら実施したので当然といえば当然ではある。&lt;/p&gt;
&lt;p&gt;社会的協力論は引き続き真面目に受講するとして，人的資源管理については理解が不十分な箇所（特に人的資源管理の歴史や，人事等級・考課制度とモチベーションの関連）があるので，今後，復習を実施していく必要があると認識。復習だからそんなに時間はかからないと思うが，最後にまとめてやろうとすると大変なので，通常の講義の予復習や研究課題レポートの執筆と並行して計画的に進めていくことにしたい。早速，org-modeで管理しているtodo管理表に，「人的資源管理の復習計画を立てること」というタスクを追加した。&lt;/p&gt;
&lt;p&gt;終わり。&lt;/p&gt;</description></item><item><title>Windows Subsystem for Linux (WSL) 2への変換</title><link>https://sonohen.net/posts/2020/05/20/</link><pubDate>Wed, 20 May 2020 14:37:27 +0900</pubDate><guid>https://sonohen.net/posts/2020/05/20/</guid><description>&lt;h2 id="バージョンの確認"&gt;バージョンの確認
&lt;/h2&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;PowerShell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PS C:\Users\sonohen&amp;gt; wsl -l -v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NAME STATE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;* Debian Stopped 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="変換を試みる"&gt;変換を試みる
&lt;/h2&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;PowerShell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PS C:\Users\sonohen&amp;gt; wsl --set-version Debian &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;変換中です。この処理には数分かかることがあります...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WSL 2 を実行するには、カーネル コンポーネントの更新が必要です。詳細については https://aka.ms/wsl2kernel を参照してください&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以下のURLにアクセスして、&lt;code&gt;wsl-update_x64.msi&lt;/code&gt;をダウンロードする。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-kernel" target="_blank" rel="noopener"
 &gt;手順 4 - Linux カーネル更新プログラム パッケージをダウンロードする&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;セットアップが終わったら，再度チャレンジする。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;PowerShell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PS C:\Users\sonohen&amp;gt; wsl --set-version Debian &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;変換中です。この処理には数分かかることがあります...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WSL 2 との主な違いについては、https://aka.ms/wsl2 を参照してください
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Windows の仮想マシン プラットフォーム機能を有効にして、BIOS で仮想化が有効になっていることを確認してください。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;詳細については、https://aka.ms/wsl2-install を参照してください&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;そもそもの手順を実施していなかったので実施する。&lt;/p&gt;
&lt;h2 id="仮想バーチャルマシンサービスのインストール"&gt;仮想バーチャルマシンサービスのインストール
&lt;/h2&gt;&lt;p&gt;管理者としてPowerShellを実行する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;PowerShell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PS C:\WINDOWS\system32&amp;gt; dism.exe /online /enable-feature /featurename&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;VirtualMachinePlatform /all /norestart&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;展開イメージのサービスと管理ツール
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;バージョン: 10.0.19041.1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;イメージのバージョン: 10.0.19041.264
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;機能を有効にしています
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[==========================100.0%==========================]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;操作は正常に完了しました。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="wsl2を既定のバージョンとして設定する"&gt;WSL2を既定のバージョンとして設定する
&lt;/h2&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;PowerShell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PS C:\WINDOWS\system32&amp;gt; wsl --set-default-version &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WSL 2 との主な違いについては、https://aka.ms/wsl2 を参照してください&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;これで今後インストールされるWSLはバージョン2となる。&lt;/p&gt;
&lt;h2 id="変換する"&gt;変換する
&lt;/h2&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;PowerShell&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PS C:\WINDOWS\system32&amp;gt; wsl --set-version Debian &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PS C:\WINDOWS\system32&amp;gt; wsl -l -v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;プレーンテキスト&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	NAME STATE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;* Debian Stopped 2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Hugoをインストールする</title><link>https://sonohen.net/posts/2020/05/06/</link><pubDate>Wed, 06 May 2020 11:36:53 +0900</pubDate><guid>https://sonohen.net/posts/2020/05/06/</guid><description>&lt;h2 id="hugoを導入する"&gt;Hugoを導入する
&lt;/h2&gt;&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ hugo new site shared/site
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cd site
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ code config.toml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;baseURL &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;http://sonohen.github.io/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;languageCode &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ja-JP&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;title &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;sonohen&amp;#39;s tech log&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ hugo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ここの時点で，publicディレクトリーが作られていることを確認する。&lt;/p&gt;
&lt;h2 id="テーマの導入"&gt;テーマの導入
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://themes.gohugo.io/" target="_blank" rel="noopener"
 &gt;Hugo Theme&lt;/a&gt;にすぐに使えるテーマが掲載されている。&lt;/p&gt;
&lt;p&gt;今回は，&lt;a class="link" href="https://github.com/carsonip/hugo-theme-minos" target="_blank" rel="noopener"
 &gt;Hugo Theme Minos&lt;/a&gt;を利用する。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cd themes/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git clone --depth &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; https://github.com/carsonip/hugo-theme-minos
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ code ../../config.toml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;theme &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hugo-theme-minos&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;paginate &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;params&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; smartToc &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ hugo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="github-pageの設定"&gt;GitHub Pageの設定
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;blogレポジトリを作る
&lt;ol&gt;
&lt;li&gt;これはprivateレポジトリで良い&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;sonohen.github.ioレポジトリを作る&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="gitの設定"&gt;Gitの設定
&lt;/h2&gt;&lt;p&gt;public/は，サブモジュールとして管理する。レポジトリが別なため。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git submodule add -b master git@github.com:sonohen/sonohen.github.io.git public&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以下のエラーではまったでござる。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git submodule add -b master git@github.com:sonohen/sonohen.github.io.git public
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;A git directory &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;public&amp;#39;&lt;/span&gt; is found locally with remote&lt;span style="color:#f92672"&gt;(&lt;/span&gt;s&lt;span style="color:#f92672"&gt;)&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;origin https://github.com/sonohen/sonohen.github.io.git
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;If you want to reuse this local git directory instead of cloning again from
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git@github.com:sonohen/sonohen.github.io.git
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;use the &lt;span style="color:#e6db74"&gt;&amp;#39;--force&amp;#39;&lt;/span&gt; option. If the local git directory is not the correct repo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;or you are unsure what this means choose another name with the &lt;span style="color:#e6db74"&gt;&amp;#39;--name&amp;#39;&lt;/span&gt; option.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;この場合，古いsubmodule情報が&amp;quot;.git/&amp;ldquo;以下に残っていることが原因なので，以下のディレクトリとファイルの中身を確認して，古いファイルを削除してやる必要がある。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;.git/modules/&lt;/li&gt;
&lt;li&gt;.git/config&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;こうならないためには，以下のようにsubmoduleを削除しましょう。&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-language"&gt;Bash&lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git submodule deinit &amp;lt;消したいsubmodueへのパス&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git rm &amp;lt;消したいsubmoduleへのパス&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="visual-studio-codeを設定して記事を書く"&gt;Visual Studio Codeを設定して記事を書く
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Hugofy（akmittal.hugofy）をインストールする。&lt;/li&gt;
&lt;li&gt;Hugofy: New Postを選択する。&lt;/li&gt;
&lt;li&gt;記事を書く。&lt;/li&gt;
&lt;li&gt;Hugofy: Buildを選択する。&lt;/li&gt;
&lt;li&gt;siteとpublicをcommit&amp;amp;pushする。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://to-developer.com/blog/?p=1970" target="_blank" rel="noopener"
 &gt;[git]git submodule addでエラー「A git directory for ‘[指定モジュール]‘ is found locally with remote(s):」&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>