Ubuntu 23.04への式年遷宮 トラブル録

普段はLTSしか使わないのだが、なんかやりたい気持ちになったので珍しく奇数系を入れてみた。

https://www.ubuntulinux.jp/News/ubuntu2304-ja-remix

をUSBメモリに焼いて(今はUbuntu公式でもEtcher使えって書いてるんですね、昔はUbuntuにUbuntuのイメージを焼くためのソフトウェアが付属していた気がするが)、PC再起動。

インストールの手順については、特に変化はなさそう。今回はLVM使用、ディスク暗号化をつけてみた。

gnome-text-editorで日本語入力できない

毎度の鬼門(と言いつつ、熱心な日本Ubuntuユーザーが結構情報を残してくれているので言うほどではない)。こちらのページが参考になった。

https://www.kkaneko.jp/tools/server/gnome_ja_input_method.html

注意点として、23.04では(正確には22.10から)はgeditに代わってgnome-text-editorというソフトウェアが入っている。こいつがfcitxとの相性が悪いのか、日本語変換が一切効かない(日本語入力モードに入れない)。シェルから開いてみるとこんなエラーメッセージが残されていた。

(gnome-text-editor:9858): Gtk-WARNING **: 03:13:56.134: No IM module matching GTK_IM_MODULE=fcitx found

意味はよくわからないのだが、fcitxを使えと言われているがgnome-text-editorがそれを理解できていないように見える。実際にはgnome-text-editorのリポジトリにこのようなエラーメッセージはなさそうなので、GTK自体に何らかの問題があるのかもしれない。

20230507追記

fcitxじゃなくてfcitx5を入れると問題が起きなかった。

vscodeで日本語入力時に確定するまで文字が表示されない

確定するまでは変換ボックスを見ないと入力中の文字が確認できず、Enterで確定すると一気にエディタ上に文字が追加される状態になった。これはUbuntu Softwareからデフォルトのsnapで入れていたのが悪いので、消してdebで入れ直したら直った。

bluetoothヘッドホンで音が鳴らない・途切れる・汚い

Linuxでbluetoothヘッドホンを使うのはコツがいる。僕が使ってるのはWH-1000XM4ね。

まず音が途切れるのはドライバのバッファリングが下手くそなせいなので、pavucontrol→出力デバイス→WH-1000XM4→高度な設定でLatency offsetを10msくらいにしてやる。ほんの少しでも設定してやるといい感じになる。

音が汚いのはコーデックがHSPになっているから。bluetoothヘッドホンの通信コーデックにはA2DPとHSPがあり、前者は聞く専用で高音質、後者はヘッドホンの付属マイクからの音声入力も可能だが音質は悪い。なのでA2DPに設定してやることで解決(これはbluemanからでも標準のbluetooth設定からでも、たぶんCLIからでもできる)。

音が鳴らないのは今回初めて遭遇した。HSPでの接続は可能だったがA2DPが選べなかったり、A2DPにすると音が鳴らなくなったりした。これは理由が不明だが、ペアリング直後にbluemanからA2DPに設定してやることで解決した。

ストレージデバイスのマウント

今回はなるべくGUIでやっちゃうのを目標にした。普段はストレージデバイスのマウントは/etc/fstabを手で編集してやっているが、今回は「ディスク」から。デバイス→パーティションを選択して、歯車マークのメニューから「マウントオプションを編集」でGUIからマウントを設定できる。ここで設定した内容がfstabに書き込まれていた。

やはり奇数系のUbuntuを使うのはエキサイティングだ。時間のあるときに限るが、楽しいんだこれが。

静的サイトをS3にデプロイしてCloudFrontから配信する

世界中で一億回やられてる作業なので僕が言うことはない。これ読む。終わり。いつ書かれたものかよくわからないけどAWSのドキュメント類は割と頑張って最新の状態に追従してるので信頼していい。

https://repost.aws/knowledge-center/cloudfront-serve-static-website

  • S3バケット作る
    • 静的ウェブサイトホスティングは無効でいい
  • CloudFrontディストリビューションを作る
    • Origin access control settingsを選ぶ
    • ディストリビューションを作った後にS3にコピペするためのポリシーのコピーボタンが表示されるので、そこでコピってS3のアクセス許可→バケットポリシーにペーストする

https://hogehoge.cloudfront.net でindex.htmlにアクセスさせたい

CloudFront側のディストリビューションの設定からデフォルトルートオブジェクトをindex.htmlに設定する

https://repost.aws/questions/QU2waf6J-gRQWvvYu8jysr4Q/questions/QU2waf6J-gRQWvvYu8jysr4Q/cloudfront-distribution-not-serving-s3-bucket-pages-unless-index-html-included-in-url

その他のhtmlファイルに.htmlなしでアクセスさせたい

S3側でhtmlファイルの.htmlを削除し、Content-Typeをtext/htmlにする(大抵最初からなってそう)

https://medium.com/@gauravduttkale/static-aws-s3-website-pages-without-html-extensions-12db3e15e153

食物依存性運動誘発アナフィラキシー?

2年くらい前から急に蕁麻疹が出て1時間くらいで収まることが何度かあった。最近はプールで泳いだ後に出るという規則性があり、医者の友人から「食物依存性運動誘発アナフィラキシー」の可能性を指摘された。食後すぐに運動するとアレルゲンが急速に吸収されて蕁麻疹や呼吸困難を起こすというものらしい。

これを実験するために天丼(withエビ)を食べてからランニングをしてみたところ、過去にないほど強烈な蕁麻疹が出た。#7119で相談したら「呼吸困難がないなら救急車を呼ぶ必要はないが医者には行け」とのことで行ったところ、やはり食事と運動の組み合わせがよくなさそうとのことだった。ちゃんと運動をするようになったせいで発覚するのは皮肉だ。

蕁麻疹が出てしばらく痒いくらいなら自分で実験したろwと軽い気持ちだったが、ひどいアナフィラキシーが出ると命も危険だったので慎重になるべきだった。今日再び天丼を食べて、普通に歩いて帰宅して大人しくしていたら蕁麻疹は起きなかった。

という訳で私は甲殻類を食べた後は走らないので、ご承知おきください。

TypeScriptの引数を分割代入したときの ‘A’ is assignable to the constraint of type ‘T’, but ‘T’ could be instantiated with a different subtype of constraint ‘B’ みたいなエラー

T型の引数を受け取ってそのまま返す関数だが、返り値の型をTにすると型エラーになる。

const f1 = <T extends { user: { id: number } }>({ user, ...rest }: T): T => {
  return {
    user,
    ...rest,
  }
}
Type '{ id: number; } & Omit<T, "id">' is not assignable to type 'T'.
  '{ id: number; } & Omit<T, "id">' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{ id: number; }'.(2322)

このエラーメッセージが難しい。 T extends { user: { id: number } } に注目する。extendsだからTはたとえば

type T1 = {
  user: {
    id: number;
    name: string;
  }
}

かもしれない(狭い型)。そうだとしても、関数内でのuserの型は { id: number } だ。nameがあることにはならない。TypeScriptならわかるかと思ったがわからないらしい。

Tに何を渡されようと返り値のuserの型は { id: number } (広い型)なので、それを T["user"] (狭い型)に渡しても要求を満たせないことがある。だから型エラーになる。

という話はここに書いてあるのだが
https://github.com/microsoft/TypeScript/issues/33579#issuecomment-534789400

このように書くと引数の型を維持できる。

const f2 = <T extends { user: { id: number } }>({ user, ...rest }: T): Omit<T, "user"> & { user: T["user"] } => {
  return {
    user,
    ...rest,
  }
}

const b = f2({user:{id: 1, name: "chao", premium: false}})
const p = b.user.premium // アクセス可能

TypeScriptくんは書き方によって推論ができたりできなかったりする。かわいい。

docker-composeのスタック名で結構苦労した話

そんなにちゃんと調べた記事じゃないです…

docker-compose upすると適当なstackが作られ、stack名はデフォルトでdocker-compose.ymlがあるディレクトリの名前になる。僕は複数のリポジトリでdocker-compose.ymlをdockerディレクトリの下に入れているから、複数のstackの名前が docker になって被る。そうするとstack内のコンテナとかボリュームの名前も docker-app とか docker-db とかになり、他のstackとぶつかりまくる。特にボリュームの名前の衝突は最悪で、特にハッシュ化とかしてないので同じボリューム名だとホストマシンの同じ場所にマウントされてDBのスキーマ違いますと怒られたりする。

stack名をちゃんと指定するにはdocker-composeの-pオプションを使うのだが、そもそもdocker-composeというのはupとdownしか覚えられない人間が使うもので、アプリケーションによって適切なオプションをつけて運用するのは不可能だ。結局僕はコンテナやボリュームの名前にアプリケーション名のプレフィックスをつけることで問題を回避したのだが、docker-compose.ymlのトップレベルにnameを入れておけば解決するらしい?(未検証)docker-compose.ymlの仕様(というかdocker系のドキュメント)、ググってもどれが信用できる情報かわからなくていつも適当にしちゃう。