My Browser Profile Chooser 3.0 released!

My Browser Profile Chooserが3.0になった

1.x, 2.xではZshスクリプトだったが、Rubyスクリプトに変更され、プロファイル設定は2.xのZsh関数として定義する形からYAMLで書く形になった。

3.xでの非互換変更を行った理由だが、設定を書くのが面倒だったからである。 互換性のため、2.x系も別のブランチとして残っている。

コード的にも簡単すぎてあまり見るべきところがないので、今回はリリース報告だけ。

mpv * Linux でハードウェアビデオアクセラレーション

この話は

  • 各ビデオカードにはビデオエンコード/デコード支援チップが載っている
  • QSVとかUVDとかVCEとかNVENCとかNVDECとか名前がついてる
  • Linux的にはVDPAUとVA-APIというAPIがある
  • Nvidiaの場合はNVENC直 (NVDEC直も可)
  • CUDAを使ったCUVIDってのもある
  • mpvで再生支援するのが便利

っていうのは理解しているという前提で始まる。

それは、「結局渡すべきパラメータはなに?」って話である。 なお、VDPAU及びVA-APIは有効である前提で話す。それがわからない人はArchwikiへGo

はじめに

mpvを使うと非常に便利で、

$ mpv video.mp4

みたいな話なんだけれども、mpvには--hwdec--voというオプションがあり、ハードウェアビデオアクセラレーションを行う場合はこれらを指定する。

で、--hwdecは話としては簡単だ。ハードウェアデコーダを使うという話。つまりはコーデック的な話。

じゃ--voは? という話になるのだが、これは「ビデオ出力ドライバ」の指定。 なんじゃそら…という感じなのだけれど、「エンコードと描画レイヤーは別の話」みたいなことらしい。 だからSDLとか、Direct3Dとか出てくる。 YUVビデオとかそのまま書くんじゃないの?とかいう気持ちになったけれど、そんなことはないようで、「ハードウェアでデコードしたらハードウェアで書くところまでしないと効果なし」みたいな話になるようだ。

とはいえ、--vox11なんてすると凄まじくCPU負荷が増えてしまうし、xvを使う理由も全くない。 だから現実的な選択肢としては、vdpau, vaapi, gpuの3つだ。

試してみる

vdpau + vdpau

VDPAUでデコードしてVDPAUで出力する、というのは悪くないようだ。

ただし、この場合ポストプロセスはVDPAUでやることになる。 VDPAUはポストプロセスに対応しているからできるのだけど、一部使えなくなるものもある。例えば、ズームは効かなくなる。

vdpau + gpu

VDPAUで出力するよりも軽い。

そしてフィルタ等はすべて使える。

vaapi + vaapi

ちゃんとアクセラレーションが効いて軽くなるけれど、エフェクト、フィルタなどは一切使えなくなる。 マニュアルにも、だめなシステム向けだと書いてある。

vaapi + gpu

VA-APIだと--vogpu指定にすべきなようだ。

ちなみに、VDPAUだと--voを書かなくても十分アクセラレーションが効くのだけど、VA-APIの場合は--vo必須。

NVDEC / CUVID

--vogpu一択。ほかはそもそも使えない。

結局…?

Intel

alias mpv='mpv --hwdec=vaapi --vo=gpu,vaapi'

AMD, Nvidia (nvドライバ)

alias mpv='mpv --hwdec=vdpau --vo=gpu,vdpau'

Intel同様にVA-APIを使っても構わない。 ただ、再生だけを考えるならVDPAUのほうが少し良い感じがする。

nvドライバ環境でハードウェアビデオアクセラレーションすべきかどうか自体が疑問。

Nvidia (nvidiaドライバ)

alias mpv='mpv --hwdec=nvdec --vo=gpu --profile=gpu-hq'

NVDEC直のほうが速い。

gpu-hq

通常の--vo=gpuはフェイルセーフで、--profile=gpu-hqすると品質優先、とのことなのだけど、 試してみた限りでは、特にgpu-hqして問題になるケースは見つからなかったので、--profile=gpu-hqつけても良いかもしれない。

その場合はfallback用に指定しているvaapivdpauvoは必要ないというか、つけないほうが良い。

私の設定

alias mpvpau="mpv --loop-playlist=yes --hwdec=vdpau --vo=gpu --profile=gpu-hq --prefetch-playlist=yes --video-latency-hacks=yes --osd-font='Fira Sans' --osd-font-size=23 --sub-font='MotoyaLCedar' --sub-font-size=32 --sub-blur=3.5 --script=playlistmanager --script-opts=playlistmanager-loadfiles_on_start=yes"
alias mpvva="mpv --loop-playlist=yes --hwdec=vaapi --vo=gpu --profile=gpu-hq --prefetch-playlist=yes --video-latency-hacks=yes --osd-font='Fira Sans' --osd-font-size=23 --sub-font='MotoyaLCedar' --sub-font-size=32 --sub-blur=3.5 --script=playlistmanager --script-opts=playlistmanager-loadfiles_on_start=yes"
alias mpvnv="mpv --loop-playlist=yes --hwdec=nvdec --vo=gpu --profile=gpu-hq --prefetch-playlist=yes --video-latency-hacks=yes --osd-font='Fira Sans' --osd-font-size=23 --sub-font='MotoyaLCedar' --sub-font-size=32 --sub-blur=3.5 --script=playlistmanager --script-opts=playlistmanager-loadfiles_on_start=yes"
alias mpvcud="mpv --loop-playlist=yes --hwdec=cuda --vo=gpu --profile=gpu-hq --prefetch-playlist=yes --video-latency-hacks=yes --osd-font='Fira Sans' --osd-font-size=23 --sub-font='MotoyaLCedar' --sub-font-size=32 --sub-blur=3.5 --script=playlistmanager --script-opts=playlistmanager-loadfiles_on_start=yes"
alias mpv="mpv --hwdec=auto --vo=gpu --sub-font='MotoyaLCedar' --sub-font-size=32 --sub-blur=3.5"

playlistmanagerスクリプトを使っている。 単独のmpvコマンドだけが単一ファイル用。

Git/Mercurial/分散バージョン管理システムの基礎

Gitに関する話をするとき、「ん???」となることがまぁまぁある。

で、多くの場合よく考えれば「GitHubの概念に引きずられている」ものが多いように感じる。

今回は、Git、そしてMercurialを含めて分散バージョン管理システムに関する概念と用語を、簡潔・明瞭に説明したいと思う。 なお、Bazzrその他に関しては私は使ったことがないので、分散バージョン管理システムの説明といいながら、GitとMercurialだけで進めさせていただきたい。

概念に関するもの

リポジトリ

恐らく、用語としてはこれが最も難しい。

「リポジトリとは歴史である」などといったりするのだが、どうも各々の定義にぶれがある。

であるから、Gitの場合は、.gitディレクトリ、あるいは*.gitディレクトリ(ベアリポジトリ)のことを指していると思えば良い。 また、.gitがあるディレクトリは「ワーキングツリー」である。

Mercurialの場合は.hgディレクトリを指す。

これは単にファイルであるだけではなく、ファイルの変更などを管理するための情報をもち、実際に管理することができる。

ローカルリポジトリ

ローカルリポジトリは、ワーキングツリーから見て、そのワーキングツリーが所属するリポジトリ(つまりは、ワーキングツリー先頭の.gitあるいは.hg)を指す。

ローカルリポジトリという語が出てくるのはリモートリポジトリに対する対比である。 なぜならば、リポジトリの操作はローカルリポジトリ(ワーキングツリー)上で行うため、「手元側」を意味することになるからだ。

リモートリポジトリ

リモートリポジトリは、ワーキングツリー、あるいはリポジトリから見て、自身ではないリポジトリを指す。

リモートリポジトリは一般的にはローカルリポジトリに対して何らかの関係性を持つ。ただし、持たない場合もある。 何らかの関係性とは、ローカルリポジトリがリモートリポジトリのことを登録しているか、リモートリポジトリがローカルリポジトリのことを登録しているかを指す。

「リモート」といっても、あくまでも「このリポジトリの外」の意味であり、ネットワーク越しであることを意味するわけではない。 むしろ、最も基本的なGitやMercurialの運用においてはリモートリポジトリはファイルシステム上にあるほうが普通であり、ネットワークにおけるリモートを指してはいない。

また、場合によってはそもそもローカルリポジトリ上で登録されたリポジトリのことだけを指してリモートリポジトリと呼ぶ場合もある。

コミット

リポジトリによって管理されるファイルのある状態の記録である。 GitやMercurialの変更は連続的に記録されるわけではなく、コミットした瞬間ごとが記録される。

コミットは本質的にリポジトリへの書き込みである。 このことから、最終的な修正が反映される権威リポジトリが存在する場合、その権威リポジトリに対するpush、あるいは権威リポジトリ上でのコミットを「コミット」と呼ぶ場合がある。 この場合、「そのリポジトリを更新する行為」を指すのであり、その行為をしうる者を「コミッタ」と呼ぶ。

ステージング

Mercurialにはない、「コミット候補」。

基本的にはGitの場合、ステージされたものはステージされた状態で保たれ、コミットされる。 ステージされてからコミットされるまでに変更は加えられないので、「コミットする前に考える」段階があると考えて良い。

実際のところ、ほとんどの場合ステージングは省略されている。

HEADはGit独自の概念である。

HEADは コミットを指している訳ではない 。 HEADはあくまで位置である。

リポジトリがリモートリポジトリと同期される関係にある場合、リモートリポジトリと同期した位置というものが記録されている。 HEADは全体で一番最後にコミットされた位置である。

コミットを取り込む場合、取り込む側(つまり、それによって変更される側)のほうがHEADの位置が前にあってはいけない。

フォーク

フォークは分散バージョン管理システムにおける用語ではない。

フォークは(由来は置いておくとして)ソフトウェアを複製し、複製元とは異なる未来を歩むことを意味する。

分散バージョン管理システムにおいては、行為としてはcloneすることがまさにforkすることを指す。 ただし、cloneした後に異なる未来を歩み、それを元のリポジトリに反映する場合や、恒常的に元のリポジトリの変更を反映する場合はforkしたとは言えない。

先割れしたフォークの先端が交わることはない。forkは決別なのである。

ブランチ

ブランチの概念はソフトウェアによって随分違う。

Gitの場合はあくまで歴史の分岐である。 ブランチを作ることでブランチ作成の起点になるコミットから、他のブランチに影響されることなくコミットを作っていける。

Mercurialの場合は、ブランチは位置情報になっている。 枝分かれしているというよりは、同じように時間が流れる平行世界みたいな状態である。

両者の大きな違いとして、Gitはブランチを作ったらそのまま完全に違う未来を歩んでもいいので、最初のブランチであるmasterブランチにそこまで特別な意味がない。 対してMercurialの場合は一種のコミットのような扱いになり、ブランチは最終的には取り込まれるか、クローズして捨てられるかすることを想定している。 だから、Mercurialの場合はdefaultブランチが本命である。

なお、Gitのmasterブランチは基本的に進んだHEADを持っているので、masterブランチをリリースブランチにするのはちょっとまずい。 リリースブランチは別に切るべきだ。 対して、Mercurialは一番進んだコミットを持つdefaultに合流するようになっており、あんまりリリースのことは考えてない感じになっている。

また、ブランチの大きな違いとして、Gitはブランチは削除できるが、Mercurialは閉鎖できるだけで削除はできない。 どうしても削除したい場合は方法がなくもないが、それはそれでMercurialでは本来禁止されている歴史操作を使ってそのブランチの世界線にあるコミットを全て消滅させるというすごいことをすることになる。

さらにもうひとつ大きな違いとして、Gitの場合ブランチは個々のリポジトリに属している。明示して送りつけない限りはpushあるいはpullするのはブランチ単位である。 対してMercurialは全てのブランチが共有される。だから、Mercurialでのpushあるいはpullするのはリポジトリ全体である。

競合 (conflict)

バージョン管理システムにおいて最も重要なのは、「同じファイルを同時に変更することに対して保護する」である。 古代のバージョン管理システムであるRCSでは、「変更可能な状態で持ち出せるのは1ユーザーだけ」という方法で管理していた。

GitもMercurialも、基本的には同一ファイルに対する変更を競合とみなす。

ただし、Gitの場合は変更点が重複していなければ競合にはならない。 Mercurialの場合は変更点が重複していなくても同一ファイルに対して変更していれば競合になる。

ただし、Mercurialの競合はそもそも歴史が割り込まれた時点で発生するため、こっちも向こうもそれぞれにコミットしたんだよね、という状態になったら確実に競合が発生する。 この変更が統合可能なのであれば、mergingという扱いにはなるものの、実際にはmergeは必要なく、単に「歴史を統合したコミット」を作れば良いようになっている。

ここらへんはGitのほうがきっちりしていて、Mercurialの場合はそれぞれが無軌道に変更を加えているとえらいことになる。 Gitではそもそもpush可能なのはベアリポジトリだけなのに対し、Mercurialではベアリポジトリという概念がなく、リポジトリは須らくワーキングツリーを持っているという考え方になっている。 でも、複数人で作業するような場合はワーキングツリーに対する変更を加えない、つまり自分でコミットを作成しないリポジトリを作ってそこにpushするようにしておかないと混乱を招くことになる。

pull request

pull request (通称プルリク)は、GitでもMercurialでもなく、 GitHubの機能である。 ちなみに、GitLabでは “Merge Request”という名前で同種の機能がある。

リポジトリに対してpushするためには、当該リポジトリに対する書き込み権限が必要である。 読み取り権限があればcloneできるため、cloneされるリポジトリは所有者が異なる可能性があり、元のリポジトリに対する書き込み権限がないことも少なくはない。

もちろん、書き込み権限があるのであれば当該リポジトリに対してpushすれば良いのだが、ない場合は当該リポジトリの書き込み権限を持つ者にpullしてもらうことになる。 しかし、その場合「pullしてほしい」と伝えなくてはならない。これを、「pullして欲しいと伝えて、変更点を明確にして、ついでにボタン一発でpullできるようにしたもの」がPull Requestである。

これに関しては誤解が深く、GitHubでGitを触り始めた人がだいたい混乱している。

アクション

init

リポジトリを作成すること、だが、どちらかといえば「今いるこの場所をリポジトリにする」のほうが実態を指している。

ただし、Gitにおいてはgit init --bareがあるためそうとも限らない。 この場合はベアリポジトリを単純に作成する。

このアクションはローカルリポジトリが存在しない状態で行う。

clone

リモートリポジトリの複製を作成する。

このアクションはローカルリポジトリが存在しない状態で行う。

push

ローカルリポジトリのコミットをリモートリポジトリに書き込む。 リモートリポジトリの書き込み権限が必要である。

pull

リモートリポジトリのコミットをローカルリポジトリに書き込む。 リモートリポジトリの読み取り権限が必要である。

add

基本的にはワーキングツリー以下のファイルをリポジトリの管理下に加えるアクション。

Gitの場合はステージングの際にも使用する。

Mercurialの場合、ワーキングツリー以下で明に除外されていないのに管理外にファイルがあることは望ましい状態ではないと考えるため、addの手順はまぁまぁ省略される。 Gitでは省略はできない。

merge

Gitにおいては異なるブランチを取り込むこと。

Mercurialにおいては、割り込みの発生した歴史を一本にまとめたコミットを作ること。

reset / rollback

resetはGitにおけるアクションで、ステージされたファイル、あるいは最新のコミットを取り消す。

Mercurialでは最新のコミットを取り消すrollbackがあり、Mercurialではコミットの歴史を操作するアクションはこれが唯一。 ステージして慎重にコミットするGitと違い、Mercurialは一発でコミットをキメてしまうため、rollbackは結構よく使うし、実際に簡単に使えるようになっている。

revert / backout

revertはGitとMercurialで全く意味が違う。

Gitにおいてはコミットを取り消す。この場合、そのコミットにおいて行われた変更そのものを元に戻す。 Mercurialは歴史を変更することはできないので、あるコミットで行われた変更を元の状態に戻す変更を加えたというコミットを作成する。それ用にbackoutというアクションがある。

Mercurialのrevertはワーキングツリーのファイルをコミットの状態に戻すことを指す。 これはGitであればgit checkout <commit> <file>に相当する操作である。 Gitのcheckoutはこれとは全く異なる「ブランチの切り替え」という機能も兼ねており、少々わかりにくい。

Gitには他にも歴史操作に関するアクションがあり、特にrebaseはまさに歴史修正主義者のためのコマンドである。

あんまり知られていないが、Gitにはblameという大変便利な歴史チェックコマンドがあったりする。 そして、実はMercurialにも似た感じのことができるannotateというコマンドがあり、hg annotate --user --numberとやればblame相当になる。

「revertするぞ」と言われたら、「お前のコミットは問題があるからなかったことにする」という意味になる。 例え実際にはMercurialを使っている場合でも「backoutするぞ」じゃなく「revertするぞ」と言う場合が多い。

diff

何か(コミット, タグ, ブックマーク, e.t.c.)の間でファイルの変更を比較するアクションである。

実はGitのdiffはGitリポジトリ外でも使うことができる。

diff -uと同じだろ?何が嬉しいんだよ」と思うかもしれないが、実はGit diffはインラインで変更を表示することができるのだ。 これがすごく便利。

stash

ワーキングツリーに対する変更を保留にするGitのアクション。Mercurialには全く存在しない。 ほとんどの場合、「作業すべきブランチを間違えた」という場合に別のブランチに変更を持っていくために行う。

すごく便利である。 そもそも、ブランチに関する操作はMercurialよりGitのほうがずっとやりやすい。

Manjaro Linux, Arch Linux共にDiscordがCommunityパッケージに

AURからなくなったDiscordの行方

先日の記事でDiscordがAURから削除され、Snappyを利用するように変更されたということを記事にしたが、2018-08-13 MANJAROのstable updateでcommunityパッケージに追加された

もう少し解説

ManjaroのリポジトリはArchとは独立しており、そのパッケージングポリシーも少し違う。 一方でArchのユーザー投稿リポジトリであるAURのパッケージのほとんどが利用できる程度には互換性がある。

原則として、AURにはArchの公式パッケージとして存在するものは投稿できないし、AURのパッケージがArchのパッケージになる場合、AURから削除される。 一方、Manjaroにおいてはもっと広く、「多くの一般ユーザーが欲しがるパッケージ」が公式パッケージに加わっているため、AURと重複するパッケージというのが存在している。これは時々トラブルの元になる。 例えば公式パッケージから削除されたときにAURパッケージがインストールされてしまうなどだ。

今回のAURからの削除は、重複するパッケージを設置しないというArchのポリシーに基づき、Snappyによってインストールすることを推奨するものかと推察された。 これに対しManjaroがAURから削除されたパッケージを「必要としている」と判断して独自にDiscordをパッケージングしたという理解だ。 だが、実際にはArchのほうもcommunityパッケージとしてDiscordが追加された

extraではなく、サポートの手厚いcommunityパッケージというのは驚きだが、これは「LinuxerにとってコミュニケーションツールはDiscordが標準となっている」ということでもあるのだろう。

やはりSnappy版よりもフォントレンダリングをはじめ全体的に良いので、よかったと思う。 ちなみに、Discord自体、最近debパッケージだけでなくバイナリパッケージも配布している。

Manjaro/Arch Linux, DiscordがAURから消滅 Snappy利用に …Snappy?

重要な追記

新しい記事に状況の更新が書かれている

あらまし

Manjaro Linuxの2019-08-07のツイートによれば

We are happy to announce the availability of @discordapp @ManjaroLinux. Read more about it on our forums: https://t.co/XbuhEJCFUC https://t.co/MH7Pjhn6EH

というわけで、なんかDiscordの扱いが変わったらしい。

というわけでAURを見てみると…AURからDiscordがなくなっている! Extra行きでもない!!

で、フォーラムを見てみると「Snappy使えよ」ということになっている。

Snappy?

Sanppy

SnappyについてはWikipediaに既に記事がある

Snappyとはカノニカルが設計・開発したソフトウェアデプロイメントシステムかつパッケージ管理システムであり、元々はUbuntu Phoneオペレーティングシステム用に設計・開発された。

a-ha?

ちゃんとArchwikiにも記事がある。 そして、snapcraftのサイトにManjaroについての記述がある

が、どれも後述するようにちょっと微妙である。

簡単に言えば、パッケージがライブラリとか全部含めてSquashFSにしてあるのでディストリビューションごとの調整とかいらないよ、という話である。

はっきりいってしまえば、いわゆるポータブルアプリである。 こういうの、前からちょいちょいあった。そして、いろんな意味で微妙なのである。

一番の理由は容量をえらいとる、というのがある。 管理がばらつくとか、制御しづらいとか、パッケージの信頼性が担保しにくいとか、他にも理由はたくさんある。

インストール

必要なのはcommunityパッケージのsnapd

$ sudo pacman -S snapd

snapdをenableしろと言っているが、snapdが必要なのはパッケージ操作時のみ。

$ sudo systemctl start snapd

Discordをインストール。結構長い。

$ sudo snap install discord

パッケージ操作はもうしないのでsnapdは止めてしまって良い

$ sudo systemctl stop snapd
$ sudo systemctl stop snapd.socket

起動と感触

Snappyを使って起動する。snapdは必要ない。

$ snap run discord

起動すると、フォント選択とフォントレンダリングに少し違和感があること、カーソルが異なるものになってしまうことが気になる。 あと、Cinnamon上でアプリケーションアイコンが表示されない(systrayには表示される。これは.desktopファイルの設定によらず改善しない)。

また、アプリケーションアイコンのコンテキストメニュー(通称デスクトップメニュー)に機能しない “New Window” がある。

使えないわけではないけど、やっぱりいまいちだ…

(2019-08-12 追記)

システムを再起動したところ

  • アイコンは出るようになった
  • discordコマンドで実行できるようになっている (/var/lib/snapd/snap/bin/discordを呼んでいる)
  • カーソルとフォントは相変わらず
  • .desktopメニューに“New Window”があるのは相変わらず。[Desktop Action]は定義されてないけれど
  • systrayのDiscordアイコンクリック時に“Top Secret Control Panel”が出る。これは右クリックの挙動で、クリック時はwindow activateされるのが正しいはず

Snappyについて

Manjaroの場合AURにDiscordがあったので、それを前提にするのであれば大幅な後退であるというのが基本的な印象だ。

しかし、それはちょっと傲慢過ぎる。

Arch LinuxやManjaro Linuxの場合、ほとんどのソフトウェアはAURにあり、そのいずれも(Launchpadと比べても)クオリティが高く調整が行き届いている。 だが、現実には依然としてバイナリのみの配布となっていて、Ubuntu向けdebパッケージのみが配布されているケースはかなり多い。Discordもそうである。

このようなソフトウェアの存在のために現実的にはUbuntuパッケージが使えるUbuntu系列のディストリビューション、AURで調整されているArch系列のディストリビューションぐらいしか選べないという状況が出来上がる。せいぜいがFedora。 実際にopenSUSE, Mageia, Sabayon Linux, PCLinuxOSを使っていたときは使えるソフトウェアに著しい制限がかかる状況であった。

そうした状況は健全とはいい難いため、そのようななんらかのポリシーによって限定的なパッケージでバイナリ配布されるソフトウェア1が広くディストリビューションを限定せずに利用できる、という意味ではSnappyによってサポートされるというのは悪い話ではない。

だが、Snappyに統一されるべきかというと、ちょっと首肯は難しい。 Snapcraftがどれだけメンテナンスされるか、きちんとチェックされるかというところで、やはり信頼感はかなり差がある。Launchpadが結構ひどく、AURがほとんどのパッケージはちゃんとしていることを考えるとやはりAURで欲しい。クオリティ的にもSnappyがいまいちであることを考えるとSnappyを理由にAURからドロップするのは結構残念な気持ちになる。

余談だが、Ubuntu向けdebパッケージで提供されるっていうのは結構扱いにくい。debパッケージはちょっと特殊なので、PKGBUILDを書いてリアッセンブルするのが割と手間なのだ。specを変換するだけのRPMのほうがずっと楽だろう…と私は思うのだが、なぜかAURのパッケージ群はRPMがあるソフトウェアでも大抵debをリアッセンブルしているので、ひょっとしたらこれは私の認識が正しくないのかもしれない。


  1. 「バイナリ配布だから限定的なパッケージである」という理解は間違っている。例えばFirefoxはLinux向け完パケバイナリが存在し、ポータブルアプリとして実行可能である。↩︎

最小限の環境を作る「フォントえらび」

私は基本、4台のコンピュータを運用している。これはまんま「3部屋+携行」なのだが、それぞれの最終システムインストール日を見ると

  • ThinStation P720 (2019-01)
  • FM2A88X (2017-12)
  • Z400 Workstation (2019-07)
  • ThinkPad X1 Carbon 5thGen (2018-06)

である。ちなみに、これはjournalctlすれば分かる。

システムセットアップ時に悩ましいのがフォントだ。 ここではManjaroを前提にして語るが、日本語フォント関連のパッケージは“font japanese”で検索すると62ほどあり、うち公式パッケージは源ノ角ゴシック、源ノ明朝、IPAフォント、花園明朝、さざなみフォントである。

フォント関連のAURパッケージはあまりメンテナンスされないことが多く、多くのフォントを維持するのはかなり厳しい。インストール時間もかかるので入れるのもしんどい。 ひとつにまとめて、それを/usr/local/share/fontsなどに入れて運用する方法もあるのだが、商用フォントの除外という手間もあるし、OS側(/usr/share/fonts)との兼ね合いもディストリビューションが違ったりすると特に発生しがちなので割と難しい。

なにより、「フォントの数」と「画面の総ピクセル数」は ものすっごく 反応速度に影響するのだ。遅い遅いと思っていたマシンをまっさらにして1366*768なディスプレイをつないだら爆速になったりしている。 だから、メインマシン(もしくはフォントを使うようなアートワーク作業をするマシン)だけにフォントを積んで、他はessentialに運用したい。

ここでは私の経験に基づいてよいと判断したessentialを紹介するが、好みによることはご了承いただきたい。

先に結論

% trizen -S adobe-source-han-sans-jp-fonts adobe-source-han-serif-jp-fonts ttf-cica ttf-ume
  • 商用フォント顔負けのクオリティで出せる源ノ角ゴシック、源ノ明朝
  • zsh-theme-powerlevel9kpowerlineを入れた場合に必要になるpowerlineシンボルなどまでカバーし、日本語コーディングフォントを必要する場合に有用なCica
  • MS日本語フォントにメトリック互換の梅フォント

という構成である。

好みのちょい足し

もう少し意味を補強すると、IPAフォントがあるとLibreofficeで文書をやりとりするようなケースでは有効である。 IPAフォントは公式パッケージなのでインストールしてもいいかもしれない。

さらにいえば、コーディングフォントは日本語フォントである必要はなかったりする。 私が様々なコーディングフォントで様々なコードや文章を書いた経験で言えば、長時間使っていて快適性が高かったコーディングフォントは

  • Hermit
  • Input Mono
  • Fira Mono
  • Meslo
  • Camingo Code
  • Roboto Mono

だった。

あと、私は個人的にMiguも好きなので、

% trizen -S otf-ipafont ttf-migu otf-hermit

好みのちょい盛り

ひょっとしたらスタイリッシュな欧文フォントがないことが不満かもしれない。 定番としてはSenとかだったと思うのだけれど、今SenはGoogle Fontsから外れてしまった。 Overlockも定番。これは個人的には静凛さんのチャット欄がOverlockなので馴染みがある。

ManjaroのロゴフォントであるComfortaaは最近のManjaroはデフォルトで入っていたりする。

あと、Joseffin Sansも好き。

かっこいいSerifフォントが欲しい、とかいうと特に定番はないので、GoogleでSerifカテゴリを選択して探していただくのがよかろう。 Serifフォントに関しては私は商用のHumanist Slab 712を使っていたりするし。 どうしてもお勧めというのであれば、MartelとかCormorant Garamondとか、Abhaya Libreとかだろうか。

そして個人的には源ノ角ゴシックも良いが、やっぱりモトヤフォントが好きだ。 それにこのラインナップでは丸ゴシックがない。

そこで小杉ゴシック小杉丸ゴシックだ。 小杉ゴシックは元「モトヤ Lシーダ W3等幅」、小杉丸ゴシックは「モトヤ Lマルベリ W3等幅」のリネームである。 これらはApache Lisence 2.0でAndroidに載っていたフォントだ。

好みの盛り盛り

ドキュメントを書く上で使いやすいフォントに欠けるので、源暎フォントを追加している。 ただし、これはドキュメント生成、つまりPandocを使う端末のみ。

あと、本文フォントは「源暎ラテミン」よりも「元陽逆アンチック」のほうが人気があるので、それも入れておく

セットアップ

言葉はいらないよな?

<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
    <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
        <its:translateRule translate="no" selector="/fontconfig/*[not(self::description)]"/>
    </its:rules>

    <description>Re-define sans-serif, serif and monospace.</description>
    <match target="pattern">
        <test qual="any" name="family">
            <string>sans-serif</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Joseffin Sans</string>
            <string>MotoyaLCedar</string>
            <string>Source Han Sans JP</string>
        </edit>
    </match>
    <match target="pattern">
        <test qual="any" name="family">
            <string>serif</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Overlock</string>
            <string>GenEi Koburi Mincho</string>
            <string>Source Han Serif JP</string>
        </edit>
    </match>
    <match target="pattern">
        <test qual="any" name="family">
            <string>monospace</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Hermit</string>
            <string>Cica</string>
            <string>Migu 1M</string>
        </edit>
        -->
    </match>
</fontconfig>
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
    <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
        <its:translateRule translate="no" selector="/fontconfig/*[not(self::description)]"/>
    </its:rules>

    <description>Substitude popular Japanese fonts</description>

    <match target="pattern">
        <test qual="any" name="family">
            <string>MS Pゴシック</string>
        </test>
        <test qual="any" name="family">
            <string>MS PGothic</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Ume P Gothic S5</string>
        </edit>
    </match>
    <match target="pattern">
        <test qual="any" name="family">
            <string>MS P明朝</string>
        </test>
        <test qual="any" name="family">
            <string>MS PMincho</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Ume P Mincho</string>
        </edit>
    </match>
    <match target="pattern">
        <test qual="any" name="family">
            <string>MS明朝</string>
        </test>
        <test qual="any" name="family">
            <string>MS Mincho</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Ume Mincho</string>
        </edit>
    </match>
</fontconfig>

Inflatonにおけるサーバープロビジョニングのおはなし

Inflatonにおけるサーバープロビジョニングに関する質問があったので、記事にしようと思う。

基本的にはこの部分は、私の(=Inflatonの)基本的方針を踏襲したものになっている。 つまり、

  • 一般的である、あるいは流行であるということにはとらわれず
  • Unixの流儀に従い
  • 堅牢で確実なツールと手法で
  • 全ての理解が容易であるように

している。

前提

Inflatonにおいては、一般的ではない前提が成り立っている。

まず、「私が前提になっているということ」である。

つまり、私に属人化することは基本的に問題視されない。 それよりも私の能力が発揮できることが優先されるのでやり方は好きに選べる。

もうひとつは、会社自体が少数精鋭になっているということだ。

これを前提に一般的な手法を避けたりもしていて、「IT業界の人間」が直ちに即戦力になるような状況にない。 戦力になるまで、1年くらいは育てて使う方針になっている。

その間賃金が低いとしても、300万円くらいは利益を出さない人のために使うということである。 しかも、まっさらな状態から1年でちゃんとやれるようになるとしたら、つきっきりで教えなくてはならない。 私だとえらいことになってしまうし、全てを教えられるレベルのエンジニアだと年俸600万円は下らないだろう。

これは「1人増えるのが一大イベント」であるからこそできることで、新卒採用があるような会社ではここまでの方法はとれない。

ここまでの前提を以て、他とは違うInflaton styleを可能にしている。

正しい方法

ConoHaの場合、「スタートアップスクリプト」という機能があり、サーバー構成時にスクリプトを実行させることができる。 cloud-config形式とシェルスクリプト形式をサポートしているという。

ConoHaに限らなければ、Chefなどのツールを使うのが一般的である。

もちろん、これらの方法はInflatonでは採用していない。

我々の方法

基本的に

  • ドキュメントを書く
  • シェルスクリプトを書く

の2点である。

ドキュメントは手順書と言っていいのかはわからないが、基本的に最低限コマンドが打てればこれだけ読んで構築できるレベルの内容になっている。 開発も実務も忙しいのに事業かけもちでドキュメントもちゃんと書いていることについては是非とも褒めまくっていただきたい。

シェルスクリプトのほうは、より正確に表現するならZshバッチになっている。 正直なところ、ドキュメントを読むよりもこちらを読むほうがわかりやすいだろう。

何のために、といったことに関しては、そのサービスを構成するものに関する、内部向け外部向けのドキュメントが存在するため、それを見れば確認できる。

それぞれちゃんとした理由がある。

まず、ドキュメントが揃っている最大の理由は、しばらく触ってないソフトウェアやサービスに関して、私が覚えていられないことと、説明する時間が割けないことだ。

弊社取締役はMimir Yokohamaの生徒さんでもあり、私が書くレベルのドキュメントがあればだいたいは理解できる。 このため、ちゃんとドキュメントがあるだけでも私の負担は確実に減る。そして、ドキュメントがなければ私は開発に戻ってくるのが大変になる。

そして、システム構成に関してはあまり固定化されていない。そもそもコンポーネントの変更をしやすいように設計してあり、サーバー面での変更というのは相当カジュアルに行われている。

もちろん、理由は私が管理しているからであるが、もうひとつの理由としてArch Linuxだからというのもある。 Arch Linuxは普通にバージョンも上がれば、役割を担うソフトウェアが変更されることもある。だから、構築から運用を固定化したところで、固定化したものが自動的に通用しなくなって困るだけなのだ。

ドキュメントに関しては単純に都度アップデートしている形だが、実はシェルスクリプトとドキュメントの2段構成にしている大きな理由として、「サーバー構築手順が次のサーバーで成立する可能性はかなり低い」というのがある。 一番躓くのがパッケージ名の変更である。Archは非常にカジュアルにパッケージ名を変更するので、インストールするパッケージ名の指定がコケる原因になる場合が多い。 加えていえば、サーバーソフトウェアの設定ファイルの項目も、意外と頻繁に変わる。

そこで

  1. ドキュメントで手順を確認
  2. そのパートのバッチスクリプトを実行、あるいはドキュメント記載のコマンドをコピペしながら実行
  3. 躓いた場合は原因を確認し、ドキュメントとスクリプトをアップデート

という形でstep by stepで進めていくと構築できるようになっている。 Inflatonとしてはサーバーを増やすのは年に数えるほどでしかないため、完全自動化するのはメリットよりデメリットのほうが大きい。

サーバーインスタンス増加による増強よりは、新しいことをやるために構成の異なるサーバーを立てる頻度のほうが高い。 だから作業においてコアになることが確定している部分…例えばzsh, grml-zsh-config, zsh-theme-powerlevel9k, screenのインストールと、/etc/zshrc.localの設定などはそれでひとつのスクリプトにまとめられている。 なので、このスクリプトは使い回しが効く。

Inflatonでサーバーを立てるということは、最近始まったばかりなので稀な話だが、「システムの構築」そのものは数え切れないくらいやっている。 今でも何らかの理由でシステムを作ることは年に10回くらいはあるし、15年とか前だと週イチなんてペースだったので、知識と経験があるし、効率化も進んでいる。 結局のところ「最適解を追い求めている以上、ゴージャスな方法で固定するよりは変更しやすい方法のほうがいい」というのが教訓なのだ。

ここには私の信念、及び流儀も絡む。 私は「完璧たりうる」と思っているし、かつ「完璧と動的である」と思っている。だからこそ、「完璧を追い求めることにこそ意味がある」と信じている。 そのためには「動いた状態」で固定することには意味がないし、「動的な最善」であるArch Linuxなのである。

一例としては、現在Plutoのサーバーではsshd_config(5)のCiphers

Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com

である。この設定の主たるところはchacha20-poly1305@openssh.comが外されていることで、外している理由はSSHの処理が比較的重いサービス特性上、サーバー側でAES-NIを使いたいからである。

余談だが、AMDプロセッサはBulldozer以降でAES-NIをサポートしており、IntelはIvy Bridgeまではi3においてAES-NIがサポートされていなかった。 こうしたことを含め、性能の低いデバイスにおいてはAES-NIがなく、計算量の多いAESは重いということになるのだが、コネクションが1本であるクライアントにとっては大した話ではなく、多数のコネクションをさばくサーバー側で軽くすることが優先である。

しかし、この設定ではaes128-ctrが最初に来ており、今後10年で変更されることを意味している。

つまり常に動的に構成され、動的に変更されるのである。 構成時はむしろ構成変更タイミングでもあると言っていい。

手順スクリプトは

pacman -S grml-zsh-config tmux zsh-completions zsh-syntax-highlighting zsh-theme-powerlevel9k zsh-history-substring-search vim vim-plugins rsync
cat > /etc/zshrc.local <<EOF
setopt vi

autoload -U history-search
#zle -N history-beginning-search-backward-end history-search
#zle -N history-beginning-search-forward-end history-search
bindkey "^P" history-beginning-search-backward
bindkey "^N" history-beginning-search-forward
bindkey "\e[5~" history-beginning-search-backward
bindkey "\e[6~" history-beginning-search-forward
bindkey -M viins "\e[5~" history-beginning-search-backward
bindkey -M viins "\e[6~" history-beginning-search-forward
bindkey -M vicmd "\e[5~" history-beginning-search-backward
bindkey -M vicmd "\e[6~" history-beginning-search-forward
...
EOF

みたいな感じで、普通にコマンドラインの手順のバッチと、catを使ったファイル生成から成り立っているのだが、ステップ中で躓いた場合、Vimでd:2してそのステップからやり直すようにすれば良い。 dggでない理由は、「失敗時にそのステップを終了する」ため、先頭で

TRAPZERR() { exit 48 }

としているからだ。

付して述べるなら、「理解していなくても使える」というのはInflatonとしては嬉しいことではなくて、「理解する前提で育てる」方向だから、 「知悉しやすい、教材としても優れたものにしておく」という考え方になってもいる。

プロビジョニングツールを使うことでディストリビューション間の差異を吸収しやすくなるという面はあるが、 ディストリビューション変更をするような場合は、パッケージに含まれるファイルの詳細を把握しなければ潜在的に危険であると考えているので、そのような吸収をしてもらう必要はない。

同様にプロビジョニングツールを使うことで構成することそのものを容易にする面もあるが、そもそも構成が普通でないので、これも全く役に立たない。 例えば私は個人としては2017年までサーバーにDeleGateを使っていたが、DeleGateを構成することなど誰も考えていないし、そこまで極端ではなくとも常に普通にはない構成になっている。 こうしたことから、定番の構成を容易にする機能というのは助けにならず、こうした機能を理由にツールを選択することもない。

サーバーに依存したツールを使うことも、「サーバーの変更」という選択を難しくさせるので、望ましいとは思えない。

Sharhiveって何か

Sharchiveの話をしたら、「それなに」という方がいたので、「あぁ、そうか。思いっきり昔話だもんなぁ」というわけでちょっとSharchiveの話をしよう。

概要

Sharchive (Shell Archive)はアーカイブファイルフォーマットである。filename suffixは.sharで、コマンド名もshar

アーカイブが7bit ASCIIで書かれたshスクリプトになることが特長。展開時はシェルスクリプトとして実行することで展開できる。

「危険ではないのか」という意見に関して答えると、非常に危険である。 純粋なシェルスクリプトであるため、Windowsの自己解凍形式なんかよりはるかに危険である。

背景

Sharは1995年頃まで使われていた。 tarがアーカイブファイルとしてはまだ一般的でない頃に使われていたのだが、アーカイブファイルフォーマットとして主流だったことはない。間違いなくやや特殊なアーカイブだった。

Unixプラットフォーム上ではshがあることは期待できたので、そうした互換性問題を回避するという面はあった。 だが、Sharが使われていた頃であってもtarがないということはそれほどなかった。

Sharが使われた最大の理由はネットニューズである。

ネットニューズを知らない人は多いだろうが、だいたいやりとりの感覚としてはメーリングリストに近い。 そして、当時はMIMEが制定される前で添付ファイルというものはなかった。つまり、データはメール内に書くしかなかった。 なおかつ、まだ8bit目がチェックディジットに使われている時であり、7bit ASCIIでしかメールが書けなかった。

もちろん、この頃でもtarでアーカイブを作り、uuencodeする、という選択肢はあった(Base64という選択肢はまだなかった)。 だが、これだとネットニューズで見ただけでは、それがどのようなソフトウェアなのかということを推定することができない。 Sharchiveであれば、特にスクリプトファイルやソースコードの場合、ネットニューズ上で確認するだけで内容を把握することができる。 メールと違い、uuencodeされたソースを展開するには取り込んでから保存してソースを取り出すという手間があるし、今と違ってX window system前提というわけでもなかったのでコピペが簡単にできたわけでもない。

こうしたことから使われていたのだが、バイナリサイズが大きくなってくると目視は困難だし、効率も悪く、なにより目視確認できないSharchiveは危険極まりない。 これによって、MIME制定以降Sharchiveは使われなくなっていき、やがて全く使われなくなった。

現在

Manjaroの場合sharutilsというパッケージがextraに存在する。

FreeBSD/DragonflyBSDのtarはlibarchiveを使っており、Sharに対応している。--formatオプションやaオプションで作成可能。

もちろん、展開はshでできる。そのため、展開そのものは今も苦労なくできる。

もはや使っている人はいないレベルだと思うのだが、Mimir YokohamaやInflatonでは使う場合がある。 その理由は、コマンドラインツールの利便性や説明の統一を狙って、Git for Windowsをインストールし、Git Bashを使う、という手順で説明することがあるからだ。

サーバー側はLinuxだし、zipでは返しづらい部分もある。こうした理由から手順が統一できるsharを使う…ということをしていたのだが、 現在は「Git for Windowsにtarが入っている」ことに気づいたのでこれも廃止した。

「シェル」と「端末(ターミナル)」の違いと詳細

【超ざっくり解説シリーズ】シェル(Shell)とは?シェルについて初心者にもわかりやすく解説するよというnoteを読み、ちょっと内容がひどかったので、Twitterで言及したものの、ちゃんと説明したほうがよかろうと考えて急遽、この記事を書くことにした。

「シェル」「端末」「端末エミュレータ」「端末デバイス」については、Mimir YokohamaのLinux基礎初級「シェルとコマンドライン」の中でやっている。 この内容をやる時期としてはかなり難しい部類に入り、かつ重要であることから、最近は端末デバイスを直接叩くといったことを含めて2時間以上じっくり取り組むことが多い。

内容自体はそれほど難しくはないと思うのだが、理解に至るには

  • 入出力
  • デバイスと接続
  • カーネルとシステムコール
  • プロセス
  • ファイルディスクリプタ
  • デバイススペシャルファイル

に対する理解が前提となるため、ちゃんと認識できていないと難しいかもしれない。

なお、このあたりはOSによって非常に大きな差異があるところなので、ここではLinuxを前提に説明する。 ここに書かれている内容では理解に至るには足りないと感じられる方は、ぜひMimir Yokohamaの授業を受けてみてほしい。 じっくりと丁寧な説明とハンズオンによって理解できるまでしっかりと授業を行っている。

カーネル

カーネルはCPUの特権モードで動作するプログラムである。

実際に定義としてはそれしかなく、カーネルが実際にどのような仕事を担っているかというのも特に決まってはいない。

とはいえ、カーネルにやってほしい重要なこととして「リソース管理」というものがある。 最近のOSはタイムシェアリングシステムなので物理的な装置数以上のプロセスを起動することができるから、プロセスが好き勝手にリソースを使ってしまうと色々奪い合ってしまうのだ。 一番わかりやすいのは、「ハードディスクのアームをどっち方向にどれだけ動かすか」というモーター制御を奪い合ってしまうという状況ではないだろうか。

というわけでリソース管理をするためにカーネルとしてはプロセス管理をしなければならぬ、ということになる。

だが、カーネルというのは基本的にそういうことをする。 つまり、コンピュータを使う上で必要な環境を整える、コンピュータという舞台を作る、というのがカーネルの仕事だ。 ここが改善されるとそれを使う全てが改善されるため開発にも力が入るというものだ。

端末とコマンドライン

カーネルはプロセスを起動する仕組みを提供し、起動したプロセスを管理してくれるのだが、ここで問題になるのは「どうやってプロセスを起動するか」だ。

Linuxの場合、カーネルロード時にinitというプログラムを実行し、initが色々なプログラムを実行するようになっているのだが、 これでは任意のタイミングで必要なプログラムを実行するという方法がない。 また、プロセスやカーネルにユーザーが対話的にやりとりする方法がない。

いや、実際にそう時代もあったのだ。 コンピュータがパンチカードマシンだった時代、プログラムを実行するというのはパンチカードを差し込んで読み込ませることだった。

だが、タイムシェアリングシステム時代になると、ユーザーとコンピュータは「やりとり」をする必要が生まれた。 それも、できるだけ使いやすく。

ここで使われるようになったのが「テレタイプ」である。

テレタイプというのは通信機能(送受信機能)をもったタイプライタである。 言ってみればモールス信号とFAXの中間みたいな感じで、電話回線を通じて(手動交換機を通じて)ほかのテレタイプの紙に印字できる。

テレタイプ自体は1920年代には存在していたもので、1960年代にコンピュータに接続して使われるようになった。 当時の「最もポピュラーのコンピュータとユーザーが意思疎通するための機械」だったのだ。

ユーザーは、タイプライタ同様にテレタイプでタイピングをする、あるいは予め打ち込んで紙テープに出力したものを読み込ませることでコンピュータに対して意思を伝える。 コンピュータからの出力はテレタイプを通じて紙に印字される。

この仲介をするのがシェルなわけだけれども、この時点ではシェルと呼ぶようなものは必ずしも必須だったわけではなく、単純にテレタイプ・インタープリターのようなものであったし、 それ自体が「OS」と呼ばれることが多かった。

Linuxでも端末のことをテレタイプ(tty)と呼ぶが、実はUnixですらテレタイプは過去のものだった。 1970年代にはビデオディスプレイ端末が登場しており(Unixは1973年に登場)、Unixの端末というと紙テープではなく画面を使うもののイメージが強い。

紙テープから画面になることの違いは、「入出力環境が複数行になる」ということである。 例えばUnixのエディタコマンドとしてex(1)とvi(1)がある。 ex(古くはe, そしてee, ed)はラインエディタであり、一行で入出力ができる。つまり、紙テープに適している。 だが、ビデオディスプレイなら複数行を表示し、それを見ながら編集できる。それがvi(VIsual)なのである。

そして、もうひとつ大きな点として「表示上での削除が可能になる」ということがある。

だから、キーボードから打ったものをそのまま解釈してプロセスを起動する、という方法より「よりよい方法」が登場する。 それが「コマンドライン」である。

コマンドラインは、ユーザーはその意図を「行」に記述することができる。 行単位なので、改行したときがその意思の確定である。

このコマンドラインを快適なインターフェイスとして利用できるようにしたのが「シェル」である。

シェル

コマンドラインの基本的な考え方は前述の通りだが、Unix原初のシェルであるshは

  • 行を編集する機能
  • コマンドラインで複数のプロセスを起動する操作
  • ファイルディスクリプタをファイルに対して再オープンする操作
  • 出力ファイルディスクリプタを別のプロセスの入力ファイルディスクリプタへのパイプにする操作

など様々な機能を搭載した「超高機能インターフェイス」であった。 ユーザーは1行の「コマンドライン」の中で実に様々な操作を行うことができる。

今にすればshなんて貧弱極まりないのだが、当時の感覚からすれば「キーボードから打ったものがそのままコンピュータの動作になる」などというのと比べ信じられないほどいろんなことができ、様々に応用できるスグレモノだったのだ。

これがスグレモノである点として、「プログラムを記述する必要性が下がる」というのがある。 インターフェイスが単にキーボードから打った内容に基づきプロセスを起動するだけであるならば、全ての操作は事前にプログラムを用意しておかなければ行えない。 shは実に様々な操作をsh自身によって提供し、なにより応用が効くようになっていたので、圧倒的にプログラムを書くのではなくコマンドラインを打つことで目的を達成できるようになったのだ。

基本的には、bashであれ、zshであれ、それらの「機能が豊富で便利」という点を強化したにすぎず、基本的には変わらない。 シェル自身もプログラムであり、別に特別なものではない。ただ、「インターフェイスが何もなければ対話的にコンピュータを使うことはできないが、シェルはただ対話的に使えるだけでなく、対話的に 便利に 使えるインターフェイスだ」というだけの話である。

カーネルに対して特別にくっついているわけではないし、Linuxシェルはユーザースペースで動作し、別にシステムコールを直に叩くわけではなく汎用性のあるライブラリ(例えばglibc)をロードし、実行する「対話的プログラム」でしかない。

ただ重要な点がある。シェルが登場したとき、コンピュータとやりとりするための機械はテレタイプ、あるいはビデオディスプレイ端末であった、ということだ。

Unixはそれがどちらであっても、あるいはどこのメーカーのテレタイプであっても抽象的に扱えるように「デバイスファイル」という仕組みによって扱うようになっている。 そのため、「端末デバイス」という抽象化したレベルで取り扱うことができ、この端末デバイスは、テレタイプのような一行のものなのか、あるいはビデオディスプレイ端末のような複数行のものなのか、という情報と合わせて取り扱うことができる。

現在は端末デバイスではなく、ビデオデバイスを通じて出力し、キーボードを通じて入力するのが普通だ。 これは一般的には「X Server→ビデオデバイス(カーネルインターフェイス)→ビデオドライバ(カーネル)→ビデオカード(ハードウェア)」の構成であるが、シェルは依然として端末デバイスを必要とする。 普通、シェルは直接にX Server、あるいはビデオデバイスを扱う機能はもたされておらず、あくまでも端末デバイスを使って入出力を行うようになっている。

端末、仮想端末

だが、現在本当に端末に繋がっているコンピュータなんてまずないので、物理的に端末を意味する端末デバイスファイルが用意できない。

そこで、実際には端末はなくても、端末デバイスとして扱える仮想端末デバイスと、コマンドラインの入出力に適した仮想端末ソフトウェアが使用される。

「テキストモード」においては、「仮想コンソール」と呼ばれることが多いプログラムを使用する。 このプログラムは、ビデオデバイスによってテキストビデオモードを設定すると共に、(テキストビデオモードの)ビデオデバイスを通じた画面出力と、キーボード入力の処理機能、 そして仮想端末デバイスの提供(Linuxでは/dev/tty*)を行う。 その上でシェルを起動すれば、シェルは/dev/tty?を端末として扱うことができるわけだ。

ターミナルエミュレータは単なるX client(あるいはWaylandクライアント)である。 つまり、グラフィカルアプリなのだが、これはこれで仮想端末を提供する。Linuxでは/dev/pts/*である。 やはり、この上でシェルを起動すれば、シェルは/dev/pts/?を端末として扱うことができる。

だから、例えば

% ls -l /proc/$$/fd/0
lrwx------ 1 haruka haruka 64  6月  1 00:19 /proc/2835/fd/0 -> /dev/pts/0

ということである。

なお、端末エミュレータはキーボードを処理しない。X serverから受け取ったキー入力を仮想端末デバイスを通じて入力するようになっている。 だから、「シェルの標準入力はデフォルトでキーボードに繋がっている」というのは嘘で、対話的シェルは入出力ともに端末デバイスに繋がっている。 仮想コンソールの場合、シェル→端末デバイス→仮想コンソール→キーボードと間接的につながっているのだが、ターミナルエミュレータの場合は全く繋がっていない。

ちなみに、「端末」といえば、DECのVT-100である。 1978年にリリースされたビデオディスプレイ端末で、まぁとにかく売れに売れて、端末といえばVT-100というレベルだった。

だから、VT-100の仕様が一般的で、VT-100と互換仕様の端末も出たし、仮想端末もだいたいVT-100と互換になっていたりする(そして、その設定がある)。

そして、もうひとつ。

xtermは、それを端末として扱うための色々なものを、自前でもっていたりする。

【Manjaro/Arch Linux注意】Yaourtは廃止になりました

すごくニュースだと思うんだけれど、全然話題になっていないけれど。

AURヘルパーである YaourtはAURからなくなりました

もう随分長いこと「非推奨」とされてきたのだけれど、ついになくなった、というかたち。

AURヘルパーの中ではYaourtが最も親しまれてきたし、最も有名だった。 「Yaourtを使う」というのが当たり前になってもいた。

けれど、近年はセキュリティ上の問題があり、メンテナンスされていないことからobsolateになっていた。 で、今ついにAURからなくなった、ということ。

これに伴って、CommunityパッケージになっていたManjaroでもYaourtは廃止に。

今後はyayなり、Trizenなりを使っていくことになる。

そのうち「Yaourtを野良ビルドして使う」みたいな記事が出てきそうだけれども、 危険なのでやめましょう

Archwikiでは2019-05-20現在、日本語版はそのままであるものの、英語版はYaourtに関する記述自体が削除されている。