今日は小さいツールを2つほど作って,ちょうど700行コードを書いた。 まあ空行とかコメント(ほとんどない気がする)も含まれるのであまり意味のある数字ではないけど。
1つはパイプラインの中で標準入力をテキストエディタで編集して標準出力に流すというもので, なんかこんなのすでにシステムにインストールされたりしてそう……。 作っている時はパイプラインの中で使うという発想があまりなかったし, あまり機会がある気がしないが,ヒアドキュメントとかヒアストリングとかを意識して hereed というゴミみたいな名前にした。
もう1つは Wake-on-LAN のユーティリティで,0個以上の予め登録したホストを 同時に Wake-on-LAN できるというものだ。 送るホストを選ぶところは,以前にテキストエディタを作った時の 端末の制御の知見があったので,それが使えた。non-canonical mode にするとか, エコーバックを無効にするとか。 まあ知ってれば何も難しいことはないけれど。 設定ファイルが json なのが Unix のツールとしてイケてないと思うけど, 設定の構造的に json が都合が良かったのでまあ使った。
なんか /var/log あたりを見ても syslog がないな,と思っていたら, systemd がすごい syslogd をやってるらしい。systemd 肥大化しすぎでは……。
で,そのログを見るには,
$ journalctl とかする。
でも,これは保存されているログが古い方から全部出てしまうのでたいていの場合は用途に合わない気がする。 僕の場合は 12 月のログとかが最初に出てきてうーん,となった。 たいていの場合はログは新しい方から見たいんではないかと思うので,そういう場合は,
$ journalctl --reverse とかすると,新しいものから表示してくれる。
あと --grep オプションとかもあって,
$ cat /var/log/syslog | grep foobar みたいにやってたところを 1 つのコマンドで済ませられるっぽい。うーん,でもこれはなんかなー。
他には --since とか --until とかもあるっぽいけど,syslog.1 とかの方がなんとなく好きだったりします。
久しぶりに触った。例によってマップの実装に使った訳だが。
プラウザの履歴をゴニョゴニョできる API だが,適当に使うのは割と簡単。
history.pushState(null, null, '?foo=bar'); みたいな感じで URL のクエリを書き換えたりとかできる。 MDN を見たら第一引数と第二引数にいろいろ渡していたが,めんどくさいので null でよさそう。
書き換えを listen する方は,
window.addEventListener('popstate', () => { // なんか処理 }); とかでよさそう。これが呼ばれたときには URL が書き換わっているので, それを location.href とかで取ればよさそうな気がする。 真面目にやるなら push したときの値を受け取って使う感じになるんだろうけど。
onload と同時に popstate が起こるブラウザもあるらしい。怖いよ〜。
参考 https://developer.mozilla.org/ja/docs/Web/API/History_API https://qiita.com/nenokido2000/items/2dd8da77d06837c8a510
ブロックの高さと名前が出せるようになった。 パーサーをサーバーとして実行てきるようにして,PHP で Unix ドメインソケットで話させる みたいな感じにした。
サーバーの実装だけど,最初 wait してなかったせいで,大量のゾンビプロセスを作ってしまった。 これは,犠牲となる子プロセスを作ったあと,そのプロセス内でプロセスを立ち上げて レスポンスを返す感じにして,即座に終了する最初の子プロセスをwaitするようにして解決した。
これは GNOME に限らず,XDG 準拠のデスクトップ環境ならどこでも使える気がするんですが。
基本的にデスクトップエントリーのファイルは /usr/share/applications か /usr/local/share/applications に作ればいいと思うんですが,権限がないときとか, システムワイドにインストールしたくない場合とかがある。そのときは ~/.local/share/applications に置けばいい。~/.local は /usr/local に対応していると考えていいっぽいです。
あと,アイコン。デスクトップエントリーのファイルでは,Icon というキーでエントリー用のアイコンを 指定できるんですが,これは,テーマごとのアイコンのディレクトリから探索されます。 で,システムにインストールする場合は, /usr/share/icons か /usr/local/share/icons に 置けばよくて,ユーザーの場合は ~/.local/share/icons に置けばいい。 icons 以下にテーマのディレクトリがあるんですが,だいたいのテーマは hicolor を継承しているので, /usr/share/icons/hicolor に置けばいいみたいです。 そしてこれはちょっとハマったんですが,48x48 のアイコンは必ず準備しないと,他の解像度のを用意しても アイコンが認識されないみたいです。あと,画像のファイルは icons/テーマ/解像度(e.g. 48x48)/apps に置く。解像度のディレクトリに直接置いても認識されないです。
今更ながら,技術評論社の Software Design を買い始めてみた。 前々から気になってはいたのだが,こういうのは一回買ったら毎回買わないといけなくなるので 今まで買わないでいた。 あと,今まで調べてなかったけど,年間購読にするとちょっとだけ安くなるみたいなのも あるっぽい。
一月は行く,二月は逃げる,三月は去るみたいな,この時期にありがちな,でもちょっと早いような話をしつつ……。 でももう二月なんで早いですよね。まあそんなことはどうでもいい。
こないだ作った Minecraft のマップ画像を生成するやつを C++ で書き直し始めてみたりした。 でもまあ今日はそんなに作業できなかったのでほとんどヘッダファイル書いたら終わったみたいな感じだけど。 もともと Python で書いていたやつは anvil-parser というライブラリを使っていて, そのライブラリは NBT なる Minecraft の独自バイナリ形式のパーズには nbt という別のライブラリに 任せているっぽかった。nbt というライブラリのリポジトリを見に行ってみたら,チャンク読むところとかも実装されていて, なんかマップを生成する example も存在したんですね。うーん。まあいいやろ。 で,anvil-parser ってのはそのライブラリのチャンクの実装とかは使ってなくて, その部分は独自でやってるみたいでした。まあ古い形式にしか対応してなさそうだったのでそのせいかな, という感じがします。
最近,というかここ1年くらい Android アプリは全然作ってなくて, 今ストアにあるやつもフェードアウトしつつある。でも意図せずタイトルが釣りになっているのか, SecureScreen というアプリは少しではあるが,毎日コンスタントにダウンロードされてるっぽかったので, 消されないように注意しつつ見守っていた。でも,アクティブに Android やってないと気づいたら消されているので, そのたびに Google Play Console を開いてストアの掲載情報をアップデートするのはかなり面倒くさい。
で,今回は12月くらいに削除したぞとメールが来ていて,面倒なので放置していたのだが, ついに今日,掲載情報をアップデートした。今回のはよくいつものに増してよく分からなかった。
ただ,アクティブに開発してないといつの間にか消されているシステムは必要なのかなと思ったりもしていて, それはなぜかというと,アクティブに開発されていないアプリは UI はさることながら使ってた API も古いものになっていき,ストアにゴミがあふれる結果になる気がするからだ。 そういう意味では,過去1年にアプリのアップデートがない場合は削除するみたいな仕組みを作ってもいいような気がする。
PAM で遊んでみた。PAM ってのは Pluggable Authentication Manager の略らしく, Linux のユーザー認証のしくみで,これの設定次第でユーザーが自由に認証の方法を変更できる。 例えばパスワード認証の代わりに指紋認証を使いたいみたいな場合もこの PAM のモジュールで実現できるはず。 当たり前だが,設定次第で認証システムを破綻(?)させることも可能で,常にログインできる PAM モジュールを使ってパスワードなしでログイン可能にしてしまったり,逆に絶対にログインできない PAM モジュールで全ユーザーを締め出したりもできてしまう。てなわけでまあ割とヤバイ部分で遊んだ。
PAM のモジュールを書くのはとても簡単な部類で,常にログインできるやつとかだと下みたいなコードで できたりする。
先日作った Minecraft のマップ画像を生成するやつが遅すぎる(7min/region)のをなんとかしたいので, Python で並列処理をする方法を調べて使ってみた。
Thread concurrent.futures.ThreadPoolExecutor を使うというもの。別に pool 使わなくてもいいけど。 でもまあ pool 使った方がいいでしょってことで。
この方法では結局 GIL のせいか全然速くならなかった。むしろ遅くなった。たしか 11min/region とかになった気がする。
Python で Thread を使うのは,主に IO がネックになってる場合っぽい。IO の待ち時間は GIL が解除されるけど,その他の状況では GIL のせいで並列処理というよりむしろ 並行処理になってる。
Process concurrent.futures.ProcessPoolExecutor を使うというもの。 fork できる環境(主にUNIX 系の OS?)ではデフォルトで fork になるって書いてあった。 これがなかなか速くて,なんでか 2 つしかプロセス起動してないのに半分未満の時間で処理できた。 Windows とかでは fork できないから遅いのかもしれないけど,Windows 使ってないのでよくわからない。