職場のSlackで「姪にお年玉いくら渡せば良いんだろう」という話になって、そういえば自分も今年秋頃に姪が出来たのでお年玉を渡す必要があると思い出しました。
そこでお年玉の金額はいくらぐらいが適切なのか考え始めました。
世間一般的には「小学生はこれぐらい、中学生はこれぐらい…」としているようです。
しかし私はこれには不満があります。
私は超過累進税率など行政の区分による分け方を常々批判してきました。ここで言う超過累進税率は、所得税などが1,949,000円までは5%で、それから少しだけ稼いだら10%になるという区分による分け方のことです。 No.2260 所得税の税率|国税庁
税金だけではなく障害年金の未成年時から発症してた場合の所得制限などにも同じような不満があります。
累進課税自体はドシドシやるべきだと思いますが、区分による分け方は非常に分かりにくいと常々思っています。
じゃあどうして欲しいのかというと単純に数値を入れて、関数を使って様々な計算をして欲しいと考えています。
区分による分け方と単純な割合による計算は昔ながらの手作業による仕分けをする場合は有用だったと思いますが、今となってはコンピュータで計算が出来るためそこまで問題では無いと考えています。むしろ区分がどちらになるのか気にせずwebなどでサクッと関数を呼び出して分かる方が便利だと思います。
そう考えているので私がそういった計算手段を使うのはダブルスタンダードだと思うのでやめます。
これをお年玉に割り当てると中学生3年生と高校1年生で大きく金額を変えるのは嫌ということです。
よって年齢引数からお年玉の金額を計算する関数を作りたいと思います。
20歳が最後で打ち止めですね。
ちなみにという数式もよく使われるようですね。これで良いかもしれませんが20歳では流石に少なくないかと思ったのと、もうこれ知った時は記事ほぼ書き終わってしまったので関数を作ります。
世間一般的な計算方法を使わないにしても、世間一般的に渡されるお年玉と大きく乖離していると世間体的に問題があると思います。
よってそれにある程度近似するようにしたいと思います。
あまり良さそうな統計が存在せず、総務省が出している統計データの1月の贈与金では自分が全体で出した額しか分かりません。統計局ホームページ/家計調査(家計収支編) 調査結果そして一番知りたい渡す相手の年齢ごとの金額も分かりません。
仕方がないので民間の調査を使うことにします。お年玉の相場を関係性や年齢別に紹介!あげるときのマナーは? | 【楽天市場】 Mama's Life
この調査によるとおおよそ以下の傾向があるそうです。
これに沿って1つの年齢にごとに対する指数を作ります。
前提として私の収入がそれなりの額で維持されてある程度余裕を持っているということにして多めに設定します。金なくなったら変えます。
また姪というある程度親しい人間に対してのお年玉ということについても考慮の余地があります。知らない人には渡しません。
区分ごとに分けていきましょう。
自分で数式を作るのは大変苦手なのでこれに近似する関数をChatGPTに作ってもらいます。
なるべくシンプルな関数にしてもらって両替も面倒くさいので端数は切り上げることにしましょう。
単純にプロンプトを作ったらPythonでnumpyとscipyを使ってcurve_fit
を使われて、
3歳の時に-100円になる謎の関数が出来てしまいました。
そもそもぶっ壊れていることと、ずっとこれが同じ結果で実行できるとも思えないので、シンプルに数式を作ってもらいます。
ライブラリを禁止した場合区分を作られてしまったため区分も禁止します。
区分を禁止したところやはり数年間マイナスの金額が発生しまったり、年齢が上がって何故か金額が下がったりということが起きました。仕方がないので指標を増やします。特に幼少期はマイナスにならないように指標を雑に増やして調整します。区分的なことが嫌だから関数を作ってもらっているのに、結局区分のようなことをしてしまっています。つらい。
プログラム言語を使わないで係数を調整するのはやはり困難らしい。最終的な関数が不安定なランタイムに依存しなければ係数を求めることにプログラミング言語を使うことは許容出来るため許可します。
お年玉の金額を計算する関数の数式を作ってください。
指標として年齢に対するお年玉の金額の返り値は以下のようになります。
この数値に近似するようにしてください。
なるべくシンプルな数式にしてください。
連続的な数値にしたいので区分分けは禁止します。
両替が面倒なので端数は100円単位で切り上げてください。
係数を計算するためにプログラミング言語などを使っても構いませんが、長く使えるように最終的な数式はプログラミング言語に依存しない汎用的な数式にしてください。
数式らしきものは得られましたがあまり近似しないので手元でPythonをじっくり回して力技で探索回数を増やしましたが、係数はあまり変わりませんでした。
これを100円単位で切り上げます。
module Main where
main :: IO ()
main = mapM_ (\x -> putStrLn $ show x <> ": " <> show (f x)) [0..20]
f :: Int -> Int
f ix = ceiling ((9.43 * x^3 - 162.70 * x^2 + 937.87 * x + 844.51) / 100.0) * 100
where x = fromIntegral ix
指数と異なるものも結構出てきましたが、曲線を保つためには仕方がないのかな。
100円単位で妙な端数を入れるのは互いに面倒くさいなと気がついたので1000円単位で四捨五入してもらうことにします。
お年玉の金額を計算する関数の数式を作ってください。
指標として年齢に対するお年玉の金額の返り値は以下のようになります。
この数値に近似するようにしてください。
なるべくシンプルな数式にしてください。
連続的な数値にしたいので区分分けは禁止します。
受け渡しが面倒なので1000円単位で四捨五入してください。
係数を計算するためにプログラミング言語などを使っても構いませんが、長く使えるように最終的な数式はプログラミング言語に依存しない汎用的な数式にしてください。
これを1000円単位で四捨五入します。
module Main where
main :: IO ()
main = mapM_ (\x -> putStrLn $ show x <> ": " <> show (f x)) [0..20]
f :: Int -> Int
f ix = round ((269.24 * exp(0.234 * x) + 1196.07) / 1000) * 1000
where x = fromIntegral ix :: Double
ChatGPTにグラフを作成させるコードを雑に吐き出させます。グラフは冒頭に貼ったやつです。
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
# 年齢とお年玉の金額のデータ
ages = np.array([0, 3, 6, 12, 15, 18, 20])
money = np.array([1000, 2000, 3000, 5000, 10000, 20000, 30000])
# 近似する関数の定義 (単純な指数関数を使用)
def money_func(x, a, b, c):
return a * np.exp(b * x) + c
# パラメータのフィッティング
params, covariance = curve_fit(money_func, ages, money)
# フィッティングした関数を使ってお年玉の金額を計算
x_values = np.linspace(0, 20, 100) # 0歳から20歳までの範囲を100点でサンプリング
y_values = money_func(x_values, *params)
# グラフの描画
plt.rcParams['font.family'] = "HackGen Console NF"
plt.figure(figsize=(10, 6))
plt.plot(x_values, y_values, label='Fitted Function', color='blue')
plt.scatter(ages, money, color='red', label='Original Data')
plt.title('年齢に対するお年玉の金額')
plt.xlabel('年齢')
plt.ylabel('お年玉額(円)')
plt.legend()
plt.grid(True)
plt.rc("svg")
plt.savefig("otoshidama-by-age.svg")
20年間のこれぐらいの計算だったら自分でゼロから考えたほうがおそらく楽だった。区分をなるべく作りたくないという謎のこだわりのせいでやたらと面倒になった。
算出過程は割と面白かったですが。
2023年11月の「Windows Update」、AI機能「Copilot in Windows」などの展開を拡大 - 窓の杜で何かしら問題が発生する可能性は高かったのですが、セキュリティフィックスが含まれていたので仕方なく即座にアップデートしました。
Keyhacによる、
wslg.exe
経由でEmacsを起動する設定が動かなくなりました。
その設定は最終的に、
keymap.ShellExecuteCommand(None, com, param, "", swmode="maximized")()
を呼び出すようになっており、引数を埋めると以下のようになります。
keymap.ShellExecuteCommand(None, "wslg.exe", "--cd ~ -d Ubuntu -- emacs", "", swmode="maximized")()
これが動かなくなりました。以下のようなエラーになります。
Traceback (most recent call last):
File "../ckit\ckit_threadutil.py", line 231, in run
File ".\keyhac_keymap.py", line 2161, in jobShellExecute
FileNotFoundError: [WinError 2] 指定されたファイルが見つかりません。
Emacsが悪いとかparamsが悪いとかではなく、とにかくwslg.exeが見つかりません。
C++部分の共有ライブラリとかに破壊的変更があったのかと思いましたが不発。
wslg.exeをPowerShellとかから起動すると動くようです。謎。
Update the path of wslg.exe for the new MSI package. by benhillis · Pull Request #1124 · microsoft/wslg で入った変更を見る限り、本物のwslg.exeが入った場所が変わったようです。
本当はPRに含まれているようにレジストリの値を見る必要があると思いますが、大抵の環境なら以下のように本物のwslg.exeを参照するように設定すれば動きます。
def program_files(*pathsegments: str) -> WindowsPath:
"""`C:/Program Files/`以下を単純に参照します。"""
# Keyhacが現状32bitで動いているため、64ビット版のディレクトリを指してくれるように指定します。
return WindowsPath(os.environ["ProgramW6432"], *pathsegments)
keymap_global["W-n"] = run_or_raise(
keymap,
check_func=check_func_emacs,
command=str(program_files("WSL", "wslg.exe")),
param="--cd ~ -d Ubuntu -- emacs",
)
動かないwslg.exe
がPATH
にあるのは罠すぎるので、とりあえず原因はさっぱり分からないのですがissueとして建てておくことにしました。
ちょっと前に知ったんですがyarn v4が10月23日に正式リリースされていました。
前にyarn v4からはバンドルされたJavaScriptプログラムであるreleasesやpluginsをGitにコミットする必要が無くなります - ncaqという記事を書きました。
この記事に書いてある通り、 yarn v4ではyarn berry(v2以後)に感じていた問題が解決されていました。その時v4が正式リリースされたら移行しようと考えていたため移行します。
その時に少しだけ躓いた問題をメモします。
私は~/.local/bin
をPATH
に追加してユーザスペースでインストールするプログラムはそこに置いてあるので、
corepackでインストールする場合以下のようなコマンドを実行します。
corepackはNode v14から追加されています。
corepack enable --install-directory ~/.local/bin npm yarn
私はGentoo LinuxのnodejsのUSEフラグで、 corepackを有効にして競合するnpmのUSEフラグを無効化しているため、 npmもcorepack管理しています。 pnpmとかも有効化出来ますがとりあえず今は使ってないのでスルーしています。
しかしyarn v3の頃は問題なかった気がするのですが、この方法でcorepackでプロジェクトに依存しないグローバルにインストールしてyarn
コマンドを使うと、そのプロジェクトがyarn classic(yarn v1)で管理されていると自動でyarn v4にマイグレーションされてしまいます。
自分のプロジェクトなら流石にそろそろberryに移行するのでそれを機会にマイグレーションしても良いのですが、他人がGitHubにホストしてるプロジェクトにちょっとしたPRを出すときに、「ついでにyarn berryに移行しておきました」と出すのは流石に気が引けます。
理想の動きとしてはberry移行しているプロジェクトでは指定されたバージョンのパッケージマネージャを使って、 yarn classicを使っているプロジェクトではyarn classicを使うようにしたいです。
ではcorepackを使うのをやめて、 Gentooが提供するyarnパッケージを使えば良いのではと考えました。
yarn v1は、 yarn v2にまつわる誤解 | Wantedly Engineer Blogに書かれてあるように、新しいyarnのブートローダとして使えます。今それをcorepackとして分離していて一応corepackはまだExperimentalなのでそれでも良いかなと考えました。
しかしそれはそれで問題があります。
corepackで管理されていると、 corepack is 何?に書かれてあるように、 package.jsonに、
"packageManager": "yarn@4.0.1"
のように書いてあれば自動でyarn v4が使われるのですが、 yarnのブートローダ機能に頼る場合はそれは使えません。
その場合、 .yarnrc.ymlに、
yarnPath: .yarn/releases/yarn-4.0.1.cjs
のように書かれてそれが読み込まれることになるのですが、そうなると.yarn
ディレクトリを消すとyarnが実行できなくなってしまうため、先の私の記事で書いたようにバンドル済み実行プログラムをgitにcommitする必要が発生してしまいます。
これの解決方法は簡単です。
corepackを使ってグローバルにはyarn classicをインストールして、プロジェクトごとにパッケージマネージャをyarn set version stable
などで指定すれば問題ありません。
具体的には以下のようにします。
# corepackでnpmとyarnを管理する。
corepack enable --install-directory ~/.local/bin npm yarn
# グローバルでは勝手にマイグレーションを行わないようにyarn classicを利用する。
corepack prepare yarn@1 --activate
自分はこれをyarn-install-world
実行スクリプトに含めて、
yarn global add
でprettierをインストールするついでに事前実行しています。
これでyarn classicが使われているプロジェクトではyarn classicが使われ、 corepackでパッケージマネージャを管理しているプロジェクトではそれが使われるようになりました。
AWS Private Certificate Authority(AWSプライベートCA)の認証機関を作成することになりました。
当然こういったものはAWS CDKを使って管理したいものです。短命な鍵オンリーなモードでもあるだけで月額50ドル飛んで行くそうなので、なおさらですね。
ただ、 aws-cdk-lib.aws_acmpcaでは、高水準な抽象化がされたクラスでの生成管理が出来なくて、 Cfnレベルのリソースを使う必要があってかなり調べるのに苦労したので、メモしておきます。
認証機関を作るだけならば、 CfnCertificateAuthorityを、適当にnewしてやれば終了です。
ただそれだと保留中の認証機関が出来るだけで、ルートCAも作成されず、様々な操作が出来ません。
手動でwebコンソールをcdk deployの間に叩きに行くとかは絶対に避けたい話ですね。
なので以下の3つのクラスを連携させる必要があります。
コンソールでは「CA証明書をインストール」となっているのでそれをすれば良いのだろうと思って、
new CfnCertificate
したのですが、
The certificate authority is not in a valid state for issuing certificates (Service: AWSACMPCA; Status Code: 400; Error Code: InvalidStateException;…)
というエラーに悩まされ続けてきました。
例外処理 - AWS Certificate Manager には確かにこのエラーが書かれているのですが、待機中の認証機関にが証明書を発行出来ないというわけで、でも待機を解くには証明書をインストールしないといけないというジレンマに陥りました。
もがき苦しんだ結果、
Creating and installing the CA certificate - AWS Private Certificate Authority
で、
--template-arn arn:aws:acm-pca:::template/RootCACertificate/V1
が指定されているのを見て、
CAデフォルトの証明書を作るにはtemplateArn
プロパティに特定のテンプレートの指定が必要だとやっと分かりました。
確かに書いてはあったんですが、誰もこれをやっていなかったのか、サンプルコードが全然転がってなくて該当の引数を見つけるのに苦労しました。
引数の受け渡しとかもちょっと微妙にわかりにくいので、スタックの例を書いておきます。
import { Stack, StackProps } from "aws-cdk-lib";
import {
CfnCertificate,
CfnCertificateAuthority,
CfnCertificateAuthorityActivation,
} from "aws-cdk-lib/aws-acmpca";
import { HostedZone } from "aws-cdk-lib/aws-route53";
import { Construct } from "constructs";
interface Props extends StackProps {
rootZone: HostedZone;
}
/**
* 短命限定で証明書を発行するAWS Private Certificate Authorityを立ち上げる。
* 短命限定モードだと比較的安いとは言え、存在しているだけで月50ドルのそれなりのコストがかかる。
*/
export default class ShortLivedPrivateCaStack extends Stack {
cfnCertificateAuthority: CfnCertificateAuthority;
cfnCertificate: CfnCertificate;
cfnCertificateAuthorityActivation: CfnCertificateAuthorityActivation;
constructor(scope: Construct, id: string, props: Props) {
super(scope, id, props);
const { rootZone } = props;
// 高水準なclassがfromで管理外から引っ張ってくる方法以外存在しないようなので、
// 仕方なくCfnの低水準なAPIを利用。
// 認証機関を生成。
this.cfnCertificateAuthority = new CfnCertificateAuthority(
this,
"CertificateAuthority",
{
type: "ROOT", // サブドメインを利用しているわけではない。
keyAlgorithm: "好きなアルゴリズムを指定してください",
signingAlgorithm: "好きなアルゴリズムを指定してください",
subject: {
commonName: rootZone.zoneName,
// 適当に証明書の情報を書いておいてください。
},
usageMode: "SHORT_LIVED_CERTIFICATE", // 短命専用モードを利用。
},
);
// 認証機関向けにルート証明書を発行。
this.cfnCertificate = new CfnCertificate(this, "Certificate", {
certificateAuthorityArn: this.cfnCertificateAuthority.attrArn,
certificateSigningRequest:
this.cfnCertificateAuthority.attrCertificateSigningRequest,
signingAlgorithm: this.cfnCertificateAuthority.signingAlgorithm,
validity: {
type: "YEARS",
value: 証明書の長さを指定,
},
templateArn: "arn:aws:acm-pca:::template/RootCACertificate/V1",
});
// 認証機関を有効化。
this.cfnCertificateAuthorityActivation =
new CfnCertificateAuthorityActivation(
this,
"CertificateAuthorityActivation",
{
certificate: this.cfnCertificate.attrCertificate,
certificateAuthorityArn: this.cfnCertificateAuthority.attrArn,
},
);
}
}
昨日起きたら、ワイヤレスイヤホンの片方が失くなってしまったので新しいものを買いたいと思います。
部屋をひとまわりひっくり返しても見つかりませんでした。
家の中で失くなってしまったので多分どこかにはあると思うんですが、呑気に見つけられるのを待ってはいられないですね。
寝落ちするために何か流すのに必要なんですよね。情報中毒者なので何もせずにいるのがすごい困難なので、何か聞いてるのが一番寝に入る姿勢としてマシなんですよ。
子供部屋おじさんなのでタブレットのスピーカーだと長いことやると怒られそう。横に置いて流しても指向性の関係上あまり音質が良くないですし。
失くしたBose QuietComfort Earbudsを買ったのも結構前の2021年3月らしいので、買い換える口実にしてしまいますか。
ノイズキャンセリングイヤホンが欲しかったので、Bose QuietComfort Earbudsを購入しました - ncaq
2年持ったと考えればよくやってくれました。
音質は一定品質あればそこまで気にしてないです。自分の耳じゃどうせ聞き分けられない。
前もBoseだったのでまず検討。
最新のものは普通に探す機能に対応しているみたいですし。
Bose QuietComfort Earbuds IIで十分そうではあるけど。
相変わらず公式サイトのUXが劇的に悪い上に知りたい情報がロクに載っていないのが気になる。
|
で28399円かあ。
うーんサイトがあまりにも酷いだけで買う気が失せてきてしまいますね。前買った後にスマートフォンでサポートサイト開いたらトラッキングだらけでクラッシュしたんですよね。
Galaxyのスマートフォンとタブレットを使っているのでオートスイッチングの連携が強そうなので候補。
Galaxy Tab S9 Ultra使ってても音響悪くないですしそう悪いものでもないでしょう。
スペック表だけ見ると自分にはGalaxy Buds FEで十分に思えてしまいますね。
12925円。
イヤホンにはスペックに現れない色々なものがありそうなので、そこが問題になりそうですが。
と思ったけれど、 Galaxy Buds2の方は定価で6000円ぐらい高いだけで、市場価格はむしろこちらの方が安いんですね。
10672円。
Galaxy Buds FEは新製品だからかなあ、でもFEの名前が示す通りエントリーモデルだから流石にBuds2の方が良さそう。
買うならBads2かなあ。特典でばら撒きされて新品未使用品が安くなってそうと思ったけれど、意外とそれはあまりありませんでした。一つラクマでそれっぽいのは見つけましたが。
まあ全く何も考えないならWF-1000XM5で終わりですよね。
価格.com - SONY WF-1000XM5 価格比較 35020円。
Galaxyの連携機能もマルチポイント接続があればだいたい賄えますし。スマートフォンとタブレットぐらいしか精々使わないので2台繋がれば十分。
これは楽天でも良いかも。
|
35980円に楽天ポイント。
もう何も考えずにこれで良い気がしてきました。
WI-1000XM2はネックバンドで失くしにくいから良さそうかと思ったんですが、なんかノイズキャンセリング性能劣ってて42678円もしますし。価格.com - SONY WI-1000XM2 価格比較
楽天で買うのがおおよそ最安値なのが多いので、 2日我慢して5のつく日に買うことにします。
多分Sonyのを買うと思いますが、値段ケチってGalaxyという案もなくは無いです。
15日までに決めます。
このページはだいたい次のページの補完的なものになっています。まずこれを読むことを推奨します。
Haskell Morpheus GraphQL で GitHub API を試す
また必要がなければGraphQL APIを無理に使わないで、 github: Access to the GitHub API, v3. などのパッケージされたREST APIを使えば良いと思います。
今回私がやりたいことを素直にやるとAPIの呼び出しがどんどんネストしていって爆発してしまうので、 GraphQL APIを使うことが必要でした。
色々と調べたのですが、基本的にGH_TOKENやPATなどを使っていることが前提になっていて、 GitHub AppとしてPrivate Keyを使って認証する方法が見つかりませんでした。
なので割と自前でjwtを生成していきました。
module Github.Auth where
import Data.Aeson
import Data.Convertible
import Import
import Network.HTTP.Req
import System.Environment (getEnv)
import Web.JWT hiding (header)
-- | GitHubのAPI、
-- `https://api.github.com/app/installations/" ++ GithubInstallationId ++ "/access_tokens`
-- の返り値を簡単に型付け。
-- `permissions`などは現状強く気をつける必要が無いので雑に辞書に入れている。
data InstallationsAccessTokens
= InstallationsAccessTokens
{ token :: Text
, expiresAt :: Text
, permissions :: Map Text Text
, repositorySelection :: Text
}
deriving (Eq, Ord, Read, Show, Generic)
-- | JSONの区切りがアンダースコアなのでHaskellらしくcamelCaseに変換。
camelToUnderscoreOptions :: Options
camelToUnderscoreOptions =
defaultOptions
{ fieldLabelModifier = camelTo2 '_'
}
instance FromJSON InstallationsAccessTokens where
parseJSON = genericParseJSON camelToUnderscoreOptions
instance ToJSON InstallationsAccessTokens where
toEncoding = genericToEncoding camelToUnderscoreOptions
-- | 環境変数のアプリインストールIDから一時的トークンを発行。
-- 発行するためにJWTを発行している。
-- アプリインストールIDはAPI経由で取得することも可能だが基本的に不変なので環境変数から取っている。
createToken :: MonadHttp m => m InstallationsAccessTokens
createToken = do
jwt <- createJwt
githubAppInstallationId <- liftIO $ convert <$> getEnv "GITHUB_APP_INSTALLATION_ID"
let url = https "api.github.com" /: "app" /: "installations" /: githubAppInstallationId /: "access_tokens"
headers =
header "Content-Type" "application/json" <>
header "User-Agent" "アプリ名を入れるのを推奨します" <>
header "Authorization" ("Bearer " <> convert jwt)
responseBody <$> req POST url NoReqBody jsonResponse headers
-- | 環境変数のアプリIDと認証鍵からJWTを生成。
createJwt :: MonadIO m => m Text
createJwt = do
githubAppId <- liftIO $ convert <$> getEnv "GITHUB_APP_ID"
githubAppPrivateKey <- liftIO (getEnv "GITHUB_APP_PRIVATE_KEY")
currentTime <- getCurrentTime
let privateKey = fromMaybe (error "GITHUB_APP_PRIVATE_KEYが正常な形式ではありません。") $
readRsaSecret (fromString githubAppPrivateKey)
encodeSigner = EncodeRSAPrivateKey privateKey
joseHeader = mempty
currentNumericDate = fromMaybe (error "現在の時刻形式が不正です。") $ numericDate $ convert currentTime
expTime = fromMaybe (error "期限切れ時刻形式が不正です。") $ numericDate $ convert currentTime + 600
jwtClaimsSet =
mempty
{ iss = stringOrURI githubAppId
, iat = Just currentNumericDate
, exp = Just expTime
}
return $ encodeSigned encodeSigner joseHeader jwtClaimsSet
token発行する部分のエンドポイントじゃないとBad credentialsになってしまったり、 POSTするべきところでGETすると404 not foundになってしまったりするので細かいところで注意が必要です。
この方法で作ったトークンを以下のように挿入するとGraphQLのクエリも実行できます。
module Github.GraphQL
( fetchWithAuth
) where
import Data.Convertible
import Data.Morpheus.Client
import Github.Auth
import Import
import Network.HTTP.Req
-- | Morpheus GraphQL Clientで通信。
fetchWithAuth :: (Fetch a, MonadIO m) => Args a -> m (Either (FetchError a) a)
fetchWithAuth = fetch resolver
-- | Morpheus GraphQL Clientの実際のHTTP通信を解決。
resolver :: MonadIO m => LByteString -> m LByteString
resolver body = runReq defaultHttpConfig $ do
tokens <- createTokens
let headers =
header "Content-Type" "application/json" <>
header "User-Agent" "アプリ名を入れるのを推奨します" <>
oAuth2Bearer (convert $ tokens ^. token)
responseBody <$> req POST (https "api.github.com" /: "graphql") (ReqBodyLbs body) lbsResponse headers
fetchWithAuth
で統一的にページング処理とか出来ないかなと思って設置していますが、出来ないような気もするので別にここは包む必要ないかもしれません。
スキーマ参照してクエリを作るのがdeclareLocalTypes
に変わっていたっぽいとかありますが、これで一応問題なくGraphQL APIを実行することが出来ます。
Windows難しすぎるだろ、なんでスタートアップ時にターミナル画面を出現させずにバックグラウンドでスクリプトを実行させておくぐらいのことに四苦八苦してるんだよ
— エヌユル (@ncaq) 2023年10月3日
GNU/Linuxならsystemdのサービス作るか.profileあたりで適当に起動すれば終わりの話だぞ
最近、 ncaq/anti-idle: If it determines that the system has been idle for a certain period of time, it will attempt to release it. というソフトウェアを作りました。
これは一定時間(現状2分)マウスカーソルの動きがなければ適当にちょっと動かして戻すという、色々な意味でくだらないソフトウェアです。
本体でやっていることは非常に単純で、ポインタの位置を保存して、 2分間sleepして、保存したポインタと現在のポインタが同じなら雑に動かすというだけです。
2分ごとに少し動かすだけでもだいたい目標は達成されているのですが、本当にポインタを使う作業をしている時に微妙に動かされて操作ミスしたら嫌だなと思ったので、一応保存して比較しています。
作った後にこの程度のものは誰かが書いているよなと気がついて調べたら、案の定いろんなもので書かれていました。まあそれは良いことにします。
どうせ殆どChatGPTとCopilotがプログラム書きましたし。 WindowsのAPIには詳しくないのでこういうのは助かりますね。
メインのプログラムは単純なので、こんなものはPowerShellで十分だろうと思って採用しました。
さてこのスクリプトをログイン時に自動実行するのはどうすれば良いでしょう。
流石にそれぐらいは知っていて、
shell:startup
フォルダにショートカットを置いておけば良いです。
しかしそれではPowerShellが実行されるウィンドウが表示されてしまいます。自分の環境ではWindows Terminalのタブになります。
PCを起動している間はずっと実行しているソフトウェアなので、 Windows Terminalを終了させたりした時に巻き添えで終了したら嫌です。
単体で実行させるとしても無駄なウィンドウが一つずっと表示され続けているのも嫌です。
powershell.exe -WindowStyle Hidden -File ".\AntiIdle.ps1"
のように-WindowStyle Hidden
を指定しても変わらずウィンドウは表示されてしまいました。
タスクスケジューラはなるべく使いたくないですね。システム権限を一切使わずに動くプログラムなので、ユーザディレクトリ以下にファイルを置くだけで自動起動を設定したいです。ファイルがあるかどうかだけ見て有効になっているかサッと確認したいというのもあります。
色々試してみたところ、
のように連鎖して起動させたらウィンドウが表示されなくなりました。
vbsで、
CreateObject("Wscript.Shell").Run ".\AntiIdle.bat", 0, True
のようにBatch Fileを起動させます。
batでは、
@echo off
powershell.exe -WindowStyle Hidden -File ".\AntiIdle.ps1"
のようにPowerShellを起動させます。
多分Batch fileはいらないとは思います。最初Batch fileからの起動でどうにかならないかなと思ってた名残です。
VBScriptから直接PowerShellを起動させて良いと思います。試してないですが。
VBScriptもBatch fileもPowerShellと同じだろとutf-8-bom
にしてはいけません。文字コードはASCIIでeditorconfig上ではlatin1
にでもしておきましょう。
PowerShellのスクリプトを書く時の諸注意 - ncaq
You could have a
powershellw.exe
which would be a GUI application that doesn't show a console window. Same as whatjavaw.exe
andpythonw.exe
do.https://github.com/PowerShell/PowerShell/issues/3028#issuecomment-311142372
で提案されていたように、
PowerShellにもコンソールを起動しないpowershellw.exe
が存在すれば楽になるんですが。
何故ターミナルを開かないスクリプトを自動起動するだけでVBScriptを経由するようなバカバカしいことをしないといけないのでしょうか。
conhost --headless powershell.exe -nop -win hidden -noni -f "C:.ps1"
— おーい (@OiOi_012) 2023年10月4日
これでどうでしょうか。手元の環境ではwindowは表示されません。
によるとconhostを指定する形でも良いらしいですね。 VBScriptを経由する方法でなんとかなった後に知ったので試していませんが。
最初から常駐してウィンドウを持たないプログラムをWindowsで書くならF#やC#を使ったほうが丸かったんじゃないかなと思いました。
PowerShellにbashやzshのような単純なシェル機能を期待するのが間違いだったということですね。
Windowsホスト側にまともな開発環境を用意してなかったので、
System.Windows.Forms
とかWin32とか使っているとWSL側で開発するの面倒くさいのではという気持ちが勝ってしまいました。多分自動実行のいざこざの方が面倒くさかったと思います。
この程度のほぼAPIを呼び出すだけのプログラムでパフォーマンスを気にする必要は多分ありませんが、一応どちらもJITコンパイルされるとは言え静的型がついている言語の方が安全かつ軽量そうですし。
将来的に例えばタスクバーに起動時にはアイコン表示させるとかの機能拡張をするなら、絶対にF#とかで書いたほうが良いでしょうしね。
こんな記事を書いた数日後にVBScriptが非推奨になるという発表が行われました。「VBScript」は非推奨に、将来のWindowsリリースで削除 - 窓の杜
いやまあ確かに色々とひどい言語なのはVBA案件やってた時によく知ってますし、こんなものをメンテナンスしたくないのも分かります。なので削除するのはそれはそうなんですが、何故かこういう時に使うことになるんですよね。モダンな代替手段を用意して欲しい。
conhostなどを使うパターンにするか、 F#で書き直すかしますか。
SSDをThinkPad P16s Gen 2 AMDのSSDの換装が非常に簡単でした - ncaqに書いた通り換装し終えたので、 Gentoo Linuxをインストールしていきます。
今回は最初からGentooの公式インストールメディアを適当にUSBメモリにdd
して起動することにしました。
セキュアブートを一度無効化します。頑張れば有効なままLinuxをインストールすることも出来ますが面倒な割にメリットを感じられません。
セキュアブート自体も現実の攻撃はランサムウェアとかバックドア設置とか、既にブートしているOSへの攻撃の報告ばかり聞くので、あんまり効果を感じないんですよね。
基本的に市販のPCはセキュアブート有効になってるから攻撃者側も狙わないだけで、実は防ぐことに成功しているのかもしれませんが。
TPM関連の機能は面白そうですが。
GNU/Linux的にもBitLockerと同じような運用方法は考えられます。 luksに2つのキーを設置して、回復キー相当の長くてセキュアですが毎回入力することは耐えられないパスワードをバックアップ用に用意してどこかにメモしておきます。そしてTPMでブート関連の設定変更が行われてないことが分かった時のみ毎回入力も容易なパスワードで解除できるようにします。これなら攻撃された時に容易なパスワードで解除できないので、変更に心当たりが無ければ警戒出来ますし、 GRUBの再インストールなど心当たりがあれば長いパスワードで回復できますね。
両方要求するような設定は出来るのだろうかと思いましたが、少なくともsystemdの設定には--tpm2-with-pin
として存在するみたいですね。
systemd - LUKS + TPM2 + PIN - Unix & Linux Stack Exchange
でもTPMから無条件で値を読み取れるかどうかを判断するという話はセキュアブートでブートローダを縛るのと関係あるんでしょうか。例えばBitLockerをPINだけで解除できるか回復キーが必要かどうかの判定はセキュアブート無効でも動いていますし。
それにさっき書いたようにセキュアブートは既に起動しているOSへの攻撃にはほぼ無力です。私が一番懸念している紛失・盗難にあったPCからデータを抜きされるケースも、 TPMチェックに引っかからないようにUSBキーボードを装って入力を試みれば良いはずなので、セキュアブートはほぼ無力なはずです。間違ってないよね?
なので素直にYubico YubiKey Bio Fido Editionみたいな、指紋認証付きのキーで解錠した方が盗難対策には適していると感じています。キーを紛失したらメモっておいた回復キーを入力します。
ただこれ結構高いんですよね。二段階認証は唯一のキーを持ち運ばなくて良いTOTPの方が便利でAWSとかは何故かYubiKeyと併用出来ないので使う気にならないので、単純に指紋認証して固定パスワードを入力してくれるだけのもので十分なんですが。ただ安物は本当にセキュアなのか不安なので何を買えば良いのか分からない。
ともかく後でセキュアブートを有効化するかは置いておいて、 Gentooの公式インストールメディアは署名されていないようなので、一度セキュアブートを無効化してインストールします。
F12で起動メニューを開けるらしいですが、数回失敗して成功しました。安定性がよく分からない。
まあ普段はWindows起動したくなってもGRUB経由で起動するので、問題にはなりませんが。
いつもの通り(いつからだ?)、家の中なので適当にパスワード設定してデスクトップPCからOpenSSHで操作します。
起動時にも出来ると促されます。
これでコピペ面倒くさい問題とかとは無縁ですし、既にセットアップ済みのデスクトップPCのEmacsからtrampで接続にも行けます。
ThinkPad P16s Gen 2には最初から有線LANポートがあるのでネットワーク接続が面倒くさい問題とは無縁ですね。いやまあUSBの有線LANアダプターを使えないケースとか殆ど無いですが。
EFIパーティションはWindowsと不本意ですが共用しますが、 bootパーティションは必要です。
bootの場所から意味のある暗号化をするのはかなり面倒な割にメリットが少ないです。なので素直にLinuxカーネルなどの別に漏れても良いファイルはbootパーティションに置いてしまいます。
前回はbootパーティションはGRUBが絶対に理解できるようにext4にしましたが、今回はBtrfsに統一します。 GRUBも結構前のバージョンの2.04からzstd圧縮のBtrfsをサポートしているので、問題ないでしょう。なるべくシンプルに保ちたい。
後述しますがやめておいたほうが良いです。素直にext4などにしましょう。
bootパーティションのサイズは余裕を持って2GBぐらい確保しておきます。本当はこんなに要らないと思いますが、後から増やすのはLVMとか使わないと面倒くさいので。前回は1GBでしたけど特に問題なかったみたいですね。どうしても容量が足りなくなったら2GBを解決しても仕方ないので2TBのSSDを買ってきます。
swapパーティションは別途作ることにします。 swapファイルは今のBtrfsなら普通にサポートしていますが、 CoWがちゃんと無効になってるかとかサブボリュームの外に置くとか面倒くさいので、あえて古臭い方法を取ります。
swapパーティションのサイズは、使うかどうかはともかくハイバネーションを考えて、メモリ容量は32GBなので少し多めの33GBを確保しておきます。
そんなに必要かどうかは全く分かりません。そもそも12スレッドしか無くて32GBメモリを積んでいるのでswapが本当に必要なのかも分かりません。一応ディスクキャッシュをどんどん積んでいって、プログラムの使わない部分は逆にswapに追いやることで高速に動作出来るとは思いますが、そもそもキャッシュ込みでも12スレッドで32GBメモリを自分の用途ではあまり使い切らないですね。
Gentooの文書では2倍が推奨されているので64GBにしようかと思いましたが、 2倍が推奨されるのは流石にメモリが少ない時代の名残りかなあという気がします。最近あまり信用してないけれどRHELもそう書いています。第15章 swap 領域 Red Hat Enterprise Linux 7 | Red Hat Customer Portal いやこれは基本的にサーバ向けの文書じゃないかというとそうなんですが。
swapが大きすぎるとさっさとOOM Killerが働いて欲しい無限ループプログラムを書いた時にディスクに延々と書き込み続けることがあります。その意味でもあまり過剰に確保はしたくありません。
また2GBレベルならともかく30GBの追加容量は空き容量が速度に関わるSSDで追加したくないですね。足りなくなったら2TBを買ってくれば良いというか、 SN850XじゃなくてSN770を買ってかなり後悔しているので買い換える口実が欲しいとかはあるんですが。
前回は742GBのパーティションになりましたが、今回は660GBのパーティションに縮小してしまいましたね。
まあ前回もそれだけあってsnapshots取りまくっても余裕があったので、今回も余裕だと思います。
足りなくなるとしたらAI関連のモデル入れまくるとかでしょうけど、 NVIDIAのGPUどころかdGPU自体積んでないこのPCでやっても効率が悪すぎるので、多分やらないと思います。
さて暗号化パーティションを生成しましょう。
まずcryptsetup benchmark
を実行してアルゴリズムの速度を調べてみます。
livecd ~ # cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1 2052007 iterations per second for 256-bit key
PBKDF2-sha256 3334104 iterations per second for 256-bit key
PBKDF2-sha512 1696724 iterations per second for 256-bit key
PBKDF2-ripemd160 783689 iterations per second for 256-bit key
PBKDF2-whirlpool 601247 iterations per second for 256-bit key
argon2i 8 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
argon2id 8 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
# Algorithm | Key | Encryption | Decryption
aes-cbc 128b 1028.8 MiB/s 4541.7 MiB/s
serpent-cbc 128b 97.5 MiB/s 720.4 MiB/s
twofish-cbc 128b 192.8 MiB/s 438.0 MiB/s
aes-cbc 256b 775.5 MiB/s 3640.0 MiB/s
serpent-cbc 256b 99.2 MiB/s 720.6 MiB/s
twofish-cbc 256b 195.0 MiB/s 436.5 MiB/s
aes-xts 256b 3771.8 MiB/s 3799.7 MiB/s
serpent-xts 256b 590.9 MiB/s 592.2 MiB/s
twofish-xts 256b 379.8 MiB/s 387.0 MiB/s
aes-xts 512b 3169.8 MiB/s 3175.5 MiB/s
serpent-xts 512b 597.4 MiB/s 592.3 MiB/s
twofish-xts 512b 381.0 MiB/s 384.8 MiB/s
という結果になりました。結局はデフォルトで指定されるaes-xts-plain64
がバランス良くて良さそうですね。
Zen4で変わるかなと思ったんですが、特に変わらないようです。後でディスクIOも測ったりAVX-512を有効化出来たとしてもオーダーが違うレベルの速度差ですね。
作者たちが当然賢いということで今回は全部デフォルトオプションで良さそうです。
前回と同じくBtrfsを使うんですが、前回と違う所はルートのサブボリュームを直接使わず、推奨ファイルシステムレイアウト - Snapper - ArchWiki に従ってある程度分離することにします。
前回は/usr/
などはサブボリュームにしてスナップショットの範囲外にしていましたが、よく考えてみると/usr/local/
とかはPortageの管理外にあるので、スナップショットの範囲内にしてディスクが足りなくなったら素直にスナップショットの量を減らした方が良いのではないかと考えました。
/usr/
のロールバックが出来ればシステムの復元もかなり実用的ですね。
一度素でmount
してサブボリュームを作ってumount
して今後は@
をマウントポイントとして使用ですね。
@
, @home
, @snapshots
, @var_log
だけ作りました。他のスナップショットしなくて良いやつは他のサブボリュームの入れ子で作ってしまいます。入れ子にするとトラブル時に独立性を保つのが面倒になりそうですが、
cache系とかは最悪破壊されても問題が無いので。
stage3を解凍するより先にサブボリュームはmount
しました。
少し嫌な予感がしてたんですが、 Downloads – Gentoo Linux でダウンロードできるデフォルトのsystemdのstage3はmerged-usrではなかったんですね。 Gentooでsystemdを使ってる人はさっさとUsrMoveしないといけないよという話
流石にsystemd公式サポート外の環境で動かすつもりもなく、後から移行すると面倒なので、最初からmerge-usrを使おうと思ってたんですが、デスクトッププロファイルをダウンロードしていたので、マージされていませんでした。
いくら選択とは言えデフォルトではそうなっていると思ってたんですが。
ディレクトリの変動よりはせいぜいUSEフラグの変化程度だろうデスクトッププロファイルから移行するほうがまだ楽そうなので、マージされたものを選択しておきます。
etc-portage
などの展開でホスト名で分岐するようにしたので、
make.conf
などの保存の前にホスト名を設定したいです。
livecdがsystemdで動いていない以上hostnamectl
はまだ使えないため、
systemd-firstboot --prompt --setup-machine-id
を実行してみます。
駄目です。再起動とかしないとコマンドには反映されないやつですね。おとなしくホスト名依存のビデオカードの設定とかは取り除いておきます。
livecdにはgitが入っていないため、リポジトリ同期をgitにしているとgitのインストールすら出来ないし、 profileの設定も出来ません。
おとなしくrsyncのデフォルト値にしておきます。
gentoo-kernelという名前で設定ファイルを読み込んで自動でコンパイルからインストールまでしてくれるパッケージが、新規にはもう推奨されるレベルに達したようですね。
Gitでカーネル設定を管理出来そうなので、こちらに移行するのも良さそうです。
細かく設定するにしてもむしろgentoo-kernelを前提に設定ファイルを組み立てていくほうがバージョン管理されて良さそうな気がします。
基本的にカーネルのサイズはさほど問題にしないので、デフォルトの値に有効にしたい機能を追加するという形で十分そうですね。
ついでにセキュアブートの対応もUSEフラグにあるので楽に出来るかもしれません。今のLTSバージョン6.1にはないみたいですが。 6.4からサポート開始するみたいですね。
新規にやることに新規にやることを重ねたくないので、やるならデスクトップ含めて全部移行かなあと思ったのですが、まっさらなシステムには最初から適応しておいた方が良さそうな気がするので、移行は最初は少し面倒かもしれませんがこれを使ってみます。
とりあえずはデフォルトの設定でインストールしてみて、カーネルの設定はまた今後やります。
例えば-march=native
が効いてないっぽいことが気になりますね。
Linuxカーネル領域で自動AVXが欲しいことはほぼ無いとは思いますが、キャッシュのサイズ検知とかで最適化は出来るはず。再頒布容易に出来るようにデフォルトでは最適化しないのは当然な気もしますが。
暗号化ディスクを使っていてもちゃんと起動できるか不安ですが、やってみます。
/etc/crypttab
書いてれば良いのかなあ。
/etc/conf.d/dmcrypt
はディレクトリから察せられるようにOpenRC向けで、
systemdブートには向いていないようなので、
crypttabに書きます。
最近はGentooでもsystemd-bootのサポート追加されてるんですね。 GRUBより高速なことが多いみたいです。ただ他のディストリビューションと違ってGentooの場合、 systemdが起動しなくてもOpenRCで起動できたりするので、 systemd絶対依存にするのは少し気が引けますね。暗号化initramfsとか少し面倒なものを取り扱うので、 GRUB継続ですね。
とりあえずGRUB_CMDLINE_LINUX
にrd.luks.uuid=暗号化されてopenの対象になるパーティションのUUID
を追加すると、起動はしました。
ただしエラーまみれでレスキューモードでの起動になってしまいました。
error: sparse file not allowed.
と表示してくるStrange error at boot - Support - Manjaro Linux Forum
によると、
GRUB_SAVEDEFAULT="true"
しているのが悪いようです。
grub は btrfs に書き込めないため、これは /boot が btrfs でない場合にのみ機能します。ただし、"sparse file not allowed. Press any key to continue." という誤解を招くエラーメッセージが生成されます。
なるほどそうだったですね。
GRUB_SAVEDEFAULT=true
は使いたいので、ブートパーティションはやっぱりext4にしておいた方が無難な気がしてきましたね。今回の教訓としましょう。
systemd-cryptsetup: Failed to deactivate: Device or resource busy
で殆どのディスクマウントに失敗するrootがalready existsで失敗するのは/etc/crypttab
を書いていたのが逆に良くないみたいですね。
rootは起動時に解読されてマウントされるので、その後またマウントしようとしてエラーになるようです。コメントアウトして問題では無くなったので、ファイルごと削除しました。
しかし/etc/crypttab
を書いているガイドもそれなりにありますね。
GRUBのカーネルパラメータかcrypttabのどっちかだけで良いということでしょうか。内部でdracutを使っているのでdracutの設定ファイルとして書くのが正解?
TRIMを有効にするオプションはここに書いていたので、ブートオプションにも移植する必要がありそうですね。
rd.luks.options=discard
で良さそう。
discardを逐一実行するのではなくTRIMを定期実行する場合でもこちらで良いのかな。
間抜けなことに暗号化を解く前のUUIDを指定していました。解いた後を指定することで無事解決。
単体で起動が出来てエラーも無くなったということで、インストールバトルとしてはここで終了で良いでしょう。
ThinkPad専用のファンコントロールツールとかあるみたいですが、それはまた今度試してみます。別に記事にはしないかも。
ThinkPadだからと言って何か苦労したことは殆どありませんでした。流石は公式でUbuntuやRHELとは言えLinuxを動作OSとして書いてあるだけのことはあります。
今回面倒だったのはgentoo-kernelを採用するか悩んだり、 initramfsの生成をそれに任せて、前のgenkernelでinitramfsを生成する方法と違う方法を使ったことにありますね。
ここにも事前に書いた通り、フラッグシップクラスの性能を出せる1TBのSSDが1万円ぐらいで買えるのに、 ThinkPadのカスタムのアップグレードで512GBにすると何故か+36000円とか平気でして、あまりにもコスパが悪すぎるので、 SSDは自分で購入して換装する予定でした。
それで先程換装してきました。
あまりにも簡単すぎて書くことも少ないのですが、一応簡単であったことをメモしておきます。
元々搭載されていたディスクはSN740です。
換装先には、 Western Digital WD_BLACK SN770の1TBを使用します。
DRAMキャッシュがない製品なので一見安物に見えて価格も安物なんですが、肝心の性能はSN850XなどのWD自身のハイエンドと比較しても、読み取り速度はあまり遜色が無く、書き込み速度もキャッシュが効いている瞬間はさほど見劣りしません。
動画編集とかで大量のデータを書き込むとかなら書き込みキャッシュ切れは気になるかもしれませんが、私は外でちょっとプログラミングする程度の使い方なので問題ないと判断しました。
ちなみにNANDチップにはキオクシアのものを使ってるそうですね。最近のWestern DigitalのSSDは大抵そうですけど。頑張ってほしい。
SK hynix Gold P31は異様に省電力らしいので、ラップトップPCに搭載するならそっちかもと悩みましたが、せっかくマザーボードがPCIe 4.0に対応しているので、 PCIe 3.0のSSDを搭載するのは気分的に嫌かなと思いました。
またSN850XもSN770が安すぎるせいかだいぶ値段が下がっており、最初は2万円を超えていた価格も1万円ちょっととなり、 AmazonでもSN770とSN850Xの価格差が3000円程度となっていました。全体を調べた最安値でもせいぜい2000円ぐらいの差でした。なので値段的にはSN850Xを買っても良かったのですが、ラップトップPCの内蔵という都合上熱管理が大丈夫か不安だったので、あえてSN770ぐらいの抑えめなものにしておきました。消費電力も常識的に考えてSN770の方が低いと思います。公証スペック通りに動くかは分かりませんが。
デスクトップPCならこの価格差ならSN850Xを買ってます。というか今のデスクトップPCのゲーム用WindowsはSN850Xにインストールしてます。
まあSN770もそれなりに発熱します。今回調べ直したらSN850XをThinkPad P14sで利用している人も居るらしく、別に熱が出てもサーマルスロットリングでパフォーマンスがちょっと落ちるだけで、元々の性能が高いので問題は無さそうに思えました。なのでSN850Xにしておけば良かったかなとちょっと後悔しています。
具体的な購入先としては最近SSDでは悪名高いAmazonを使いました。
ちょうどポイントバックキャンペーン中で、 1万円を切っててそんなに高くなかったので。
ダッシュボードを見る感じ偽物は掴まされてないと思います。そのへんの表示まで弄くられると流石にもう分からないですが。パッケージの様子を見る限りは中古でも無いとは思います。 SMARTの値を信用して良いのかとかも謎ですが。
念のためWindowsの回復ドライブをUSBメモリに生成します。
Bitlockerの回復キーも保存します。最近のWindows搭載PCはHomeでもBitLockerが有効になっています。セキュアで良いですね。 Microsoftアカウントに保存するだけでは不安ならしておいた方が良いでしょう。どうせ換装するので初期設定もロクにしてないのでデータ消えても構わないと言えば構わないんですが。
また高速スタートアップを無効化しておきます。こういう作業の前にはハードウェアを完全にシャットダウンしたいですし、どうせLinuxをデュアルブートする予定なので、高速スタートアップが有効になっているとNTFS周りなど色々と面倒なんですよね。
そして重要なポイントとしてUEFI BIOSの設定でバッテリーを無効化しておきましょう。バッテリーは危険物なので、分解前にはしておきたいですね。マニュアルにもしろと書いてあります。まあ今回の内容だと必須じゃないような気がしなくもないですが。一応誤って電源ボタンが作動しないとかはあるかもしれません。やってて損はないです。
移す元も先もWestern DigitalのSSDなので提携公式ツールを使用してディスクのクローンを行います。別に他のツールでも出来るとは思います。お手軽だから選んだだけです。
WD 製品のソフトウェア、ファームウェア、およびドライバーからAcronis True Image for Western Digitalをインストールして、ディスクのクローンを行います。
SN770を適当にUSB接続出来るようにするケースに入れてクローンします。
使ったケースは以下のやつらしいですね。貰い物を流用したので正確には分からない。
クローン生成方法は手動を選択しました。パーティションのサイズはそのままにして、初期値である256GBはWindowsに割り当てて、 1TBの余りをLinuxに割り当てると丁度良いかなと考えたためです。
クローンの終了予定時刻が表示されるまで時間がかかりそうだと思ってトイレに行って水飲んできて戻ってきたらクローンが終わっていました。速すぎる。本当に終わったのか流石に不安になってチェックしましたが終わってたらしい。
私はUSB 3.1 Gen 2のことを舐めていたようですね。
これに従って作業します。
ThinkPad T16 Gen 2 および ThinkPad P16s Gen 2 ハードウェア保守マニュアル
公式で分解マニュアルがあるのはとても助かりますね。
ネジは外れるタイプではなく、緩めるだけで外れないタイプになっています。私はネジをなくしやすいのでとても助かります。
ネジを緩めてケースの縁をずらして開くとこんな感じです。
シンプルで美しいですね。
右上のSSDを交換します。普通のデスクトップPCに接続するのと同じです。
ちょっとネジが異様に固くて、ネジ穴潰してしまったのかとヒヤヒヤしてしまいましたが、根気強くゆっくりと回すと外れました。
再起動するとWindowsのハードウェア変更検知すら走らず、そのまま利用できました。
PS5のSSD追加の方が大変なレベルで簡単でした。
ThinkPadがプログラマに人気な理由の一つが分かりました。
自宅サーバをリプレースして暗号化などで安全に隔離された環境を作る · Issue #152 · ncaq/www.ncaq.net にも書いていたけれど、いい加減自宅サーバをリプレースしたいです。 Intel Celeron G1820では何かやるにしてもいちいち遅いので。
このクラウド時代、仕事でやるならそりゃ可用性確保でAWS Fargateとか使いますが、いちいち一つ一つのタスクにお金がかかるというのは色々と躊躇する要因になってしまいます。一つのサーバに詰め込めば節約になりますね。
またフルのバックアップは暗号化前提でもネットワーク上に上げるのは怖い。
本格的に常時負荷がかかるwebサーバとかで常時稼働するわけではないため(将来的にはするかもしれませんが)、そこまで性能は求めていませんが、 SATAポートはRAID HDD用に確保したいので、最低でも2ポートほしいです。
なのでミニPCはちょっと敬遠したいですね。 SATA HDDをUSB接続できるケースを使う手もありますが。あんまり余計なレイヤーを挟みたくないです。
ミニPCの何が良いかってその名の通りミニなことで、違う部屋に前使ってた自作PC用のクソでかいケースを置いておくのを許容出来るなら、デスクトップマシンとしてサーバを組んだ方が基本的にコスパが良いなという感想ですかね。
あとミニPCには基本的にWindowsがバンドルされているので、ノイズを避けてベアボーンキットを探すのが大変です。ラップトップですらWindowsほぼ使わずに、 Windows使うのは仕事で仕方ない時とゲームするときぐらいで、ディスプレイも繋げないサーバでWindows常時起動はしませんからね。
CPUなどに何を使うかずっと悩んでいて、頭の中でじっと考えていても仕方がないかなと思ったので、 2023年9月17日にちょっと書き出しを始めました。
前提として、使えるSSD、HDD、電源、ケースなどは既存の余っているものを流用します。クーラーは不要だったり付属のやつを使います。
今更あんまりSocket AM4のマザーボードとかDDR4メモリ買いたくないので、なるべくZen4を選びたいですね。ただコスパはZen3 Socket AM4に比べて主にマザーボードの価格であまり良くないのと、オーバースペック気味にも感じます。
ちなみにちょっと前まではZen4のRyzen 3が出るまで待とうと考えていたんですが、 Ryzen 3 4100 とか見ても、価格こそ低いですけどTDPは65Wで同世代のRyzen 5と変わらないんですよね。だったら別に待たなくても良いかなあという思いで待たないことにしました。
素直にZen4のデスクトップCPUで最安値のものです。電力的にもこれが良さそう。ミニPCならラップトップ向けCPUとかもありますが。
ドスパラで約30000円。 AMD Ryzen 5 7600 BOX | パソコン通販のドスパラ【公式】
Amazon価格はクーポン込みで約36000円。 https://amzn.to/3LneqYD
こんなにAmazonでの価格が高いのは珍しいですね。マーケットプレイスとかの販売ではなく、 Amazonが販売しているものなので尚更です。
そんなに発熱とか気にして最高性能を求めるマシンじゃないので、素直に最安値のものを選ぶことにしました。拡張性が物足りなければ別にマザーボードだけでも入れ替えられますし。
最安値のパソコン工房がそのままAmazonにも出して10880円。 https://amzn.to/3LnfcF1 とメモを書いて様子見してたら安い方は売り切れてしまいました。
ラップトップの方は作業中のストレスを考えて、 12スレッドでもデフォルトの16GBではなく32GBにすることにこだわりましたが、サーバの方はユーザがあんまり操作しないし、 GUIも動かないので16GBで良いかなという判断です。まあ別に最近メモリはかなり安くなってて32GBにしても良いぐらいなんですが。オーバークロックなしの定格メモリなら後から雑に買い足しても動作するだろうという目算もあります。
それなりに信頼できそうな安物を選択。
Crucial 16GB DDR5-4800 UDIMM | CT16G48C40U5 | Crucial JP
5880円。 Crucial CT16G48C40U5 [DDR5 PC5-38400 16GB×1枚] | パソコン工房【公式通販】 6590円。 https://amzn.to/453CBm0
通常のCore i(Raptor Lake, Alder Lake)なども検討してみました。 EコアだけのAlder Lake-NとかのIntel ProcessorでもCore i3ブランドの商品があるので呼称がややこしい。
Core i3-13100とかの通常のIntelプロセッサは、 i3でもTDPは60WでRyzen 5の65Wとさほど変わらないですね。 6コアCPUに対する4コアCPUなのに… まあPPTとターボパワーで比較するべきかもしれませんが、それもあまり変わりませんね。高い方のCore i3でも価格が2万円ぐらいでマザーボードも安いのは魅力ではあるけど、それでIntelプロセッサを買う強い理由にはなりませんね。
ゲーミングでマルチスレッド処理はあまりしないため、 Ryzen 3Dの一番安いのも許容できない極安ゲーミングPCを組むのであれば割と魅力的ですが、今回はそこまで予算に余裕がないわけでは無いので。
となると検討するべきなのはAlder Lake-NのN100のみですね。他の8C8Tとかのモデルはやっぱりそれ買うならRyzenで良くないという話になってしまいます。
ミニPCは拡張性に乏しいですが、マザーボードにCPUがくっついてるタイプがあります。
22468円。 https://amzn.to/44Q9rql
普通の自作PC的な電源ではなく、 USB PDに移行する前のノートPCやミニPC向けの電源が必要です。
詳しく調べていませんが3000円ぐらいみたいですね。 https://amzn.to/3PGAX50
エレコムの製品は買いたくないので真面目に検討するなら別のものを買いますが。
エレコムは金輪際リナックスを使わない | スラド Linux
家の中に眠ってるかもしれないが流石に仕様がよく分からないものを使いまわしたくない
Crucial 16GB DDR4-3200 UDIMM | CT16G4DFRA32A | Crucial JP
5498円。 https://amzn.to/3PH9pg0
周波数帯にこだわらなければDDR5とDDR4はそんなに価格変わらなくなりましたね。
価格差が結構激しそうだと思っていましたが、電源などのパーツを使い回せるので、意外とそこまででもないことが分かりました。ファンレスじゃなくても良く、 TDPをそこまで気にしないのであれば、 CPUのパフォーマンスを考えてRyzenの方が良さそうです。
というわけで今回はAMD Ryzenを選択することにします。
サーバのパーツは明日18日に買うことにします。楽天の還元日が発生するので、楽天とAmazonのキャンペーンが重なるので、得するところで買っていきます。
組み立て行く時間が取れるか怪しいレベルなので、そんなに急ぎではないです。
なので価格優先で行きます。
ASRock A620M-HDV/M.2+は、 ASRock A620M-HDV/M.2+ | パソコン工房【公式通販】で購入します。 Amazonに出してる分は在庫無くなったみたいですが、自社サイトは在庫あるようですね。
メモリも最安値のパソコン工房で。 Crucial CT16G48C40U5 [DDR5 PC5-38400 16GB×1枚] | パソコン工房【公式通販】
あとパソコン工房はハピタス経由だとポイントがつくみたいですね。
ついでに私は個人事業主でもあるので、その情報を登録して新規会員登録したら1000円割引クーポン貰ったので使いました。
Ryzen 5 7600はドスパラで買います。 AMD Ryzen 5 7600 BOX | パソコン通販のドスパラ【公式】特に理由もなく6000円の違いはそこそこ大きいですね。何故か知らないですが今回はドスパラではポイントつかないですが。
と思ったけれど、パソコンSHOPアークでも同じ価格ですし、 ValueCommerceのアフィリエイト経由の自己購入ならば1%のポイントがつくみたいなので、一応そっちにしておきますか。
ark開いて初めて知ったんですが、パソコン工房もアークもユニットコム傘下の企業で、ユニットコムのメンバーカードを作っているとポイントが共通で貯まるみたいですね。でも流石に売掛金に出来るメンバカードは軽々しく作りたくないですね。クレカよりやバイので信用枠に関わりそうですし。もう別に統合してしまっても良いのでは?
と思ったけど(二転三転)、【楽天市場】AMD(エーエムディー) 【国内正規品】AMD CPU 7600(Ryzen 5) 100-100001015BOX:Joshin web 家電とPCの大型専門店で買うとポイントで大差がなくなり、別件で購入したい商品があったけど1000円オフクーポンが5000円以上じゃないと使えなかったので、楽天の方で購入しました。
Amazon使いませんでしたね、これならちょっと前に買ったSN770も楽天の方で買ったほうが微妙に得だったかも? 誤差レベルですけど。
他人に以下のようにPrologプログラムを書いてもらう時、
:- module(find_undefined, [foo/0]).
foo :- bar(buz).
述語bar
に渡すbaz
の定義が存在しない場合、
Emacs向けのSweepやVSCode向けのVSC-Prologなどの編集支援機構に警告してほしい。
Prologはかなり動的な言語なので、これは不可能な要求のようにも思えます。
しかし、
foo :- assertz(buz).
のようにassertz/1を使うと、
Undefined predicate buz/0, use C-c RET to define it
のように警告してくれます。
assertz
はビルドイン関数ですが、何かしらの方法で似たような属性を付けることが出来るのではないかと考えました。
SWI-Prologのソースコードをassertz
で検索してみましたが、ビルドインライブラリの定義などにも使われているようなので数が多くて難しいです。
削除する方のretract
でも検索してみます。こちらの方が流石に使われている量は少ないと思うので。
ガチャガチャ検索してみた結果、 SWI-Prolog -- library(prolog_xref): Prolog cross-referencer data collection を経由して、 SWI-Prolog -- (meta_predicate)/1 に辿り着きました。 xrefよりはまだ言語機能に近い気がします。
SWI-Prolog以外で動くかは謎。一応GNU Prologには定義があるようですが… Predicate information
実装はどうせ自分でやるため、編集支援機能で正常に動けばそれで良いです。
meta_predicate
を使ってみます:- module(find_undefined, [foo/0]).
:- meta_predicate bar(0).
bar(_).
foo :- bar(buz).
の場合、
Undefined predicate buz/0, use C-c RET to define it
と警告が出てくれます。
さて定義されたものの場合は警告されないようにします。
:- module(find_undefined, [foo/0]).
:- meta_predicate bar(0).
buz.
bar(_).
foo :- bar(buz).
のように雑に述語(事実?)を定義してやれば警告は消えます。
しかし、
bar(X) :- atom(X), write(X).
のようにatom
の場合write
するようにすると、この場合X
は述語のためfalse
を返すようになってしまいます。
またatomじゃなくなるのでパターンマッチにおいても、
:- module(find_undefined, [foo/0]).
% :- meta_predicate bar(0).
bar(buz).
foo :- bar(buz).
では、
?- foo().
true.
となりますが、コメントアウトを外して、
:- module(find_undefined, [foo/0]).
:- meta_predicate bar(0).
bar(buz).
foo :- bar(buz).
とすると、
?- foo().
false.
と動作が変わります。
そもそもatomは「定義」されるものではないので、仕方がないことではあるのですが。
パターンマッチは行えないと不便ですね。
以下のように修飾して述語を参照するとパターンマッチも成功します。
:- module(find_undefined, [foo/0]).
:- meta_predicate bar(0).
buz.
bar(find_undefined:buz).
foo :- bar(buz).
?- foo().
true.
find_undefined:buz
という修飾名はめっちゃ長く思えますが、実際のプログラムではもっと短い名前を使います。
その短めの名前のモジュールの述語を参照すれば、集合の一つの要素のように扱えるため、下手なatomよりも堅牢なパターンマッチが出来るとも考えられます。
本当はもっと静的にチェックしていきたいのですけれど、その場合はそもそも動的なPrologを使うのが誤っています。 DSLを書くにしても自分でゼロから設計するのが正解ですね。
メールサーバをPostfixとDovecotで運用するのはそれなりに面白い体験でしたが、もうそろそろ変化もないですし、マネージドなサービスに任せたいと思いました。
料金が月680円でそこそこ高いというのも理由の一つですが、ストレージサービスなども含めるとそれなりのリターンのあるサービスだとは思います。
しかしもう私は個人用のGoogleアカウントを持っており、 Androidアプリの購入紐付けなどはそこに発生しているため、個人アカウントの利用をやめるのは不可能です。更にGoogle Workspaceのアカウントを活用しようとすると、複数のアカウントを頻繁に切り替える必要があって非常に面倒くさいことが予想されます。
なので有料のGoogle Workspaceはちゃんとリターンを受けられる状態で使うことが出来ません。
もっと個人事業主としての活動が活発になって、 Meetやカレンダーの共有機能などを使うようになったら、切り替え覚悟で契約した方が便利かもしれませんが。
最初はさくらのレンタルサーバーを検討していました。
理由の一つは日本のサービスだからです。
別に国産信仰とかいうわけではなくて、メールというのは必然的にストレージとしての機能があるので、日本国内で問題ないデータを保持していても、海外の基準で雑にアカウントを凍結される可能性があるというのは嫌だなと思いました。
日本でも違法なものは外部サービスを使っている場合ではないので考えないことにします。
ちなみにさくらのメールボックスというメール専用のサービスもありますが、さくらのメールボックスが86円で、さくらのレンタルサーバは最安プラン(ライト)で128円でメール機能もついてきて、あまり値段が変わらないことに気が付きました。
さくらのレンタルサーバーのメール機能はメールボックスの完全上位互換かよく分からなかったので問い合わせてみました。
お問い合わせいただき、誠にありがとうございます。さくらインターネット カスタマーセンターの**と申します。
この度は、弊社サーバのご利用をご検討いただきまして、誠にありがとうございます。
つまり、さくらのレンタルサーバのライトのメール機能は、さくらのメールボックスプランで行えることは全て行なえますか?
上記、お客様のご認識の通りでございます。
また、さくらのレンタルサーバ[ライト]プランではWEB機能が利用できますので、WEBとメールの運用をご希望であれば、[ライト]プラン以上のご利用をご検討いただけますでしょうか。
※[ライト]プランでメール機能のみ使用することは可能です。
[さくらのメールボックス / さくらのレンタルサーバ]を新規にお申し込みいただきますと、2週間の無料お試し期間がございますので、ご要望に叶う運用が可能かお試し期間中に動作をご確認いただければ幸いでございます。
上位互換だそうです。
一応ストレージが100GBついてくるので、 ftpバックエンドでGitリポジトリを置いておくとかに良いかもしれませんね。
さくらぽけっと - レンタルサーバーはさくらインターネットを使ってクラウドストレージ的に使っても良いかもしれません。
レンタルサーバらしく制限が激しくて、当然rootは貰えませんし、 CGIで動くごく一部のもの以外は動かせませんし、ライトプランだとssh接続も出来ませんが。
VPSの方は一番安くても590円なのでそれならGoogle Workspaceでも大差ないですね。そもそもVPSの方はメール機能ついてないのでソフトウェア的な保守は結局自分でやる必要がありますが。
もう一つの理由は価格が月128円で格段に安いということですね。
Protonは月額15ユーロ、つまり1500円。
Thunderbirdなどが使えないことに目を瞑ったとして、(瞑れるものではないですが!) Tutanota ご利用料を使ったとして1ユーロで144円は良いんだけど、 1GBのストレージは少なすぎる。 2ユーロ足せば10GB増えるますが。
Secure e-mail for private and business customers | mailbox.org は3ユーロで470円ぐらいで、確かに値段と機能は良さそうだけど、やはりドイツだと法律がかなり違ってきそうですし気が引けます。
ちなみに、
「さくらのメールボックス」はどえらく激安だが、独自ドメインだとSPFにもDKIMにも対応しない粗末な仕様
にはDKIMにもSPF対応してないって書いていますがSPFは対応してるはずです。
おそらく、
SPFレコードの設定は、弊社ネームサーバーを利用しているドメインのみ有効です。
の記述を見て勘違いしたのでしょうが、
一応お問い合わせをして、
お客様にてご確認いただいております通り、サーバコントロールパネルから SPFレコードを設定する場合、弊社ネームサーバを利用しているドメインのみ有効でございます。
▼SPFレコードを設定したい https://help.sakura.ad.jp/domain/2306/
大変恐れ入りますが、他社のネームサーバを利用するご予定の場合は、他社のネームサーバ側でSPFレコードを設定いただく必要がございます。
他社のネームサーバ側でSPFレコードを設定する場合は、以下例のように TXTレコードに弊社のサーバ情報を追記していただけますでしょうか。
例)TXT "v=spf1 a:www○○○.sakura.ne.jp mx ~all"
※「www○○○.sakura.ne.jp」はさくらのレンタルサーバのホスト名であり、 サーバのお申し込み完了後、サーバコントロールパネルのサーバー情報より ご確認いただけます。
▼サーバー情報を確認したい https://help.sakura.ad.jp/rs/2232/
なお、ゾーン情報の編集後、インターネット上にドメインの情報が浸透するまで数時間~最大48時間程度お時間を要します。あらかじめご了承ください。
ご不明な点やご質問等ございましたら、本メール返信にてお問い合わせください。
今後ともさくらインターネットをよろしくお願いいたします。
単にこのヘルプページで解説しているDNSレコード編集画面が、さくらにのみ対応していないだけで、外部でDNSレコードを管理している場合はその外部で編集すれば問題ありません。
というわけでさくらのレンタルサーバーの12ヶ月(1571円)を2週間お試しで試していました。
135円お得のために128*36=4608円も前払いはしたくないかと思って12ヶ月お試しです。もっと得度が高いなら考えますが。
しかし以下の問題があり本当にこれを使って良いのか悩ましくなってきました。
アカウントの2段階認証を有効化出来なかったので、以下のようにお問い合わせをしました。
二段階認証が設定できない。
さくらのレンタルサーバーを使おうと思っていますが、とりあえずアカウントのセキュリティを高めようと二段階認証を設定しようとしたのですが設定できませんでした。
TOTPを使って設定しようとしたのですが、アプリにQRコードを読み込ませるところまではうまく行きますが、ワンタイムパスワードを入力してセットアップしようとしても、
19:39:28.610 XHRPOST
https://secure.sakura.ad.jp/auth/api/auth/two_step/authenticate/totp
[HTTP/1.1 401 Unauthorized 580ms]
という通信になってしまって、正常にセットアップが出来ません。
番号がおかしいのかなと思って何度か試したのですが、失敗しました。二段階認証アプリにAuthyを使っているのが悪いのかと思いましたが、それで成功している人は居るようです。さくらインターネットの2段階認証を有効化しました | にーまるろく あーるしー どっと ねっと使っているブラウザのUAは以下の通りです。
Mozilla/5.0 (X11; Linux x86_64; rv:109.0** Gecko/20100101 Firefox/117.0
お問い合わせいただき、誠にありがとうございます。さくらインターネット カスタマーセンターの**と申します。
ご連絡いただきありがとうございます。 2段階認証の設定につきまして、お手数をおかけしております。
システムエラーとなる場合、ご利用のブラウザが関連している可能性がございます。誠に恐れ入りますが、以下サポートページをご確認の上、推奨環境・ブラウザにて再度お試しいただけますでしょうか。
と帰ってきたんですが推奨環境にFirefox入ってるし、 webブラウザで完結する以上、流石にLinuxだからどうこうということは無いと思います。
もしWindowsでしか二段階認証が使えない場合は、普通に使わない理由に入るレベルですね。
Thunderbirdで開いたら受信トレイしか出てこなくてびっくり。「購読」を選択したら、
のように他も出てきたんですがIMAPのマッピングがおかしいです。受信トレイの中に送信済みトレイが入ってるのは流石におかしいです。
POPだと単一の受信トレイしか認識されないです。
一応お問い合わせをしたのですが、こういう根幹の部分は修正される気があまりしませんね。
実用上の問題はそこまで無いと思うけれど、流石に気持ち悪すぎます。
Thunderbirdの設定で手動設定したら、受信トレイの下にあるとか、ローカライズされてないとかの問題はそのままだけど、とりあえず色だけは認識されるようにはなりました。 Thunderbird 60.x + IMAP + さくらインターネットの組み合わせ - 日々雑事&備考録
お問い合わせいただき、誠にありがとうございます。さくらインターネット カスタマーセンターの**と申します。
お問い合わせいただきましたところ誠に恐れ入りますが、メールソフトについてはサーバに接続する設定以外弊社にて情報を持ち合わせておらず、接続後の同期設定やメールソフト側のフォルダ表示についてはサポート対象外といたしております。
ご希望に沿えない回答となり申し訳ございませんが、何卒ご理解賜りますようお願いいたします。
お手数ではございますが、お客様にてウェブドキュメントなどからお調べいただきますか、メールソフト提供元へとご確認いただけますようお願い申し上げます。
これ関係で色々調べていたら、もう無料の方のGmailを経由して送受信しても良いのではと思い始めました。
個人でメインで既に使っているGoogleアカウントのGmail機能は有効化しません。メールアドレス名が黒歴史なのでそれを検索結果ページとかで毎日見ていたら強迫性障害を刺激して苦しくなることが予想されます。別のユーザー名
でたまに見かけるだけでも苦しい。
Googleアカウントのメールアドレス名を変更することは出来ません。 OAuthとかの仕様を見ているとそこで同一性判断をするidになってしまっているのでこれが覆ることは無いでしょう。
なのでGoogle Workspaceと同じくアカウントは新しく発行することになります。
プライマリのGoogleアカウントのGmailを使っても結局はPGPを近々導入予定なので、 AndroidのGmailアプリは使わずにK-9 Mailを使う予定なので、あまりアカウントを統合するメリットはありませんしね。 PCでももちろんThunderbirdを使います。
ただAndroidでGmailアプリを利用するメリットとして、連携機能とかでカレンダー自動書き込みとかやってくれるらしいのが気になってはいるんですよね。強迫性障害がまたQoL下げてますね。
Googleのサービス継続は信用できないので、 Google Workspace契約して即座にGoogleが仕様変更して終了とかが現実的な恐怖ですが、無料版ならGmail + Cloudflareでも良いかなと思い始めました。無料ならアカウントの機能を使い倒せなくてもそんなに損をした気持ちにはなりません。途中で使えなくなっても無料なら仕方がないと思えます。
最初の方に述べてたアメリカリスクについては、もうプライベートでも仕事でもGoogleやAmazonやMicrosoftにドシドシ依存しているので、本当は気にしてもどうしようも無さそうというのが正直なところです。
一応強迫性障害以外のデメリットとして、 Googleでログインとかの連携機能とか、 Google自身の自動メール作成とかで、古いメールアドレスが誤爆的に使われてしまう危険性はあります。
というわけで、 Gmail利用でうまく行ったらさくらのレンタルサーバーの試用期間は申し訳ないがキャンセルかなと思って作業を進めました。
受信では、 CloudflareのEmail Routingで脱・無償版G Suite(卒業) – Toto Note が割とまとまっていたので、これだけ読んでいれば良いと思います。送信については私のケースでは参考になりませんでした。
Thunderbirdで2GBほどのメールをコピーするのに20時間ぐらいかかりました。一回mbox形式とかでexportしてimportするのをやった方が良かったかもしれません。 1ファイルごとにコネクション張ってて効率悪いとかありそう。やってる間ほぼ寝てたのでなんとかなりましたが。
雑に転送設定して、他のGmailアカウントから送信したら無事到達しました。迷惑メール扱いされてましたけど。
メールの内容が簡素すぎたからか、 Cloudflareを通して転送してたからか、それともToがGmail自身のものじゃないからか…
簡素すぎるなら問題はないけれど、他の理由なら対策をしないといけませんね。
まあとりあえず受信は簡単に出来ました。
などで紹介されている送信する方法は、アプリパスワードを使ってGmailのSMTPサーバを使うというものです。
これは私の求める環境を満たしませんでした。
何故ならばDMARCの認証に失敗するからです。
SPFをpassしてもDMARCはメールサーバのホスト名を判定するため、
ncaq@ncaq.net
のFROM
でSMTPサーバがsmtp.gmail.com
だと、以下のようにDMARCはfailします。
Authentication-Results: mx.google.com;
spf=pass (google.com: domain of ncaq.net@gmail.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=ncaq.net@gmail.com;
dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=QUARANTINE) header.from=ncaq.net
DMARCの認証ってSPFやDKIMと何が違うんですか?を説明してみる。|藤田紀行(株式会社WOW WORLD CTO)が参考になりました。
仕方ないし、やはりさくらのレンタルサーバーを使うかと思ったのですが、これ多分そういう問題ではないですね。 DMARC的にSMTPサーバのドメインがFROMのドメインと完全に不一致だとダメになるわけで、さくらのレンタルサーバーでもそれを解決するためには、おそらくさくらインターネットの方でドメインを管理する必要があるでしょう。流石にCloudflareから移管するのは結構嫌ですね。 CloudflareのDNS画面は使いやすいし、 DNSの設定が反映されるのが早いですし、ドメイン登録している所で管理した方が楽そうですし。そもそも管理してもSMTPサーバが独自ドメインになってくれる保証は無いので、移管しても解決しない危険性もあります。
DMARCを無効化するのは多分多くの人がやっている選択肢ですが、それは流石に嫌です。
迷惑メールとして扱われる可能性が高くなるというのは些細な問題ですが、怖いのは「メールが送れないこと」ではなくて「私のメールアドレスだと誰かが偽ってソーシャルハッキングを行うこと」の方です。
Cloudflare MailChannelsの使用を検討しましたが、多分これweb APIで送るためのものでSMTPサーバとして接続するためのものではないですね。
送信済みトレイとかに残らないとなると色々と不便です。
SendGridが1日100件まで無料で、 SMTPサーバを提供していました。
仕事でSendGridの安いEssentialsプランを使うのは辞めよう - Qiita に書いてあるように、無料版だとIPまとめてブラックリストにぶちこまれるリスクがありますが、個人なら最悪Gmailから直接送信すれば良いです。どうせ送信しませんし。
余談ですが、これSpamhaus側もDMARC時代に適合して、設定してるものはドメイン名でも照合するとかしてくれるようになりませんかね。ドメイン名は未だスパム目的でもコストを考えて雑に取りまくるというわけにはいかないはずなので。
SendGridのガイド通りに設定するだけでDKIM含めてらくらく設定が可能でした。
SMTPの検証するときは指定されたGmailでアカウント追加する時にサーバにユーザ名とパスワード設定して、雑なところにメールを送りました。送らなくても良かったかもしれません。
CloudflareのDNSレコードがいよいよ混沌としてきたので、いい加減Terraformとかで管理した方が良さそうですね。
SendGridを使うことでSPF、DKIM、DMARC全てパスすることが容易に実現できました。
さらにGmailを経由していると出てくる経由の表示も消えました。
ただ一つ問題があって、 SendGridにアカウント登録した後にcompany nameを聞かれるんですよね。開業届を提出済みの個人事業主なのでそれで押し通ることにしました。一応検索してダメか調査してみましたがいまひとつ分かりません。怒られたりしてダメだったらまた何か考えます。仕方がないので送信SMTPサーバだけは自宅サーバで運用するとか。受信ではなく送信なら障害起きても致命傷では無いですし、セキュリティ的な問題も中々起きないと思います。
Gmailは一般的なメールサーバとは違って、少しIMAPの設定が特殊です。
Thunderbirdは本来Gmailの設定を読み取って自動で設定してくれるのですが、独自ドメインを入力すると行ってくれません。
そうすると送信済みトレイとかの設定が少し奇妙なことになります。
独自ドメインのメールアドレスをそのまま入力するより、一度Gmailのアカウントを追加して、その後にアカウント名などを変更した方が良いでしょう。
またSendGridのパスワードが受信用のものと違うので、そのままセットアップすると、保存されているパスワード欄から削除してログインをやり直す必要があります。
それを考えるとやはり一度Gmailでセットアップして別途SMTPサーバを追加した方が良いでしょう。
ThunderbirdでSendGrid経由でメールを送信するとき、本文が空だとDKIMのチェックが失敗します。
DKIMが本文も署名のために使っているので仕様かと思ったんですが、ちょっと調べてみてもよく分かりませんでした。
色々と要素が多すぎて何が原因なのか今ひとつ分かりません。
実用的に本文が空のメールはあまり送らないと思いますし、送ってDKIMのチェックが失敗してもSPFとDMARCはパスしているので、致命的に迷惑メール判定を食らうわけでも無いです。
なのでみんな気にしてないのかなと思います。
K-9 Mailも、独自ドメインを入れるとどのGmailアカウントに接続するべきか判別がつかなくなり、特にメインなど他のアカウントを独自ドメインアカウントでログインできるようにしていると、ログイン名を無視して別のGmailアカウントにOAuth接続を試みてしまいます。
なのでK-9 MailもThunderbirdと同様に、一度Gmailアカウントを追加して、その後にアカウント名などを変更した方が良いでしょう。
FROMとSMTPも後からの変更で問題ありません。
ただ、ゼロから構築する場合はそれで問題ないのですが、エクスポートとインポート機能を使って認証しようとしても、こういうイレギュラーな設定は想定されていないのかうまく認証が通りませんでした。
超絶暇になったらこういうケースにも対応するようにパッチを書いてみたいですね。
こういうのでちまちま消耗してしまったので、最初からGoogle Workspaceに月680円払って雑に済ませておいたほうが良かったかなと思いました。
自分の時給とか考えると、そっちの方が絶対に良い。
今回初期セットアップに使った時間を時給換算すると、これをGoogle Workspaceの料金で相殺されるまでにどれぐらい時間を使うのか計算していませんが、相当な時間だと思います。
前に4K 144HzモニタであるLGのUltraGear 27GP950-Bを買いました - ncaqに書いたように、長らくLG UltraGear 27GP950-Bを使っています。
この機種には概ね満足していたのですが、故障が非常に多かったです。
それがファームウェアアップデートで無事治ったようなので、履歴でも書いておきます。
購入報告記事にも書いたように、まず初期不良が存在しました。
これを確認したのは2021年09月03日です。
これの対応については前の記事に書いたので、そちらを参照してください。
うーんやっぱいLG Ultragear, たまに中央が重なるんだよな
— エヌユル (@ncaq) 2021年12月13日
パネル接合してるっぽいのは分かるんだけどどういうハードウェアバグでこんな現象が起きるんだろう
再起動すれば治るけど面倒になってきた
LG Ultragearの中央がたまに重なるのやっぱり修理出した方が良いのかなあ
— エヌユル (@ncaq) 2021年12月13日
分かりにくいけど面倒の面とかが重なってる
これがたまに発生しなければ最高のモニタなんだけど
悪化して再起動しても治らなくなってその時に保証切れてたりすることを考えると修理出すべき?
でも修理出すの面倒 pic.twitter.com/BDpLOARvPf
画像だと少し分かり難いんですが、ピクセルのマッピングがおかしいのか中央部分の表示がおかしくなってしまって、多重に表示されてしまう現象が発生していました。
一度入力ソースをDisplayPortから適当にHDMIにでも切り替えて戻せば治るのですが、そうするとPCからはモニタが切断されたと認識されてしまい、ウィンドウの配置などが滅茶苦茶になってしまうので、結構ストレスです。単純に切り替えて戻すのも面倒ですし。
特にこれはデュアルブートのOSを切り替える時に多く発生していた認識です。
このモニタは2つのパネルを接合しているのですかね? 初期不良は左半分だけがおかしくなりノイズまみれになって表示されなくなって、次の不良は中央部分の接合がおかしくなってしまうという問題でした。
というわけで集荷サービスを利用しました。
LGの集荷来た
— エヌユル (@ncaq) 2022年10月22日
向こうでエラーが再現するといいけど
再現しない場合は単に送り返してくるのかな
LGからモニタ帰ってきたけど恐れていた「再現しない」だった
— エヌユル (@ncaq) 2022年10月28日
一応基盤とパネルは交換したらしいが…
再現しないことにならないか電話で確認したけど大丈夫じゃないですかとか言われたんだよね
まあ費用は一切かかってないんだが
ウワー、LGモニタの多重表示、修理出して再現しないけどLCDと基盤交換してもらったけど治ってない…今日再現した…
— エヌユル (@ncaq) 2022年10月30日
というわけで再現しないと言われてしまったので、再度こういう感じでちゃんと調査してくれと頼みました。
添付画像のようにたまに画面中央部分が多重表示になる問題が発生しています。これに関して先日修理に出して、再現しないということでLCDと基盤を交換して返却されました。しばらくは発生しなかったので治ったのかと思いました。しかし、今日起動したらやはり発生してしまい、治ってないことが分かりました。
もう一度修理に出してもやはり再現しないということで返却される気がします。そもそもこのモニタは初期不良があり、左半分がノイズまみれでまともに表示されないということでLCDを交換してもらいました。よって根本的に左半分と右半分の同期がうまく行っていない気がします。なので、いくら部分的に修理を試みてもダメなのではないですか。同等品を含め、まるごと交換を行うことも視野に入れて対応してほしいです。
別機器接続時に症状が発生するかどうかは記憶にないとは言いましたが、発生していないとハッキリ述べてはいません。何故ならば別機器を使うことがかなり少なく、使うときもこのバグの解除条件である「入力切替を行う」が行われるため、それで回避できている可能性があるためです。発生するかもしれないので、その時は追加でメールします。
また、私はこのモニタ、 LG製モニタ27UL500-W.AJL、 Acer製モニタ2つの計4台をPCに繋げて常に使っていますが、このような問題が起きるのはこのモニタだけです。 DisplayPortケーブルも修理に出す前はサードパーティのを使っていましたが、戻ってから試しに同梱ケーブルを使ってみたらギリギリ長さが足りていたので、同梱のものを使いましたが問題は起きました。可能性としてはDisplayPort使用時のみ問題が起きるということがありますが、私はこのモニタの4K144Hzが出せるという特性に惚れ込んで買ったので、もしも144Hzが出せないHDMI接続をしろと言われたとしても困ります。
書き忘れていましたが、電話対応時に「Macで起きる場合は設定の工夫で起きなくなる事案があった」という話だけ聞いて、自分はLinuxとWindowsで発生するので関係ないかなということで具体的な設定を聞かなかったのですが、もしかすると共通して問題解決の糸口になる可能性があるため、その人にどういう指示をしたのか教えてくださると幸いです。
設定についてはApple側が対応してしたので内容を把握してなかったらしい。
現在DisplayPortに接続できる機器は当該デスクトップPCしか所有していません。変換ケーブルなどを買えばノートPCからも接続可能だとは思いますが。
PCは自作ですが、 GPUをGeForce RTX 2080 Tiにしても、このような現象はこのモニタを買うまでは起きませんでした。
モニター1:1とはハブなどを使っているかという質問でしょうか。それならばモニタとGPUを同梱されていたDisplayPortケーブルのみを使って直接繋いでおります。
そういうやり取りをしていたら集荷ではなく発送を案内されたので困惑して返答。
再度送ってまた設置し直すのにも手間がかかりますし、前回「再現しないってことはないと思います」と言われて送ったのに、再現しないということで送り返されたのですが、また再現しないとして送り返されない保証はあるのでしょうか。
またもやLCDと基盤を交換するだけだと、このモニタの交換してないパーツに問題があるという疑念が当たってる場合同じことになる気がします。買った当初に初期不良が存在したため、それを疑っています。
また、モニタの大きさから自分で運ぶのは困難なので、前回も前々回も集荷して貰ったのですが、今回は自分で持ち運びばないといけないのでしょうか。
集荷についてはすると案内されましたが再現問題について返答されなかったため聞き返しました。
集荷してもらうのはそれで良いんですが、前半の質問の「再現しない」にまたなったらどうなるかについて返答が欲しいです。
集荷してもらうとはいえ取り外しの手間がかかって、送っている間(前は一週間ぐらいでした)は使えないわけなので、また問答をしたくないので明確な返答が欲しいです。
再現しない場合やっぱり送り返されるらしい。渋々そのまま送りました。
「集荷する時に連絡します」ってLGのカスタマーセンターがメールに書いてたから連絡きてからモニタを梱包すれば良いかと思ってたら、連絡がないどころか不在票が入っていた
— エヌユル (@ncaq) 2022年11月22日
いや、連絡してほしいのだが…
LGに修理に出したモニタ、問題再現たまにしかしないからちゃんと確認して…って書いたからか3週間ぐらい存在しないままだな
— エヌユル (@ncaq) 2022年12月9日
素直に完全な新品を寄越してくれればそれで良いのだが
LGくんの修理結局土日も何も返信なかったし電話するか…
— エヌユル (@ncaq) 2022年12月18日
そろそろ1ヶ月経つぞ
LGからの返答
— エヌユル (@ncaq) 2022年12月21日
モニターのファームウェアがバグってたのが原因だったので韓国本社で調査してソフトウェアアップデートしてたので時間がかかった
返答できなかったのはZendeskのシステムの都合上一度しか返答出来なかったので内容まとまってから返信するつもりだった
今返送する手続きしてる
まあ治って戻ってくるなら消費者としては良いんだけど、進捗伝えられないサポートシステムは採用するべきじゃないなと思ってしまった…
— エヌユル (@ncaq) 2022年12月21日
技術者としてはなんでこんなことが起きてたのか気になったが、流石に企業機密だろうしサポセンに聞いても答えられないだろうし聞かなかった
LGからモニタ返却されてきたので組み立て直さないと
— エヌユル (@ncaq) 2022年12月23日
ソフトウェア更新で治って良かったねというだけの話を書くつもりでしたが、なんかまた故障しています。
電話で問い合わせして、メールで動画を添付してほしいと言われたので、動画を添付しました。
故障は昨日(2023年04月09日)から。
最初はゲームやってる時に発生して、何も映らなくなりました。 Windows側からは認識してるみたいですが、モニタの下のメニューボタンとか押しても全く反応しなくなるという状況です。
Windowsの電源切って、電源コード抜いてしばらく放置して、差し直したら復活したので、一時的なものかととりあえず見逃すことにしました。
今日(2023年04月10日)になって、 Windowsのデスクトップ画面映すだけで1分も持たない状況になりました。
これでは全く使い物にならないため、なんとかなって欲しいです。
これで修理に出す場合4回目の修理なので、流石に個体がおかしいのではないかとやはり疑っています。
モニタ3年保証してくれるのは誠実で良いんだけどさあ、このモデルなんか妙なエラー表示をシャットダウン時とかにしてたりしたし、4回も修理するのこっちもLGも負担だろうし、改良した新モデル寄越してくれたほうが良いんじゃないの
— エヌユル (@ncaq) 2023年4月10日
LG、モニタ修理してくれるのは良いんだが、メイン基板とLCD異常で交換したってもうそれ新品くれ
— エヌユル (@ncaq) 2023年5月28日
モニタ、3回目の修理で直した問題が4回目の修理で基盤交換になってファームウェアのバージョンが戻って再発したっぽい?
— エヌユル (@ncaq) 2023年6月12日
流石にいい加減にしてほしいんだが
そういうことを愚痴っていたら、 LGモニターはファームウェアをユーザー側で更新できるという情報を教えてもらいました。
そういえばLGのモニターってUSBケーブルを接続すればユーザー側でもファームウェア更新出来るらしいですが、そちらは試されましたか…?
— あかくさ (@ak9sa) 2023年8月14日
サポートページ行ってファームウェア更新(Windowsなどが必要です、1時間ぐらいかかるので余裕のある時にやりましょう)してみて、とりあえず今日まで画面が多重になる問題は発生しなくなりました。
製品自体は良いものですし、 3年保証もちゃんとやってもらったんですが、流石に4回も修理に出すのは面倒でした。
無償とかじゃなくて明らかにLG側の問題なのですから、手数料とかこちらが欲しいぐらいですね。その間使えないわけですし。 3回目の修理とかじっくり調査してファームウェアのバグを修正していたのか一ヶ月も修理に時間をかけていたので、尚の事です。
しかしゲーミングにも使える安定した品質でそんなに高くないものってLGかDellで、結局DellもLGのパネルを使っていることが多いんですよね。それならばこういう不運なケースを引いても、 3年保証をちゃんと履行してくれるLGのモニタは悪くないとは思います。まあDellのモニタも3年保証はついているので、そちらでも良いかもしれませんが。
Alienware m17に買い換えてGentoo LinuxをBtrfs on dm-cryptでインストールしてNVIDIAのGPUを有効にして起動しました - ncaq で買ったAlienware m17のCPUがi7-8750Hでそろそろ限界なため。カタログスペックを見るだけだとそこまで悪くないように見えますが、少しでも負荷をかけると発熱が酷く、ビルド作業をすると動作周波数が相当落ち込んでしまいます。
CPU以外はそこまで不満ないので、少し買い換えるのは勿体無い気もしますが、父親のPCとして働いて貰うのでそんなに問題ないでしょう。
フルリモートでモバイルPC使う機会が激減したとはいえ、たまに外に出かける時にこれをメンテナンスしないといけないのはかなりストレスです。
ただ今回は外でそんな頻繁に仕事とかをする予定はないので、そこまでお金をかける気は無いです。
前から買い替えたいなと思ってたのですが、明日楽天リーベイツでlenovoの20%ポイント還元をやると教えてもらったためです。
前はHシリーズを選びましたがどうせ発熱で理論スペックは満たせないのでUシリーズでも良いです。 Pシリーズですら無くても良いです。
OLED(有機EL)が圧倒的に綺麗なのはスマートフォンやテレビももうみんなOLEDにしたので分かっているんですが、 PCはスマートフォン以上に長時間同じ画面を表示することが多いので焼付きが怖いです。
Windowsにメーカ製の焼付き防止ツールと一緒に動かすならともかく、自分はGNU/Linuxをメインに使うことになりますし。
自分はInspiron, XPS, XPS, AlienwareとDellのPCをこれまで買ってきました。
そうなるとDellがまず候補に上がるようになるのは当然でしょう。
メモリとSSDをアップグレード。
結構前にThinkPadが欲しいなと思うようになりました。同僚が持ってたThinkPadのキーボードを押すとかなり快適そうだったからという理由です。トラックポイントの存在も、私は基本的にキーボードでPCを操作するのでトラックパッドが誤爆すると鬱陶しいので無効化しているため、誤爆しづらいトラックポイントで済ませられるのは大きなメリットです。
ただこれまで買ってこなかったのはThinkPadのディスプレイは解像度が高いやつが全然なくて、フラッグシップモデルでもフルHDかWUXGA 1920*1200しか無かったのと、同じようなスペックのDellのPCに比べてかなり高額だったことが理由です。
しかし最近画面解像度も高いものが搭載できるモデルが増えてきました。 4Kを超える解像度だとOLEDにカスタマイズ必須でかなり高額になってしまうことが多いですが。普通にフルHDより少し多め程度で十分で、自分の使い方だとOLEDは焼き付きが怖いんですよね… +72600円は高すぎます。
高額という問題も自分の収入が増えたことでそこまで問題ではなくなりました。
全体的に言えますがThinkPadはアップグレードが異様に高額です。一つの例ではSSDのアップグレードが256GBから512GBに上げるだけで+36000円となり、ハイエンドSSDのSN850の1TBが12600円であることを考えるといくらなんでも高額すぎるため、流石に自分で換装することになります。
メモリの16GB -> 32GBが+41800円なのも相当なのですが、これはオンボードなので仕方がないと諦めます。
SSDの方はM.2 PCIe接続であることと、 Lenovo公式のPDFで交換できると書いてあることと、前の世代の例ですが実際に換装したレポートがあることで、「ThinkPad X1 Carbon(2018)」を1TB NVMe SSDに換装、容量/速度アップでWindows 11移行も視野に - AKIBA PC Hotline! 換装可能と判断しています。不器用なのでこういうことはあまりしたくないのですが、仕方がありません。
メモリとディスプレイとキーボードと電源アダプターをアップグレード。
メモリとディスプレイとキーボードと電源アダプターをアップグレード。
i7-1355Uはマルチコアだとi7-1370Pのおおよそ7割ぐらいの性能になり、シングルコアだと殆ど変わらないようですね。これなら流石に安い方を選びますか。
日本でメジャーメーカーでdGPU無しでAMD Ryzen Zen4搭載してるメーカー全然ないなと思ってましたが、なんかちょうどつい最近発表されてました。
レノボ、Ryzen PRO搭載の14型/16型モバイルワークステーション - PC Watch
メモリとキーボードとバッテリーをアップグレード。
素のスペックは良かったのですが、カスタムしてない時点で35万円を超えてしまうので、このPCは本気では使わないのでパス。
前の世代のモデルの情報ですが、 Linuxだとサスペンドが正常に動かないらしいです。 Thinkpad P16s (AMD) + Linux? : r/thinkpad
元々私はサスペンドを使わないので気にしないことにします。それ以外はちゃんと動くらしいという情報を得てむしろ満足です。
後同じマザーボードを使っているらしきものがアップデートで直ったという報告もありますね。 ThinkPad T14 Gen3 のサスペンド問題 - tmtms のメモ
メモリとキーボードとバッテリーをアップグレード。
14インチのより安くなるのか。
多分ThinkPad P16s Gen 2 AMDを買うと思います。
カスタマイズは別のものにするかもしれませんが。
チャットサポートと相談する上で頻繁にチャット画面が画面下の範囲外に飛んでいってしまうのですが、開発者ツールを開くとかで一度縦画面のサイズを変動させてから戻すと画面内に戻ってきます。
ACアダプターの選択で、
があり標準では上が選択されていますが、下を選んでも0円なこと。
同じ価格で同じ出力ならスリムな方が直感的には良いと思うのですが、完全に下が優れているのに同じ価格なことがよく分からなかったので、「通常品よりスリム品が劣っている所はありますか?」と聞いてみました。
同じ65Wなので、変わりありませんが、スリーム型より重量・サイズが大きくなるので、お選びならスリームの方をお勧めいたします。
とのことでした。チャットサポートの人の知識が万全とは限りませんが、とりあえず目に見えてスリムが劣っていることは無いようです。
スリムを選択しましょう。
これまたPremier Asset Tagの項目で、 0円でプレミア・サポート・アセット・タグというのが選択できます。これについて調べても何も分からなかったので、チャットで聞いてみました。
PC筐体に貼られるシートになります。
0円なんでつけてもらいましょう。
とのことでした。
なんとなくそんな気はしていました。
ついでに「LenovoってEクーポンとか色々割引がややこしいので手っ取り早く一番割引を受けるにはどうすれば良いですか?」と聞いてみたら、「この商品は既に割引対象なので大幅な割引は難しいですが端数を取り除くぐらいは出来るかもしれません」と返答を貰いました。
とりあえず指示通りにカートに入れて値引きを依頼します。
177,617円が165,000円になりました。なんと12,617円ものの割引です。
と思ったんですが、楽天リーベイツの20%還元とは併用できないとのことでした。残念。
でも担当者番号を入力する場合Amazonギフト券1000円貰えるらしい。
FHD+の画面が不満ですが、流石に7万円以上プラスしてOLEDにするのはすぐやめる判断をしました。
CPUもどうせ発熱で最大スペックは出せなさそうなのと、今回は省電力を重視したいのでRyzen 7 7840UにはせずRyzen 5 7540Uに止めました。 GNU/Linuxを使うなら今の所Ryzen AIは使えませんし。
メモリを32GBにアップグレードするか、 16GBで留めるかはかなり悩ましかったんですが、ゲーミングマシンならともかく一応外でプログラミングとかするためのマシンなので、ビルド中に編集作業が出来なくなるとか起きたら嫌だなあと思って32GBにしました。
バッテリーはほんの少しの価格で相当大きく出来るのでアップグレードしておきました。代償として急速充電は出来なくなってしまうみたいですが。
前回が34万円であったことを考えると177,617円に楽天リーベイツの20%還元が入って実質14万円になるのは比較的かなり安いですね。このマシンで真面目に開発をすることは殆ど無いだろうので抑えめにしました。前の34万円のPCよりディスプレイが4KからFHD+になってしまったことと、バッテリー容量(これは省電力性を考えると実質こちらが上回っている)と、 SSDの容量(換装すればほぼ同じ)以外、ほぼ上位互換なので技術が進歩したなあと感じます。
SSDは自分で換装するのでもう少しかかりますが、せいぜい12,000円ぐらいで満足できるものが手に入るはずです。
Samsung Galaxy Z Fold5の発売があともう少しで行われます。
自分は今回はドコモで買う予定です。 auの予約後の審査何故か落ちて萎えたのと、いつでもカエドキプログラム+での1年単位の買い替えに魅力を感じたからです。
ドコモは現在端末のみだと予約が出来ないので発売後に買うことになるので、ドコモの方の審査が通るかは謎ですが。
しかしCICに500円払って信用情報を開示したのですが何も問題なくて、なんでauで落ちたのか分からないんですよね。思い当たることはGalaxy Z Fold3 5Gの分割支払いがまだ残っていることぐらいですが、その場合は言ってくれても良いと思うんですよね。
そもそも返却プログラムを使いたいだけで分割払いしたいわけでは一切ないので、数十万円ぐらい最初に払って返却時にキャッシュバックを貰いたい。
さてそろそろGalaxy Z Fold3 5Gも退役するので、この端末の修理履歴でも書いておこうと思います。
当時のメモを少し変換しています。
普通のレビューは以下の記事を参照してください。 Galaxy Z Fold 3 5Gを今更レビュー - ncaq
2023年3月15日頃に普通に開いた所フィルムに大量の気泡が入ってしまいました。
Galaxy Harajukuのご案内 | Samsung Japan 公式を見ても自分の契約でやってもらえるのか不明なのが気になりました。
povo 2.0のSIMを入れて通信していることもあるので。別にpovoと契約してGalaxyを手に入れているわけでは無いんですが。
Galaxy Harajukuに電話してみた所、無料スマホ健康診断ご希望を受けた後普通にフィルム張り替えて貰えるらしいです。 Povoを契約している場合でも、 Galaxy Harajuku店頭修理のご案内ではスマホの画面保護フィルムの無料貼り替えはあくまで無料張り替えであって、修理では無いので修理拒否とはならないらしいですね。
フィルムの在庫は行く前に一応確認しておいた方が良いらしいです。
もし有償修理する事態になった場合auから買ったのであれば回線契約無しでもauに問い合わせするべきらしいです。
そうなると郵送修理になりそうだからやっぱりバックアップ用の廉価な端末か、 Androidタブレットを買っておいた方が良さそうだと思いました。ここでGalaxy Tab S8を購入していなかったことを後悔しました。郵送でも問題ないように代替機は用意したほうが良さそうだよね。
しかし自分は「povoだけどどうなります?」って聞いたのですが、黙ってSIM抜いて「SIM契約無しで家で使ってます」ってヘラヘラ言ったらどうなるんですかね… 「契約なしでも動くんですけどSIM抜けば良いんですかね?」とも聞いたのですが、曖昧な返事で回答はよく分かりませんでした。
頼むからSamsungはGalaxy Zシリーズをキャリア通さず直接売ってくれと思います。もう折りたたみに慣れると離れられないし、 FeliCa対応して技適も通したちゃんと日本で合法で使えるフォルダブルスマートフォンはGalaxy Z Foldシリーズしか存在しないんだよな。ドコモやau経由だと別にZシリーズは2年返却以外の割引は無いですし、返却前提の価格なので割高です。 Samsung公式の下取りサービスとか使って乗り換え続けたいです。
そして無償で張り替えてもらって完全に治ったと思いました。
問題なくなったと思ったんですが、悲しいことにヒンジ部分がもうダメだったみたいで、中央から緑色の線がいきなり現れて、白い線に変わって出現してしまいました。
そもそもフィルムに空気が入ったのもヒンジが半ば故障していたせいだったのでしょう… 仕方がないので有償修理に出します。
こういうときのために、クロネコ「スマホもしも保険」/ヤマト運輸株式会社に入っていたので、 3000円の実費負担で済むはずです。保険入ってて良かった。 2年フルに入ってたとしても470*24=11280ですが、修理にそれ以上の額を請求される可能性は十分ありますので。
クロネコヤマトに電話したらこの機種はこちらでは修理受付してないと言われてしまいました。 auに直接連絡するしかないようです。
とりあえず近所のauショップに電話したら定休日不定期って書いてたのに、実際は月曜日が定休日だとアナウンスが流れてきました。
どちらにせよ端末のみだと修理受付してくれるかよく分からなかったので、仕方ないので預かり修理 | スマートフォン・携帯電話をご利用の方 | auから電話することにしました。
結局電話なので何を話したのかよく覚えていないんですが、こんな感じで会話しました。
しかしなんだってGalaxy原宿はキャリアのはドコモ版のGalaxyしか修理してくれないんだろう。それでドコモ版の魅力は少し上がりますが、ロゴとかプレインストールとかの問題があり、対処できるとはいえ絵文字問題があるので、やはりau版の方がマシに思えるんですよね。
頼むからSamsungは直接Galaxy Zシリーズを売ってくれ。多少は割高になってもキャリアとのわけの分からんやり取りをもうしたくない。
一応ダメ元でGalaxy原宿に修理できるか聞いてみたら「auから購入した端末でも修理できる」という返事が帰ってきました。は? 「この前電話した時はドコモしかダメと言われたんですが…」って聞いたら、「povo契約ですか?」って言われたので、嘘つくわけにもいかないので、「まあSIMはpovo刺してますね…」って答えたら、「povoは申し訳ないですが無理です」とのこと。「自分は嘘つくの苦手なのでPovo契約してるって言っちゃいましたけど、黙ってSIM抜かれたら分からないですよね…?」って聞いたら曖昧な感じで、「私どもからはpovo契約してると聞いた限りはそれ以上は契約の関係で言えない」とのこと。
意味が分からない。なんで単体購入した端末にどのSIMを差し込むかでサポートが受けられるか決まるんだ…? これなら親から一時的にahamoのSIM貰ってそれ差し込んで、「今はahamoのSIM刺してます!」って答えるべきだったのですかね。
auに4月5日に提出したら、 4月10日に帰ってきました。 2週間見積もりとか書いてたけど思ったより速い。保証修理って書いてあって金額どこにも書いてないし、無料修理になったようです。買ってから1年経ってないし無償になったようですね。
2023年08月14日にまたフィルムに空気が入ってしまいました。
18日に修理の郵送手続きをしました。
24日に帰ってきて代引きで16720円請求されました。
なので保険手続きをしました。
代引きの領収書をアップロードする必要がありました。
代引き手数料440円は修理の代金では無いため保険の対象範囲外らしい。まあそれはなんとなく納得はいくから別に不満はないけれど、だったらau側も代引きじゃなくて他の決済で引き落としてほしかったですね。他には通信費から引くものがあるらしいけれどそれは端末のみ購入の自分には当てはめられない、金額が決まってないものを勝手にクレジットカードから引き落とすわけにはいかない。そう考えると仕方ないかあ。
と言うわけで自己負担額の3000円に代引き手数料の440円で3440円の修理代金ですね。 Fold5にすぐ切り替えすると考えると少し勿体ない気もするけれど、auに返却する時に値引きされると困るし仕方がないです。流石に修理したのに値引きされることは無いと信じたいところです。
損保ジャパン子会社なので不安に思っていましたが、無事保険金は振り込まれました。
やはりフォルダブルは壊れやすいので保険は入ったほうが良さそうです。ただし少なくとも今回の場合最初の1年は通常保証がされるので不要かもしれません。そこからは保険に入った方が良いです。
ただ次のFold5は強制保険加入でドコモで1年で買い替えサイクル回していく予定なので、追加の保険には入らなくて良いかもしれません。
弊社pluszeroでは生産性向上のために、希望者にはGitHub Copilotを無料で配布するようになりました。
自分は拡張版のGitHub Copilot Xが、 Visual Studio CodeとVisual Studio以外の、具体的にはNeovim向けにも提供されるまで様子見して、提供されたら一ヶ月の試用期間で使ってみて継続して契約するか決めようかと様子見していました。
そんなことを考えていた理由は、私はEmacsを使っていて、ここから離されると生産性が落ちることが目に見えていたためです。
GitHub CopilotはEmacsには公式には対応していないのですが、 zerolfx/copilot.el: An unofficial Copilot plugin for Emacs.で非公式サポートされています。
これの実装方法はNeovim向けのクライアントに依存しています。 GitHub Copilotは嘆かわしいことにクライアントすらプロプライエタリです。 GitHubに投稿されたコードを利用しているのですから、クライアントぐらいフリーソフトウェアにするのが望ましいと思うのですが。せめてドキュメント化されたAPIを提供してほしい。
ともかくそういう事情があるのでNeovim向けにはどうもlsp(少なくともNode.jsとJSON RPCしている)で接続しているようで、 Emacsの非公式クライアントはNeovimのクライアントをコピーしてくる形で実装されています。
なのでEmacs向けにCopilot Xを実装するにはNeovim向けのクライアントがCopilot Xを待つ必要があったわけです。
一回しか無料の試用期間は使えないのでCopilot Xが実装できそうな雰囲気が出たら使ってみて、コントリビュートも考えていました。一ヶ月1500円ぐらいはそこそこ高いですからねえ。
しかし会社が無料で配布してくれるならXじゃない範囲でも使います。補完はGPT-3の性能的にあんまり期待してなかったのですがそれなりに便利です。どちらかと言うとリファクタリングやドキュメントコメント生成に期待してたのでCopilot Xを待っていましたが、補完だけでも使う価値がかなりありますね。
copilot.elのドキュメント的にはprog-mode-hook
にcopilot-mode
を追加するのが推奨で、それで概ね動きます。
ただもちろんそれだとプログラミング言語のモードでしか動きません。
Gitのコミットメッセージこそdiffをソースにかなり自動化できそうですね。
EmacsにはMagitというEmacs以外を入れても最強に近いGitクライアントが存在するので、私はこれを使っています。
なのでgit-commit-setup-hook
にcopilot-mode
を追加してやれば当然EmacsのGitのコミットメッセージ編集画面でCopilotは動きます。
しかしMagitのコミット画面ではコミットメッセージ編集画面は簡素になっていて、
diff画面とコミットメッセージ画面が横に2分割されてdiffを見ながらコミットを書くことが出来るようになっています。これは通常の使い方では特に文句はないのですが、
copilot.elは今のバッファとファイルしか読まないようなので、この状態ではcopilotはfeat: add init.el
のようなざっくりとしすぎている上に間違っているコミットメッセージしか作れません。どのファイルに変更があったかぐらいしか見れないからですね。
バッファの内容を読むのであれば当然バッファに入れる情報を増やしてやれば良いわけです。
Magitでコミットする時--verbose
オプションを有効にしてやればコミットメッセージ入力バッファにdiffも入力されるので、
feat: add git-commit-setup-hook to copilot
のようなそれっぽいコミットメッセージが生成されるようになってくれます。
--verbose
をデフォルトにしたいさて--verbose
を毎回有効にするのは面倒なのでデフォルトにしたいですね。
How can I make --verbose
flag be enabled by default in magit commit screen? - Emacs Stack Exchange
の作者による回答を参考にすると、
--verbose
を有効にしてC-x C-sを実行すれば(magit-popup-save-default-arguments)
が実行されてデフォルトになるようですね。実際の動作を辿ると.emacs.d/transient
ディレクトリに永続化されるようですね。
それでもうだいたい目的は達成されているのですが、複数端末での利用や.emacs.dのgit clone
だけでの再構築を考えると、自動で変更される部分ではなく、手動で書くGitマネージドなコード部分にデフォルト値は書いておきたいですね。
昔はmagit-commit-arguments
は単なるリストだったようなのですが、今はmagit-popup
-> transient
の管轄になっているようなので単純に--verbose
をリストに追加する方法では対応できません。
MagitではなくGit自体の設定でgit config --global commit.verbose true
のように設定すれば表示されるようになるので、実用的にはこれでも良いかなと思いました。
Magitのフラグ表示と実際の挙動が異なるのはかなり気持ちが悪いですが、 Transient User and Developer Manualを見たり、 forgeの使用例を見ても解決策が思いつきませんでした。
多少汚いですがadviceで(magit-commit-arguments)
をaroundして解決しようかと思いましたが、構築段階ではなくコミット生成段階で閲覧するためGit自体の設定で解決するのと結果は変わらないですね。
transient
の複雑性と真面目に向き合う必要性を今の所感じないのでこれで良いとしてしまいます。
一応Emacs以外(コマンドラインとか)からコミットを開いたときも設定の有効性を得られるメリットもあります。
以前にこういうメモを書きました。 StackはGHCやCabalに並列ビルドのjobsオプションを伝えていませんが, 伝えたとしてもGHCの問題で全然速くならない - ncaq
以前の記事では実際に測ってみてGHCの-j
オプションは役に立たないことを確かめました。
しかし最近以下の記事を読みました。 GHC 9.8の新機能
これによると新しいGHCでは-jsem
オプションを実装することで、対応したCabalなどのビルドツールでパッケージ単位とモジュール単位の並列化の両方のジョブ数を制御出来るようになったようです。つまりGHCのモジュール単位の並列化に意味があることをアテにした実装がなされています。
ということは今のGHCのバージョンでもモジュール単位の並列化は有効に動くのではないかと考えました。
とりあえず計測あるのみです。
現在の最新であるStackageのLTS 21が利用するghc-9.4.5を使って測定しました。 GHC 9.8系を使わなくても、以前からモジュール単位の並列化が意味を成すものになっているのであれば、これでも有効なはずです。
デフォルトと並列化有効化の時でそれぞれ当然ですがcleanしてからビルドして、
time
のtotalの値を見ます。
実際に仕事で使うモジュール並列化の速度を計測したいため、依存ライブラリは事前にビルドしておきます。
Stackを使っているのでpackage.yaml
のghc-options
に-j
を記載しました。
stack test --no-run-tests 167.03s user 6.98s system 101% cpu 2:51.65 total
-j
有効化stack test --no-run-tests 315.04s user 47.82s system 324% cpu 1:51.75 total
モジュールが非常に多いパッケージとして選びました。 Cabalを使いましたが、 Stackにも対応しているのでそちらで測るべきだったかもしれません。
cabal build 276.47s user 4.18s system 100% cpu 4:40.59 total
-j
有効化cabal build --ghc-option='-j' 850.04s user 53.86s system 642% cpu 2:20.76 total
仕事で使っているパッケージに関しても、モジュールが多いパッケージに関しても、ビルドが約2/3
程度には高速化されました。
早速含めてコミットすることにしました。
16コア32スレッドを使い切ってくれないのはモジュール同士の依存関係が絡み合ってるのと、一つのモジュールにたくさん書いてしまうのが横行しているからでしょう。 cycle importの解決はかなり面倒ですし、これまではモジュールを分けても並列ビルドによる高速化が期待出来なかったので、速度面では差分ビルドの高速化ぐらいしか分けるモチベーションがありませんでしたからね。
StackでもCabalと同じく-jsem
を実装しようとする動きはあるようです。
Support GHC's -jsem <sem>
initiative · Issue #6131 · commercialhaskell/stack
これが実装されればstack install
をglobalな環境向けに実行するときも、高速にビルドさせるのが容易になりそうです。これまでもモジュール単位では並列ビルドしてくれましたが、どうしてもpandocなどがモジュールたくさんで遅いという状態になっていたので今後の進展に期待です。他にもGTKなどのバインディングも大量の並列したモジュールが含まれるため期待できます。
最近GitHub issueでTODO管理とかしたり、 Zennのスクラップのように時系列だけで考えをまとめずにメモることが多いです。
しかしGitHub issueはそのままだとテキストデータとして扱いにくいです。記事化したりDeepLに翻訳させるときに問題になります。
ちなみにDeepLのブラウザ拡張機能の、 DeepL Pro特典のページ全体の翻訳はGitHub issueではうまく動きません。というかページ全体翻訳がきちんと動くページの方が少ないと思うんですが、これは自分の環境の組み合わせが悪いんでしょうか?
そこでGitHub CLIに適切なjqのクエリを渡すことで、単一のMarkdown形式でエクスポート出来るコマンドを使っています。
アカウントごとのGitHub Projectsを使った公開TODO管理が割と良い感じ · Issue #145 · ncaq/www.ncaq.netを見る限り2023年3月に作ってるみたいですね。
私は今はQiitaとかZennとか、独自ドメインでのはてなブログすら使っていません。
このサイトはMarkdownからhakyllとその内部のpandocを使って、 HTMLとして出力してCloudflare Pagesでホスティングしています。 Cloudflare Pagesにすら大して依存していなくて単純にHTMLなどを配信しているだけなので、いつでも自宅サーバのNGINXを使ったホスティングに戻すことが可能です。今では珍しくなってしまったHTMLレベルで管理するwebページを提供しているのは、自分のデータはなるべく自分でコントロールしたいという思想から発生しているものです。
Qiitaが信用できなくなったからZennやはてなブログに記事を移動させたとかいうページを見るたびに、 Zennが今後Qiitaのようにならないと思う確信はどこから来るんだろうなと思います。
確かにQiitaのやらかしは擁護できないものですが。
しかし今回これはGitHubにデータを保存して使っているので既にGitHubに依存してしまっています。それならZennのスクラップを使っても良かったのではないかと少し思いました。依存先を減らすのは意味があるかもしれませんが。
gh issue view
だと微妙なフォーマットをかけられてしまいます例えば、 descriptionもGoogle任せではなく設定する · Issue #155 · ncaq/www.ncaq.net を閲覧してみます。
2023-08-10T17:42:19 ⬢ [Systemd] ❯ gh issue view https://github.com/ncaq/www.ncaq.net/issues/155
descriptionもGoogle任せではなく設定する #155
Closed • ncaq opened about 5 months ago • 2 comments
Labels: Estimate: 2, Priority: Low, Type: Bug, Type: Feature
自動解析されてfooterを出されることが増えてきた
———————— Not showing 1 comment ————————
ncaq (Owner) • Mar 4, 2023 • Edited • Newest comment
適当に100でええか
Use --comments to view the full conversation
View this issue on GitHub: https://github.com/ncaq/www.ncaq.net/issues/155
Markdown形式で記事化したりDeepLに投げ込むにはこれでは不向きですね。余計なメタデータが多すぎることと、せっかく元がMarkdown形式であるにも関わらず中途半端にフォーマットされてしまっています。
--template
フラグを使って制御しようかとも思いましたが、どちらかと言うとこれはメタデータをフォーマットするためのフラグであることと、
Markdown文法に対して一つずつ対応させるのが面倒です。元がMarkdown形式なので生の情報を取れれば十分なわけです。
--json
フラグでJSON形式でほぼ生のデータを取れて、
jq
のコマンドを使ってフォーマット出来るようなので、その方針で実装しました。
gh-issue-export
コマンドgh-issue-export
コマンドとして置いています。
#!/bin/zsh
set -eu
gh issue view $@ --json author --json createdAt --json body --json comments \
--jq '{
top_level: ("@" + .author.login + " " + (.createdAt|fromdate|strflocaltime("%Y-%m-%dT%H:%M:%S %Z")) + "\n\n" + .body),
comments: [.comments[] | "@" + .author.login + " " + (.createdAt|fromdate|strflocaltime("%Y-%m-%dT%H:%M:%S %Z")) + "\n\n" + .body]
} |
.top_level + "\n\n---\n\n" + (.comments | join("\n\n---\n\n"))' | \
tr -d '\r'
--json
と--jq
で本文とコメントとその本文を全て取得して、投稿者と時間と本文を出力しています。そのままだと投稿間の区切りが分かりにくいため、
---
で投稿を区切るようにしています。また改行がCRLF形式になってしまう部分があるためtr
コマンドでCR部分を除去しています。
例えば先程の、 descriptionもGoogle任せではなく設定する · Issue #155 · ncaq/www.ncaq.net の例で実行すると以下のように出力されます。
2023-08-10T17:45:57 ⬢ [Systemd] ❯ gh-issue-export https://github.com/ncaq/www.ncaq.net/issues/155
@ncaq 2023-02-20T02:53:17 JST
自動解析されてfooterを出されることが増えてきた
---
@ncaq 2023-03-04T19:07:59 JST
長さは少し切り詰めたほうが良さそう
---
@ncaq 2023-03-04T19:07:59 JST
適当に100でええか
最初は以下のシンプルなものを使っていましたが、
DeepLに放り込むと投稿者が分からないと困ると気がついたため、そちらはgh-issue-export-only-body
コマンドとして分けることにしました。
#!/bin/zsh
set -eu
gh issue view $@ --json body --jq '.body' --json comments --jq '.body, .comments.[].body|., "\n---\n"'|tr -d '\r'
クリップボードにコピーしたい時はXSelを使った、以下のto-clipboard
エイリアスにパイプで流し込みます。
alias to-clipboard='xsel --logfile /dev/null --input --clipboard'
だいぶ前からのGitHub CLI | Take GitHub to the command lineで、
gh repo fork
した後gh pr create
すると、以下のようなエラーが出てくるようになってしまいました。
X No default remote repository has been set for this directory.
please run `gh repo set-default` to select a default remote repository.
Release GitHub CLI 2.21.0 · cli/cliでの変更ですね。
私はちょっとした修正をPRとして投げることが多いので、ストレスになります。
サクっとforkしてPRをgh pr create --assignee @me --web
で生成して、
web画面で再確認したいのに、これはかなり鬱陶しいと前から思っていました。
調べた限りGitHub CLI自身のオプションでこれを避ける方法は見つかりませんでした。
gh repo set-default
のワンコマンド化まずはgh repo set-default
をインタラクティブな動作なしに済ませられるようにしました。
gh repo set-default
には当然引数を渡せてリポジトリを設定することも出来ますが、
owner/repo
の形式で渡す必要があるため、
cloneしてくると毎回違う引数を設定する必要があります。これを自動的にupstream
のリポジトリを設定するようにしたいですね。
これはシェルスクリプトで比較的容易に達成出来ます。
#!/bin/zsh
set -eu
# `gh repo set-default`で`upstream`の設定をインタラクティブに行うのが面倒なのでスクリプトで行えるようにします。
# `upstream`のURLを取得します。
upstream_url=$(git remote get-url upstream)
# `https://github.com/`の部分を削除して、`owner/repo`形式の文字列を得ます。
upstream_repo=$(echo $upstream_url|sed -e 's/https:\/\/github.com\///' -e 's/\.git$//')
# 得られた`owner/repo`を引数として`gh repo set-default`コマンドを実行します。
gh repo set-default $upstream_repo
git remote get-url
なんてコマンドは知りませんでした。
これを~/.zsh.d/bin/gh-repo-set-default-upstream
に保存しておきます。
gh repo fork
した時に自動で実行されるようにalias
を設定してそれを使うようにしました。
clone側に設定するのも考えましたが、単にソースコード見たくてcloneして、後から間違いとかを見つけてforkしたいとかのシナリオを考えて、 fork側に紐付けることにします。
alias gk='gh repo fork && gh-repo-set-default-upstream'
gf
は既に使用されていたためgk
にします。
色々とインタラクティブな部分は残ってたり、エラー処理をちゃんと行えている気がしないのが心残りですが、一回解決としておきます。
SWI-Prologには、 jamesnvc/lsp_server: Language Server Protocol server for SWI-Prolog というLSPサーバがあり、 lsp-modeにも、 Prolog - LSP Mode - LSP support for Emacs として公式にサポートされています。
swipl -g 'pack_install(lsp_server).'
としてインストールして、
(lsp-register-client
(make-lsp-client
:new-connection
(lsp-stdio-connection (list "swipl"
"-g" "use_module(library(lsp_server))."
"-g" "lsp_server:main"
"-t" "halt"
"--" "stdio"))
:major-modes '(prolog-mode)
:priority 1
:multi-root t
:server-id 'prolog-ls))
のように登録すればスムーズに使えるようになります。
しかし、 VSC-Prolog - Visual Studio Marketplace などの動きを見たあとにこれを見ると、定義されていない述語を報告してくれなかったり、かなり機能が貧弱と言わざるを得ません。
VSC-Prologの説明を見るとSWI-Prologの機能を使っているようなので、 Emacsでも似たようなものを使うことが出来るのではないかと思って調べました。
Program Development Tools には"Using GNU-Emacs"の項目があり、 Sweep: SWI-Prolog Embedded in Emacs というEmacs専用の開発支援機能があることが分かりました。
正確には開発支援機構に留まらず、 Emacs LispからSWI-Prologを使ったりすることも出来るようです。
これのセットアップに少々手こずったので、メモをしておきます。日本語文献が当然のようにない。
まず公式には手動でgit clone
しろと書いてありますが、流石にやりたくありません。
GitHubに載ってるため最初はel-get
を使おうかと思いましたが、
NonGNU ELPAにはパッケージがあります。
NonGNU ELPA - sweeprolog
melpaには載っていないようです。
これまでmelpa
とgnu
だけでやりくりしてきましたが、ついにnongnu
をリポジトリ一覧に追加する日が来たようです。
しかしsweeprolog
パッケージはEmacs側でインストールするだけでは動かないことがあります。
C言語のモジュールを使ってやり取りをしているからです。
Gentooだと普通にemerge swi-prolog
するだけで、多分minimal
とか設定されてなければ、
sweep-module.so
がインストールされるため余分なことは不要でした。
しかしUbuntuだとaptからインストールしたSWI-Prologではsweep-module.so
が入りませんでした。
アップデートへの追随とかを考えると、あまり手動でビルドをしたくないから、なんとかパッケージマネージャを使いたくなるのですが、とりあえず今回は早くSweepを動かしたいので妥協してビルド前提にすることにしました。
SWI-Prolog -- Installation on Linux, *BSD (Unix) を参考にビルドしてインストールします。
ビルドには様々なパッケージが必要です。
Ubuntuの場合は/etc/apt/sources.list
のdeb-src
のコメントアウトを外して、
apt-get build-dep swi-prolog
を実行すると良いでしょう。
コメントアウトを外してネットワーク通信を多くしたくない人は、素直に大量のapt-get install
をしても良いと思います。
root権限を必要とする箇所を不用意に変えたくないので、
/home/
以下にインストールする上のビルド方法を使うのですが、そのままだと変な感じにインストールされてしまうため、改変が必要でした。
変えた部分は、
cmake -DCMAKE_INSTALL_PREFIX=$HOME -G Ninja ..
の部分を、
cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local/ -G Ninja ..
に変えてxdg準拠にするだけです。これだと~/.local/bin/
を既にPATH
に入れているような標準的環境だと、
SWI-Prologの実行ファイルのPATH
は新規に通さなくて良いです。
ただしaptで入れた場合と違い、
prolog
コマンドは無くなってしまうようなので、
EmacsにSWI-Prolog特化しているという設定をするか、シンボリックリンクでも貼っておく必要があるでしょう。
私はSWI-Prologに特化していくことにしました。
(leaf prolog :custom (prolog-system . 'swi))
手動でインストールした場合だとライブラリパスが貼られないので、
sweeprolog-libswipl-path
を設定する必要があるかもしれません。私の場合は設定しなくても実行バイナリからの繋がりなのか接続できましたが、人によっては"~/.local/lib/swipl/lib/x86_64-linux/"
のように設定する必要があるかもしれません。
これで(sweeprolog-mode)
を使えるようになりました。
端的にしか説明してなかったのと、日本語資料がなくてちょっと戸惑ってしまいましたが、方法としては普通でしたね。
Sweepはデフォルトではflymakeを使うようですね。普段flycheckを使っているので出来ればflycheckにしたいです。
lsp-modeの普及で基本的にセットアップが不要になったので、 flycheckからflymakeに回帰しても良いのではないかと思うときも度々ありますが。
軽く調べた所Sweepがflycheckを直接サポートしていることは無いようです。
flycheckがflymakeのラッパーをやれば良いのではないかと思って少し調べたのですが、そう簡単な話でもないらしいですね。
仕方がないのでflymakeの設定を以下のようにしておくことにしました。
(leaf flymake
:bind (:flymake-mode-map
("C-z" . flymake-show-buffer-diagnostics)
([remap previous-error] . flymake-goto-prev-error)
([remap next-error] . flymake-goto-next-error)))
(sweeprolog-top-level)
名前とキーバインドがEmacsの風習から少し外れていたので少し気がつくのに時間がかかりましたが、
(sweeprolog-top-level)
で普通にREPLは起動できました。
これでVSCodeのVSC-Prologと同程度、いやそれ以上かもしれない開発支援を手に入れました。これでインタプリタ開発のためのテストコード記述などが少しは捗ってくれるでしょう。
sweepが一定のPrologソースコードでクラッシュして、クラッシュするソースコードとしないソースコードがあるので不思議に思いました。とりあえずスタックトレースを見るとswipl
が関わっているのでGitHubで報告をしました。
Emacs crashes with segv when opening library/clp/bounds.pl
in Emacs with sweep enabled · Issue #1188 · SWI-Prolog/swipl-devel
報告したら開発者が調査してくれて詳細はよく分からないんですが、
Emacsのxwidgets機能を有効にしているとクラッシュするらしいです。とりあえずビルドの./configure
から--with-xwidgets
を抜いて凌ぐことにします。今の所WebKitの機能そんなに使うことないですしね。
SWI-Prologの開発者さんの努力でクラッシュ問題は解決しました。
C言語追いかけるのが面倒なのとSWI-Prologのソースコードがそれなりの大きさであることで完全には把握してないんですが、どうもxwidgetのWebKitとSWI-PrologのGUI機能でシンボルが衝突してクラッシュしてたらしいです。