Architect's Log

I'm a Cloud Architect. I'm highly motivated to reduce toils with driving DevOps.

Today I Learned - 2026-05-29

はてなブログワークフローで記事を投稿する

テンプレートリポジトリ: https://github.com/hatena/Hatena-Blog-Workflows-Boilerplate

セットアップは省略。組織ではなく個人利用を想定。

下書きを作成する

プルリクエストを作成する。

  1. Actions から create draft を選択し、Titleに記事タイトルを設定、Branch: mainに対して実行する
  2. 作成した下書きを含むプルリクエストが作成される

下書きを含むブランチがリモートに作成される。ブランチ名は draft-entry-xxxxx という形式になっている。

ローカルで下書きを編集する

リモートの情報を取得してからスイッチする。

git fetch origin
git switch draft-entry-xxxxx

記事を公開する

下書きを編集したらフロントマターのDraft: trueを削除し、コミット、プッシュする。

git push origin draft-entry-xxxxx

-u (--set-upstream) で次回からブランチ指定を省略できる。マージ後にブランチは削除するので、今回はつけていない。

プルリクエストを main ブランチにマージすると記事が公開される。

はてなブログワークフローで既存記事を修正する

main ブランチに修正を直接プッシュしても、記事には反映されない。修正ブランチを main ブランチにマージする必要がある。

修正ブランチを作成する。

git switch -c fix/entry

修正をコミットしたらプッシュする。

git push origin fix/entry

GitHub でプルリクエストを作成し、main にマージすると、記事に反映される。

Linuxディストリビューションのバージョンを取り出す

ディストリビューションのバージョンを確認したい。

Amazon Linux 2023 の例。

$ cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2
# Amazon Linux 2023.7.20250331

元の出力は以下のようになっている。

$ cat /etc/os-release
# NAME="Amazon Linux"
# VERSION="2023"
# ID="amzn"
# ID_LIKE="fedora"
# VERSION_ID="2023"
# PLATFORM_ID="platform:al2023"
# PRETTY_NAME="Amazon Linux 2023.7.20250331"
# ANSI_COLOR="0;33"
# CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2023"
# HOME_URL="https://aws.amazon.com/linux/amazon-linux-2023/"
# DOCUMENTATION_URL="https://docs.aws.amazon.com/linux/"
# SUPPORT_URL="https://aws.amazon.com/premiumsupport/"
# BUG_REPORT_URL="https://github.com/amazonlinux/amazon-linux-2023"
# VENDOR_NAME="AWS"
# VENDOR_URL="https://aws.amazon.com/"
# SUPPORT_END="2029-06-30"

なお、カーネルのバージョンを出力するには、以下のコマンドを使用する。

$ uname -r
# 6.12.20-23.97.amzn2023.x86_64

Webサーバーを構成していないターゲットに対してALBのエンドポイントにリクエストして疎通確認する方法(続き)

til-2026-05-28 のコードを再掲する。

python3 -c "
import http.server, socketserver

class Handler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b'OK')
    def log_message(self, format, *args):
        pass  # ログ抑制

with socketserver.TCPServer(('', 8443), Handler) as httpd:
    httpd.serve_forever()
"

リッスンポートは環境依存なので、環境変数で渡すようにする。

PORT=8443 python3 -c "
import http.server, socketserver, os

PORT = int(os.environ['PORT'])

class Handler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b'OK')
    def log_message(self, format, *args):
        pass  # ログ抑制

with socketserver.TCPServer(('', PORT), Handler) as httpd:
    print(f'Listening on port {PORT}')
    httpd.serve_forever()
"

出力の際にプロンプトが改行されず見づらいので、末尾に改行を入れる。

PORT=8443 python3 -c "
import http.server, socketserver, os

PORT = int(os.environ['PORT'])

class Handler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.end_headers()
-        self.wfile.write(b'OK')
+        self.wfile.write(b'OK\n')
    def log_message(self, format, *args):
        pass  # ログ抑制

with socketserver.TCPServer(('', PORT), Handler) as httpd:
    print(f'Listening on port {PORT}')
    httpd.serve_forever()
"

Ctrl + Cでエラーが出力される

^CTraceback (most recent call last):
  File "<string>", line 16, in <module>
  File "/usr/lib64/python3.9/socketserver.py", line 232, in serve_forever
    ready = selector.select(poll_interval)
  File "/usr/lib64/python3.9/selectors.py", line 416, in select
    fd_event_list = self._selector.poll(timeout)
KeyboardInterrupt

Ctrl+C による KeyboardInterrupt を Catch して、いったん解消した。あとで精査する。

with socketserver.TCPServer(('', PORT), Handler) as httpd:
     print(f'Listening on port {PORT}')
-    httpd.serve_forever()
+    try:
+        httpd.serve_forever()
+    except KeyboardInterrupt:
+        pass
 "

Ctrl + Cで終了した直後に再度実行するとエラー終了する

Traceback (most recent call last):
  File "<string>", line 14, in <module>
  File "/usr/lib64/python3.9/socketserver.py", line 452, in __init__
    self.server_bind()
  File "/usr/lib64/python3.9/socketserver.py", line 466, in server_bind
    self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use

使用中のポートへの再バインドで失敗している。SO_REUSEADDR を有効にすると、TIME_WAIT 状態のソケットが残っていても同じポートにバインドできるようになる。

+socketserver.TCPServer.allow_reuse_address = True
 with socketserver.TCPServer(('', PORT), Handler) as httpd:
     print(f'Listening on port {PORT}')
     try:
         httpd.serve_forever()
     except KeyboardInterrupt:
         pass

これらをすべて取り込んだ改良版。

PORT=8443 python3 -c "
import http.server, socketserver, os

PORT = int(os.environ['PORT'])

class Handler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b'OK\n')
    def log_message(self, format, *args):
        pass

socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer(('', PORT), Handler) as httpd:
    print(f'Listening on port {PORT}')
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass
"