#きょうのsystemd: Surface Proを持ち歩いている人はサーバーを持ち歩いていると言おう

完全にネタ。

hostnamed needs a quirk database for chassis type · Issue #7390 · systemd/systemd · GitHub

レナートがタイトルを変えちゃってるけど、もともとは "hostnamectl reports chassis-type as server for a Surface Pro tablet(hostnamectlがSurface Proタブレットの筐体をサーバーと報告する)"

#きょうのsystemd : (翻訳) どうやったらSysV initのスクリプトをsystemdのサービスファイルに換えられるのか? (systemd for Administrators, Part 3)

概要

これは

systemd for Administrators, Part III

の翻訳。

どうやったらSysV initのスクリプトをsystemdのサービスファイルに換えられるのか?

伝統的にUnixLinuxのサービス(デーモン)はSysV init スクリプト経由で起動されている。 これらはBourne Shellスクリプトであり、通常は/etc/rc.d/init.dといったディレクトリに置かれている。 これらのスクリプトstartstoprestartといった数個の標準化された引数(動詞)を与えられて呼び出されたときに、件のサービスの制御、すなわち、起動、停止、再起動をおこなう。 起動の場合、スクリプトは通常、デーモンのバイナリーの呼び出しに関わり、バックグラウンドのプロセスをフォークする(より正確にはデーモン化させる)。 これらは非常に柔軟性がある(なんといったって、これらは単なるコードである)が、いくつかのことはシェルスクリプトでは適切におこなうことが非常に難しい。 具体的には、実行をパラレル化するように並べる、適切にプロセスを監督する、あるいは、非常に細かいところまで実行のコンテクストを設定するといったことである。 systemdはこれらのシェルスクリプトとの互換性を提供しているが、ここで指摘した短所ゆえに、インストールされているすべてのデーモンがネイティブなsystemdサービスファイルをインストールすることが推奨される。 また、ディストリビューションに合うよう調整しなければいけないSysV initスクリプトと比べると、systemdのサービスファイルはsystemdを動かしているディストリビューション(最近どんどん増えている)ならどの種類でも互換性がある。 となると、次に続くのは、どのようにSysV initスクリプトを取り上げ、ネイティブなsystemdサービスファイルに翻訳するかの完結なガイドということになる。 理想的には、上流のプロジェクトがそれらのtarballにsystemdサービスファイルを同梱しインストールすることだ。 もし、SysVスクリプトガイドラインに従ってうまく変換しているならば、そのファイルを上流にパッチとして送ってしまうのはいい考えだ。 このようなパッチを準備する方法は、後の投稿で論じるつもりだが、現時点で十分に言えることは、systemdに同梱されているdaemon(7)のマニュアルページには、これに関する有益な情報が多く含まれているということだ。

閑話休題。 一例として、ここではABRTデーモンのinitスクリプトをsystemdサービスファイルに変換することにしよう。 ABRTは各Fedoraのインストールの標準的なコンポーネントであり、Automatic Bug Reporting Toolの略だ。 何をするかはその名のとおりで、クラッシュダンプを集めるサービスである。 これのSysVスクリプトはもうここに上げてある。

こういったスクリプトを変換するときの第一歩はこれを読むこと(驚け、驚け!)で、たいていは長いこのスクリプトから有益な情報を抽出することだ。 ほとんどすべてのケースで、スクリプトはほとんど決まり文句のコードで構成されている。 このコードはすべてのinitスクリプトで一致ないしは少なくともかなり似ており、通常はあっちからこっちへのコピペである。 さて、上でリンクを張ったスクリプトから興味深い情報を抽出してみよう。

  • サービスの説明文は「クラッシュしたアプリを検出するデーモン」である。 見たらわかるとおり、ヘッダーのコメントには余分な数の説明の文字列が含まれている。 これらのいくつかは実際のサービスを説明しているというよりかは、それをスタートさせるinitスクリプトについての説明をしている。 systemdサービスも説明文は含んではいるが、それが説明すべきなのはサービスのことであり、サービスファイルのことではない。

  • LSBヘッダー*1には依存関係の情報が含まれている。 systemdはそのソケットベースのアクティベーションの設計のため、通常は手動で依存関係を設定する必要はまったく(ないしはほんの少しだけしか)ない(ソケットアクティベーションの詳細はオリジナルのアナウンスのブログ投稿を見てほしい)。 今回の場合は$syslogに依存(これはabrtdがsyslogデーモンを必要としているということがエンコードされている)することが唯一、価値のある情報である。 ヘッダーがその他の依存関係($local_fs)を挙げているが、これはsystemdには余分な情報である。 というのも、通常のシステムサービスは常にすべてのローカルファイルシステムが利用可能な状態で起動されるためだ。

  • LSBヘッダーはこのサービスがランレベル3(マルチユーザー)と5(グラフィカル)で起動するべきことを示唆している。

  • デーモンのバイナリーは/usr/sbin/abrtdである。

準備はととのった。 この115行のシェルスクリプトの残りの行は全部、単なる決まり文句か余分なコードだ。 このコードで、スタートアップの同期やシリアル化(つまり、ロックファイルを検討するコード)を取り扱ったり、状態メッセージを出力(つまり、echoを呼び出すコード)したり、単に動詞をパース(つまり大きなcaseブロック)したりしている。

上で抽出した情報から、もう、systemdサービスファイルを書くことができる。

[Unit]
Description=Daemon to detect crashing apps
After=syslog.target

[Service]
ExecStart=/usr/sbin/abrtd
Type=forking

[Install]
WantedBy=multi-user.target

このファイルの中身についてちょっと説明しよう。 [Unit]セクションにはサービスに関する汎用的な情報が含まれている。 systemdはシステムサービスを管理するだけでなく、デバイスやマウントポイント、タイマー、あるいはその他のシステムのコンポーネントも管理している。 systemdでぇあこれらのオブジェクトすべてに汎用的な用語を与えており、それはユニットという。 そして[Unit]セクションにはユニットに関して、サービスだけでなく、systemdが維持しているその他のユニットタイプでも適用可能かもしれない情報をまとめている。 今回の場合、次のようなユニットの設定をおこなっている。 説明の文字列を設定し、デーモンがSyslog*2の後に開始されるように設定した。これはオリジナルのinitスクリプトのLSBヘッダーに書かれているのと同じようなことだ。 このsyslog依存関係のために、After=という種類の依存関係をsystemdのユニットであるsyslog.targetに対し作った。 後者はsystemdでは特別なターゲットユニットであり、これはsyslog実装を制御するための標準化された名前である。 これら標準化された名前についての詳細はsystemd.special(7)を見てほしい。 After=という種類の依存関係は示唆された順番をエンコードしているにすぎず、実際にabrtdが起動しするときにsyslogを起動させようとするものではないことに注意してほしい。 そしてこれが実際に我々が求めていることあることにも注意してほしい。abrtdは実際にsyslogが動いていなかったとしてもうまく動くためだ。 とはいえ、2つとも起動していれば(そして、普通はそうだ)、この2つを含む順序はこの依存関係によって制御される。

次のセクションは[Service]であり、これにはサービス自身の情報が含まれている。 これにはサービスにだけ適用される、すべての情報が含まれており、systemdが維持している他の種類のユニット(マウントポイント、デバイス、タイマー、……)にはない。 ここでは2つの設定が使われている。 ExecStart=はサービスが起動したときに実行されるべきバイナリのパスが書かれている。 Type=では、サービスがどのようにしてinitシステムに自身が起動を終えたことを伝えるかが設定されている。 伝統的なUnixデーモンではバックグラウンドデーモンのフォークと初期化が終わってから、親プロセスに戻ることでこれを実現しているため、ここではforkingに設定している。 これはsystemdに対し、スタートアップバイナリーが戻ってくるまで待ち、その後、デーモンプロセスを動かしているプロセスを考慮するように伝えるのである。

最後のセクションは[Install]である。 これは示唆されるインストレーションがどのように見えるべきかについての情報を含んでいる。 つまり、どの環境とどのトリガーに寄ってサービスがスタートすべきかである。 今回の場合、簡単に、このサービスはmulti-user.targetユニットがアクティブになったら開始されるべきと言っている。 これは特別なユニット(既述)であり、基本的には、古典的なSysVのランレベル3*3の役割を引き受ける。 WantedBy=という設定は実行時のデーモンにはほとんど効果がない。 これはsystemctl enableコマンドによってのみ読み込まれる。 このコマンドはsystemdでサービスを有効にするのに推奨されている方法だ。 このコマンドは我々の小さいサービスが、すべての通常起動*4でオンになるmulti-user.targetが要求されればすぐに自動的にアクティブになるようにするものである。

中身の説明はここまでだ。 さて、もう機能する最小限のsystemdサービスファイルを手に入れた。 テストするため、これを/etc/systemd/system/abrtd.serviceにコピーし、systemctl daemon-reloadを実行しよう。 これでsystemdにこのサービスファイルの存在を気づかせ、systemctl start abrtd.serviceを使ってサービスを起動させられるようになる。 systemctl status abrtd.serviceを使って状態を確かめることができる。 systemctl stop abrtd.serviceでサービスを再び停止させられる。 最後に、systemctl enable abrtd.serviceこれを有効にし、次回以降の起動時にデフォルトでこのサービスがアクティブになるようにすることができる。

上のサービスファイルは、十分かつ、基本的な1対1のSysV initスクリプトの翻訳(機能その他)なのだが、まだ改善の余地がある。 ここで、ちょっとだけアップデートしてみる。

[Unit]
Description=ABRT Automated Bug Reporting Tool
After=syslog.target

[Service]
Type=dbus
BusName=com.redhat.abrt
ExecStart=/usr/sbin/abrtd -d -s

[Install]
WantedBy=multi-user.target

さて、何が変わっただろうか? 答えは2つだ。説明の文字列をちょっと改善した。 しかしもっと重要なのは、サービスの種類をdbusに変えて、サービスのD-Busバス名を設定したことだ。 なぜこうしたのか? すでに述べたとおり、伝統的なSysVサービスはスタートアップ後にデーモン化する。 これは通常ダブルフォークとすべてのターミナルからのデタッチが起こる。 これはデーモンがスクリプト経由で起動されるときには便利であり、必須なのだが、systemdのような適切なプロセスのベビーシッターが使われている場合、逆効果なのに加え、不必要(で遅い)のだ。 その理由はフォークされたデーモンプロセスは通常、systemdによって起動されたオリジナルのプロセスとほとんど関係を持たないからであり、それ故、systemdが、フォークが終わった後に、サービスに属しているプロセスのどれがメインプロセスでどれが単なる補助のサービスなのかの見分けるのが難しいためだ。 だが、この情報は高度なベビーシッター、つまり、プロセスの監督、異常終了時の自動的な再スポーン、クラッシュおよび終了コード情報の収集、などを実装するには重要なことだ。 systemdがデーモンのメインプロセスを見つけるのが簡単になるようにサービスタイプをdbusへ変更した。 このサービスタイプのセマンティクスは、サービスの初期化の最終段階でD-Busシステムバス上に名前を取るすべてのサービスに適切なものである*5。 ABRTはその1つである。 この設定によりsystemdはABRTプロセスをスポーンするが、(訳注: 今度の)そのプロセスはもはやフォークしない(これはデーモンに与えられた-dsスイッチで設定されている)し、systemdはバス上にcom.redhat.abrt`が現れたら、すぐにサービスが完全に起動したとみなすようになる。 この方法でsystemdがスポーンしたプロセスはデーモンのメインプロセスであり、systemdはデーモンが完全にスタートアップした時を知る信頼できる方法を手に入れ、systemdはそれを簡単に監督することができるのだ。

それだけのことだ。 オリジナルのSysV initスクリプトでは115行でエンコードされていた以上の情報を10行でエンコードした、簡単なsystemdのサービスファイルを手に入れた。 そして、実はまだsystemdが提供するより多くの機能を使って、さらに改善する余地がたくさんある。 例えば、Restart=restart-alwaysを設定し、systemdにサービスが死んでしまったときにこれを自動的に再起動するように伝えることができる。 あるいはOMMScoreAdjust=0500を使うことで、カーネルにお願いだから、このプロセスをOOM Killerが大損害を与えるときにこのプロセスだけは見逃してくれるよう頼むことができる。 あるいはCPUSchedulingPolicy=idleを使うことで、abrtdプロセスのクラッシュダンプをバックグラウンドでのみ取得し、カーネルに何であれ他に動いていて、CPU時間を必要としているものにパフォーマンスを与えることができる。

ここで言及した設定オプションについての詳細情報は対応するmanページ、systemd.unit(5)systemd.service(5)systemd.exec(5)を見てほしい。 あるいはsystemdのmanページすべてをブラウズするのでも良い。

もちろん、すべてのSysVスクリプトがこれみたいに簡単に変換できるわけではない。 だが、嬉しいことに、実際には大半が簡単に変換できることがわかっている。

今日はここまで。次回の投稿ですぐまた会おう。

*1:原文注: initスクリプトのLSBヘッダーはSysV initスクリプトのトップにあるコメントブロックでサービスについてのメタデータを含ませる慣習であり、Linux Standard Baseで定義されている。これはディストリビューション間でinitスクリプトを標準化することを意図したものである。ほとんどのディストリビューションはこのスキームを採用しているが、ヘッダーの取り扱い方はディストリビューション間でかなり違っており、実際、各ディストリビューションごとにinitスクリプトを調整する必要がある。このようにLSBの仕様は自分がした約束を決して守っていないのである。

*2:原文注: 厳密なことをいうと、この依存関係は実はここで書く必要はなかった。というのも、Syslogデーモンがソケットアクティベーション可能なシステムなら、これは余分なのだ。モダンなsyslogシステム(例えばv5)はソケットアクティベーション可能なよう上流でパッチが当てられている。もしinitシステムがAfter=syslog.targetの設定を使っているなら、依存関係は余分であり、暗黙のものとなる。だが、アップデートされていないsyslogサービスとの互換性維持のために、ここではこの依存関係を含ませた

*3:原文注: 少なくともFedoraではそのように定義されていたものだ。

*4:原文注: systemdではグラフィカルなブートアップ(graphical.targetつまり、SysVランレベル5の役目を引き受ける)はコンソールのみのブートアップ(multi-user.targetつまりランレベル3のようなもの)の暗黙的なスーパセットである。これは後者でサービスを起動させれば、前者でもそのサービスが上がってくることを意味する。

*5:実際、デフォルトのFedoraインストールのサービスの大多数はいまやスタートアップ後にバス上に名前を取る

いろいろ新調した

昨日、今日とで色々新調した。

昨日はユニクロに服を買いに行った。最低限の冬の準備はできたと思う。

今日は友人に会いに秋葉原へ。 ついでに、つくもへSSDを見に行った。

これまで使っていたSSDIntelの330で60GBと120GBで、前者を/、後者を/homeとしてマウントしていた。 とても調子よく動いているが、買ったのが5年以上前のため、そろそろ不安になってきた。 あと、データドライブで120GBは手狭になってきているので、60GBを外して、120GBを/に、新しいSSD/homeにとスライドさせることにした。

新しいSSDはこれ。

TLCなのが気になるけど、まぁ、ええかということで。

rsync -av/homeをまるごと移したけど、SSD同士なので超早かった。

現役からは引退させる60GBも何らかの形で使いたいので、これをポチった。

透明でかっこいい。

あと、IntelNICも買った。

インテル Gigabit CT Desktop Adapter EXPI9301CT

インテル Gigabit CT Desktop Adapter EXPI9301CT

実は、デスクトップ機にもかかわらず、ずっと無線LANPCI-Eカードを挿してネットに繋いでいた。 実家にいた頃はそのほうが便利だったから仕方がない。

ただ、

  • 実家から出たので、無線である必要はなくなった
  • systemd-nspawnで遊ぶのに、MACVLANをすると、無線ではちょっと困ることがわかった

ということで、以前より有線にしたいなとは思っていた。

ところが、IvyBridgeのCPU + H77のマザボなので、オンボのNICが蟹さん。 「なので」というのは、オンボNICIntelはHaswell世代のマザボは多くがそうだったり、Ivy世代でもチップセットが最上位のZ77だとそうだったり、という印象・記憶。 色々惜しい。

ネットで見て記憶していた値段より安かったので、エイヤということで買った。若干早い気がする。気だけかも。

#きょうのsystemd: (翻訳) どのサービスがどのプロセスを動かしてる? (systemd for Administrators, Part 2)

概要

systemd for Administrators, Part II

の翻訳。

どのサービスがどのプロセスを動かしている?

ほとんどのLinuxシステムで、実質的にはデフォルトでかなりの数のプロセスが動かされている。 どのプロセスが動いていて、それが何の、どこに属しているのかを知ることはどんどん難しくなっている。 サービスのいくつかは1組のワーカープロセスを維持していることすらあり、これらは、たいてい簡単には見分けのつかない数多くの追加のプロセスでpsの出力を乱雑にしている。 デーモンが任意のサードパーティーのプロセスを、ApacheCGIプロセスでやっていたり、cronがユーザージョブでやっているように、動かそうものなら、状況はさらに複雑になる。

この状況へのほんのわずかな対処になるのは、たいてい、プロセスの継承ツリーで、これはps xafによって表示されるようなものだ。 だが、これは普通、信頼できるものではない。 というのも、親プロセスが死んだプロセスはPID 1を親に設定し直すためであり、したがって、継承に関するすべての情報が失われてしまう。 プロセスが「ダブルフォーク」している場合、このプロセスはそれを開始したプロセスとの関係も失ってしまうこととなる。(これは実際には特徴であり、伝統的なUnixのデーモン化のロジックに依存している。) さらに、プロセスはPR_SETNAMEargv[0]をパッチすることにより、自由に名前を変えることができ、これもまた、プロセスを識別するのを難しくしている。 事実、プロセスはこの方法で管理者とかくれんぼを楽しくやっているのだ。

systemdではサービスから名前を取ったコントロールグループにスポーンされたすべてのプロセスを置いている。 コントロールグループ(あるいはcgroup)は基本の「き」として、簡単にプロセスのグループなのである。そして、プロセスのグループは階層的に、別個にラベル付けされて、整理されるのである。 プロセスが他のプロセスをスポーンしたら、その子プロセスは自動的に親プロセスのcgroupのメンバーとなる。 したがって、cgroupsはプロセスに対し、それが属しているサービスに沿ってラベルをつける効果的な方法の一つとして使うことができ、どれだけフォークしても名前を変えても、そのラベルからサービスを逃さないようにすることができるのである。 さらに、これは安全にサービスとそれが作り出したすべてのプロセスを安全に停止させるのに使うことができる。ここでも、プロセスは逃れることができない。

さて、今日の投稿では、2つのコマンドを紹介しようと思う。 これらはシステムのサービスとプロセスに関係して、使うことができるものだ。 最初はよく知られたpsコマンドなのだが、これはcgroupの情報をプロセスの他の詳細情報と合わせて表示することができるようにアップデートされてきてる。 こんな感じだ

$ ps xawf -eo pid,user,cgroup,args
  PID USER     CGROUP                              COMMAND
    2 root     -                                   [kthreadd]
    3 root     -                                    \_ [ksoftirqd/0]
[...]
 4281 root     -                                    \_ [flush-8:0]
    1 root     name=systemd:/systemd-1             /sbin/init
  455 root     name=systemd:/systemd-1/sysinit.service /sbin/udevd -d
28188 root     name=systemd:/systemd-1/sysinit.service  \_ /sbin/udevd -d
28191 root     name=systemd:/systemd-1/sysinit.service  \_ /sbin/udevd -d
 1096 dbus     name=systemd:/systemd-1/dbus.service /bin/dbus-daemon --system --address=systemd: --nofork --systemd-activation
 1131 root     name=systemd:/systemd-1/auditd.service auditd
 1133 root     name=systemd:/systemd-1/auditd.service  \_ /sbin/audispd
 1135 root     name=systemd:/systemd-1/auditd.service      \_ /usr/sbin/sedispatch
 1171 root     name=systemd:/systemd-1/NetworkManager.service /usr/sbin/NetworkManager --no-daemon
 4028 root     name=systemd:/systemd-1/NetworkManager.service  \_ /sbin/dhclient -d -4 -sf /usr/libexec/nm-dhcp-client.action -pf /var/run/dhclient-wlan0.pid -lf /var/lib/dhclient/dhclient-7d32a784-ede9-4cf6-9ee3-60edc0bce5ff-wlan0.lease -
 1175 avahi    name=systemd:/systemd-1/avahi-daemon.service avahi-daemon: running [epsilon.local]
 1194 avahi    name=systemd:/systemd-1/avahi-daemon.service  \_ avahi-daemon: chroot helper
 1193 root     name=systemd:/systemd-1/rsyslog.service /sbin/rsyslogd -c 4
 1195 root     name=systemd:/systemd-1/cups.service cupsd -C /etc/cups/cupsd.conf
 1207 root     name=systemd:/systemd-1/mdmonitor.service mdadm --monitor --scan -f --pid-file=/var/run/mdadm/mdadm.pid
 1210 root     name=systemd:/systemd-1/irqbalance.service irqbalance
 1216 root     name=systemd:/systemd-1/dbus.service /usr/sbin/modem-manager
 1219 root     name=systemd:/systemd-1/dbus.service /usr/libexec/polkit-1/polkitd
 1242 root     name=systemd:/systemd-1/dbus.service /usr/sbin/wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -B -u -f /var/log/wpa_supplicant.log -P /var/run/wpa_supplicant.pid
 1249 68       name=systemd:/systemd-1/haldaemon.service hald
 1250 root     name=systemd:/systemd-1/haldaemon.service  \_ hald-runner
 1273 root     name=systemd:/systemd-1/haldaemon.service      \_ hald-addon-input: Listening on /dev/input/event3 /dev/input/event9 /dev/input/event1 /dev/input/event7 /dev/input/event2 /dev/input/event0 /dev/input/event8
 1275 root     name=systemd:/systemd-1/haldaemon.service      \_ /usr/libexec/hald-addon-rfkill-killswitch
 1284 root     name=systemd:/systemd-1/haldaemon.service      \_ /usr/libexec/hald-addon-leds
 1285 root     name=systemd:/systemd-1/haldaemon.service      \_ /usr/libexec/hald-addon-generic-backlight
 1287 68       name=systemd:/systemd-1/haldaemon.service      \_ /usr/libexec/hald-addon-acpi
 1317 root     name=systemd:/systemd-1/abrtd.service /usr/sbin/abrtd -d -s
 1332 root     name=systemd:/systemd-1/getty@.service/tty2 /sbin/mingetty tty2
 1339 root     name=systemd:/systemd-1/getty@.service/tty3 /sbin/mingetty tty3
 1342 root     name=systemd:/systemd-1/getty@.service/tty5 /sbin/mingetty tty5
 1343 root     name=systemd:/systemd-1/getty@.service/tty4 /sbin/mingetty tty4
 1344 root     name=systemd:/systemd-1/crond.service crond
 1346 root     name=systemd:/systemd-1/getty@.service/tty6 /sbin/mingetty tty6
 1362 root     name=systemd:/systemd-1/sshd.service /usr/sbin/sshd
 1376 root     name=systemd:/systemd-1/prefdm.service /usr/sbin/gdm-binary -nodaemon
 1391 root     name=systemd:/systemd-1/prefdm.service  \_ /usr/libexec/gdm-simple-slave --display-id /org/gnome/DisplayManager/Display1 --force-active-vt
 1394 root     name=systemd:/systemd-1/prefdm.service      \_ /usr/bin/Xorg :0 -nr -verbose -auth /var/run/gdm/auth-for-gdm-f2KUOh/database -nolisten tcp vt1
 1495 root     name=systemd:/user/lennart/1             \_ pam: gdm-password
 1521 lennart  name=systemd:/user/lennart/1                 \_ gnome-session
 1621 lennart  name=systemd:/user/lennart/1                     \_ metacity
 1635 lennart  name=systemd:/user/lennart/1                     \_ gnome-panel
 1638 lennart  name=systemd:/user/lennart/1                     \_ nautilus
 1640 lennart  name=systemd:/user/lennart/1                     \_ /usr/libexec/polkit-gnome-authentication-agent-1
 1641 lennart  name=systemd:/user/lennart/1                     \_ /usr/bin/seapplet
 1644 lennart  name=systemd:/user/lennart/1                     \_ gnome-volume-control-applet
 1646 lennart  name=systemd:/user/lennart/1                     \_ /usr/sbin/restorecond -u
 1652 lennart  name=systemd:/user/lennart/1                     \_ /usr/bin/devilspie
 1662 lennart  name=systemd:/user/lennart/1                     \_ nm-applet --sm-disable
 1664 lennart  name=systemd:/user/lennart/1                     \_ gnome-power-manager
 1665 lennart  name=systemd:/user/lennart/1                     \_ /usr/libexec/gdu-notification-daemon
 1670 lennart  name=systemd:/user/lennart/1                     \_ /usr/libexec/evolution/2.32/evolution-alarm-notify
 1672 lennart  name=systemd:/user/lennart/1                     \_ /usr/bin/python /usr/share/system-config-printer/applet.py
 1674 lennart  name=systemd:/user/lennart/1                     \_ /usr/lib64/deja-dup/deja-dup-monitor
 1675 lennart  name=systemd:/user/lennart/1                     \_ abrt-applet
 1677 lennart  name=systemd:/user/lennart/1                     \_ bluetooth-applet
 1678 lennart  name=systemd:/user/lennart/1                     \_ gpk-update-icon
 1408 root     name=systemd:/systemd-1/console-kit-daemon.service /usr/sbin/console-kit-daemon --no-daemon
 1419 gdm      name=systemd:/systemd-1/prefdm.service /usr/bin/dbus-launch --exit-with-session
 1453 root     name=systemd:/systemd-1/dbus.service /usr/libexec/upowerd
 1473 rtkit    name=systemd:/systemd-1/rtkit-daemon.service /usr/libexec/rtkit-daemon
 1496 root     name=systemd:/systemd-1/accounts-daemon.service /usr/libexec/accounts-daemon
 1499 root     name=systemd:/systemd-1/systemd-logger.service /lib/systemd/systemd-logger
 1511 lennart  name=systemd:/systemd-1/prefdm.service /usr/bin/gnome-keyring-daemon --daemonize --login
 1534 lennart  name=systemd:/user/lennart/1        dbus-launch --sh-syntax --exit-with-session
 1535 lennart  name=systemd:/user/lennart/1        /bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session
 1603 lennart  name=systemd:/user/lennart/1        /usr/libexec/gconfd-2
 1612 lennart  name=systemd:/user/lennart/1        /usr/libexec/gnome-settings-daemon
 1615 lennart  name=systemd:/user/lennart/1        /usr/libexec/gvfsd
 1626 lennart  name=systemd:/user/lennart/1        /usr/libexec//gvfs-fuse-daemon /home/lennart/.gvfs
 1634 lennart  name=systemd:/user/lennart/1        /usr/bin/pulseaudio --start --log-target=syslog
 1649 lennart  name=systemd:/user/lennart/1         \_ /usr/libexec/pulse/gconf-helper
 1645 lennart  name=systemd:/user/lennart/1        /usr/libexec/bonobo-activation-server --ac-activate --ior-output-fd=24
 1668 lennart  name=systemd:/user/lennart/1        /usr/libexec/im-settings-daemon
 1701 lennart  name=systemd:/user/lennart/1        /usr/libexec/gvfs-gdu-volume-monitor
 1707 lennart  name=systemd:/user/lennart/1        /usr/bin/gnote --panel-applet --oaf-activate-iid=OAFIID:GnoteApplet_Factory --oaf-ior-fd=22
 1725 lennart  name=systemd:/user/lennart/1        /usr/libexec/clock-applet
 1727 lennart  name=systemd:/user/lennart/1        /usr/libexec/wnck-applet
 1729 lennart  name=systemd:/user/lennart/1        /usr/libexec/notification-area-applet
 1733 root     name=systemd:/systemd-1/dbus.service /usr/libexec/udisks-daemon
 1747 root     name=systemd:/systemd-1/dbus.service  \_ udisks-daemon: polling /dev/sr0
 1759 lennart  name=systemd:/user/lennart/1        gnome-screensaver
 1780 lennart  name=systemd:/user/lennart/1        /usr/libexec/gvfsd-trash --spawner :1.9 /org/gtk/gvfs/exec_spaw/0
 1864 lennart  name=systemd:/user/lennart/1        /usr/libexec/gvfs-afc-volume-monitor
 1874 lennart  name=systemd:/user/lennart/1        /usr/libexec/gconf-im-settings-daemon
 1903 lennart  name=systemd:/user/lennart/1        /usr/libexec/gvfsd-burn --spawner :1.9 /org/gtk/gvfs/exec_spaw/1
 1909 lennart  name=systemd:/user/lennart/1        gnome-terminal
 1913 lennart  name=systemd:/user/lennart/1         \_ gnome-pty-helper
 1914 lennart  name=systemd:/user/lennart/1         \_ bash
29231 lennart  name=systemd:/user/lennart/1         |   \_ ssh tango
 2221 lennart  name=systemd:/user/lennart/1         \_ bash
 4193 lennart  name=systemd:/user/lennart/1         |   \_ ssh tango
 2461 lennart  name=systemd:/user/lennart/1         \_ bash
29219 lennart  name=systemd:/user/lennart/1         |   \_ emacs systemd-for-admins-1.txt
15113 lennart  name=systemd:/user/lennart/1         \_ bash
27251 lennart  name=systemd:/user/lennart/1             \_ empathy
29504 lennart  name=systemd:/user/lennart/1             \_ ps xawf -eo pid,user,cgroup,args
 1968 lennart  name=systemd:/user/lennart/1        ssh-agent
 1994 lennart  name=systemd:/user/lennart/1        gpg-agent --daemon --write-env-file
18679 lennart  name=systemd:/user/lennart/1        /bin/sh /usr/lib64/firefox-3.6/run-mozilla.sh /usr/lib64/firefox-3.6/firefox
18741 lennart  name=systemd:/user/lennart/1         \_ /usr/lib64/firefox-3.6/firefox
28900 lennart  name=systemd:/user/lennart/1             \_ /usr/lib64/nspluginwrapper/npviewer.bin --plugin /usr/lib64/mozilla/plugins/libflashplayer.so --connection /org/wrapper/NSPlugins/libflashplayer.so/18741-6
 4016 root     name=systemd:/systemd-1/sysinit.service /usr/sbin/bluetoothd --udev
 4094 smmsp    name=systemd:/systemd-1/sendmail.service sendmail: Queue runner@01:00:00 for /var/spool/clientmqueue
 4096 root     name=systemd:/systemd-1/sendmail.service sendmail: accepting connections
 4112 ntp      name=systemd:/systemd-1/ntpd.service /usr/sbin/ntpd -n -u ntp:ntp -g
27262 lennart  name=systemd:/user/lennart/1        /usr/libexec/mission-control-5
27265 lennart  name=systemd:/user/lennart/1        /usr/libexec/telepathy-haze
27268 lennart  name=systemd:/user/lennart/1        /usr/libexec/telepathy-logger
27270 lennart  name=systemd:/user/lennart/1        /usr/libexec/dconf-service
27280 lennart  name=systemd:/user/lennart/1        /usr/libexec/notification-daemon
27284 lennart  name=systemd:/user/lennart/1        /usr/libexec/telepathy-gabble
27285 lennart  name=systemd:/user/lennart/1        /usr/libexec/telepathy-salut
27297 lennart  name=systemd:/user/lennart/1        /usr/libexec/geoclue-yahoo

(この出力は短くなっていることに注意。このブログストーリーと関係がないため、カーネルスレッドのほとんどはここでは削除している。)

3つ目の列で、それぞれのプロセスをsystemdがどのcgroupに割り当てているかを確認することができる。 udevプロセス群がname=systemd:/systemd-1/sysinit.servicecgroupにあることがわかるだろう。 systemdがブートの初期段階をカバーするsysinit.serviceサービスで起動されたすべてのプロセスをここに配置している。

個人的におすすめなのが、シェルのエイリアスpscを上で示したようなpsコマンドラインに設定することだ。

alias psc='ps xawf -eo pid,user,cgroup,args'

これで、たった4回キーを押すだけで、サービスの情報が見られる!

同じ情報を表示する別の方法はsystemd-cglsで、これはsystemdに同梱されている。 出力はこんな感じだ

$ systemd-cgls
+    2 [kthreadd]
[...]
+ 4281 [flush-8:0]
+ user
| \ lennart
|   \ 1
|     +  1495 pam: gdm-password
|     +  1521 gnome-session
|     +  1534 dbus-launch --sh-syntax --exit-with-session
|     +  1535 /bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session
|     +  1603 /usr/libexec/gconfd-2
|     +  1612 /usr/libexec/gnome-settings-daemon
|     +  1615 /ushr/libexec/gvfsd
|     +  1621 metacity
|     +  1626 /usr/libexec//gvfs-fuse-daemon /home/lennart/.gvfs
|     +  1634 /usr/bin/pulseaudio --start --log-target=syslog
|     +  1635 gnome-panel
|     +  1638 nautilus
|     +  1640 /usr/libexec/polkit-gnome-authentication-agent-1
|     +  1641 /usr/bin/seapplet
|     +  1644 gnome-volume-control-applet
|     +  1645 /usr/libexec/bonobo-activation-server --ac-activate --ior-output-fd=24
|     +  1646 /usr/sbin/restorecond -u
|     +  1649 /usr/libexec/pulse/gconf-helper
|     +  1652 /usr/bin/devilspie
|     +  1662 nm-applet --sm-disable
|     +  1664 gnome-power-manager
|     +  1665 /usr/libexec/gdu-notification-daemon
|     +  1668 /usr/libexec/im-settings-daemon
|     +  1670 /usr/libexec/evolution/2.32/evolution-alarm-notify
|     +  1672 /usr/bin/python /usr/share/system-config-printer/applet.py
|     +  1674 /usr/lib64/deja-dup/deja-dup-monitor
|     +  1675 abrt-applet
|     +  1677 bluetooth-applet
|     +  1678 gpk-update-icon
|     +  1701 /usr/libexec/gvfs-gdu-volume-monitor
|     +  1707 /usr/bin/gnote --panel-applet --oaf-activate-iid=OAFIID:GnoteApplet_Factory --oaf-ior-fd=22
|     +  1725 /usr/libexec/clock-applet
|     +  1727 /usr/libexec/wnck-applet
|     +  1729 /usr/libexec/notification-area-applet
|     +  1759 gnome-screensaver
|     +  1780 /usr/libexec/gvfsd-trash --spawner :1.9 /org/gtk/gvfs/exec_spaw/0
|     +  1864 /usr/libexec/gvfs-afc-volume-monitor
|     +  1874 /usr/libexec/gconf-im-settings-daemon
|     +  1882 /usr/libexec/gvfs-gphoto2-volume-monitor
|     +  1903 /usr/libexec/gvfsd-burn --spawner :1.9 /org/gtk/gvfs/exec_spaw/1
|     +  1909 gnome-terminal
|     +  1913 gnome-pty-helper
|     +  1914 bash
|     +  1968 ssh-agent
|     +  1994 gpg-agent --daemon --write-env-file
|     +  2221 bash
|     +  2461 bash
|     +  4193 ssh tango
|     + 15113 bash
|     + 18679 /bin/sh /usr/lib64/firefox-3.6/run-mozilla.sh /usr/lib64/firefox-3.6/firefox
|     + 18741 /usr/lib64/firefox-3.6/firefox
|     + 27251 empathy
|     + 27262 /usr/libexec/mission-control-5
|     + 27265 /usr/libexec/telepathy-haze
|     + 27268 /usr/libexec/telepathy-logger
|     + 27270 /usr/libexec/dconf-service
|     + 27280 /usr/libexec/notification-daemon
|     + 27284 /usr/libexec/telepathy-gabble
|     + 27285 /usr/libexec/telepathy-salut
|     + 27297 /usr/libexec/geoclue-yahoo
|     + 28900 /usr/lib64/nspluginwrapper/npviewer.bin --plugin /usr/lib64/mozilla/plugins/libflashplayer.so --connection /org/wrapper/NSPlugins/libflashplayer.so/18741-6
|     + 29219 emacs systemd-for-admins-1.txt
|     + 29231 ssh tango
|     \ 29519 systemd-cgls
\ systemd-1
  + 1 /sbin/init
  + ntpd.service
  | \ 4112 /usr/sbin/ntpd -n -u ntp:ntp -g
  + systemd-logger.service
  | \ 1499 /lib/systemd/systemd-logger
  + accounts-daemon.service
  | \ 1496 /usr/libexec/accounts-daemon
  + rtkit-daemon.service
  | \ 1473 /usr/libexec/rtkit-daemon
  + console-kit-daemon.service
  | \ 1408 /usr/sbin/console-kit-daemon --no-daemon
  + prefdm.service
  | + 1376 /usr/sbin/gdm-binary -nodaemon
  | + 1391 /usr/libexec/gdm-simple-slave --display-id /org/gnome/DisplayManager/Display1 --force-active-vt
  | + 1394 /usr/bin/Xorg :0 -nr -verbose -auth /var/run/gdm/auth-for-gdm-f2KUOh/database -nolisten tcp vt1
  | + 1419 /usr/bin/dbus-launch --exit-with-session
  | \ 1511 /usr/bin/gnome-keyring-daemon --daemonize --login
  + getty@.service
  | + tty6
  | | \ 1346 /sbin/mingetty tty6
  | + tty4
  | | \ 1343 /sbin/mingetty tty4
  | + tty5
  | | \ 1342 /sbin/mingetty tty5
  | + tty3
  | | \ 1339 /sbin/mingetty tty3
  | \ tty2
  |   \ 1332 /sbin/mingetty tty2
  + abrtd.service
  | \ 1317 /usr/sbin/abrtd -d -s
  + crond.service
  | \ 1344 crond
  + sshd.service
  | \ 1362 /usr/sbin/sshd
  + sendmail.service
  | + 4094 sendmail: Queue runner@01:00:00 for /var/spool/clientmqueue
  | \ 4096 sendmail: accepting connections
  + haldaemon.service
  | + 1249 hald
  | + 1250 hald-runner
  | + 1273 hald-addon-input: Listening on /dev/input/event3 /dev/input/event9 /dev/input/event1 /dev/input/event7 /dev/input/event2 /dev/input/event0 /dev/input/event8
  | + 1275 /usr/libexec/hald-addon-rfkill-killswitch
  | + 1284 /usr/libexec/hald-addon-leds
  | + 1285 /usr/libexec/hald-addon-generic-backlight
  | \ 1287 /usr/libexec/hald-addon-acpi
  + irqbalance.service
  | \ 1210 irqbalance
  + avahi-daemon.service
  | + 1175 avahi-daemon: running [epsilon.local]
  + NetworkManager.service
  | + 1171 /usr/sbin/NetworkManager --no-daemon
  | \ 4028 /sbin/dhclient -d -4 -sf /usr/libexec/nm-dhcp-client.action -pf /var/run/dhclient-wlan0.pid -lf /var/lib/dhclient/dhclient-7d32a784-ede9-4cf6-9ee3-60edc0bce5ff-wlan0.lease -cf /var/run/nm-dhclient-wlan0.conf wlan0
  + rsyslog.service
  | \ 1193 /sbin/rsyslogd -c 4
  + mdmonitor.service
  | \ 1207 mdadm --monitor --scan -f --pid-file=/var/run/mdadm/mdadm.pid
  + cups.service
  | \ 1195 cupsd -C /etc/cups/cupsd.conf
  + auditd.service
  | + 1131 auditd
  | + 1133 /sbin/audispd
  | \ 1135 /usr/sbin/sedispatch
  + dbus.service
  | +  1096 /bin/dbus-daemon --system --address=systemd: --nofork --systemd-activation
  | +  1216 /usr/sbin/modem-manager
  | +  1219 /usr/libexec/polkit-1/polkitd
  | +  1242 /usr/sbin/wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -B -u -f /var/log/wpa_supplicant.log -P /var/run/wpa_supplicant.pid
  | +  1453 /usr/libexec/upowerd
  | +  1733 /usr/libexec/udisks-daemon
  | +  1747 udisks-daemon: polling /dev/sr0
  | \ 29509 /usr/libexec/packagekitd
  + dev-mqueue.mount
  + dev-hugepages.mount
  \ sysinit.service
    +   455 /sbin/udevd -d
    +  4016 /usr/sbin/bluetoothd --udev
    + 28188 /sbin/udevd -d
    \ 28191 /sbin/udevd -d

(これも短くしている。同じ方法だ。)

見てわかったとおり、このコマンドはcgroupつまりサービスごとにプロセスを表示しており、systemdがサービスに従ってラベルを付けている。 例えば、簡単にわかるとおり、auditサービスのauditd.serviceは3つの別々のサービス、auditdaudispsedispatchをスポーンしている。

詳しく見ると気づくと思うが、多くのプロセスが/user/1というcgroupに割り当てられている。 ここでは簡単に、systemdはサービスをcgroupsで管理しているだけでなく、ユーザーセッションのサービスも同じようにcgroupsで管理している、ということにしておいてほしい。 のちのちの投稿でこの件についてはもっと詳しく論じることとする。

ここでおしまい。次の投稿を楽しみに、すぐ戻ってきてね!

#きょうのsystemd: ハイブリッドcgroupのセットアップは動くのか?

ちょっと前から気になっていたsystemd-develでのやり取りについて。

そもそも、「はいぶりっどこんとろーるぐーぷ?」なのだが、ちょっとまとめてみる。

ことの発端はUmut Tezduyar Lindskog*1の以下のメール。

[systemd-devel] How does hybrid cgroup setup work?

ハロー、

(訳注: cgroupの)CPUコントローラーをv1で、メモリコントローラーをunifiedにしようとしているんだけど、思ったとおり動かないんだ。 CONFIG_MEMCGを有効にすると、cgroupが/proc/cgroupsにポップアップしてきて、mount_cgroup_controllers()がかなり早くそれをマウントしている。 いったんこれがv1でマウントされると、v2では使えなくなってしまう。

ハイブリッドがどのように動くのか、自分が誤解しているんだろうか? Umut

v1だの、unifiedだの、v2だの、すでによくわからない。

ぐぐると、 id:defiant さんのブログがヒット記事が出た。systemdをやっている限りは足向けて眠れない気しかしない。

http://tenforward.hatenablog.com/entry/20160414/1460560309

http://gihyo.jp/admin/serial/01/linux_containers/0037 http://gihyo.jp/admin/serial/01/linux_containers/0038

v1 の問題点のひとつに、コントローラがばらばらに実装されているため、コントローラ間の連携ができないという問題がありました。

というわけで、「どうしてこうなった」という疑問は深堀しないことにして、これを解決するために、cgroupの構造を単一構成構造にしたのが、cgroup v2ととりあえず理解しておく。

なので、unifiedとv2は同じ、「ハイブリッド」はv1とv2のハイブリッドと理解してよさそうだ。そもそも、cgroup v1もろくに理解している気がしないのだが。

スレッドを読み進めよう。レナートのメール。

[systemd-devel] How does hybrid cgroup setup work?

ハイブリッドが意味するところは、v2がサービスのトラッキングにのみ使われているということ(これはいいことだ。なんせ、cgroupが存在するときに安全な通知をしてくれるからだ)で、どのコントローラーとしても使われていないということだ。 これは、ハイブリッドモードはほとんどピュアなv1と互換性があることを意味し、例外は、もう1つの階層構造(v2のそれだ)があって、systemdがそれをsystemdの目的のために使っているということだ。

レナート

端的に言うと、systemdはcgroup v2をフルには使っていません、というわけだ。

Umutが質問を続ける。

[systemd-devel] How does hybrid cgroup setup work?

v1からいくつかのコントローラーを、v2からいくつかのコントローラーを、みたいな幅広いハイブリッドにできない技術的な理由があるのか?

自分たちは、CPUに関してはv2が承認されるまではv1を使い続けて、一方で、メモリーに関してはv2のメリットを享受したいんだ。

UMUT

いいたいことはなんとなくわかる。

レナートの解説が入る。

[systemd-devel] How does hybrid cgroup setup work?

さて、現時点では、3つのタイプのセットアップがある。

1) レガシー

/sys/fs/cgroup/ → tmpfsインスタンス /sys/fs/cgroup/memory/ → メモリーコントローラーの階層構造 /sys/fs/cgroup/cpu/ → CPUコントローラーの階層構造 … /sys/fs/cgroup/systemd/ → namedの階層構造でsystemdがその管轄するものを管理する(そして、ほとんどsystemdの内部で利用される)もの

2) unified:

/sys/fs/cgroup/ → 単一階層構造(つまり、これは1つディレクトリを上がったところ、tmpfsのあったところだということに注意)

3) ハイブリッド:

/sys/fs/cgroup/ → tmpfs /sys/fs/cgroup/memory/ → メモリーコントローラーの階層構造 /sys/fs/cgroup/cpu/ → CPUコントローラーの階層構造 … /sys/fs/cgroup/systemd/ → namedの階層構造で互換性のため /sys/fs/cgroup/unified/ → 単一階層構造で、コントローラーはなく、systemdがその管轄するものを管理する(そして、ほとんどsystemdの内部で利用される)もの

さて、#1と#2をサポートするのは、なるほど納得である。1つは古いセットアップで、もう1つは将来のセットアップだ。 #3はたいていの方法で#1と互換性がある。唯一変わっていることは階層構造がもう1つ増えたということだけだ。 だが、古いコントローラーの階層構造は同じ場所に残っている。 別の言い方をすれば、systemdのプライベートな階層構造は変わっているが、その他の管轄するも*2のはまったく同じ場所に残っているということだ。

さて、君らが目指しているのは1と3とのどちらにも似ていない(3は単一階層構造からみて、動いてしまっているからだ)。 あるいは#2にも近くない(というのも、単一のディレクトリは/sys/fs/cgroupにはならない。なぜならレガシーなコントローラーをマウントさせる場所がないからだ)。

なので、君らの目指していることを加えようとすると、間に合わせにしかならないんだ。 つまり、加えたその瞬間に、すでに、終わりが見えている。 僕は、そんなに長くは生きないだろうとしているもののサポートを今から加えようとするのには消極的だな……。

そして、大きな問題がある。 cgroupのコードは難しすぎて、3つの異なるセットアップをサポートはできないんだ。 これにさらに付け加えるなんてことがないなら、本当にそれがいいと思う。 事実、僕は本当に、単一構造のcgroupを除いて、すべてのcgroupのサポートを、自分たちの(訳注: コード)ツリーからドロップできる日が待ち遠しいよ。 そのときには、めっちゃコードを消せるね! ハッカーがコードを書くよりも唯一好きなことは、コードを消すことさ…… ;-)

レナート

続くメールでUmutは「先生、先生の見込みではそれいつですか?」と聞いている。

[systemd-devel] How does hybrid cgroup setup work?

私も気になる。

レナート先生の回答*3

[systemd-devel] How does hybrid cgroup setup work?

自分がTejun*4の話を咀嚼すると、主要なコントローラーはすべて(訳注: v2に)動かすつもりなんだけど、いくつかは全体的にドロップするみたいだ。例えば、"devices"(というのも、これのやっていることは正確にはリソースの管理じゃなくて、アクセスの管理で、seccompと/devをどう一緒にするかを注意深く選び取れば、こいつはほとんど余分だからだ。)

モリーコントローラーはもう完全に移っただろう。 systemdのMemoryMax=はすでに正しくことを運んでいる。

*1:ぐぐると名前がそこそこ出る人であった。経歴は彼のLinkedinページを参照。systemd.conf 2015でもどうやら喋っているようだ。発表のタイトルを見る限り、組み込み系の人だろうか。

*2:原語は'stuff'なのだが、訳語はいつもどうしたらいいのか悩む……。

*3:ちょっと誤字・脱字が多いみたいなので補正している

*4:cgroupsのメンテナーsystemdのコミッターWikipedia - cgroupsLinkedin

#きょうのsystemd: (翻訳) ブートアップを確かめる (systemd for Administrators, Part 1)

概要

以下は、レナートのブログの

0pointer.de

を翻訳したものである。

管理者のためのsystemd パート1

読者の多くが知っているようにsystemdFedoraの新しいinitシステムであり、Fedora 14から採用された。 また、同じような方法で他のディストリビューションの多く(例えば、OpenSUSE)でも採用されている。 管理者向けにsystemdは数多くの新しい新機能を提供しており、管理上のプロセスをかなり変化・強化している。 数カ月の間、だいたい毎週、シリーズとして記事を投稿しようとしている。 このブログストーリーはその最初のパートである。 それぞれの投稿でsystemdの新しい機能を1つ取り上げて説明しようと思う。 これらの機能の多くは小さくてシンプルなものなので、これらのストーリーが多くの読者の関心をひくものだろう。 ただ、折りに触れて、読者に提供されているsystemdの素晴らしい新しい機能について少しだけ掘り下げることもしようと思う。

ブートアップを確かめる

伝統的に、Linuxシステムがブートアップするとき、スクリーンを流れていく短いメッセージを目にするだろう。 ブートプロセスを速くしよう、パラレル化しようと我々が努めた結果、これらのメッセージを目にする時間はどんどん短くなり、そして、どんどん読みづらくなっている。 今日ではPlymouthのようなグラフィカルなブートスプラッシュテクノロジーを使って、できれば表示されないようになってすらいる。 それにもかかわらず、ブートスクリーンの情報はこれまでも、そして現在でも非常に適切なものである。 というのも、ブートアップの一部として起動されていたそれぞれのサービスがうまく起動したか、それとも失敗したか(緑か赤の[ OK ][ FAILED ]で示される)を示してくれるからである。 高速にブートアップし、パラレル化されたマシンの状況を改善するために、そして、この情報を実行時にもっとうまく使えるようにするために、我々はsystemdに新しい機能を追加した。 それは、それぞれのサービスについて、スタートアップは成功したかどうか、0出ない終了コードで終了したかどうか、タイムアウトしたかどうか、(セグフォやその他の)異常終了したかどうかを、スタートアップ時、実行時の両方で、追跡し、記憶するものである。 簡単にsystemctlとシェルでタイプすると、すべてのサービス、つまり、systemdネイティブなサービスとSysV/LSBサービスの両方の状態をクエリーすることができる。

[root@lambda] ~# systemctl
UNIT                                          LOAD   ACTIVE       SUB          JOB             DESCRIPTION
dev-hugepages.automount                       loaded active       running                      Huge Pages File System Automount Point
dev-mqueue.automount                          loaded active       running                      POSIX Message Queue File System Automount Point
proc-sys-fs-binfmt_misc.automount             loaded active       waiting                      Arbitrary Executable File Formats File System Automount Point
sys-kernel-debug.automount                    loaded active       waiting                      Debug File System Automount Point
sys-kernel-security.automount                 loaded active       waiting                      Security File System Automount Point
sys-devices-pc...0000:02:00.0-net-eth0.device loaded active       plugged                      82573L Gigabit Ethernet Controller
[...]
sys-devices-virtual-tty-tty9.device           loaded active       plugged                      /sys/devices/virtual/tty/tty9
-.mount                                       loaded active       mounted                      /
boot.mount                                    loaded active       mounted                      /boot
dev-hugepages.mount                           loaded active       mounted                      Huge Pages File System
dev-mqueue.mount                              loaded active       mounted                      POSIX Message Queue File System
home.mount                                    loaded active       mounted                      /home
proc-sys-fs-binfmt_misc.mount                 loaded active       mounted                      Arbitrary Executable File Formats File System
abrtd.service                                 loaded active       running                      ABRT Automated Bug Reporting Tool
accounts-daemon.service                       loaded active       running                      Accounts Service
acpid.service                                 loaded active       running                      ACPI Event Daemon
atd.service                                   loaded active       running                      Execution Queue Daemon
auditd.service                                loaded active       running                      Security Auditing Service
avahi-daemon.service                          loaded active       running                      Avahi mDNS/DNS-SD Stack
bluetooth.service                             loaded active       running                      Bluetooth Manager
console-kit-daemon.service                    loaded active       running                      Console Manager
cpuspeed.service                              loaded active       exited                       LSB: processor frequency scaling support
crond.service                                 loaded active       running                      Command Scheduler
cups.service                                  loaded active       running                      CUPS Printing Service
dbus.service                                  loaded active       running                      D-Bus System Message Bus
getty@tty2.service                            loaded active       running                      Getty on tty2
getty@tty3.service                            loaded active       running                      Getty on tty3
getty@tty4.service                            loaded active       running                      Getty on tty4
getty@tty5.service                            loaded active       running                      Getty on tty5
getty@tty6.service                            loaded active       running                      Getty on tty6
haldaemon.service                             loaded active       running                      Hardware Manager
hdapsd@sda.service                            loaded active       running                      sda shock protection daemon
irqbalance.service                            loaded active       running                      LSB: start and stop irqbalance daemon
iscsi.service                                 loaded active       exited                       LSB: Starts and stops login and scanning of iSCSI devices.
iscsid.service                                loaded active       exited                       LSB: Starts and stops login iSCSI daemon.
livesys-late.service                          loaded active       exited                       LSB: Late init script for live image.
livesys.service                               loaded active       exited                       LSB: Init script for live image.
lvm2-monitor.service                          loaded active       exited                       LSB: Monitoring of LVM2 mirrors, snapshots etc. using dmeventd or progress polling
mdmonitor.service                             loaded active       running                      LSB: Start and stop the MD software RAID monitor
modem-manager.service                         loaded active       running                      Modem Manager
netfs.service                                 loaded active       exited                       LSB: Mount and unmount network filesystems.
NetworkManager.service                        loaded active       running                      Network Manager
ntpd.service                                  loaded maintenance  maintenance                  Network Time Service
polkitd.service                               loaded active       running                      Policy Manager
prefdm.service                                loaded active       running                      Display Manager
rc-local.service                              loaded active       exited                       /etc/rc.local Compatibility
rpcbind.service                               loaded active       running                      RPC Portmapper Service
rsyslog.service                               loaded active       running                      System Logging Service
rtkit-daemon.service                          loaded active       running                      RealtimeKit Scheduling Policy Service
sendmail.service                              loaded active       running                      LSB: start and stop sendmail
sshd@172.31.0.53:22-172.31.0.4:36368.service  loaded active       running                      SSH Per-Connection Server
sysinit.service                               loaded active       running                      System Initialization
systemd-logger.service                        loaded active       running                      systemd Logging Daemon
udev-post.service                             loaded active       exited                       LSB: Moves the generated persistent udev rules to /etc/udev/rules.d
udisks.service                                loaded active       running                      Disk Manager
upowerd.service                               loaded active       running                      Power Manager
wpa_supplicant.service                        loaded active       running                      Wi-Fi Security Service
avahi-daemon.socket                           loaded active       listening                    Avahi mDNS/DNS-SD Stack Activation Socket
cups.socket                                   loaded active       listening                    CUPS Printing Service Sockets
dbus.socket                                   loaded active       running                      dbus.socket
rpcbind.socket                                loaded active       listening                    RPC Portmapper Socket
sshd.socket                                   loaded active       listening                    sshd.socket
systemd-initctl.socket                        loaded active       listening                    systemd /dev/initctl Compatibility Socket
systemd-logger.socket                         loaded active       running                      systemd Logging Socket
systemd-shutdownd.socket                      loaded active       listening                    systemd Delayed Shutdown Socket
dev-disk-by\x1...x1db22a\x1d870f1adf2732.swap loaded active       active                       /dev/disk/by-uuid/fd626ef7-34a4-4958-b22a-870f1adf2732
basic.target                                  loaded active       active                       Basic System
bluetooth.target                              loaded active       active                       Bluetooth
dbus.target                                   loaded active       active                       D-Bus
getty.target                                  loaded active       active                       Login Prompts
graphical.target                              loaded active       active                       Graphical Interface
local-fs.target                               loaded active       active                       Local File Systems
multi-user.target                             loaded active       active                       Multi-User
network.target                                loaded active       active                       Network
remote-fs.target                              loaded active       active                       Remote File Systems
sockets.target                                loaded active       active                       Sockets
swap.target                                   loaded active       active                       Swap
sysinit.target                                loaded active       active                       System Initialization

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.
JOB    = Pending job for the unit.

221 units listed. Pass --all to see inactive units, too.
[root@lambda] ~#

(上の出力はちょっと削って、このブログ投稿に関係のない行は削除した。)

ACTIVE列を見てほしい。 これはサービスの高度な状態を示している(実際にはsystemdがメンテしているすべての種類のユニットの状態を示している。これらのユニットは単なるサービス以上のものでもありうる。ただ、これについては後々のブログ投稿で一瞥するつもりだ)。 示される状態はactive(つまり、実行中)、inactive(つまり、実行していない)ないしはその他の状態だ。 よくよく見ると、リストにあるアイテムの1つがmaintenanceとマークされ、赤でハイライトされているのに気づくだろう*1。 これで、あるサービスが起動に失敗したか、さもなくば、問題にぶち当たったことを知ることができる。 今回の場合、ntpdである。 さて、ntpdに実際に何が起きたかを調べることにしよう。 systemctl statusコマンドを使う

[root@lambda] ~# systemctl status ntpd.service
ntpd.service - Network Time Service
      Loaded: loaded (/etc/systemd/system/ntpd.service)
      Active: maintenance
        Main: 953 (code=exited, status=255)
      CGroup: name=systemd:/systemd-1/ntpd.service
[root@lambda] ~#

コマンドの結果は、NTPが実行時(PID953として動作していた)に終了したことを示している。 これは正確なエラーの状態を示している。 プロセスが終了コード255で終了したのだ。

のちのsystemdのバージョンでは、この機能強化リクエストがフィックスされたらすぐに、これをABRTまで引き上げることを計画をしている。 そうすれば、もしsystemctl statusがクラッシュしたサービスについての情報を示せば、ABRTにある適切なクラッシュダンプに利用者を直ちに案内するだろう*2

要約

systemctlsystemctl statusを使おう。これは、伝統的な、SysVサービスのブートアップ時の状態メッセージのモダンで、より完璧な代替だ。 systemctl statusはより詳細にエラーの状態を取得するだけではなく、スタートアップのエラーに加え、実行時のエラーも表示する。

今週はここまで。管理者のためのsystemdについての次の投稿を読みに、きっと来週には戻って来てほしい。

*1:仕様上、赤くできていない。あとでレナートが書いているが、該当するのはntpd.serviceだ。

*2:自分用メモ: 要追跡調査

#きょうのsystemd: (翻訳)Socket Activation (1)

今日のUbuntu Weekly Recipeはsystemdネタだった!

gihyo.jp

それで、というわけでもなく、ちょうどたまたま書き溜めてただけだけど、今日はsocketユニットについて。

またですが、レナートのブログ記事の翻訳。

原文: 0pointer.net

ソケットアクティベーション

systemdについてオリジナルなブログストーリーで、私はなぜ、ソケットアクティベーションがサービスをスポーンするための素晴らしい技術であるかについて説明しようとした。 ここでちょっと、その背景を繰り返しになるが説明しようと思う。

ソケットアクティベーションの基本的な考え方は新しいものではない。 inetdスーパーサーバーは、ずっとほとんどのLinuxUnixシステムで標準的なコンポーネントであった。 その挙動はこうだ。 起動時にすべてのローカルのインターネットサービスをスポーンする代わりに、スーパーサーバーがそれらのサービスの代わりにリスンする。 そして、接続が来たらいつでも対応するサービスのインスタンスがスポーンされるというものである。 これによりリソースの少ない比較的貧弱なサーバーでも多種多様なサービスを同時に提供することが可能になった。 しかし、この方法はすぐに、いくぶんか遅いという評判を得るようになってしまった。 接続が入ってくるたびに、デーモンがスポーンされるため、サービスのフォークと初期化--それぞれの接続につき1回だ。それらすべてについて1回ではない--にたくさんの時間が必要となる。

接続のたびに1つのインスタンスをスポーンするのはinetdの主たる使われ方であった。一方で、inetdは現に別のモードも理解した。 こちらの挙動はこうだ。 最初の接続が入ってきたら、poll()(ないしはselect())を通じて、このことを伝え、以降のすべての接続のために1つだけインスタンスをスポーンさせる(これはwait/nowaitオプションでコントロールできる)。 この方法だと最初の接続はセットアップに時間がかかるが、続く接続ではスタンドアローンのサービスと同じくらい早い。 このモードでは、inetdは真の意味でオンデマンドモードとして動作する。つまり、サービスは必要とされるときになって初めて利用可能になるのである。

inetdのフォーカスは明らかにAF_INET(つまりインターネット)ソケットにあった。 ときが進んで、Linux/Unixがサーバーという枠から離れ、デスクトップやモバイル、組み込みといった環境に徐々に関係するようになった結果、inetdは時間のトラブルに巻き込まれるようになる。 その評判は遅いというものであったし、インターネットサービスのみがLinuxの焦点でなくなったことで、inetd(ないしは、xinetdのようなその新しい実装の1つ)を動かしているLinuxマシンは一般的ではなく例外的となった。

AppleのエンジニアがMacOSのブート時間の最適化に取り組んでいたところ、彼らはソケットアクティベーションを使う新しい方法を発見した。つまり、彼らはAF_INETソケットからAF_UNIXソケットに焦点をシフトさせたのである。 そして、彼らは、オンデマンドのソケットアクティベーションは物語の一部に過ぎなかったことに気づいた。つまり、何があっても起動時にスタートさせなければならないモノを含め、すべてのローカルサービスにそれを使えば、ソケットアクティベーションがもっともっと強力になると気づいたのである。 彼らはこのアイディアをlaunchdで実装した。launchdはモダンなMacOS Xシステムの礎石となるものであり、おそらく、MacOSがすぐに起動してくる一番の理由である。

しかし、次へ行く前にここで、非オンデマンド、非インターネットサービスへのソケットアクティベーションを使うことの利益が何であるかを詳細に見ておこう。 Syslog、D-Bus、Avahi、Bluetoothデーモンの4つのサービスを考える。 伝統的なLinuxシステムではD-BusはSyslogにログを書き出すため、Syslogより後に起動しなければならない。 同様に、AvahiははSyslogとD-Busを必要とするためこの2つのあとに起動しなければならない。 最後に、BluetoothはAvahiと似ており、SyslogとD-Busを必要とするが、Avahiとは接続されていない。 伝統的なSysVベースのシステムでは同時に1つのサービスだけしか、起動中のプロセスにできないため、スタートアップのシリアル化は次のようになる。Syslog→D-Bus→Avahi→Bluetoothである(もちろん、AvahiとBluetoothは逆の順序で起動させることもできる。しかし、ここでは1つだけを取り上げたいので、単純にアルファベット順にする)。 これを図式化すると、これがシステムのスタートアップで始まるスタートアップの順番を示しているプロットになる(トップに来ている)。

f:id:popo1897:20171116223724p:plain

特定のディストリビューションではこの厳格なシリアルのスタートアップを改善しようとしている。AvahiとBluetoothとは互いに独立しているため、これらは同時に開始することができる。 パラレル化が進み、全体のスタートアップ時間は少し小さくなっている(これはプロットの真ん中で図示されている)*1

ソケットアクティベーションは4つすべてのサービスを、いかなる順序化もなしに、完全に同時に開始させることができる。 リスンするソケットの作成をデーモン自身の外に移すことにより、これらを同時に実行することができ、これらは互いのソケットにすぐに接続することができるのである。 つまり、単一のステップで/dev/logソケットと/run/dbus/system_bus_socketソケットを作成し、次のステップで4つすべてのサービスを同時にスポーンさせるのである。 D-Busがsyslogにログを書き出したいと思ったときは、D-Bus/dev/logにメッセージを書くだけである。 ソケットバッファーがいっぱいにならない限りは、D-Busはその他、初期化のためにしたいと思うことをすぐに続けることができるのである。 syslogサービスがD-Busに追いつけば、syslogはキューに入っているメッセージの処理を始める。 もし、ソケットバッファーがいっぱいになった場合には、クライエントのロギングはソケットが再び書き込み可能になるまで一時的にブロックされ、ログメッセージが書き込み可能になるまでそれが続く。 これは、サービスのスケジューリングが全体的にカーネルにより行われることを意味する。ユーザースペースの観点からすると、すべてのサービスは同時に実行され、あるサービスがそれを必要とする他のサービスに追いつかない場合は、前者は後者の要求を一時的にブロックすることになるが、リクエストが発行されるとすぐに続く。 したがって、以前は厳格にシリアル化が必要であると考えられていたサービスを同時に起動することができようになったことで、ソケットアクティベーションによりスタートアップのパラレル化は劇的に進むことになる。 多くのLinuxサービスはコミュニケーションチャネルとしてソケットを利用している。ソケットアクティベーションでこれらのチャネルのクライアントとサーバーの起動を同時におこなうことができるのである。

しかし、話はパラレル化だけにとどまらない。ソケットアクティベーションは他にも多くの利点がある。

  • 我々はもはや依存関係を明示的に設定する必要がなくなる。ソケットはすべてのサービスの前に初期化されるため、簡単に利用可能になる。また、ユーザースペースでのサービスのスタートアップを順序化する必要ももうなくなる。したがって、ソケットアクティベーションはサービスの設定と開発を劇的に単純化する。
  • サービスが死んだとしても、ソケットはそのままで残り、メッセージをロストすることがなくなる。クラッシュしたサービスが再起動したら、サービスが残してしまったものを引き継ぐことができる。
  • サービスがアップグレードされると、ソケットを残したままサービスを再起動させることができ、これで、サービスが継続的に反応できるようになる。アップグレード中にコネクションが1つも失われることはない。
  • クライアントに見えないような方法で実行中のサービスを入れ替えることだって可能になる。例えば、systemdを動かしているすべてのシステムが小さいsyslogデーモンを起動時に動かしている。これはすべてのログメッセージをカーネルメッセージバッファーに繋がっている/dev/logに書き出す。この方法で信頼の置けるユーザースペースロギングを起動時の最初の瞬間から提供することができる。そして、実際のrsyslogデーモンが起動すると、ミニ版のデーモンを停止させ、それを本物のデーモンに置き換えられるようになる。オリジナルのロギングソケットを維持し、これを2つのデーモンで共有することで、メッセージを1つも失わなくて済む。rsyslogが起動後にカーネルログバッファーをディスクに書き出すため、カーネルからの、ブートの初期段階からの、実行時からの、すべてのメッセージを完全にディスク上に置くことができる。

この考えについての他の説明はsystemdのオリジナルのブログストーリーを参照してほしい。

2へ続く

というか、2いるかな?

*1:UbuntuについてはRethinking PID 1Upstartをこき下ろしているが、SUSEの件は軽くスルーされている。SUSE(自分が触ったことのあるSLES 11)の場合、startpar(manページ)というのを利用し、サービス起動のパラレル化を図っている。これは、/etc/init.d以下のLSBヘッダーを読み取り、依存関係(=起動順)に指定あるものだけをピックアップし、理解する。これを

  • /etc/init.d/.depend.boot
  • /etc/init.d/.depend.start
  • /etc/init.d/.depend.stop

というパスでMakefileの書式で保持する。.depend.*に書かかれたサービスはその内容にしたがって起動・停止され、何も書かれていないサービスはパラレルに起動・停止される。

管見の限り(ググった限り)では、日本語で読めるのは次のサイト: