Assyのリベラル文学研究所もご覧ください。

Linux

そもそもLinuxとは

Linuxは、北欧フィンランドの当時大学生だったリーナス・トーバルズによって開発された、オープンソースUNIX互換OSの「カーネル」と呼ばれるソフトウェア。
まず、OSには、カーネルとユーザーランドがある。カーネルとは、低水準なハードウェアデバイスを操作したり、プログラムを複数同時に実行したり、ファイルやディレクトリといったファイルシステムやソケット通信のネットワークを低レベルレイヤーで提供したりというように、全てのプログラムに共通に必要な機能をユーザーランドのプログラムに提供するための基盤となるソフトウェア。このカーネルの上で、OSの全てのプログラムは動いている。カーネルの上で動くプログラムのことをユーザーランドという。
リーナスは、このカーネルという部分を開発した。
OSは通常、カーネルだけでは使えない。その上にさまざまなコマンドラインプログラムあるいはGUIプログラムがなければ、人間がそもそもコンピュータを使う目的である、さまざまな機能を持った「アプリケーション」がなければ、それはOSとは言えない。
UNIX業界では、Linuxよりも古くからフリーソフトウェアだけでUNIX互換OSを作ろうとするGNU (GNU's Not Unixの略)というプロジェクトがあり、コンパイラC言語ソースコードを実行ファイルに変換するソフトウェア)やコマンドラインシェル(コマンド入力から指定のプログラムを実行する)などユーザーランド一式を提供していた。Linuxは、GNUコンポーネントと組み合わせて利用される。GNUが「LinuxではなくGNU/Linuxと呼ぶべきだ」と主張しているのはこのため。
LinuxオープンソースのライセンスであるGPLでライセンスされており、ソースコードが万人に開かれている。

Linuxの歴史

そもそも、UNIXというソフトウェアも、またLinuxGNUとは別個の、それも太古の昔のOSである。
UNIXアメリカの電話・通信会社AT&Tベル研究所によって1960年代に開発がはじめられた。Multicsという巨大プロジェクトを抱えていたベル研だったが、巨大かつ複雑すぎて使い物にならなかった。ベル研のMultics開発メンバーはこれに嫌気がさし、シンプルかつ単純なUNIX(Multiに対してUni)と呼ばれるOSを開発した。
AT&T独占禁止法からコンピュータ業界への参入を禁じられており、UNIXパブリックドメインで公開した。無料で利用でき、ソースコードを見ることも、コピーすることも改造することも第三者に与えることも自由だった。
技術的に見ると、当時としては目新しい、C言語である高級言語(CPUに依存した機械語の命令セットを使う直接のアセンブリ言語ではなく、開発した後で機械語に変換する人間に読みやすいプログラミング言語)で書かれており、別のCPUプロセッサやアーキテクチャに移植することが簡単だった。また、マルチタスク・マルチユーザのタイムシェアリングシステムとして設計されており、文字ベースのコマンドを使いながら、複数の端末でひとつの中央コンピュータ(ワークステーション)を操作し、全てのプログラムを並列かつ多数のタスクで動かすことができた。
UNIXは、大学や研究機関のワークステーションに爆発的に普及する。
また、カリフォルニア大学バークレー校の学生たちは、UNIXに独自のソフトウェアや改造を加えたBSDバークレー・ソフトウェア・ディストリビューション)を開発。これにはviやcshを開発したUNIX界の神様のようなスーパープログラマーであるビル・ジョイも開発者に含まれる。
また、UNIXは商業的なエンタープライズシステムとして、Sun Microsystemsなどの商業会社にも使われる。Sunにはビル・ジョイも入社している。当時のUNIXの強みはネットワークとオープン。Sunは「ネットワークこそコンピュータ」であるという宣伝文句によって、NFSJavaなどの技術を開発し、自社のSunOS(以後にSolarisという名前になる)と呼ばれる商業UNIXSPARCという独自のプロセッサとともにライセンス販売を行う。
そうしたオープンだったUNIXだが、AT&T独占禁止法から解放されたため、パブリックドメインではなくプロプライエタリになり、ソースコードにアクセスできなくなる。
ここで、MIT AIラボのリチャード・ストールマンは、フリーなUNIXのクローンとしてGNUの開発を決め、自身もテキストエディタEmacsコンパイラGCCを開発しながら協力者を探す。また、新しいGNUのOSのライセンスとして、「コピーレフト」と呼ばれる継承条項(OSのコードをオープンソースに公開しなければならず、改良版や誰かが派生した派生版についてもGPLで同じ権利を守らなければならない、つまりいつまでもGPLを継承しなければならない)を持ったGNU GPLというパブリックドメインより厳しいライセンスを裁定した。これにより、絶対にGNUがフリーでなくなることがなくなった。
BSDからAT&Tのコードを削除した386BSDなども開発されるが、起訴問題などにより配布できなくなる。
GNUは優れたコンパイラフリーソフトウェアとして提供していたため、コンパイラや開発ツールとして良く使われたが、GNU Hurdというマイクロカーネルの開発がいつまでたっても進まなかった。ここではマイクロカーネルという問題があった。カーネルの設計には旧来のモノリシックカーネルと先進的なマイクロカーネルがあるが、マイクロカーネルモノリシックカーネルよりも開発や実用化が難しい。そのためGNUカーネルだけが開発されないまま、ほとんどのUNIXツールの開発を終え、カーネルさえあれば使い物になるレベルになった。
ここで、フィンランドリーナス・トーバルズによるLinuxが開発される。リーナスは当初Minixと呼ばれる教育用のUNIX系OSを使っていたが、Minixの機能に限界を感じ、自分でMinixを改良する。その結果、改良した部分のコードだけでOSとして成り立つようになった。
当時は、Intel 386プロセッサによって「庶民のコンピュータ」が実現されつつある時代であり、リーナスも386プロセッサでUNIXワークステーションを使いたいと思ったが、そのためにGNUBSDも386向けのフリーに入手できるカーネルを提供できていなかったため、リーナスはひとりで386向けのカーネルを書いた。
リーナスは、このLinuxカーネルをインターネットのニューズグループで公開し、フリーで配布するとともに開発者として参加したい人を募った。最初はIntel 386向けの小さなカーネルだったが、開発参加者によってさまざまなアーキテクチャに移植され、またMinixコンポーネントGNUコンポーネントに置き換えられ、独自の商用利用を禁じたライセンスはGPLに変更された。当時、UNIXワークステーションIntel 386のPC/AT互換機でも使いたいという人はたくさんいて、こうした人々が「善意のボランティア」として参加した結果、Linuxはバグのないとてもパフォーマンス(速度・性能・効率・安定性)の高いカーネルに成長した。
Linuxカーネルの特徴として、モノリシックカーネルであることが挙げられる。Hurdとは違い、カーネルの中の各コンポーネントをサーバーに分けることはせず、一枚岩の巨大なソフトウェアとして実装する。これは伝統的でありパフォーマンスも良くなるが、Minixの作者タネンバウムからは「時代遅れだ」と批判された。
また、Linuxはただのカーネルであり、ユーザーランドのソフトウェアがなければ動作しないが、伝統的にLinuxカーネルGNUのツールとともに組み合わさって提供される。GNUBashGCCなどUNIXのほとんどのツールを開発・提供している。また、GNULinuxとが協調して動くために、Linuxの開発者とGNUの開発者は協力した。こうしたことから、GNUストールマンは「LinuxではなくGNU/Linuxと呼ぶべき」だと主張している。
また、LinuxGNUプログラムは、最初から組み合わせて使うことを想定している場合が多いため、LinuxカーネルGNU、そしてX Window SystemUNIXGUIのグラフィックスアプリケーションを使うのに必要となるウィンドウシステムと呼ばれるソフトウェアで、以前はXFree86という名前で386向けのものが提供されていたが、今ではプロジェクトのごたごたでX.orgという新しいプロジェクトに置き換わった)など、必要となるツールを一緒に配布し、簡単にインストールできるようインストーラが付属したものが提供されており、これを「Linuxディストリビューション」と呼ぶ。
昔はSlackwareなどが普通だったが、今ではソフトウェアの管理をしやすくするパッケージ管理システムと呼ばれる、ソフトウェアを自分で手作業で調整しなくても、ある程度インストールや依存関係の把握などを自動でやってくれる機構を使って作られている。代表的なものはRPMというパッケージ形式を使うRed Hatというアメリカのオープンソース会社による商用ディストリビューションや、Red HatのライバルであるドイツのSUSE、また会社ではなくコミュニティで作られている、Debというパッケージ形式を使う硬派なDebianなどが有名だが、ディストリビューションは雨後の竹の子のように増えており、必ずしもこれらを使うわけではなく、Distrowatch.comというサイトで最新のディストリビューションの情報を得られる。
Linuxを使う時は、こうしたディストリビューションのどれかを導入し、その上でLinuxカーネルGNUユーザーランドを使う形になる。
また、Linuxのベースシステムでは、コマンドを用いた単純な文字ベースのプログラムしか用意されていないが、X Window System(Xにバージョン番号を加えてX11と略される)とともにGNOMEKDEといったデスクトップ環境を使うことで、Windowsと同等の「デスクトップPCで操作しやすい」環境を導入することができる。KDEはドイツ、GNOMEはメキシコで生まれ、二大デスクトップ環境となっている。
Linuxのもっとも大きな特徴は、オープンソースであること。全てのソフトウェアがオープンソースで公開されており、フリーで利用できる。フリーとは無料という意味ではなく自由という意味で、自由にソフトウェアをコピーしたり再配布したりソースコードを確認・変更できることを意味する。
また、Linuxカーネルは「バザール開発」と呼ばれるオープンな新しい開発方式を用いて、インターネットとメールを通じたゆるやかな集団として開発が行われており、たくさんの「善意のボランティアの貢献者」によって開発されている。「伽藍とバザール」という論文を書いたエリック・レイモンドは、「数千人の片手間のプログラマによって超一流のOSが生み出された破壊的現象」と記述していて、これがMicrosoftとのブラウザ戦争に負けたNetscapeがブラウザを存続させるためにオープンソース化した「Mozilla.org」の動きにつながる。今では、アフリカ発のUbuntu南アフリカ人によって開発)など全く目的や理想の違う人々とともに開発されている。
また、最近ではIBMIntelなどの巨大企業もLinuxのオープン開発に参加するようになっていて、特にRed Hatのようなオープンソース企業はGPLでソフトウェアをライセンスしながら、長期サポート(セキュリティホールやバグの修正)によって利益を上げている。

ソフトウェア開発とオープンソース精神

OSのようなソフトウェアは、「パソコンでコードが動いている」という理解をしている人が多いと思いますが、このコードは、どのパソコンでも基本的に同じコードが動いています。
場合場合によって、異なる使い方がされるプログラムのコードですが、コード自体はどの実行状況でも同じコードが動きます。
開発者は、全ての使用ケースを想定しながら、どんな状況にでも対応できるように、コードを書かなければなりません。
ですが、「どんな場合にも対応できるようにコードを書く」ということは、とても難しいことです。
ソフトウェアのバグにはたくさんの種類や状況がありますが、単なる書き間違いのバグや、言語やプラットフォームや使用する技術のことを不勉強だから起きるバグや、アルゴリズムそのものが実装できていない「作りかけ」のバグだけではなく、こうした「想定外」の状況が起きることで、使用されると思っていた状況だけではない状況でそのプログラムを動かすことで起きるバグ、というものもあります。(ほかにも、設計そのものが間違っていたり、機能を増やすことで従来の設計が成り立たなくなったり、そもそも作りたいと思っていた完成形のソフトウェア像や要求された仕様そのものに間違いがあることもあります。)
こうした「想定外のバグ」は、商用企業はお金を儲けることでそのお金を使ってバグを直しますが、それでも、ひとつの会社がクローズドソースでテストし修正するバグ修正には限界があります。
これに対して、オープンソースでよく言われるのが、「目玉がたくさんあれば、どんなバグも深刻ではない」という考え方です。
これは、ソースコードをオープンに公開し、同時にたくさんの参加者がそのコードを「使用する人間自らがチェックする」ことで、みんなでバグがあるかどうかを確認し、それぞれがそれぞれの環境でテストし、バグを修正することで、どんなバグでも直すことができる、という、「ハッキング性善説」のような考え方です。みんなでハックすれば、どんなバグでも必ず修正できる、という理想郷のような考え方がLinuxにはあります。
ですが、これはユーザーが開発者と同じ能力やスキルを持っている場合に限られます。そのため、オープンソース界では、「Do-it-yourself」という精神がよく言われます。ユーザーには開発者と同等のスキルや知識、あるいは開発者よりも高い技術が求められます。最初から、そうした「できる人材」だけを求めていて、使えないソフトウェアがあった場合には、自分の手間や時間を捧げて「自分で使えるものになるように改良する」という精神が求められるのです。
また、WindowsはそもそもMicrosoftの利益のために開発されており、ユーザーが広がっても得をするのはMicrosoftに限られます。Windowsユーザーの利益にもなるとは思いますが、使い続けるためにはお金を払わなければいけません。これに対して、オープンソースソフトウェアは、「使うのも作るのも自分たち」であるため、力を持つのはユーザー自身です。そのため、オープンソースで開発すること、それを外部に無償で貢献することは、「ソフトウェア業界全体の公共の利益」になると言えます。

プログラムからハードウェア機器を操作しやすくする仲介役

OSとは、ソフトウェアとハードウェアの間に入って、ソフトウェア(プログラム)からハードウェア(実際の電子機器)を操作しやすくする、仲介役として使われる「基本ソフトウェア」です。
OSは、ハードウェアの操作のために必要な「低水準な処理」と、ソフトウェアからそのハードウェアを操作するための「システムインターフェース」を提供します。
OSがあるために、プログラムからハードウェア機器が操作しやすくなり、たとえばopen/close/read/writeというシステムコールでストレージデバイスの中のファイルシステムを簡単に操作したり、socket関数を利用することで実際のネットワークプロトコルを意識しなくても、ネットワーク機器による通信をプログラムから簡単に実現できます。
現代的なOSでは、ハードウェアを単純に操作する以外に、多くの機能を提供します。
たとえば、仮想CPU(非常に短い時間で複数のプログラムを順番に実行することで並列処理を実現する)や仮想メモリ(仮想アドレス空間を導入することで、プログラムが使う仮想メモリ領域を現実の物理メモリ領域に変換し、たくさんのプログラムを安全に同時実行する)といった機能によって、マルチタスク(同時に複数のプログラムを実行する)が実現されます。
ほかにも、UNIXにはカーネルとユーザーランドの権限を分け、ユーザーのデータを他のユーザーから見えなくするマルチユーザーの機能があり、ひとつの中央コンピュータを複数の端末から同時にログインして使うことができます。
また、デバイスドライバを使うことで、個々のデバイスの詳細を知らなくても、同じインターフェースからデバイスを操作できます。割り込み機能によって、デバイスの処理を待っている間、OSは別の処理を行うことができます。
ストレージデバイスにおいては、ファイルシステムにより、記録媒体の低レベルな処理をしなくても、ファイルやディレクトリを使ってストレージデバイスの中のデータを読み書きできます。UNIXファイルシステムは、入出力機構と統合されており、コマンドの入出力は簡単にファイルに読み書きできます。
またネットワーク通信の機能があることにより、クライアントとサーバーの双方で、細かい方式やプロトコルを知らなくても、たとえばLANにおけるイーサネットTCP/IPによる通信ができます。
こうした機能を提供するソフトウェアを、OSの中核という意味で「カーネル」と呼びます。LinuxなどのOSの設計では、ハードウェアデバイスとソフトウェアの間に必ずカーネルがあり、カーネルを通じてプログラムはデバイスにアクセスします。
Linuxのように、カーネルの全ての機能を、ひとつのプログラムとして実装した一枚岩で実装したものを「モノリシックカーネル」と呼び、MachやL4のように、カーネルには最低限の機能だけを実装し、あとはサーバーとして実装したものを「マイクロカーネル」と呼びます。マイクロカーネルは新しい発想ですが、処理の効率や性能に問題があり、実装も難しいため、Machを元に開発されているGNUHurdは、今でも完成されていません。
また、カーネルの上で動くソフトウェアとして、UNIXのコマンドツール(GNU CoreutilsやコマンドシェルのBash、vi/Emacsエディタなど)やCライブラリのlibc、コンパイラやリンカなどを集めたGNUツールチェイン(GCCなど)、WindowsのようなGUIインターフェースを提供するX Window System、あるいは書籍を出版するための組版システムTeXなどがあります。こうしたライブラリや低水準のソフトウェアを使うことで、システムの機能を拡張でき、標準Cライブラリ関数のさまざまな機能を使ってプログラムを開発するなど、「もっとたくさんのことができる」ようになります。また、ApacheJava/Tomcat/JBossのようなミドルウェアカーネルの上で動かすことで、エンタープライズ向けの機能を使うことができます。こうしたソフトウェアを含めて「広義のOS」と呼びます。そして、この広義なOSとしてのLinuxを呼称する際に、カーネル以外のソフトウェア・システムとしてGNU由来のソフトウェアを多く採用しているため、GNUは「LinuxではなくGNU/Linuxと呼んでほしい」と主張しています。Debian GNU/Linuxなどは、そうしたGNUの意見を踏まえて名称を決定しています。
Linuxカーネルオープンソースであり、OSの設計図が公開されており、簡単にコピーや改造や再配布ができます。Linuxカーネルはモジュールという単位でカーネルの機能を分割したり動的読み込み(最初の起動時にはその機能を読み込まず、必要になった段階で動的に読み込む)ができます。必要のない機能は削除できるほか、自分でコードを書き直したり分割したりすることもできるため、別の技術者が改良したりカスタマイズすることに長けています。このため、組み込みやIoTなどの「パソコン以外のOS」に搭載されることも多く、モバイルOSであるAndroidカーネルLinuxを使っています。最近では自動車などでもオープンソースで安定しバグの少ないLinuxのコードベースが利用される機会も増えています。
ですが、LinuxGNUによるGPLと呼ばれるライセンスで配布されており、このGPLではGPLで一度配布されたソフトウェアを再度配布したい場合には、GPLに基づいて配布しなければなりません。よって、Linuxをカスタマイズして作った派生版Linuxカーネルは、元のLinuxと同じようにGPLで配布する必要があります。これには、派生ソフトウェアや一部のソースコードを利用して作られたソフトウェアも含まれます。こうしたLinuxカーネルの「厳しいライセンス」に比べて、Linuxと同様のUNIX系のOSカーネルとして、FreeBSDNetBSDOpenBSDがあり、これらはBSDライセンスと呼ばれるライセンスで提供されています。BSDライセンスでは、再配布する際に同じライセンスで配布する必要が無く、商用利用のためのコードベースとしてはLinuxよりも優れています。
また、最近のパソコン向けのOSは、インターフェースがコマンドラインではなく、グラフィカルなウィンドウシステムを搭載しています。最近は、OSと言えばこうした「GUIインターフェース」を指すようになりました。Windowsでは、カーネルと統合されたデスクトップ環境(Explorer)が動作しますが、Linuxではこうしたウィンドウシステムはカーネルと統合されていません。X11と呼ばれる専用のディスプレイサーバーソフトウェアの上で、GNOMEKDEといったそれぞれのデスクトップ環境を動作させることができます。GNOMEを使う場合はGNOMEのインターフェース、KDEを使う場合はKDEのインターフェースを用いながら、GNOMEアプリケーションやKDEアプリケーションを利用できます。
LinuxWindowsに比べてあまり普及していないのは、Windowsの囲い込み戦略によります。WindowsではMS-Officeなどを抱き合わせて販売し、そのファイル形式が広まることで、結果MS-Officeが必要となり、他のOfficeを使うことは現実的でなく、LibreOfficeのように互換性のある無料Officeがあったとしても、「せっかく買ったMS-OfficeをLibreOfficeと引き換えに失うのは避けたい」という心理が働くため、結果MS-Officeを使わざるを得ません。ですが、Windowsは昔はフリーズとバグの多いOSでしたが、最近はWindows 9x系のカーネルWindows NTカーネルに書き直し、また.NET Frameworkと呼ばれるJavaと同様の機構を使うことで、最近は安定して動くようになりました。サーバーなどの用途ではLinuxが使われる機会が多いですが、デスクトップなどの用途ではLinuxオープンソースMicrosoftに負けています。これは、単なる競争というよりも、「IT資本主義とオープンソース共産主義の戦い」であると言えます。Microsoftは資本主義の大企業であり、とても長大な利益をあげて、その利益によって製品を作っているため、UNIXの基本設計がいくら優れていても、オープンソースと比べて細部の品質やできが良く、今のWindowsUbuntuなどと比べて「どうして良いか分からなくなるような問題や不具合」が少ないため、Windowsもしばらくは「MSの信頼できるOS」として使われ続けるでしょう。
Windowsに比べたLinuxの良さは、「シンプルであること」ではないかと思います。Linuxというカーネルの上でコマンドが動く、言ってしまえばそれだけのシステムにすぎません。ごちゃごちゃとしたウィンドウシステムはありますが、それらはオープンに開かれており、自分の手で開発できます。こうした「開かれたシンプルさ」が、UNIXが長らくワークステーションで使われてきた理由ではないかと思います。そのため、systemdに代表されるようなLinuxの新技術は、たまにきわめて嫌われることがあります。「UNIXはシンプルであるべき」という格率のようなものがあるため、GNOMEKDEのような「巨大なデスクトップ環境」は多くの人に嫌われており、Xfceのような軽量なデスクトップ環境が好まれることも多いです。WindowsはOSにたくさんの機能を統合したため、複雑で致命的なバグの多いものになっています。特に、セキュリティホール脆弱性は毎度のことのように見つかっており、またMFCや.NETなどは複雑すぎて分かりにくいという一面があります。

OSはハードウェア抽象化であると同時にシステムの操作環境でもある

OSについて言えることとして、「ハードウェアとアプリケーションを繋ぐ抽象化・階層化レイヤー」であると同時に、「システムの操作環境」であると言えます。
カーネルはプログラムと現実の機器を「上手くつなぐ」という役割だけではなく、ユーザーが実際に操作するための「操作環境」でもあります。
そのため、単にカーネルだけでOSというのではなく、コマンドラインシェルやコマンドユーティリティ、X11なども合わせて、OSであるとするのが一般的です。
LinuxではGNUのツールを用いますが、LinuxGNUだけがLinuxの操作環境ではありません。操作環境をどこまでもカスタマイズでき、頑張って勉強して設定すれば、シンプルな環境からクールな環境まで、「自分の手でカスタマイズできる部分が多い」というのが、Linuxの操作環境としてのOSのひとつの特徴かもしれません。また、元々がコマンドラインオープンソースなOSであるため、スクリプトなどを書いて自動的に管理したり、多くのファイルに同じ処理をかけたりすることがしやすく、またソースコードを参考にすることで自分の手で動作を研究し確かめられる、という点も優れているでしょう。たとえば、同じホームページを作るのであっても、ブログで書くのであれば豪華な機能は使えますが、HTMLファイルのように自動的にスクリプトで大量のファイルに処理をかけるのは難しいかもしれません。前者がWindowsであれば後者がLinuxであると言えます。

OSとは

オペレーターとオペレーティングシステム

OSが開発される以前の昔のバッチ処理のコンピュータでは、オペレータと呼ばれる専門の技師が紙カードやテープなどに書かれたプログラムを適切に読み取り、コンピュータを適切に操作して実行・管理していた。
だが、コンピュータ技術が向上し、リソースにも余裕がでてくると、こうしたオペレータの役割をソフトウェアにさせることで自動化させることができるようになった。これをオペレーティングシステム(OS)と言う。
また、ビジネス的な観点から考えると、それぞれの処理専用のコンピュータを作らなくても、汎用的なコンピュータを作ってその上でOSを乗せることで、さまざまなプログラムをOSの上で実行することができるようになった。これにより、コスト削減と利益の向上に繋がった。

カーネル

カーネルはOSの中の中核機能であり、アプリケーションとハードウェアとの間に介入することで、プロセス管理、メモリ管理、ファイルシステム、ネットワークなどの機能を提供する。
モノリシックカーネルでは、単一のプログラムがカーネルの機能を提供するが、マイクロカーネルでは、カーネルの機能を複数のサーバーに分けて、カーネルは最低限の機能だけを提供するマイクロカーネルとし、カーネルやサーバと通信することでアプリケーションにさまざまな機能を提供する。
現在のUNIX系OSでは、カーネルモノリシックカーネルをベースとしてモジュールローディング機能を加えたものが一般的である。
後日注記:Linuxカーネルをモノリシックであることを理由に「時代遅れだ」と批判する人も居るが、これは当たらない。歴史上の多くのUNIXカーネルはモノリシックであり、Linuxも同様にモノリシックである。確かに、OSの研究では多くがマイクロカーネルに研究が移っているが、それでも現実的な処理速度や安定性を考えて、モノリシックカーネルは一般的な悪くない設計である。

OSの役割

OSの基本的な役割には以下のようなものがある。

ハードウェアの差異の吸収

WindowsIntel互換のCPUを用いたシステムであれば、東芝DynabookでもSONYVAIOでも動くように、ソフトウェアとハードウェアの間に入って、ハードウェアの差異を吸収し、OSレベルでハードウェアを抽象化し、ソフトウェアに対して共通のインターフェースを提供することで、同じプログラムをさまざまなハードウェアで動かすことができる。
これはIntelPC/AT互換機でしか動かないWindowsでは、あまり恩恵を受けられないかもしれない。だが、Linuxや*BSDのようにカーネルやlibc/コンパイラなどのレベルでさまざまなアーキテクチャに対応している移植性の高いUNIXでは、C言語で書かれた同じプログラムが、再コンパイルすることで、x86_64のアーキテクチャでも、PowerPCやARMのアーキテクチャでも、同じプログラムを動作させることができる。
また、カーネルC言語のレベルでは、ハードウェアに近いそれぞれのアーキテクチャ機械語のバイナリが動作するため、別のアーキテクチャで動作させるには再コンパイルが必要だが、Javaのようなミドルウェアを間に挟むことで、再コンパイルをしなくても別のアーキテクチャに対応することができる。

複数のプログラムの同時実行

UNIXWindowsなどのマルチタスクのOSでは、

  • スケジューラ機構・コンテキスト切り替え
    • 複数のプログラムの命令をとても少ない間隔で交互に動作させることで、複数のプログラムを実行させる。
    • CPUのレジスタ情報を退避させ、短い間隔で停止・再開させ続ける
  • 仮想アドレス機構
    • 複数のプログラムのメモリを、実アドレス空間ではなく仮想アドレス空間を与え、メモリとプログラムの間にカーネルが入って領域を管理することで、別々のメモリ領域をそれぞれのプログラムに安全に与える

を使うことで、複数のプログラムを同時に実行させることができる。これを「タイムシェアリングシステム」と呼ぶ。
また、特にUNIXのようなOSでは、複数の端末からひとつのコンピュータのリソースを安全に共有する技術が長けている。これをマルチユーザーと呼ぶが、こうしたシステムはネットワークと親和性が高く、ネットワークを通じて同じユーザー情報を共有したり、ファイルシステムをネットワークで共有したりすることができる。

ネットワークやファイルシステムレベルの簡単なインターフェースからの機能の提供

現代的なOSでは、ネットワークやファイルシステムの機能は欠かせないが、こうした機能を簡単なインターフェースからアクセスできるようにする。これは、UNIXではCライブラリやカーネルシステムコールを使って行う。
ファイルシステムは、ファイルやディレクトリといったツリー構造の外部記憶へのデータの取得・格納機構で、ストレージデバイスとともに使用する。WindowsではFATやNTFSLinuxではext4やXFSのような複数のファイルシステムを使うことができる。ネットワークはソケットと呼ばれるインターフェースを用いてTCP/IPなどの複雑な機構を簡単なものに抽象化できる。
ネットワークやファイルシステムのデータ資源は、IT用語では「リソース」と呼ばれる。こうしたリソースへのアクセス手段について、OSは共通で一般的な同じインターフェースを提供する。同じOSだけではなく抽象化されているため、WindowsLinuxは互いにソケットで通信することができる。

人間とコンピュータの接するインターフェースの提供

また、CUIのOSではコマンドラインシェルによって、コマンドで操作するユーザーインターフェースを提供する。
また、MacWindowsのようなGUIのOSでは、マウスのようなポインティングデバイスを使った、ウィンドウ、メニュー、ボタン、アイコンのような「視覚的に分かりやすい外見」による、直感的な操作を可能とする。
LinuxなどのX Window Systemを用いたGUIでは、ツールキット(ボタン・メニューなどのGUI部品集ライブラリ)がGTK+やQtを選べるほか、さまざまなデスクトップ環境やウィンドウマネージャが開発されており、こうした外見をカスタマイズして、さまざまなルック・フィールを使うことができる。

サーバーやデータベースのスループレットの向上

サーバーやデータベースにおいては、効率的にプログラムを実行することで、スループレット(性能)を向上させる。

現代的なOSの種類

OSには以下のようなものがある。

Windows

Microsoftによる商用のOS。DOSから進化したパソコン用のOSで、IBM PC/AT互換機とIntel CPUで動作する。現代のIT社会で広く標準的に使われている。標準的になった理由は、Windows 95のインターフェースがウィンドウ描画として革命的であったことや、OfficeやIEのようなアプリケーション・ソフトウェアが長らく標準的な地位を占めていたこと。オープンソースではないがIBM PC/AT仕様が標準化されているため、同じIBM PC/AT互換機であれば、ドライバなどがあればどの機種でも動作する。
実際のところMacLinuxに比べて特別優れているわけではないが、ビルゲイツが言うようにソフトウェアは「勝者が総取り」であり、90%以上のシェアを占めるため、「他のOSの存在を忘れてしまう」ような普及状況になっている。
1995~2000年に販売されたWindows 9xシリーズは、不安定かつフリーズしやすいとして不評だったが、それでもIBM PC/AT互換機のパソコンでGUIが使えることは画期的であり、多くのユーザーが不安定ながらも楽しんでWindowsを使った。そして設計と実装を書き直したWindows NTが開発され、Windows 2000やXPのような「IT黄金期」の時代を支えた。Windows NTは安定性が飛躍的に向上し、ほとんどフリーズしなくなった。まさに、金の力は恐ろしいものである。また、Vista以降では.NET FrameworkというJavaと同様の仮想マシン機構を大々的に使うことになり、ほとんどフリーズや強制終了がなくなった。
LinuxでもGUI環境が整いだした最近でも、Windowsが多くの場合使われるのは、LinuxGUIの方が不具合やバグが多い、それは致命的なフリーズを起こすものでなくても、ユーザーが実際に使用する場面を良く考えていないから起きる不具合が多く、またボランティアによるオープンソース開発にはフォントが少ないとか翻訳の質が悪いなどの限界があり、今でもWindowsが多くの場合使われている。
また、最近ではWSLという機能があり、WindowsでもLinuxと同等のUNIX APIを使うことができる。また新しいバージョンのWSL 2ではLinuxカーネルをそのままWindowsと共存させられる。このため、「WindowsでしかWindowsアプリケーションは動作しない」と今まで言われていたが、「UNIXアプリケーションもWindowsから利用できる」ようになってきている。ただしオーバーヘッドなどの問題もあるほか、DockerなどのコンテナアプリケーションがLinuxの上でのLinuxしか動作できないため、完全にLinuxの分野を食いつぶすほどには至っていない。

Mac

Appleによる商用のOS。アラン・ケイダイナブック構想をApple社のスティーブ・ジョブズが見学して作られた、GUIのウィンドウ操作としてはオリジナル的な存在。標準化はされておらず、Apple社独自のハードウェアでしか動作しないが、UNIXをベースとしており、UNIXアプリケーションを動かすことができる。デザインなどの分野で良く使われている。
Macには「デザイン哲学」のようなものがあり、先進性が高いが、「使いやすさよりも目新しさを重視する」というところがある。また、高スペックかつ高価で、多くのユーザーにとってみればコストパフォーマンスが悪い。だがデザイナーやiOSなどのモバイル系のプログラマには良く使われている。特にNeXTSTEPの技術をベースに開発されたMac OS X以降のMac(最近ではmacOSという名称になった)はプログラミング的にとても優れていて、Swiftのような新しいプログラミング言語を使うこともできる。またHTMLレンダリングエンジンのWebKitAppleによってKDEKHTMLをベースに開発され、Google Chromeなどでも同様の技術(WebKitからGoogleが派生したBlink)が採用されている。

UNIX

今ではもう化石のようなOSだが、昔のワークステーションと呼ばれる少し高価なコンピュータで動作するOSで、コマンドから操作し、たくさんの端末からひとつのワークステーションにログインして使用する。ネットワーク機能が優れていることで有名。
昔のOSだがコマンドラインでネットワークから操作するような用途に長けており、viやEmacsのような一部の神格化されたアプリケーションがあるなど、多くの意味でWindowsなどと今でも競い合っている。商用UNIXとしてはSolarisなどがあるほか、UNIX互換OSにはLinuxFreeBSDがあり、今では「UNIX=Linux」のような人間が増えている。
UNIXはOSとしての設計がシンプルであるほか、早くからタイムシェアリングシステムやネットワークを想定して設計・実装されているため、安定性や信頼性に優れており、この安定性はLinuxにも大きく引き継がれている。LinuxFreeBSDは、Windows 9xに比べてフリーズせずきちんと動く。だが、NTカーネルや.NETなどの新技術を頑張って作るMicrosoftの努力により、今ではWindows 7や10もかなり安定性が上がった。だがWindows Vistaや8にもあるように、Windowsはたまに期待外れのバージョンをリリースする。UNIXLinuxは古くから変わらない化石のような技術を使っていることもあり、多くのUNIXが安定したOSとして提供されている。

Linux

UNIX互換のOSで、UNIXIntelのパソコンでも使用できるということで1990年代に人気を集めた。オープンソースのOSであり、OSの仕組みを自分で研究したり、改造したりすることができる。専門の高度な知識があるシステム管理者向けに、サーバーやモバイルなど高性能・高信頼性や省力化が必要な部分で今でも使われている。
Linuxはインターネットのみんなで作った楽しいOSであり、その開発手法が「バザール開発」と言って有名になったが、そもそもは「フリーソフトウェアのOSを作る」というGNUストールマンの活動と成果がベースになっており、Linuxカーネルだけではなく、コンパイラ、サーバーソフトウェア、プログラミング言語、データベース、そしてウィンドウシステムやデスクトップ環境に至るまで、ほとんど全てのものがオープンソースかつ無料でフリーソフトウェアとして手に入る。そのため、インターネットインフラ的なハッカープログラマに好まれる。Dockerやgitのような一部の技術はどのシステムよりも最新のものであり、MicrosoftクラウドでのLinux OSの利用やgithubを買収するなど、今ではMicrosoftLinuxに対して多くのコミットメント(貢献)を行っている。
Linuxの弱点はアプリケーションの質が低いこと。Microsoft Officeの代替となるLibreOfficeや、Adobe Photoshop/Illustratorの代替となるGIMP/Inkscapeなどは、まだまだ進歩の途上であり、まともに使うことができない。また商用ソフトウェアはほとんどがWindows/Mac向けに作られていることが多く、Linuxではメーカーから提供されるドライバやファームウェアもないことがあり、プリンターなどの用途ではLinuxから印刷ができないことが多い。またLinuxの過去のバージョン全てをサポートすることは現実的ではなく、昔のRed Hat Linuxなどを使って作られたシステムは、Windows XPなどと同様サポートされなくなってセキュリティホールを生み出す。多くのLinuxは最新版とその以前のバージョンぐらいしかサポートしていない。このため、標準的なWindowsを使わざるを得ない。
ただし、一部のデスクトップアプリケーションはWindowsのものよりも無料で品質が高いことも少なくない。FedoraUbuntuを個人の趣味や遊びで使う用途では多くのソフトウェアがオープンソースかつ無料で試すことができ、開発にも簡単に参加できる。あるいはシステム管理のための用途として、特にサーバー管理者にとってはUNIX互換のツールや最先端の開発環境が手に入るため、一般的サーバーのシステム構築のために使いやすいシステムである。まさに、エンジニアを目指すなら一度は学びたいOSである。
後日注記:Intel CPUは32bit~64bitになり、一昔のHPやSunのワークステーションよりも優れたマシン環境になっている。この環境にLinuxを足すことで、いっぱしのワークステーションとして使うことができる。そのため、LinuxFreeBSDなどのIntel PC向けUNIX互換OSは、90年代末頃の時代に流行した。当時はUNIXと同じようにオープンソースソースコードが公開された、「フィンランド人のリーナスという学生が作った無料のOS」として有名だった。

FreeBSD

UNIXの直接の流れをくむBSDと呼ばれるOSを、PC環境で使えるようにしたもの。FreeBSDの他、NetBSDOpenBSDといった兄弟たちが居る。Linuxと同様にオープンソースであり、Linuxと遜色のない機能を持っている。
後日注記:PCで使えるワークステーションとしては昔からLinuxと同じくFreeBSDも良く使われており、大学のUNIXワークステーションなどでは多くがFreeBSDを採用していた。ただしLinuxの現れた時代にはさまざまな著作権などの問題があって、PC向けのBSDは長い間提供ができなくなっていた。

Android

Googleによるモバイル用のOS・ミドルウェアシステムで、Linuxカーネルをベースにしている。スマホのような小さな画面でも使えるようにインターフェースが工夫されており、タッチパネルディスプレイでタップすることで操作を行う。

IBM z/OS

IBMワークステーションで動作するエンタープライズのOS。会社のシステムや信頼性が必要なインフラ基盤やデータベースで使われている。

UNIXの仕組み

ユーザーとグループ

UNIXにはユーザーとグループがある。すなわち、自分の所有するファイルは、他のユーザーから見ることはできない。
ただし、実際のところ、他のユーザーとも共有したいファイルがあるかもしれない。そういう時に、グループという機能を利用できる。
ユーザーは、所属ユーザーには読み書き実行を許可し、所属グループには読み込みだけ許可したりすることができる。このために、ファイルにはパーミッションと呼ばれる権限が定められている。
こうしたユーザーの仕組みに対して、ひとつ特権的なユーザーがUNIXには必ずあり、それを「rootユーザー」という。
rootユーザーは、全てのユーザーのデータにアクセスでき、全てのユーザーのプロセスに干渉できる。

プロセスとマルチタスク

UNIXでは、プロセスという「実行コンテキスト」を持っている。
プロセスはプログラムの意味でもあるが、複数のプログラムを順次実行するプロセスや、同じプログラムを実行する複数のプロセスというのも考えられる。
昔のOSでは、プロセスはひとつしか存在せず、CPUはプロセスが専有し、メモリのアドレス空間はひとつだけだった。
UNIXマルチタスクと呼ばれる仕組みを採用しており、タイムシェアリングシステムとも呼ばれる。
UNIXでは、プロセスは複数同時に実行でき、それぞれのプロセスが別々のアドレス空間を持つ。
そのために、プログラムをそれぞれ別々に実行するスケジューラと呼ばれる機構があり、複数のプログラムを時間ベースで次々に切り替えて実行する。
実際は、プログラムを実行している時に別のプログラムの実行が要求されると、プログラムはレジスタなどの必要なデータをレジスタ外に退避させ、そのプログラムを停止する。そして新しいプロセスが実行される。スケジューラによって次々にこの切り替え命令が実行される。切り替えが行われると、今動いているプロセスを停止して別のプロセスを実行できる。
また、プロセスの持つアドレス空間は、実際にアクセスされる前にカーネルによって翻訳される。よって、プログラムがメモリを使用するために必要なアドレス空間を、それぞれのプログラムの中に「閉じる」ことができる。

ファイルとディレクト

ファイルはデータの保管を抽象的に扱ったもので、プログラムはデータをストレージに保管する際にファイルとして保管する。
UNIXでは「原則ファイルとして扱う」という哲学があり、デバイスドライバによって操作されるデバイスもファイルとして扱われる。
また、ディレクトリはファイルを集めてひとつの場所に格納するもの。

絶対パス相対パス

絶対パスはルートディレクトリ(/)から始まる絶対的なファイルの場所のこと。
相対パスは、今の自分のいるディレクトリ、すなわち「作業ディレクトリ」から始まる相対的な場所のこと。
通常、ファイル名だけでアクセスする時は、作業ディレクトリからの相対パスとして扱われるが、「/」から始まるパスを指定すると絶対パスとして扱われる。
相対パスにおいて、「.」は現在のディレクトリ、「..」は現在のディレクトリの上のディレクトリ(親ディレクトリ)を表す。「./hogehoge」とすることで、現在のディレクトリの中にあるhogehogeを指定できる。

リンク

ファイルには、名前が設定されるが、この名前は本当は複数設定できる。名前のことをリンクあるいはハードリンクという。
だが、さまざまな制約(ユーザがディレクトリに対するハードリンクを作れないことや、同じファイルシステム内のハードリンクしか作れないこと)があることから、通常ハードリンクは使われなくなった。ハードリンクは名前を複数設定するだけのものだが、これに対して、小さなリンク専用のファイルを作ってそこからパスを辿っていく、ソフトリンクあるいはシンボリックリンクが広く使われている。
ファイル、ディレクトリ、シンボリックリンク、ブロック型デバイスファイル、キャラクタ型デバイスファイルのほか、名前付きパイプやソケットなどもファイルとして扱われることがある。

ブロック型デバイスとキャラクタ型デバイス

バイスファイルには複数の種類があり、ブロック型デバイスとキャラクタ型デバイスと呼ばれる。
ブロック型デバイスはデータの蓄積として扱われ、別々のファイルを前後しながら読める。キャラクタ型デバイスはストリームとして扱われ、別々のファイルを読むことも、前後して読むこともできない。
一般的に、ブロック型デバイスファイルシステムに「マウント」されてファイルを読み書きするために使われる。キャラクタ型デバイスはマウスやキーボードなど、「バイト列を読む」ために使われる。
これとは別にネットワークインターフェースのデバイスドライバがあり、通信に利用し、デバイスファイルからの読み書きはできない。
実際のところ、Linuxではデバイスドライバによって感知されたデバイスは/devディレクトリの中にファイルができる。これをデバイスファイルと呼ぶ。
プログラムがデバイスファイルにアクセスすると、対応するI/Oデバイスを用いて、デバイスを直接触ることができる。

シェルとコマンド

コンソールのUNIXが起動すると、ログインとパスワードを要求する。パスワードを入力するとパスワードを確認するプログラムが実行され、ログインできるとコマンド入力を受け付けるシェルが実行される。
ただし、XなどのGUI環境ではこの限りではない。通常はウィンドウシステムと、ウィンドウの操作を行う「ウィンドウマネージャ」が別プロセスとして起動し、それぞれの画面を構成するそれぞれのプロセスがたくさん起動する。ターミナルエミュレータを開くと、そのターミナルのウィンドウとシェルのプロセスが起動し、シェルから別のプロセスを実行する。
コマンド操作環境では、プログラムのバイナリ名を指定して、その後にスペースを開けて引数やオプションを指定する。バイナリは環境変数のPATHの中から検索される。引数にはプログラムに与えるファイルのファイル名などを指定する。オプションは-abcのようなショートオプションと、--helpのようなロングオプションがある。

カーネルモードとユーザモード

UNIXカーネルは、CPUのカーネルモードとユーザモードという「ハードウェアの機能」を利用して、カーネルとユーザーの世界を分けている。
UNIXで実行されるプログラムは、多くの場合ユーザーモードで実行される。カーネルの機能が必要になった段階で、ユーザーはシステムコールを通じて、カーネルに処理を要求する。これに応える形でカーネルカーネルモードにプログラムを切り替えて処理を切り替えて、カーネルモードでプログラムを実行する。
現代的なUNIXカーネルでは、カーネルカーネルスレッドの集合体として設計されることがある。この時、カーネルスレッドの切り替えはプロセスの切り替えよりも素早く、効率的に行われる。

割り込みと同期処理

カーネルは、常に多くの割り込み処理、すなわち目的のプログラムを実行し続けながら、ハードウェアからの応答に対応してプログラムの実行を切り替える必要がある。
このために、カーネルの中では「同期処理」が行われる。必要とあれば、カーネルはロックを行う。

シグナルとプロセス間通信

プロセスに対して「強制終了せよ」という命令を下すために、UNIXカーネルはシグナルと呼ばれる機構を採用している。
また、プロセスとプロセスの間でデータを共有するために、プロセス間通信(IPC)という機構をUNIXは採用していることが多い。

移植性

Linuxはそもそもリーナス・トーバルズによってx86システム向けに設計されたが、さまざまなカーネル開発者によって他のCPUアーキテクチャに移植された。
これらの機種依存のコードはarchサブディレクトリの中にある。多くはC言語アセンブリ言語で記述されている。

標準規格

UNIXにはPOSIXのような標準規格がある。POSIXでは、UNIXカーネルのインターフェース部分についての標準化が行われている。
そのため、別のUNIXで動いていたコードは、Linuxでも動く場合がある。標準的なシステムコールしか使っていない場合は、何の変更もパッチも当てなくても、そのまま動く。
POSIXではインターフェース部分の標準化しか行われていないため、カーネルの内部については干渉されない。カーネルがどのような設計で実装されていても、カーネル開発者の自由である。

カーネルの開発体制

Linuxカーネルは、商用UNIXとは違い、商用の企業目的で機能が実装されない。このため、不安定かつ使えない機能が大々的な宣伝とともに採用されることが少ない。
Linuxカーネルは、自由に開発されており、また、効率を重視して機能が採用されている。このため、非効率的な機能(STREAMSなど)をリーナスが却下することもある。

カーネル

レジスタとメモリ

実際のところ、レジスタとはCPU内部の高速なメモリに過ぎません。ですが、レジスタ機械語で命令の処理に使われるため、小さく、少なく、そしてプログラムの実行にとって重要です。そのため、レジスタは少ない領域のものを、プロセスを切り替えるたびに「読み込んだり退避したり」します。
これに対して、メモリは低速で、大容量です。このため、それぞれの領域に分割して、プロセスがそれぞれのアドレス空間を持ち、機械語の命令としてメモリにプロセスがアクセスしようとした時は、カーネルが仲介して論理アドレス物理アドレスに翻訳するのです。
そのため、コンテキストの切り替えは比較的容易です。ソフトウェアだけで実現できます。
メモリ管理を行うためには、ハードウェアの機能を用いてカーネルが仲介し、論理アドレスをリニアアドレス・物理アドレスに変換します。この時、ハードウェアのセグメンテーション回路とページング回路を利用します。また、それぞれのメモリ領域はページと呼ばれる単位でカーネルによって管理されます。

割り込みとは

要するに、ハードウェアの要求をカーネルが待っていると遅いので、カーネルが待っている間別の処理をし、ハードウェア側で何かあったら「割り込み」としてカーネルの処理に割り込んでくる、という仕組み。

シグナル

以下の内容は、ふつうのLinuxプログラミング Linuxの仕組みから学べるgccプログラミングの王道を参考に執筆・編集して引用しました。
カーネルによるデフォルトのシグナル扱い時の挙動は3つ。
1.無視する
2.プロセスを終了させる
3.プロセスのコアダンプを作成して異常終了させる
この挙動はプロセスが変更することもでき、挙動を変えてやれば、デフォルトで無視されるシグナルも役に立つ。
後日注記:この説明は間違っているかもしれません。@ITの記事によれば、「無視」「プロセスの強制終了」「プロセスの終了とコアダンプ出力」「一時停止」「停止中の場合は再開」がデフォルトとなっています。
シグナルの挙動をカーネル任せにせずプロセスで処理することを「シグナルの捕捉」あるいは「トラップ」と呼ぶ。
シグナル捕捉インターフェイスはsignal(2)で、UNIXの最初期から存在する。
後日注記:signal()は単純だがさまざまな点から問題があり古いため、新しいプログラムであればsigaction()を使うべきだとされている。

カーネルの手動コンパイルの方法

Linuxカーネルは、手動でコンパイルすることで、さまざまなオプション機能を有効にしたり、無効にしたりすることが出来る。各機能は有効・無効あるいは動的にいつでも読み込めるモジュールにすることができる。
カーネルの手動コンパイルの方法は、
1./usr/src/linux-3.16.5-mykernel(/usr/src/linuxにリンクを張ることが多い)などにカーネルソースを展開してクリーンナップ(make clean && make mrproper)し、
2..configファイルをmake menuconfigで作り、
3.makeやmakeコマンドのその他のオプションでカーネルカーネルモジュールをコンパイル(make && make modules_install)し、
4.ブートパーティションにbzImageをコピーする(make install)

カーネルモジュールの手動ロード

カーネルモジュールは*.koという拡張子で、/lib/modules/にある。
カレントディレクトリにあるkoファイルのロードは以下のようにする。

# insmod hello.ko

ロードされたドライバはlsmodで確認できる。

# lsmod
(ドライバが表示される)

アンロードはrmmodで行う。

# rmmod hello

modprobeコマンドを使うことで、カレントディレクトリのkoファイルではなく、「/lib/modules/`uname -r`」からドライバを探す。RCスクリプトなどでLinux起動時にドライバをロードしたい時などによく使われる。

カーネルモジュールの設定

カーネルモジュールを手動で読み込むためには、/etc/modules-load.d/*.confに自動的にロードしなければならないモジュールを改行区切りで記載する。
モジュールのオプションは/etc/modprobe.d/*.confに記載する。
基本的にはudevが自動で検知したハードウェアのモジュールをロードするため、手作業で行う必要は必ずしもない。

コンパイラとリンカ

コンパイラインタプリタ

コンパイラとは、プログラミング言語で書かれたソースコード機械語に翻訳するアプリケーション。一度のコンパイルで全てを機械語に変換する。
インタプリタとは、プログラミング言語を「動的に」読み込みながら、逐次機械語の命令に翻訳していくアプリケーション。

プログラムとライブラリ

UNIXにおいては、プログラムには二種類ある。それは「プログラム」と「ライブラリ」である。
main関数が含まれたプログラムには、実行命令が下ると即座にmain関数から実行を始める。多くのコマンドプログラムや自立したアプリケーションはこちらに当たる。
これに対して、main関数が含まれていないライブラリと呼ばれるプログラムは、それ単体では実行できない。
ライブラリは、別のプログラムから呼び出される形で実行される。
ライブラリは、さまざまなプログラムに点在する「呼び出し命令」に基づいて、プログラムの中で下請けの専門業者のように、必要なところで必要な時に実行される。
ライブラリやその呼び出し規約を「API」と呼ぶ。このAPIに基づいた命令によって、プログラムは「難しい機能でも簡単に呼び出せる」ようになり、たとえばCの標準APIが含まれるlibcや、X11APIが含まれるxlib、あるいはGTK+やQtのようなツールキットなど、さまざまな命令や機能を「自分のプログラムから呼び出したい」時に、こうしたAPIを使う。
ライブラリAPIを使うことで、全てのことを自分で作る必要はなく、ライブラリを呼び出す形で簡単に高度で複雑なプログラムを開発できる。

コンパイラとリンカ

通常、Cのソースコードコンパイルすると、プリプロセス(#includeのようなマクロ処理を行い、ソースコードコンパイルできる形式に整形する)、コンパイルC言語の文法を解釈してアセンブリ言語に変換する)、アセンブルアセンブリ言語機械語に変換する)が行われ、この時点で機械語のオブジェクトファイル(*.o)が作られる。
このオブジェクトファイルは機械語で記述され、ELFという形式のフォーマットに保管される。そして、リンカがこれらのオブジェクトファイルをそれぞれリンク(それぞれのオブジェクトファイルでの関数などの呼び出し情報を結合する)して、実行ファイル(Linuxでは特に拡張子はつかない)またはライブラリ(*.aまたは*.so)を作って、実行可能なプログラムになる。
それぞれのオブジェクトファイルはリンクの段階でプログラムあるいはライブラリになる。プログラムは実行ファイルとしてそのまま実行されるが、ライブラリは他のプログラムから呼び出されて実行されるため、特殊な形式のオブジェクトファイルに変換される。これが、静的ライブラリ(*.a)あるいは動的ライブラリ(*.so、共有オブジェクト)と呼ばれるものである。「libc.so.6」のようにバージョン番号がつくこともある。
静的ライブラリは、スタティックリンクと呼ばれ、コンパイル時に作成するプログラムに物理的に連結される。
一方、動的ライブラリは、ダイナミックリンクと呼ばれ、ビルド時には最終的なコード結合を行わず、必要な関数が存在するかだけチェックされる。そのライブラリを呼び出すプログラムが実行された時(実行時)に、リンクローダによってメモリ上で動的に結合される。よって、実行されるまでは、どのプログラムに結合されるかは分からない。
現在Linuxで使われているリンクローダは/lib/ld-linux.so.2で、実行ファイルの中にリンクローダの名前が記載されており、カーネルがプログラムの起動時にそれを見て処理する。また全てのプログラムは暗黙のうちにlibc.so.6とダイナミックリンクされている。これらはlddコマンドで確認できる。
基本的に、スタティックリンクとダイナミックリンクでは、ダイナミックリンクを用いるのが一般的だが、Muslなどのように一部スタティックリンクに最適化された軽量なCライブラリなどもある。

/binと/lib

/binディレクトリには、実行可能ファイルを置き、/libディレクトリには共有ライブラリ(*.so)を置くのが一般的。
また、/usr/binや/usr/libがある環境では、/binや/libにはシステムを起動し管理するための最低限のプログラムを置き、アプリケーションプログラムなどは/usr/binや/usr/libに置く。これにより、もし/usrディレクトリが破壊されても、/binや/libが残っていればシステムの復旧や最低限の管理を行うことができる。

/etc/ld.so.confとldconfig

/etc/ld.so.confは、共有ライブラリがどこにあるかを指定するパスが含まれた設定ファイルで、ldconfigはこの情報をOSに伝えるコマンド。

シェルとコマンド

ユーザーとカレントディレクトリ・ホームディレクト

UNIXにはユーザーやパーミッションという考え方があり、シェルにログインしプログラムを実行するユーザーによってプログラムが実行される「権限」が決められる。
また、UNIXコマンドラインシェルには「カレントディレクトリ」という考え方がある。これは、今の作業ディレクトリを意味しており、シェルには常にカレントディレクトリがどこであるか、という情報とともに、プログラムを「環境として」実行することができる。
また、各ユーザーには「ホームディレクトリ」というディレクトリが与えられる。これは/home/usernameに存在する。この中で、ユーザーは自由なデータやファイルを保管し、自由に作業することが出来る。
また、システムには管理権限を持つrootユーザーが一人存在し、システムを変更・破壊する権限を持つ。パッケージ管理システムなどでシステムをアップデートする場合は、root権限が必要な場合がある。シェルでrootユーザーになるためには、

$ su -
(rootユーザーのパスワードを入力)
#

と実行する。一般的に、通常ユーザーのシェルは$から、rootユーザーのシェルは#から始まる。コマンド入力例などでこの例があった時、$や#を入力する必要はない。(上の例では、通常ユーザーのシェルにsu -と入力すれば良い。$を入力する必要はない。)
sudoというコマンドを使うことで、いちいちrootユーザーにならなくても、特定のコマンドをrootユーザーで実行することが出来る。Ubuntuなどの一部の初心者向けディストリビューションではこちらのスタイルがとられる場合もある。

パイプとリダイレクト

あるコマンドを実行した結果の出力を、他のコマンドの入力として渡せる「パイプ」と、入出力とファイルを変換できる「リダイレクト」。
たとえば

find ~ | grep "2012"

とすることで、ホームディレクトリにある、「2012」を名前とパスに含むファイルを列挙出来る。
findで~の中を「サブディレクトリまで含めて」列挙し、そこからgrepで名前を検索する。
パイプは、使うとやみつきになる。UNIXは、こうした多数のコマンドプログラムに分けながら、ユーザーが自分の力で環境を操作することを哲学としている。

シェルスクリプト

基本的に、コマンドをそのまま列挙したファイルを作って、実行すればシェルスクリプト
だが、引数や関数定義が使えたり、if文なども出来るなど、応用範囲は多い。
UNIXでは、何でもかんでも再利用することで、応用性のあるシステム設計を行っている。

シェル変数と環境変数

コマンドライン環境の中で利用できる、変数のようなもの。
シェル変数と環境変数がある。シェル変数はシェルの中だけで保たれ、起動したプロセスには引き継がれない。シェル変数は、

$ FOO=foo

と設定する。
一度シェル変数を設定した上でexportすることで、環境変数を設定できる。

$ export FOO

コマンドのバイナリファイルを探すPATHやユーザーのホームディレクトリを探すHOMEなどが有名である。

コマンドの詳細

コマンドの詳細は、manと言うコマンドで見ることが出来る。

$ man ls

コマンドラインオプションは、例えば、詳細表示をしたい時は、以下のように使う。

$ ls -al

それ以上のコマンドの詳しいことは、manを参照のこと。manは、設定ファイルについても調べることが出来る。

ログイン・ネットワーク・セキュリティ

UNIXではマルチユーザーという仕組みを採用している。これによって、端末にログインし、その中のリソースにどのようにアクセスするかを、パーミッションという仕組みで管理することができる。
Windowsなどに慣れたユーザーからは考えづらいかもしれないが、Linuxはユーザーにログインして作業する、ということが一般的である。
ログインはローカル資源だけではなく、ネットワーク資源についても言える。SSHなどを使ってネットワークログインし、ネットワーク上で作業することもある。また、Apache httpdなどでは、外部ユーザーにネットワークからプロセス実行要求することもある。
ログインとパーミッションでは、コマンドを実行するユーザーに対して、そのファイルにどれだけアクセスできるのか、という考え方をする。一般ユーザーは/usr/binなどのシステムディレクトリは「破壊」することはできないが、自分の作業ディレクトリの中で自分のファイルを操作・処理するために「利用」することはできる。
ユーザーにはホームディレクトリが与えられ、この中にデータを保存して作業する。だが、大切な顧客のデータをホームディレクトリに保存することはできるだけ避けたい。SQL関係データベース管理システムを用いて、バックアップも定期的にとることが勧められる。ホームディレクトリを簡単な作業のために使うか、あるいは大事なデータの置き場所にも使うかは議論の分かれるところであるが、SQLサーバーなどを使うこともできるし、専用のユーザーを作って普段そのユーザーを使わないようにしても良いだろう。ApacheはホームページデータをDocumentRootで指定するが、/var/www/htmlなどを指定することが多い。
このほか、システムを「破壊」できるrootユーザーに制限をかけたり、HTTPなどのプロセス単位で制限をすることのできる、SELinuxというセキュアなLinuxも利用することができる。
UNIX系のOSでは、ログイン端末とユーザーの使うコンピュータを分けるなど、「コンピュータの分業化」が比較的やりやすいと言われる。ネットワーク透過なX端末のような発想はここから生まれている。だが、現代的な「パーソナルユーザー」が使うパソコン用OSとしては、少し古びて見えるかもしれない。だが、今日のGNOME/KDEなどは、Windowsの統合などを大きく超えている。GmailGoogle Driveのようなネットワーク上のサービスにログインしてファイルマネージャからアクセスしたりすることは容易である。だが、伝統的な仕組みも今なお提供されており、NFSなどを用いてネットワーク上にファイルサーバーを作ることも簡単にできる。

ファイルシステム

ファイルシステムの基本

UNIXでは、ハードディスクやUSBメモリのようなストレージデバイスの中のデータは、ファイルシステムと呼ばれる決まりによって扱われる。
ファイルシステムにおいては、全てのデータはファイルという単位で格納され、複数のファイルをひとつにまとめる(ひとつの場所に置いてまとめて管理する)ためにディレクトリと呼ばれるツリー構造の階層を作る。
ディレクトリは、/(ルートディレクトリ)を一番上に、/usrや/homeや/etcなどの重要なディレクトリがある。
ストレージデバイスデバイスドライバによって認識されると、/devディレクトリにデバイスファイルができる。これは/dev/sdaのようになる(パーティションが区切られている場合は/dev/sda1や/dev/sda2のようになる)。
このデバイスファイルを、ext2のようなLinuxカーネルで使うことのできるファイルシステムにフォーマットすることで、このデバイスをマウントして使えるようになる。マウントとは、ブロック型デバイスファイルにアクセスするカーネルの機構であり、ext2ファイルシステムを一度作ってしまえば、そのデバイスは/以下のどこにディレクトリにもマウントすることができる。ファイルシステムを作ってマウントすることで、その中にファイルやディレクトリを作ったり、プログラムから読み書きしてデータを保存することが可能となる。
また、/dev/sdaxの最後のxはハードディスクを複数に分割するパーティションを意味する。パーティションはハードディスクを複数に分割する機能で、それぞれのパーティションを個別に別々のディレクトリにマウントすることができる。この時、それぞれのパーティションには別々のファイルシステムを構築できる(たとえば、/bootをext2で、/をext4で、といった具合)。パーティションファイルシステムをフォーマットする前に、事前にfdiskなどで作る必要がある。
Linuxでは、ファイルはコマンドに対して「ls /usr/bin」のように引数として与えることで、「/usr/binの中のファイルの一覧を表示しろ」という命令として使える。また、コマンドプログラムの中からは、open, write, read, closeのようなカーネルシステムコールや、システムコールにバッファ操作など使いやすい機能を加えたlibcのライブラリ関数(stdio)からファイルを操作できる。

パーティションの分け方

パーティションの分け方。簡単に言えば、/と/usrを分けると、/binなどは/に出来て、/usr/binなどは/usrに出来る。

マウント

マウントによって、デバイスファイルシステムとして、ディレクトリとして使うことができる。
UNIXではマウントという概念があり、ファイルシステムを作成したデバイスをデバイスファイルをとっかかりにマウントすることで、ディレクトリツリーにそのファイルシステムを追加し、ファイルシステムとしてその中のファイルを編集・操作することができるようになる。
例えば:

# mkdir /media/usb
# mount /dev/sdb1 /media/usb

パーティション設定ファイル(/etc/fstab)

パーティションを記載する設定ファイル。ここに記述されたボリュームはOS起動時に自動的にマウントされる。
NFSでネットワーク上にあるボリュームをマウントする場合も、同様に/etc/fstabを編集する。

Linuxカーネルファイルシステムの基本

Linuxカーネルがopen, write, readなどのシステムコールを受け付けると、カーネルの中でインターフェースとなるファイルオブジェクトが作成される。
ファイルオブジェクトが作成されると、

と関連付けられ、ファイルオブジェクトのポインタを返す。
カーネルの内部では効率化のために読み書き情報をキャッシュしており、iノードが実際に書きこまれたことを示すフラグのことをダーティビットと呼ぶ。
LinuxではVFSという機構を使っており、カーネル内のシステムコールであるsys_read(), sys_write()が、VFSの機能であるトランスレーションによって、ext2など具体的なファイルシステムの固有の関数に置き換えられる。
ext2Linuxで標準的に使われるブロック型ファイルシステム。データをデータブロックやスーパーブロックを持ったブロックグループに分けて管理する。
このほかに、データベースで良く使われる「Bツリー」(B木)という技術を応用したさらに高速・堅固なファイルシステムがある。その中でもReiserFSやXFSなどが有名だが、将来の標準候補であると注目されているのがBtrFS。
また、ジャーナリングに対応したext3/4のようなファイルシステムでは、システムを途中で強制停止した場合でもファイルの整合性を保ち、壊れることが無い。

Linuxファイルシステムの種類

基本的にext2, ext3, ext4, JFS, XFS, Btrfs, FAT, FAT32などがある。
Linuxでしかファイルシステムを使わない場合は、一番優れていて安心できるのはext4LinuxのルートファイルシステムLinuxのシステムをインストールするファイルシステム)にはext4を使うのが無難。Bツリーファイルシステムはまだまだ未熟である。
LinuxでもWindowsでも読み書きできるようにファイルシステムをフォーマットしたい時はFAT形式がおすすめである。USBハードディスクなどを使う場合でも、WindowsからもLinuxからも読む場合はFAT形式を使おう。

ジャーナリング

ext3ext4(現在のLinuxの標準)などのファイルシステムジャーナリングファイルシステムと呼ばれ、ジャーナリングによってシステムの整合性を保つ機能が搭載されている。
ジャーナリングに対応していないと、不意に異常終了した時にファイルシステムが破損する場合がある。

VFS

LinuxではVFSという機構を使うことで、各ファイルシステムの差異を吸収することが出来る。
プログラマやプログラムは各ファイルシステムの実装の詳細を知らなくても、VFSインターフェイスだけを使ってあらゆるファイルシステムに対応することができる。

B-Treeファイルシステム

ext2-4などのブロック型ファイルシステムには、ブロック数が対応するディスクのジオメトリ数に制限されること、ファイルサーチにO(n)かかること、ファイルサイズに関係するパフォーマンス低下など、いくつかの問題がある。
これに対して、ReiserFS、JFS、XFSなどのファイルシステムでは、早い段階からデータベース技術をファイルシステムに取り込んできた。これらのファイルシステムでは、「B-Tree」アルゴリズムが使われている。

B-Treeインデックスの基本

値を検索する時、一番単純なのは先頭から順に探していく方法だが、これでは時間がかかる。
速く見つけるためには、二分探索を用いて中央値より大きいか小さいかで次の検索対象を判断する。中央値より小さければ左に、大きければ右に進みながら検索する。
二分探索木は、二分探索しやすいように値を大小で振り分けたデータ構造。
AVL木は、木の高さが深くなりすぎないように、木の高さに変更があった時に回転を行うデータ構造(平衡木)。木を回転することで、ひとつのノードを上にし、別のノードを下にする。
B-Treeとは、1つのノードがm個(m>=2)の子ノードを持つことができる平衡木構造のこと。
B-Treeでは、まずルートノードから出発し、ほかに子ノードとリーフノードがある。ルートノードと子ノードはキー値と子ノードへのポインタを持つ。リーフノードの各ページは、キー値とデータ(保管されているデータ本体)へのポインタを持つ。
検索は、ルートノードから出発して、子ノードへのポインタに沿ってリーフノードを探す。まずルートノードに行き、検索値よりも大きな値のポインタが見つかったら、その左側の子ノードへ移動する。検索値よりも大きな値が見つからない時は、キーの最大値の右側の子ノードへ移動する。子ノードでも同じことを繰り返し、最終的に目的の値が存在しないとするか、リーフノードにたどり着く。
B-treeインデックス入門 - Qiitaを参考に執筆しました。)

さまざまなファイルシステム

ext2-4以外にも、

ファイルシステム 解説
btrfs さまざまな機能があるがまだ未熟
f2fs フラッシュメモリ向け
JFS IBMの信頼できるファイルシステム
ReiserFS 大量の小さなファイルがある場合向け
XFS 堅牢でスケーラブル

などの先進的なファイルシステムがあります。Windows向けのものとしてはvfat, NTFSなどがあります。
RHEL 7では標準のファイルシステムがXFSになったとのこと。結構メモリを食うらしい。
Btrfsは進歩の期待度が高い。将来デフォルトになるかもしれないそうだ。
ZFSLinuxではGPLとの兼ね合いで利用できないが、Btrfsの機能と良く似ているとのこと。
後日注記:最近はLinuxでもZFSを利用することができる。ライセンス問題を何とか解決しているようである。詳しくは自分で調べてほしい。

入出力APIシステムコール

システムコールとライブラリ関数

LinuxC言語によるAPIの基本は、システムコールとライブラリ関数です。
システムコールLinuxカーネルによる機能で、ストリーム、ファイルシステム、ネットワーク、プロセス、メモリ管理などで、カーネルの機能を使う時に使用します。
C言語のライブラリ関数は、主にglibcなどによる「標準Cライブラリ」です。
システムコールとライブラリ関数では、似たような機能を提供する関数もあります。
たとえば、システムコールのread(2), write(2), open(2), close(2)は、stdio版として、fopen(3), fclose(3), fgetc(3), fputc(3), getc(3), putc(3), getchar(3), putchar(3), ungetc(3), fgets(3), fputs(3), puts(3), printf(3), fprintf(3), scanf(3), fread(3), fwrite(3)などなど、さまざまなライブラリ関数があります。
ここで、(2)や(3)は、システムコール(2)かライブラリ関数(3)かを表しています。
システムコールは、バッファリングを行わないため、動作が遅いです。バッファリングだけの問題ではなく、ライブラリ関数よりもシステムコールの方がずっと遅いです。ライブラリ関数の方が普遍的なため、通常はライブラリ関数を優先して使いましょう。

四大システムコール

システムコールでは、ファイルの情報はファイルディスクリプタと呼ばれる整数値のデータを使って保持します。これはOSがストリームの識別のために使います。
以下は四大システムコール

  • open(2)
    • ファイルを開く。ファイルに接続するストリームを用意する。
  • close(2)
    • ファイルを閉じる。ストリームを始末する。
    • 使い終わったストリームはclose()で後始末しないといけない。
  • read(2)
    • ファイルを読み込む。ストリームからバイト列を読み込む。
  • write(2)
    • ファイルを書き込む。ストリームにバイト列を書きこむ。

ファイルと言うよりは、ストリームを読み書きします。ですので、標準入出力に読み書きすることも可能です。たとえばcatコマンドを作ったり出来ます。
また、四大システムコールの美しさを保つために、それ以外の雑多な処理は全てioctl()で行う。

  • ioctl(2)
    • バイスに特化した色んなことをやる。

stdioの基本関数

stdioでは、バッファリングを行うため通常はシステムコールよりも動作速度が速い。また、固定長バイトだけではなく、文字単位(バイト単位)や行単位での入出力ができる。
これらのCライブラリ関数では、FILE型のポインタを使ってファイルの情報を格納します。
FILE型はファイルディスクリプタのラッパーで、stdioバッファの情報も含まれています。

  • fopen(3), fclose(3), fread(3), fwrite(3)
    • ライブラリ関数の版。
    • バッファリングを行うため、通常はシステムコールより動作が速い。
  • printf(3)
    • printfはフォーマットされた文字列を出力出来ます。
    • 任意の文字列や変数の中身を展開して表示する場合など、良く使います。
  • scanf(3)
  • getchar(3)
    • バイト単位(一文字単位)で文字を入力できる。
  • putchar(3)
    • バイト単位(一文字単位)で文字を出力できる。

stdioの入出力

以下はさらに詳しい解説。

  • fopen(3)
    • open(2)に対応するライブラリ関数。
  • fclose(3)
    • close(2)に対応するライブラリ関数。
  • fread(3)
    • 固定長バイト列の入力。
  • fwrite(3)
    • 固定長バイト列の出力。

バイト単位入出力

以下はバイト単位(一文字)での入出力。

  • fgetc(3)
    • バイト単位(一文字)で入力するAPI
  • fputc(3)
    • バイト単位(一文字)で出力するAPI
  • getc(3)
    • マクロ。基本的にfgetc(3)と同じ。
  • putc(3)
    • マクロ。基本的にfputc(3)と同じ。
  • getchar(3)
    • 入力元をstdinに固定してバイト単位(一文字)で入力する。
  • putchar(3)
    • 出力先をstdoutに固定してバイト単位(一文字)で出力する。

行単位入出力

以下は行単位での入出力。

  • fgets(3)
    • 行単位での入力API。一行の文字列を入力できて便利。
  • fputs(3), puts(3)
    • 行単位での出力API。一行の文字列を出力できて便利。
  • セキュリティの問題があるgets()は廃止されました。

フォーマット入出力

  • printf(3), fprintf(3)
    • フォーマット出力。
  • scanf(3)
    • フォーマット入力。

使うべきでない関数

gets()とscanf()はバッファオーバーフローを起こす可能性があるため、使ってはならない。
ポインタとして入力用のデータを指定するため、配列のサイズよりも大きな文字列が与えられると、バッファオーバーフローを起こす。
gets()は絶対に使ってはならないし、scanf()は使うことをおすすめしない。scanfの場合は文字幅指定で回避できるが、getsはそもそも回避できない。
代替としてfgets()の利用が推奨されている。
gets()は2011年の改定のC11の標準CライブラリやC++14の標準C++ライブラリより廃止されている。

ファイルディスクリプタ

ファイルディスクリプタとFILEポインタ

基本的に、システムコールでファイルにじかにアクセスする時は、OSの識別番号であるファイルディスクリプタを使う。stdioで使うFILE型のポインタはファイルディスクリプタのラッパーで、stdioのバッファリング情報などが含まれている。
以下はふつうのLinuxプログラミング Linuxの仕組みから学べるgccプログラミングの王道を参考に執筆・編集して引用しました。

ファイルディスクリプタ

システムコールはストリームを表すために整数のファイルディスクリプタを用いるが、stdioではFILE型のポインタを用いる。
この中に、ファイルディスクリプタやstdioバッファの情報が入っている。

プロセスのファイルディスクリプタ

プロセスには最初からファイルディスクリプタとして3つのストリームが用意されており、

ファイルディスクリプタのストリーム 番号
標準入力(STDIN_FILENO) 0番
標準出力(STDOUT_FILENO) 1番
標準エラー出力(STDERR_FILENO) 2番

となる。

open()によるファイルディスクリプタ

また、open(2)システムコールを使うことで、パスとして表されるファイルにつながるストリームを作成できる。
open()はそのストリームを指すファイルディスクリプタを返す。
ファイルディスクリプタを指定してread(2)やwrite(2)でファイルに対してデータを読み書きできる。
またclose(2)を使うことでファイルを閉じることができる。

FILE型

FILE型はファイルディスクリプタのラッパーで、内部にファイルディスクリプタの情報が入っている。
システムコールであるopen, read, write, closeではなく、標準Cライブラリの標準入出力関数で読み書きする場合は、このFILE型のポインタを使う。

stdioとバッファリング

システムコールは、バイト単位でしか読み書きすることができない。また、文字単位や行単位での読み書きもできない。そして、システムコール呼び出しは、関数呼び出しよりもずっと遅い。
「標準入出力ライブラリ(stdio)」では、1バイトでの読み書き、1行での読み書き、数値や文字列のフォーマット出力をサポートしている。
Cのstdio(標準入出力)の関数では、何度も読み書きするデータのために「バッファリング」を提供する。バッファは一時的なデータの保存場所で、read()を使ってバッファに入力し、プログラムから要求されるたびにバッファから一文字返す。これを「バッファリング」と呼ぶ。
バッファリングはJavaなどの入出力でも良く使われます。分かっているとためになるでしょう。

コマンドラインオプションの解析

  • getopt(3)
    • ショートオプション(ls -a -s -kやls -ask)を解析する。
  • getopt_long(3)
    • ロングオプション(ls --all --size --kilobytes)を解析する。

コマンドラインオプションには慣習があり、以上のAPIを使うことで、ショートオプションとロングオプションを解析できる。

ファイルシステム操作のシステムコール

メモリ管理のシステムコール

メモリ管理のAPI

  • malloc(3)
  • calloc(3)
    • メモリを割り当てる。
  • realloc(3)
    • メモリの割り当てられた領域を拡張・縮小する。
  • free(3)
    • メモリを解放する。
  • brk(2)
  • sbrk(2)

プロセスAPI

以下の内容は、ふつうのLinuxプログラミング Linuxの仕組みから学べるgccプログラミングの王道を参考に執筆・編集して引用しました。

プロセスの概念

Linuxでは、どんなプロセスもfork()かそれに類するAPIで作成される。このプロセスを親子関係でつないでいくと、1つのツリー構造にまとめられる。pstreeを使うことで、この親子関係を表示できる。
親子関係以外に、プロセスを体系づける、セッションとプロセスグループと呼ばれる概念もある。
コマンドをたくさん使ったパイプを起動した時、コマンドの一部を間違えて時間がかかったりして、Ctrl+Cを打って処理を中断した場合に、パイプを構成する全プロセスを止めるために、プロセスグループが考案された。
また、セッションは、ログインシェルを起点に、ユーザが同じ端末から起動したプロセスを1つにまとめる働きをする。
「ps j」を実行すると、セッションやプロセスグループを見ることができる。
表示されている欄の意味は、PIDがプロセスID、PPIDがプロセスの親のID、PGIDがプロセスグループID、SIDがセッションID。
PIDとSIDが等しいプロセスはセッションリーダーで、最初にそのセッションを作ったプロセスがセッションのリーダーになる。
また、PIDとPGIDが等しいプロセスはプロセスグループリーダーで、セッションと同じく、最初にそのプロセスグループを作ったプロセスがリーダーになる。
「ps ax」でTTYの欄が「?」になっているプロセスは、制御端末を持たないプロセスで、デーモンプロセス、あるいは単にデーモンと呼ぶ。サーバーを作る時にお世話になる。

fork(2)

fork()を呼び出すと、カーネルはプロセスを複製して、2つのプロセスに分裂させる。これによって新しいプロセスを作り出す。
分裂された時点で、複製前と複製後のプロセスは、どちらもfork()を呼び出した状態になっている。
2つのプロセスの両方にfork()の呼び出しが戻って、両方のプロセスでfork()以後のコードが実行される。
この時、元のプロセスを親プロセス、複製されたプロセスのことを子プロセスと呼ぶ。
後日注記:fork()のエラー処理を行ったり、子プロセスと親プロセスで違った処理をさせるためには、fork()の返り値(通常はpidなどの変数に格納する)をif文で-1や0と比較する。fork()は、失敗した時は-1、成功した時は子プロセスの場合は0、親プロセスの場合は子プロセスのPIDを返す。fork()した後で、親プロセスが子プロセスの終了を待つためにはwait()を実行する。あるいはそれぞれのプロセスを個別に終了するためには_exit()あるいはexit()を実行する(子プロセスの場合は_exit()、親プロセスの場合はexit()を使う)。

exec(2)

自分を上書きして、新しいプログラムを実行する。
execを実行すると、その時点で現在実行しているプログラムが消滅し、自プロセス上に新しいプログラムをロードして実行する。

wait(2), waitpid(2)

親プロセスが子プロセスの終了を待つ。
fork()したプロセスの終了を待つには、wait()かwaitpid()を使う。
いずれもシステムコール
wait()は、子プロセスのうちどれか1つが終了するのを待つ。
waitpid()は、pidで指定したプロセスが終了するのを待つ。

その他プロセス関係のシステムコール

_exit(2), exit(3)は、プロセスを終了させる。
pipe(2)などについて。pipe(2), dup(2), dup2(2), popen(3), pclose(3)などは、パイプとしてストリームを繋げる一連のAPI
getpid(2), getppid(2)は、プログラムから自分の親を知る。

setsid(2)

新しいセッションを作る。デーモンを作る時に役に立つ。
新しいセッションを作成し、自分がセッションリーダーになる。
同時に、そのセッションで最初のプロセスグループを作成し、そのグループリーダーになる。
setsid()を読んで作成した新しいセッションは制御端末を持たない。
つまり、セッションリーダーになると同時にデーモンにもなる。

ユーザーとパーミッション

プロセスの権限とファイルのパーミッションによるマルチユーザーOS

UNIXでは、そのユーザーが実行したコマンドプロセスはそのユーザーの権限において実行される、という「ユーザーの権限」がある。
ファイルやディレクトリには、所有者や所属グループやその他のユーザーに対して、どのような許可を与えるか、という「パーミッション」が決められている。
UNIXでは、ユーザーのプロセス権限とファイルのパーミッションにおいて、それぞれのユーザーとプログラムの「出来ること」が決まっている。これが、UNIXにおけるマルチユーザーシステムである。
ある意味、「旧世代的だ」と感じられるかもしれない。昔の、UNIXが開発された頃の、「たくさんの端末に1つの共有コンピュータが使われている」という状態の再来のように感じられるかもしれない。だが、本当は今でも、そうした「1つのコンピュータとたくさんのユーザーが繋がる」という場面は多くて、たとえばHTTPサーバーなどはそうした利用の形態に当たるだろう。完全にマルチユーザーシステムと合致するわけではないが、本来そのような用途を想定し、たとえばユーザーがログインするコンピュータとデータコンピュータを分けて管理する、といったコンピュータの「柔軟な構成」が可能である。こうした点が、UNIXが「ネットワークとの親和性が高い」と言われる点かもしれない。

本当は今のWindows PCが必ずしも正しいわけではない

ただ、本当のことを言うと、今のWindows PCのように「全てのパソコンにOSを入れる」というモデルが正しいわけではない。
たとえば、Windowsにはサポート期限というのがある。もう少しすると、Windows 7もサポートが切れてしまう。今の、全てのPCにWindowsを導入するモデルだと、全てのPCの分だけライセンスを購入しなければならない。10台あれば、ライセンスの価格は10倍になる。これは大きな出費だ。
それに対して、ひとつの中央コンピュータにのみLinuxワークステーションを使い、それぞれ個別のPCではX端末を使うようにすれば、(X端末を導入するクライアントPCのOSはどうするのかという問題はあるが)OSの管理はひとつのワークステーション分だけで済む。
ただし、そもそもOSのバージョンアップが必要なのか、という問題もあるし、端末にも何らかのシステムを導入して使うことを考えると、これも考え物である。
僕としては、家庭内のLANに繋がったサポートの切れたコンピュータを、ひとつの(たとえばルータのファイアーウォールのように)経路を中心にし、何らかの形で「家庭内LANの全てのコンピュータを守る」ような、新しいセキュリティとアンチウイルス技術が必要になってくるのではないかと思う。全てのOSでWindows Updateをかけなくても、ひとつの中央コンピュータだけをきちんと管理していれば、他のコンピュータはその中央システムが守ってくれるような、そういうシステムが必要ではないかと思う。

ホームディレクト

UNIXでは、ホームディレクトリ(/home/username)がそれぞれのユーザに与えられ、このディレクトリが基本的にユーザのデータや作業の場所になる。ホームディレクトリ以外は、一部の例外を除いてrootユーザにならなければ、どんなアプリケーションでも変更することは出来ない(読み取りや実行は出来る場合が多い)。そのため、セキュリティが高い。
逆に言えば、注意すべきなのはホームディレクトリの中のデータだ。重要なデータはバックアップを取って、スパイウェアに知られないように、パスワードなどの重要なデータはネットワークに繋がった場所に置かないようにしよう。
ホームディレクトリは、最近ではデスクトップやドキュメントのような便利なディレクトリが自動的に作られる。それから、ユーザそれぞれの設定ファイルとして、「.」から始まる「ドットファイル」というファイルがアプリケーションの使用時などに作られる。自動的に作られる場合もあれば、自分で設定する場合(.emacsなど)もある。ドットファイルは、ファイルマネージャなどからは隠しファイルとして扱われる。lsコマンドでドットファイルまでを一覧したい場合は、ls -aオプションを使う。

$ ls -a

ドットファイルは、.bashrcなど、アプリケーションにとってはとても重要なファイルであることが多いため、良く注意して管理しよう。

パーミッションの説明

ファイルには所有ユーザーと所属グループがあり、そのユーザー(あるいはグループ・その他)が実行するプログラム(プロセス)において、ファイルに対してどれだけの権限を与えるかを決められる。これをパーミッションと言う。
パーミッションには、記号表記と八進表記がある。記号表記は「rwx------」など、八進表記は「644」など。
まず、一番左の「rwx」あるいは「6」が所有者における(ファイルやディレクトリの)読み込み(r, 4)、書き込み(w, 2)、実行(x, 1)の(権限の)許可を表す。八進表記では、それぞれの値を足し算で足す(4 + 2 = 6)。
真ん中は、同一グループにおける読み込み・書き込み・実行、一番右は、その他のユーザーにおける読み込み、書き込み、実行を表す。
ちなみに、「-rw-r--r--」や「drwxr-xr-x」のようにもう一つ左に多く表示された場合は、最初の1文字目はファイル種別を表している。「-」はファイル、「d」はディレクトリ、「l」はシンボリックリンク
ディレクトリの場合、rは一覧表示、wはディレクトリ内にファイルを作成したり削除したりできるかどうか、xはディレクトリの中に進めるかどうか(cdできるかどうか)を表す。
Windowsのように.exeなら実行できる、というわけではなく、実行ファイルやスクリプトを実行させたい時は基本的にパーミッションの許可が必要(厳密に言えば、スクリプトの場合、rubyなどに引数を与えて実行させることはできる)。
パーミッションの確認はls -lで見ることが出来る。

$ ls -l
 -rw-r--r--  1 user group      9  1月 1 00:00 hoge.txt
 drwxr-xr-x  6 user group  20480  1月 1 00:00 ダウンロード

パーミッションの変更コマンド

以下のようなコマンドで変えるか:

$ chmod 756 index.html

あるいは、このように変えるかです。
所有者に読み書き実行権を与える

$ chmod u+rwx index.html

グループ所属ユーザに読みと実行権を与える

$ chmod g+rx index.html

グループに所属しないユーザーから実行権を削除する

$ chmod o-x index.html

ユーザーとパーミッションの適切な使用法

UNIXにはユーザーとパーミッションの概念があるとして、どこでこれを使うか。
これは、ファイルシステムの役割を柔軟にしたい時に使います。
たとえば、Apacheのhtmlデータの入るディレクトリは、多くの場合/var/www/htmlですが、ユーザーhogeが居たとして、Webサーバのデータをhogeしか変更しないのであれば、/var/www/htmlの所有者やグループをhogeに属させる、などといったことができます。ただし、実際はユーザーとグループをapache:apacheとした上で、apacheグループにユーザーhogeを所属させるのが良いでしょう。
また、/mnt/usbhddをhogeしか使わないのであれば、これもhogeに所有権を与えることができます。
あるいは、/usr/local/hogeのようなディレクトリを作って、このディレクトリをhogeの所有とし、hogeにこのディレクトリを変更する権限を与えることで、/usr/local/hoge以下のprefixはhogeの自由に変えられます。
僕も無知のため色々と問題はあるかもしれませんが、このようにすることで、システムの一部だけをユーザーやグループに開放したりすることができます。

ディレクトリ階層とファイルシステム

基本

ディレクトリの階層構造。
ルートディレクトリには以下のようなディレクトリツリーがある。

ディレクト 説明
/ ルートディレクトリ。
/home ユーザーのホームディレクトリ。
/root rootのホームディレクトリ。
/bin OSの基本プログラム。アプリケーションのプログラムは/usr/binにあります。
/sbin OSのシステムプログラム。アプリケーションのシステムプログラムは/usr/sbinにあります。
/usr アプリケーションなどのファイル。あとで記述するように、さらに階層があります。
/etc 設定ファイル。使っていてもファイルのサイズが変化しないファイルを置く。
/var ログなどの使っていて変化するファイルを置く。
/tmp 一時的なディレクトリ。
/dev バイスファイル。
/mnt バイスをマウントするためのディレクトリ。
/proc システム情報。
/lib 共有ライブラリ。
/boot OSのブート用ファイル。

また、/usr以下にはアプリケーションをパッケージ管理システムでインストールした時のアプリケーションの構成ファイルの入るサブディレクトリツリーがある。

ディレクト 説明
/usr/bin アプリケーションの基本プログラム。沢山のプログラムがあります。
/usr/sbin アプリケーションのシステムプログラム。
/usr/lib アプリケーションのライブラリ。
/usr/share ドキュメントなど、アーキテクチャに依存しないファイル。
/usr/include C言語用ヘッダファイル。
/usr/local アプリケーションのローカルなインストール場所。

アプリケーションのインストール先の違い

アプリケーションのインストール先の違いは、以下のようになります。

  • /bin と /sbin
    • システムの最低限の起動、操作、管理に必要なバイナリファイル。
    • 最近は/usr/binにリンクが張られていることもある。
  • /usr/bin
    • 通常のアプリケーションのインストール先。
    • パッケージ管理システムでインストールしたディストリビュータ公式の配布ファイルがインストールされる。
  • /usr/local/bin
  • /opt
  • /home/hoge/bin
    • hogeユーザーが自分で入れたバイナリファイル。

最近はAppImageのように、ディストリビューションによらない、共通の簡単インストールの可能な仕組みも用意されています。Windowsフリーソフトようにダウンロードして簡単に実行出来るようになっていくでしょう。

パーティションのマウントの仕組み

パーティションを分けると、その部分のディレクトリ以下が別パーティションとしてマウントされる。
たとえば、/と/usrを分けると、/binや/sbinは/パーティションの中に、/usr/binや/usr/sbinなどは/usrパーティションの中に出来る。
これによって、大量のファイルがある場合などに、/homeのようなデータを分けることで、/homeだけを使いまわしたり、バックアップをしたり、障害があった時にシステムが起動不可能にならないようにするなどの対応がしやすくなる。
だが、今日のLinuxデスクトップの用途では、ハードディスクを一時的にメモリの代わりに使うswapパーティションを作り、/bootパーティションext2で保持し、それから/パーティションぐらいの、最低限の分け方をしていれば、問題になることは少ない。

このようなディレクトリ編成になっている理由

このようなディレクトリ編成になっている理由は、いくつかあります。
まずひとつは、上に書いたように、パーティションで簡単にディレクトリを分けることができます。/homeや/varや/etcを簡単に/と分けられるほか、それぞれに独自のファイルシステムを適用することもできます。
そして、もうひとつは、コマンドで操作しやすい、ということが挙げられます。たとえば、ソースコードだけを編集したいなら、find /usr/src | xargs sed -iなどで簡単にソースコードだけを自動編集できます。
さらに言えば、シェルから見て、PATHなどを設定する都合が良いということが言えます。シェルはPATHのような環境変数から、システムにある全てのバイナリへと簡単にアクセスできます。
反面、難点としては、「パッケージをさくっと削除できない」というのが挙げられます。もし/usr/firefox/binのようなディレクトリ構成をしていれば、firefoxディレクトリだけを簡単に削除できます。ですが、そのためにRed HatRPMというパッケージ管理システムを作りました。そのため、Windowsよりもはるかに簡単にパッケージを依存関係を含めて管理・更新できるようになっています。

/var/spoolとスプールファイル

/var/spoolにはスプールファイルやキューファイルが置かれる。
スプールとは、印刷ジョブの転送など、転送に時間がかかったり、処理速度に大きな時間の差がある場合などに、データを一時的にスプールファイルとしてファイルに書き出し、少しずつ転送する仕組み。

GoboLinux

Filesystem Hierarchy Standardからの脱却を目指すディストリビューション。「ファイルシステムがパッケージ管理データベース」であることを目指している。

設定・管理

/etcディレクト

Linuxの設定ファイルは、基本的に/etcディレクトリに存在する。
/etcディレクトリの中に、システムの設定はほとんどある。特に重要なディレクトリは/etc/rc.d/や/etc/init.d/で、Linuxが起動時にinitで実行する設定スクリプトがある。
また、Red Hat系のLinuxでは、/etc/sysconfig/にさまざまなシステムの設定ファイルがあり、/etc/init.d/networkや/etc/sysconfig/network、/etc/sysconfig/network-scripts/ifcfg-eth0などは見慣れて久しい。
Linuxでは、/usr以下のディレクトリは個人で変更するのは控えた方が良いところがあるが(システムのバイナリリソースが置かれており、パッケージ管理システムで管理すべき)、逆に/etc以下のディレクトリはどんどん個人で変更して構わない。
また、/etc以外のディレクトリにも、Linuxの管理に必要なディレクトリがいくつかある。
/varディレクトリは、/etcとは違い「使っていて容量が変化するファイル」を置くディレクトリで、システムによって使っている間に変化していく。ログファイルやスプールファイルが置かれる。全てのログファイルは/var/log/以下にある。
/tmpディレクトリには、一時的なファイルが保管される。一時的に生まれては消えていく。
/mntディレクトリには、静的にマウントしたデバイスファイルシステムが置かれる。
/mediaディレクトリには、/mntディレクトリと同じようにマウントしたディレクトリが置かれるが、デバイスを接続するたびに自動的にマウントされる。
/devディレクトリには、デバイスドライバによって利用可能となったデバイスファイルが置かれる。今のLinuxではudevがこのデバイスファイルを自動作成する。また/sysにはデバイスの情報が入っている。
/procにはカーネルやプロセスの情報が入っている。
また、これら以外にも、/usr以下にシステム管理のためのファイルが入っていることがある。たとえばudevでは、カスタマイズしたルールファイルは/etc/udev/rules.dにあるが、そのデフォルトの設定は/usr/lib/udev/rules.dにある。また、/usr/share/docにはドキュメントが置かれ、/usr/share/fonts/truetype/にはフォントが置かれる。

ドットファイル

こうしたシステムの設定ファイルの他に、ユーザー個人個人のための設定ファイルが、原則ホームディレクトリ(/home/username/以下)に置かれる。
これらのファイルは、UNIXの慣習から、ファイル名の最初が「.」から始まる。たとえば、「.emacs」とか「.bashrc」といった具合である。これらを「ドットファイル」と呼ぶ。
ドットファイルは、標準のlsなどのコマンドやファイルマネージャなどでは「隠しファイル」として扱われるため、表示されないことがある。適切なコマンドオプションやアプリケーションの設定を変えることで、これらのドットファイルを含めて全てのファイルを表示できる。
ドットファイルにアクセスするためには、ホームディレクトリにcdしてvi .bashrcのようにするか、ホームディレクトリを表す「~」を使って~/.bashrcとしたり、/home/username/.bashrcとすれば良い。
Linuxでは、/etcの設定を空白のタブで区切られたプレーンテキストで行い、ドットファイルは「初期化スクリプト」とすることが慣習的にままある(そうでない場合も多い)。特に.bashrcや.xinitrcなどは内部がシェルスクリプトであり、アプリケーションの起動時に自動的に読み込まれ実行される。
ドットファイルには、こうしたホームディレクトリに置かれるファイルの他、いくつか例外的に、それぞれのデータディレクトリの中に作られることもある。Apacheディレクトリ単位での設定ファイルである.htaccessや、gitの.gitディレクトリなどがこれに当たる。

シェル変数と環境変数

シェル変数は、シェルの中だけで保たれる。

$ FOO=foo

シェル変数を参照するには、$を変数名につける。

$ echo $FOO
foo

環境変数は、システム全体に適用される変数。設定するにはシェル変数を指定した後でexportする。

$ FOO=foo
$ export FOO

たとえば以下のようにPATHを変更できる。

$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/hoge/bin
$ PATH=$PATH:/usr/local/pgsql/bin:/usr/local/mysql/bin
$ export PATH

.bash_profileや.bashrc、.xsessionや.xinitrcなどに上記設定を記述することで、システムで常に同じ設定を使用できる。
シェル変数の一覧はsetコマンド、環境変数の一覧はenvコマンドで表示できる。
現在のシェルでのスクリプトの読み込みにはsourceコマンドを使う。

$ source .bashrc

一時的に設定を変えることで、「LANG=Cの状態でmanを見る」などということもできる。

$ LANG=C man ls

主な設定ファイル

設定ファイル 説明
.bash_profile Bashのログイン時に読み込まれる。
.bash_logout Bashのログアウト時に読み込まれる。
.bashrc Bashの起動時(ログイン後を含む)に毎回読み込まれる。
.bash_history コマンド履歴が記録される。
.xsession Xを用いたディスプレイマネージャからログインした時に読み込まれる。
.xinitrc テキストモードからxinitやstartxでXを立ち上げた時に読み込まれる。
.Xdefaults Xクライアントのリソース(大きさ、色、フォント、ボタンの形状など)を記述する。
.xmodmap キーコードと文字の対応を記述する。
/etc/ld.so.conf ライブラリのパスを記述する。
/etc/fstab マウント設定。
/etc/crontab cronに実行させる処理。
/etc/passwd パスワードの設定。
/etc/shadow シャドウパスワードの設定。
/etc/group グループの設定。
/etc/gshadow グループのシャドウパスワードの設定。
/etc/sudoers sudo設定ファイル。
/etc/shells ログインシェルの一覧。
/etc/host.conf ホスト名の検索順序を指定。
/etc/hosts ホスト名とIPアドレスの対応表。
/etc/resolv.conf DNSサーバの情報。

ロギング

ロギングとは、ログを取ること。システムの基本的なログは/var/log/syslogにある。

モニタリング

モニタリングとは、システムの稼働状況を監視すること。特にサーバーなどのマシンでは、自分からプロセスを実行しなくても、稼働中のシステムが勝手にプロセスを動かす。
プロセスやスレッドの情報を監視するためには、topコマンドを使う。

システムロガー

システムロガー

システムのログを取ってくれる。システムにどんな不良があったのか、いつ何をしていたのか(いつ何が起きたのか)を知るために役に立つ。
デフォルトでは、/var/logディレクトリにさまざまなログファイルがある。システム全般のログは/var/log/syslogにある。

ログファイル

  • /var/log/messages
    • 一般的なシステム関連
  • /var/log/secure
    • セキュリティ
  • /var/log/cron
    • 定期的に実行される処理結果
  • /var/log/maillog
    • メール
  • /var/log/spooler
    • 印刷
  • /var/log/boot.log
    • OS起動時関連

auth.log

/var/log/auth.logには認証に関するログが記録されている。
一人で一台のLinuxを使っている時は関係ないが、ネットワークに繋がっている場合などにチェックすることで、GDMやsu/sudoコマンドにログインしたユーザのことをチェックできる。
認証だけではなく、システム全般のログを参照するためには、/var/log/syslogを参照すること。

journalctl (journald)

長らくシステムロガーの吐くログファイルはless /var/log/syslogで読むことができたが、systemd導入の結果、今ではjounalctlを使うようになった。

cronデーモン

定期的に特定の処理を実行してくれる。決まった時間にコマンドを実行することが出来る。

サーバーのバックアップを勝手にやってほしいならcron

「サーバーマシンのバックアップやアーカイブの作成なんか、勝手にやってほしい」とか、「NFSに適当に定期的にコピーしてほしい、それもバックグラウンドで」とか、そういう、「バックグラウンドで定期的にやってほしい」というサーバー管理者の想いを叶えてくれるのがcronです。
基本的には、定期的に実行する「スケジュール」と、やってほしい「処理」を書くだけです。処理にはシェルスクリプトを書くこともできます。
特に、サーバー管理者のタスクとして、Apacheの設定やSSHでのリモートログインに匹敵する重要なタスクがcronです。ただ、書く処理を間違えると悲惨なことになるので、良く確認しましょう。
バックアップをUNIXで行う時は、rsyncを使って全ファイルをフォルダごと同期するか、tarを使ってアーカイブを日ごとに作っていくか、どちらかを選択することが多いでしょう。古いアーカイブは自動的に消すようにしても良いでしょう。簡単に一行では書けないところもあるので、詳しくはネットで検索してその情報に頼ってください。
自分でサーバーのWebアプリケーションを開発するのであれば、最初からMySQLなどで一元的にデータベースを管理することも、信頼性の確保に繋がります。ですが、レンタルサーバーのような場合、全ての顧客のデータをSQLで一元化することは難しいこともあります。cronでrsync/tarを行うのは、そういうニーズが根強いためです。SQLデータベースの使える環境では、最初からRDBMSを使いましょう。
SQLデータベースを使う場合は、「差分のバックアップ」と「全体のバックアップ」を上手く管理する必要があります。それぞれのデータベース管理システムで、こうした機能は必ずあります。UNIXファイルシステムには、そもそも、バージョンを管理する機能もありません。バージョンを管理したい時は、gitなどのバージョン管理システムでひとつひとつコミットするか、あるいはtarで毎日バックアップするしかありません。そういうわけで、cronには限界がありますが、使えないわけではありません。
注意:UNIXでのバックアップとしてtarやrsyncが一般的であるかのようなことを書きましたが、FreeBSDハンドブックにもあるように、多くの場合UNIXで最も一般的なのはdumpとrestoreというコマンドで、/dev/sda1のようなブロック型のデバイスをいっぺんにバックアップ・復旧することができます。ですが、イメージファイルが巨大になる上に、イメージ単位でのバックアップになるため、ファイルシステムの一部だけをバックアップしたり、複数のファイルシステムにまたがるディレクトリツリーをバックアップすることができません。dumpとrestoreは、大事なデータのバックアップというよりも、システム全体の復旧をしたい時に有効です。通常、大事なデータのバックアップには、tar, rsync, cpioなどのコマンドを使います。ですが、システム管理者になりたいのであれば、dump, restore, ddなどのコマンドも覚えておくと良いでしょう。
後日注記:そもそも、データベース管理システムを使う場面というのは、「億単位のデータから瞬時に検索する」場合のように、本当にデータの信頼性と性能が必要な場合だけです。多くの設定ファイルや個人データなどで、データベース管理システムを使うというのは考えられません。よって、そうしたデータはcronでバックアップを取りましょう。その代り、上手くやらなければ「たくさん圧縮ファイルが生まれて訳が分からない」ことになるので、古いデータは自動で削除するなどの処理をスクリプトに書いて、そのスクリプトをcronで実行するようにします。

編集コマンド

crontabを編集するためのコマンド:

crontab -e

cronの書式

crontabの書式:

* * * * * [実行コマンド]

設定項目は左から「分」「時」「日」「月」「曜日」となっている。

cronの設定ファイル

cronの設定ファイル:

ファイル ユーザ 説明
/var/spool/cron/user 全ユーザ ユーザの自動タスク設定ファイル
/etc/crontab root 毎時、毎日、毎月、毎週のメイン設定ファイル
/etc/cron.hourly root 毎時実行されるディレクト
/etc/cron.daily root 毎日実行されるディレクト
/etc/cron.monthly root 毎月実行されるディレクト
/etc/cron.weekly root 毎週実行されるディレクト
/etc/cron.d root 上記以外の自動実行設定ファイルを置くディレクト

crontabの例

/etc/crontabの例:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# run-parts
01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly

0-59/5 * * * * root /usr/bin/mrtg /etc/mrtg/mrtg.cfg

systemd timer

システムロガーと同様、長らくcronだった定期的な時間処理は、systemd timerを使ってやるようになった。

UNIXの3つのインターフェース

CUI

UNIXには、主に「キャラクタユーザインターフェース(CUI)」と、「グラフィカルユーザインターフェース(GUI)」という2つのインターフェースがある。
CUIUNIXの標準で、Bashなどのコマンドシェルプロンプトからプログラム名とオプションをキーボードで記述してENTERキーでコマンド実行し、プログラムが出力を表示したり、場合によってはコマンドプロンプトと同様にキーボード入力をしてデータを入力したりして、プログラムが正常に終了するとコマンドシェルプロンプトに戻るインターフェース。
CUIGUIよりも劣っているわけではなく、自動化や機能へのアクセスのしやすさなどの面から言って、場合によってはWindowsのようなGUIよりも高度で使いやすい場合がある。特に、シェルスクリプトを使ってバッチ処理を自動化したりできるし、設定システムもテキストで用意されている場合が多く、GUIよりも柔軟でカスタマイズブルな設定ができることが多い。
Linuxでは、Windowsと違い、今でもこのCUIインターフェースを固持している。主な理由は、「サーバーにGUIは要らない」という考え方や、GUIを統合しない方がセキュア(セキュリティ的に安全)でバグがなく、高速、軽量、そして安定性が高いなどの理由もあるからである。

GUI

だが、LinuxでもWindowsのようなGUI画面が使えないわけではない。それどころか、OSにExplorerが統合されているWindowsとは違い、多種多様なGUI環境が存在する。
LinuxWindowsのようなGUIのデスクトップ環境を使うためには、X Window Systemというソフトウェアを使う。これはサーバー(X Server)とクライアント(X Client)に分かれたシステムで、ウィンドウシステムはモニターのピクセル単位でのグラフィックスの描画と、マウスやキーボードの入力、フォントや画像の描画、そしてメッセージングを担当する。メッセージングとは、「今サーバーでマウスがクリックされたから、クライアントさん、マウスクリック時のイベントを実行してね」と言う風に、グラフィックスへの描画やハードウェアのデータやり取りをするXサーバーとそれぞれのウィンドウの中でプログラム処理を行うXクライアントの間を取り持ち、ハードウェアとソフトウェアの間で相互に「メッセージ」をやり取りするシステム。
そもそも、GUIアラン・ケイによる「メッセージング」というダイナブック構想から生まれたものだが、UNIXX11は歴史が古く、UNIXのグラフィックスシステムとしては正統派で、伝統的である。X Window SystemのことをX11と省略する。
Linuxでは、X11はウィンドウを表示してメッセージングを行う部分を担当しているが、デスクトップの見た目や操作性はX11とは分離されている。たとえば、X11でアプリケーションを作る際、Xプロトコルの詳細を知らなくてもXプロトコルを使ったアプリケーションが開発できるように、Xlibと呼ばれるXクライアント向けのライブラリがあるが、ここにはボタンやメニュー、あるいはフォームへの配置のようなGUIツールキットは用意されていない。それらは、また別のプロジェクトが開発している。
伝統的にX11で使われているMotifというツールキットは、ボタンやメニューなどをXクライアントが簡単に使って作れるようにした関数ライブラリのAPIで、Motifで作られたアプリケーションは「Motifアプリケーション」などと呼ばれる。Motifは完全なフリーソフトウェアでなかったし、TrollTechの開発したQtもフリーではなかったため、GNUはこうしたGUIUNIX環境の整備に苦労した。結果、今では、LinuxにおけるツールキットはGIMPによるGTK+とオープンかつフリーになったQtが使われている。
また、ツールキット以外に、ウィンドウを操作するウィンドウマネージャと呼ばれるプログラムも必要となる。Linuxでは、ウィンドウマネージャを別のものにすることで、WindowsからMacにデスクトップ環境を乗り換えた時のように、「全く別のウィンドウ操作環境」をカスタマイズして入れ替えることが可能である。これは、Windowsユーザーの感覚からすると、OS全体を入れ替える感覚に近い。
また、ツールキットだけでアプリケーションは開発できるものの、ユーザーがGUI画面を使う場合において、さまざまな必要なユーティリティが必要になる。たとえば、端末エミュレータX11でグラフィカル環境でもコマンドシェルプロンプトから入力したい場合は必須だし、他にもアプリケーションランチャー(アプリケーションを起動するメニューを表示するプログラム)やファイルマネージャ(シェルからmkdirとかlnなどとしてコマンドで操作しなくても、GUIで操作出来るファイル管理ツール)などが必要である。そして、Windowsを使っていたら分かるように、ブラウザやメールクライアントなども、GUI画面の標準として用意されるべきだし、共通のルック&フィールや操作性を持つべきである。そして、開発者が見ると、WindowsにはレジストリやCOMのようなアプリケーションの開発をしやすくする「総合的ライブラリAPI」が用意されている。このような「統合デスクトップ環境」はLinuxでは、GNOMEKDEXfceLXDEなど複数ある。また、先のウィンドウマネージャの種類も合わせると、OpenboxやFVWMenlightenmentWindowMakerなど、さまざまなルック&フィールのデスクトップ環境がある。Linuxでは、こうしたデスクトップ環境を、同じ「X Window System」という仕組みの中で、複数使うことができる。

TUI

また、GUIでもCUIでもない中間のインターフェースとして、「テキストユーザインターフェース(TUI)」というものがある。
これは、テキストエディタのviを考えてもらえば分かりやすいかと思われるが、CUIではコマンドを実行して出力が返り、またコマンドを実行する画面に戻るため、「画面いっぱいを作って文書やメールなどを見る、インタラクティブに操作する」ということが難しい。
TUIでは、CUIと同じようにキャラクタ(文字)ベースのインターフェースを提供するが、コマンド入力ではなく、画面いっぱいにスクリーンを表示して、その中でプログラムの機能を実行したり、メニューを表示したり、複数行のマルチテキストボックスでデータを編集したりすることができる。
要は、MS-DOSMS-WordLotus 1-2-3を使うような、そういう感覚である。
TUIを使った操作は、たとえばDOSより以前の「専門的事務コンピュータ」を考えると分かりやすい。昔は、企業には専門の事務コンピュータがあったほか、文書の作成には日本企業が作っていた「ワープロ」と呼ばれるワードプロセッサーやプリンターが搭載された白黒画面の文字だけのワープロを使っていた。TUIはそんな感じである。UNIXに慣れたユーザーなら、viをTUIの一例だと思えば分かりやすいだろう。

Linuxユーザランド

コマンド

Linuxユーザランドは、主に、コマンドプログラム、デーモン、設定ファイルやその他のデータファイルによって構成されている。
まず、コマンドは、多くの場合C言語によって記述されたソースファイル(*.c)あるいはヘッダファイル(*.h)に、main関数から始まり、シェルのコマンドライン引数をmain関数の引数として、多くの場合コマンドラインオプションをgetopt()やgetopt_long()で解析する形で、C言語の文法や関数を使って記述されている。
プログラムが小さい場合は、ひとつのプロセスとして動くひとつのプログラムがひとつあるいは数個の*.cファイルで記述されていることが多いが、大規模なプログラムでは、*.cファイルが数十以上になることもある。それぞれのソースファイルには関数の形でプログラムを記述し、ヘッダファイルがそれぞれのソースファイルの中で関数のシンボル名を共有する。
C言語では、main関数からプログラムが始まり、if文やfor文で条件に応じて分岐・反復し、演算結果を変数に格納したり、独自に実装した関数に数値や文字列を引数として与えながらサブルーチンを実行したり、文字列やのファイル入出力やシステムコールなどのシステム関数・APIを使うことで、プログラムを*.cファイルに記述する。*.hファイルには、多くのソースファイルから呼び出される関数のプロトタイプ宣言や、共有されるグローバル変数や構造体のデータ型定義などを記述する。小さな処理であれば*.hファイルの中に関数の実体を記述することもある。
Cのソースファイルでは、他にも、必要な型や定数の宣言を行ったり、条件分岐によって違う値を返したり違う関数を実行したり、あるいは変数の中身によって違う値を関数に与えたりする。他にも、算術演算子、代入演算子、論理演算子などを使う。たとえば、フラグのようなものを設定する時は、あらかじめ定数を宣言した上で、その値をシフト演算子や論理演算子で比較する形で(たとえばFLAG_ONE | FLAG_TWOのように)、分岐を変えたり違う値を返したり与えたりする。三項演算子(~ ? ~ : ~)もよく使われる。また、ヘルプ文字列などは多くの行に渡って記述されることもある。ファイル処理を行う場合はエラー処理もする必要がある。
これらのソースファイルは、ビルドする際にひとつひとつGCCなどのCコンパイラによってコンパイルされ、アセンブルされて機械語のオブジェクトファイル*.oに変換され、リンクされて実行ファイルに変換される。C言語のソースファイルは必ず暗黙的にlibc.so.6とリンクされる。また、ダイナミックリンクの際にはリンクローダである/lib/ld-linux.so.2とリンクされる。それらが終わって、実行可能なバイナリが作成される。
ビルドは、多くの場合直接gccコマンドによってコンパイルされることはなく、MakeやAutotoolsなどのビルドシステムを使う。MakeはMakefileに従って、既にコンパイルされていて新しく再コンパイルする必要のないファイルを無視し、必要なファイルだけをコンパイルする。また、Autotoolsはシステムの環境全てをチェックしてMakefileを自動作成するconfigureスクリプトを作成することで、UNIXプログラムの移植性を高めるGNUの自動ビルドシステムで、GNU製ソフトウェアの配布に標準的に使われている。
インストールは、tarball(tar.gz)からのインストールであれば、make installでprefix(インストール対象となるシステムのバイナリの場所で、ソースtarballならば/usr/local/bin)にファイルがコピーされてインストールされる。
パッケージ管理システムからのインストールであれば、バイナリを一度作成した段階で、RPMならばspecファイルと呼ばれるシステム情報や依存するパッケージの情報などと一緒にファイルをパッケージングし、リポジトリに配布する。ユーザはリポジトリからパッケージ管理ツールを用いてこのパッケージをダウンロードし、システムのprefix(パッケージならば/usr/bin)にファイルをコピーすることでインストールする。
こうしたバイナリは、多くの場合/usr/binあるいは/binに存在する。Bashのようなシェルを使う時、これらのprefixはPATHと呼ばれる環境変数に格納される。コマンドラインシェルでコマンド名を実行すると、シェルの内部コマンドである場合を除いて、シェルはPATHの中のディレクトリからプログラムを探し、コマンドラインオプションをそれらのプログラムに渡して、プログラムを実行する。
UNIXのプログラムは、ユーザーランドだけで完結するプログラムもあれば、カーネルに処理や機能を要求する場合もある。この場合、カーネルシステムコールを呼び出すことで、カーネルに「お願い」をする。あるいは、Cの標準ライブラリを使う場合は、libcにある関数やAPIを呼び出すこともある。この場合、標準入出力関数であればシステムのstdio.hをincludeしなければならない。他にも、socketを使ったり、あるいは標準Cライブラリに存在しない別のライブラリを呼ぶこともある(zlibやgtkなど)。このプログラムをコンパイルするためにはそのヘッダファイルが必要となり、実行するためには何らかの形でライブラリとリンクする必要がある(共有ライブラリとのダイナミックリンクなど)。また、このプログラムを再配布する場合にパッケージ化する場合は、依存関係にそのライブラリの記述をしておくことが必要となる。ソースからインストールする場合は、自分でパッケージ管理システムと同じことをする、すなわちライブラリとヘッダも何らかの方法で自分で導入・管理する必要がある。

デーモン

こうしたコマンド実行のプログラムはUNIXにおいて一般的なプログラムだが、一部コマンド実行ではなく、システムが稼働している間常にサービスを提供する形で実行されるプログラムがある。それがデーモンであり、Apacheなどの「サーバーソフトウェア」は多くの場合デーモンとして実行される。
デーモンは普通のコマンドプログラムと変わらないが、永続的に実行される形式で記述され、起動スクリプトから並列起動されることで、システムにおいて常に実行される。サービスとしてイベント駆動で実行されるため、何らかの外部的なイベントがなければ処理を行わないプログラムが多い。
デーモンは、自動起動の設定がされている時は、システムの起動時にinitやsystemdから実行され、システムの終了時に停止される。その実行は、initならばシェルスクリプトによる起動スクリプトで、systemdであれば並列起動が可能なUnitファイルをsystemdが読み込む形で行われる。管理者が必要とする場合は、起動・停止・再起動や状態の確認は起動スクリプトあるいはsystemdの管理コマンドの実行によって行われる。
デーモンに限っての話ではないが、システム管理者は今のプロセスがどのように稼働しているかを監視(モニタリング)し、異常があった場合は何が起きたのかをログを取って確認すること(ロギング)を行わなければならない。このためにtopコマンドやsyslogdなどのシステムロガーなどが利用できる。

設定ファイル

コマンドとデーモン以外に、UNIXファイルシステムには設定ファイルやデータファイルがある。
たとえば、/etcには設定ファイルが置かれる。多くのプログラムの設定ファイルがここに置かれるため、形式は多数の種類があるが、UNIXではシステムの設定ファイルはシンプルなプレーンテキストのファイルを用いることが多く、タブや空白を使って一行にひとつの設定を行う。あるいは、Bashシェルスクリプトを使って、環境変数を設定したり(PATHなど)、ログイン時に必要なユーザー独自の自動起動の処理を行ったりすることができる。システムの標準設定は/etcに、一般ユーザーの設定は/home/username以下のドットファイル(.から始まるファイル)に記述されることが多い。ドットファイルは通常隠しファイルとして扱われるが、ls -alなどのオプションをつけることで表示できる。
また、/varには運用していてサイズやファイル数が変化することのあるデータファイルを設置する。ログやメール・印刷のスプールファイルが置かれるほか、HTTPサーバーのHTMLファイルもここに置かれることが多い。
他には、/mntにはマウントポイントが置かれる。新しいハードディスクやUSBメモリースティックなどをシステムに接続した時、こうしたファイルはUNIXでは適切にマウントしなければ使うことができない。明示的にマウントポイントを作る場合は/mntにサブディレクトリを作る。あるいは、USBのホットプラグなどで自動的にマウントされる場合、最近のLinuxではudevという仕組みを用いて/mediaなどに自動マウントされる。
他にも、プログラムでないデータファイルとして、フォントやドキュメントなどがあるが、こうしたアーキテクチャに依存しないファイル(Intelでも他のCPUでも動くファイル)は/usr/shareに置かれる。
設定ファイルに限らず、システムのファイルはパーミッションによって読み書き実行の適切な権限の許諾が行われる。一般ユーザーがシステムのファイルを破壊することはできない。また、別のユーザーや別のグループのファイルにアクセスすることも制限できる。設定ファイルを読んだり、プログラムを実行することはできても、それを変更することは管理者権限がなければできない。

カーネル

カーネルは、ブートローダによってシステムの起動時に実行され、システムにおいて常にCPUやメモリやデバイスを管理しているが、自分から何かを行うことは基本的になく、プログラムがシステムコールなどで要求した時に常にサービスを提供することができるように準備し、システムコールがあった時に適切にCPUのカーネルモードとユーザーモードを切り替えてサービスをプログラムに提供する。ファイルシステムやネットワーク接続は、プログラムが必要となった段階でカーネルシステムコールを要求し、それに対してカーネルがデバイスへと接続して処理を行い、その結果をポインタやディスクリプタなどの形でプログラムに返すことで行われる。
また、カーネルはプログラムの実行を行う。そのため、プログラムを複数実行しようとするとカーネルがシステムを仮想化することで、CPUやメモリがそれぞれのプロセスに「占有されているかのような幻想を与える」ことで並列実行する。CPUは短いタイムスライスでプロセスをコンテキスト切り替えすることで、CPUレジスタの値を退避したり読み込んだりすることで並列実行を可能とする。またメモリは物理アドレス空間と論理アドレス空間を翻訳しながらページングすることで、アドレス空間を分割して複数作り出す。
また、カーネルはCPU、メモリ、ストレージ、ネットワーク、入出力などのデバイスを支配している。

ウィンドウシステム

これに対して、ウィンドウシステムであるX11では、グラフィックドライバを使ってグラフィックボードにアクセスすることで、モニターに操作画面を表示し、マウスやキーボードを管理し、ウィンドウとハードウェアデバイスとの間でメッセージがやり取りできるようにする。コマンドプログラムではない、GUIのプログラムは、カーネルの上にウィンドウシステムが君臨し、そのウィンドウシステムのサーバーにアクセスすることで、グラフィックスフォームの表示が行われる。
ボタンやメニューなどのツールキットはこのX11の仕組みを利用しており、ボタンクリックなどのウィジェット上のイベントに応じてコールバック関数を実行する。
X11におけるプログラムは、コマンドラインシェルから実行することもできるが、多くの場合ウィンドマネージャと呼ばれるプログラムから実行し、ウィンドウの終了や移動やサイズ変更や重ね合わせなどの手法はウィンドウマネージャに委ねられる。GUIからX11アプリケーションを使う場合、このウィンドウマネージャが操作環境の主となる。
ウィンドウマネージャは、多くの共通のルック・フィールや開発するためのライブラリ・フレームワークと合わせて「デスクトップ環境」と呼ばれることも多く、GNOMEKDEXfceがデスクトップ環境として知られているが、実際にはもっとたくさんの多くのウィンドウマネージャが存在し、好きなものを使用することができる。ただし、自分のウィンドウマネージャの使い方が分からない場合には自分で習熟する必要があるし、iBusなどの日本語入力エンジンを使う場合にはiBusと統合されているGNOMEを使うのが多くの場合良い選択である。

Bash

シェルとは

シェルは、ユーザーのライン入力を受け取って、任意のコマンドプログラムを実行するプログラム。ユーザーが思い通りにさまざまなコマンドのプログラムを実行できるようにした、人間であるユーザーと機械とのインターフェース。
GNU/Linuxで一般的なBashには、コマンドやパスの補完、ヒストリ機能(一度実行したコマンドを履歴から探索できる)、マルチタスクの機能(&を使ったプログラムの非同期の実行やjobsコマンドなど)、コマンドの別名を作れるエイリアス、(厳密にはシェルではなくOSの機能だが)コマンドとコマンドを繋げるパイプの実行、シェルスクリプトの実行などの便利な機能が備わっている。ライバルはFreeBSDなどで一般的なcsh/tcsh(Cシェル系のシェル。シェルスクリプトなどの記法がC言語に近い)。

PATH

Bashなどのコマンドラインシェルは、基本的にユーザーの入力を受け取ってコマンドを実行するが、このコマンドは環境変数であるPATHのディレクトリの中から検索される。
PATHに含まれていないコマンドや実行ファイルでも、/sbin/serviceのようにフルパスで指定するか、./configureのように相対パスで指定すれば実行できる。
また、ユーザーのホームディレクトリを得るHOMEという環境変数もある。Bashでは、ホームディレクトリを~(チルダ)で表現し、ホームディレクトリの中にある.bashrcは~/.bashrcと記述してシェルからアクセスできる。

一般ユーザーとrootユーザーのシェル

シェルには、一般ユーザーのシェルとrootユーザーのシェルという二種類のシェルがある。慣習的に、コマンドの入力例などを記述する際に、一般ユーザーのシェルは$、rootユーザーのシェルは#を行頭につけて表現する。この$や#を入力する必要はない。
UNIXでは、誤った操作によるシステムの破壊を防ぐために、通常はシステムの変更・破壊権限を持たない一般ユーザーとしてログインし、一般ユーザーのシェルを起動させて操作する。データはホームディレクトリのような場所に保存し、多くの操作は一般ユーザーで行う。
だが、ソフトウェアパッケージのインストール・アンインストールや、システムの定期的な更新など、一部の操作はrootユーザーになった上で行う必要がある。
この時は、su -コマンドを使うことで、rootユーザーのシェルを起動できる。

初期化スクリプト

特に、PATHの永続的な設定をしたい場合など、ログイン時に特定のコマンドを実行したい場合、起動スクリプトに記述することができる。
たとえば、上のPATHの設定の例では、そのコマンドを実行した時にしかPATHが設定されず、シェルを終了してしまうと次回のシェルでまた手動で実行しないといけない。このような時に初期化スクリプトを使う。
初期化スクリプトはホームディレクトリにある.bash_profile(ログイン時)と.bashrc(シェルの毎回起動時)などがある。
だが、これはコマンドシェルとしてログインした場合であり、Xサーバーでグラフィカルなディスプレイマネージャ(GNOMEならGDMなど)でログインした時には実行されない。
Xサーバーを実行した時にコマンドを実行したい場合は、.xsession(Xログイン時)や.xinitrc(startxコマンドでXサーバーを手動で起動する時)などにコマンドを記述する。.xinitrcは、たとえばtwmではなく独自のウィンドウマネージャを起動したい場合などにその起動コマンドを記述すると、startxを実行した時に自動でウィンドウマネージャを起動できて便利である。日本語入力のためのインプットエンジンの設定も.xinitrcに記述することが多い。(最近のiBusなどの新しい世代のインプットエンジンでは、.xinitrcを編集する必要はなく、GUIで設定できる。)

コマンドの強制終了とエラー

コマンドを実行している時に、途中で実行を中止し、強制終了したい時はCtrl+Cを実行する。
また、プログラムを実行して、何も出力せずにプログラムが終了し、元のシェルの入力に戻った時は、コマンドは正常に処理を完了している。何かエラーを出した時(途中で不正終了した時)はエラーが表示される。

作業の終了

別のユーザーとしてログインしたい場合など、シェルそのものを終了させたい時はexitコマンドを実行する。また、システムを終了させたい時はshutdownコマンドを実行する。システムの終了は-h、再起動は-r。

# shutdown -h now

コマンド

ファイルシステム関係

ファイルシステム関係のコマンド一覧

コマンド 説明
cp ファイルやディレクトリをコピーする。とても良く使うコマンド。
ln ファイルやディレクトリにリンクを設定。シンボリックリンクを作る時に使う。
ls ファイルやディレクトリの情報を表示する。ディレクトリの中のファイル内容をリストする時に使う。オプションを使いこなそう。
mkdir ディレクトリの作成を行う。
mv ファイルの移動とファイル名の変更を行う。
rm ファイルやディレクトリを削除する。間違えて使わないように、エイリアスなどで確認表示をデフォルトにすることもある。
rmdir ディレクトリを削除する。空のディレクトリを削除する。
sync バッファの内容をディスクに書き込む。
touch タイムスタンプを更新する。内容を変更せずftpなどで更新したい時に使う。

find. grep, sed, awk

コマンド 説明
find ファイルを詳しく検索する(ディレクトリ階層を一覧表示し、条件で検索する)。簡単な検索ならデータベースを使うlocateの方が高速。
grep ファイルやテキストから文字列を検索する。とても良く使う便利なコマンド。パイプから使うことも多い。
sed ファイルやテキストの文字を変換する。findやxargsと一緒に使うことで、簡単に全ての文字を検索・置換できる。
awk カラムを取り出したり、簡単なスクリプト処理まで。

フィルタ・テキスト処理

コマンド 説明
basename パス名の中からファイル名を取り出す。findなどから解析できる。
cat ファイルやストリームの内容を全部表示する。
cut テキストの文字列を切り出す。
echo 文字列(テキスト)や変数の値を表示する。シェルスクリプトなどでprintfの代わりに使える。
head ファイルやテキストの先頭部分を表示する。パイプで使うことが多い。
tail ファイルやテキストの末尾を表示する。パイプで使うことが多い。
wc ファイルやテキストの文字数・行数をカウントする。パイプで使うことが多い。

ページャ

コマンド 説明
less ファイルやテキストの内容を1画面に表示する(2)。とても良く使う便利なコマンド。
more ファイルやテキストの内容を1画面に表示する(1)。便利だが逆戻りが出来ないためlessを使うことが多い。

シェル

コマンド 説明
alias コマンドの別名を登録する。rmについて確認表示をデフォルトに登録したりできる。
cd カレントディレクトリ(現在のシェルのディレクトリ)を変更する。
clear 画面をクリアする。
exit ログアウトする。
history コマンドの履歴を表示する。
pwd カレントディレクトリを表示する。
unalias コマンドの別名を解除する。
which コマンドのパスを表示する。

プロセス

コマンド 説明
jobs バックグラウンドジョブを表示する。
kill プロセスやジョブを強制終了する(シグナルを送る)。
nohup ログアウト後もプログラムを実行する。
ps 実行中のプロセスを表示する。
sleep 一定時間スリープする(一時停止)。

マニュアル

コマンド 説明
man コマンド・設定ファイル・関数などのマニュアルページを表示する。初心者から上級者まで知っておくべきコマンド。

フィルタ・テキスト応用

コマンド 説明
diff ファイルやテキストの内容の違いを調べる。ソースコードの差分などを求めるのに便利なコマンド。
sort ファイルやテキストの行を並び替える。プレーンテキストの簡単なソートができる。
split ファイルやテキストを分割する。csplitという特定の文字から分割するコマンドが便利。

ファイルシステム

コマンド 説明
df ディスクの使用量(ハードウェア単位)を調べる。
du ディスクの使用量(ディレクトリ単位)を調べる。

圧縮・解凍

コマンド 説明
compress .Z形式のファイルの圧縮・復元。
gunzip .gz形式の圧縮ファイルの復元。
gzip .gz形式のファイルの圧縮・復元。
tar アーカイブの作成と復元を行う。
uncompress .Z形式の圧縮ファイルの復元。
unzip .zip形式の圧縮ファイルの復元。
zcat 圧縮ファイルの内容を表示する。
zip .zip形式のファイルの圧縮。

同期

コマンド 説明
rsync 2つのディレクトリの同期をとる。完全にファイル内容を同じにしたい場合、バックアップを取りたい場合などに使える。
ただ間違えて同期してファイルが消えることがあるのでtarコマンドなどとの併用がおすすめ。

psとkill

psコマンド

psはプロセス状態を表示するコマンド。killと一緒に使う。

ps [オプション]

psのオプション

オプション 説明
-A, -e 全てのプロセスを表示
-a 端末を持たないプロセス以外の全てのプロセスを表示
a 端末を持つ全てのプロセスを表示
-C コマンド 表示するコマンドを指定。
複数コマンドの場合は「,」で区切る。
--cols 数値 スクリーン幅の指定
--width 数値 表示幅の指定
e コマンド名の後ろに環境変数などを表示
h ヘッダを非表示
r 実行中のプロセスのみを表示
x 制御端末のないプロセスを表示
-s セッションIDで表示指定。
fオプションを追加するとツリー構造表示。
T 端末の全てのプロセスを表示
-U、u ユーザ名 実行ユーザ名や実行ユーザIDのプロセスを表示。
複数指定は「,」で区切る。
-G グループ名 グループ名やグループIDで表示。
p、-p プロセスIDを選択して表示
-プロセスID 指定したプロセスIDで表示
--ppid プロセスID 指定したプロセスIDの親プロセスIDを表示
-t、t 端末名 指定した端末に関連づけられたプロセスを表示
-l 長いフォーマットで出力
f アスキーアートで階層表示
-o 出力形式 出力形式を指定してプロセス状態を表示

表示項目については、PID(プロセスID)、TTY(プロセスに関連付けられた端末名)、TIME(累積利用CPU時間)、CMD(実行ファイル名)となる。
状態は、D(割り込み不可能なスリープ状態)、R(実行中・実行可能状態)、S(割り込み可能なスリープ状態)、T(ジョブ制御中。トレース中もしくは停止中)、X(死んでいる状態)、Z(終了しているが親プロセスに回収されなかったゾンビ状態)となる。
また、プロセス状態の負荷情報として、<(優先順位が高い)、N(優先順位が低い)、s(セッションリーダー)、l(マルチスレッド化されたプロセス)、*(フォアグラウンド中のプロセス)となる。
(「[改訂第3版]Linuxコマンドポケットリファレンス」を参考に執筆・引用しました。)

killコマンド

killはプロセスにシグナルを送るコマンド。

kill [オプション] プロセスID

オプションは

オプション 説明
-s シグナル プロセスに送るシグナルを指定
-l シグナル シグナルを一覧で表示する。
シグナル名を指定した場合、シグナルIDを表示する。

たとえば、

$ kill -l
(シグナル一覧が表示される)
$ kill 2233
(プロセスにシグナルを送って終了させる)

(「[改訂第3版]Linuxコマンドポケットリファレンス」を参考に執筆・引用しました。)

nice

niceは実行優先度をつけてコマンドを実行するコマンド。

nice [オプション] [コマンド [引数 ...]]

オプションは「-n 優先度」でNICE値を指定してコマンドを実行する(デフォルトは10)。
また、reniceで実行しているプロセスの優先順位を変更できる。

renice 優先度 [オプション]

オプションは「-n NICE値」「-g グループ名」「-u ユーザ名」「-p プロセスID」。
(「[改訂第3版]Linuxコマンドポケットリファレンス」を参考に執筆・引用しました。)

ディストリビューション

ディストリビューションって何?

Linuxは、カーネルとしてはkernel.orgでオープンソースで配布・開発されているが、ここにあるのはOSの中核であるカーネルのみ。
GNU/LinuxとしてのLinuxシステムを構築するためには、他のプロジェクトで配布されているソフトウェア一式と組み合わせる必要がある。
そのため、この組み合わせ作業をしている会社やコミュニティなどを「ディストリビューター」と呼び、その配布物を「ディストリビューション」と呼ぶ。
Linuxをきちんと使うためには、このディストリビューションをインストールする必要がある。
ディストリビューションの構築にはたくさんの開発・メンテナンス作業が必要となる。
GNUプロジェクトは、Linuxと言うソフトウェアはカーネルだけを指しており、LinuxをOSとして使う場合、GNUコンポーネント一式をそのまま使うことから、呼び名として「GNU/Linux」と呼ぶべきだ、と言う主張をしている。特に、Debian GNU/Linuxのように、コミュニティ寄りのディストリビューションは、GNU/Linuxと言う呼び名を採用しているものもある。
昔はSlackwareのようにtarballパッケージでインストールしていたが、パッケージの管理作業が面倒なことから、現在はRPMDebのような「パッケージ管理システム」でディストリビューションを作るのが一般的だ。
GNU/Linuxがどのようなソフトウェアコンポーネントで成り立っているのかを見るには、LFSやBLFSを見ると良いだろう。

何でこんなにたくさんディストリビューションがあるの?

Linuxは、WindowsMacと違い、どこかの特定の一企業が配布やライセンスに対する主導権を持っているわけではない。
そのため、「誰もが自分のLinuxを作って配布することが出来る」と言うポリシーのようなものがある。
だが、簡単にディストリビューションが個人で作れるわけではない。たくさんのパッケージをメンテナンスする必要がある。
そのバランスから、さまざまな開発母体を持ったディストリビューションが存在する。
後日注記:昔のLinuxではディストリビューションが公式でパッケージを用意するのが普通だったため、メンテナンスなどの問題から小規模なディストリビューションは使えないものだったが、今はflatpakやflathubなどの新しい仕組み・サービスがあり、小規模なディストリビューションでもそうした最新の追加パッケージを導入できる。そのため、MX Linuxなどの小規模なディストリビューションも最近はとてもよく使われている。

Debian GNU/Linux

コミュニティによるディストリビューションとしては最大規模。
システムとしては安定志向で、そのためにリリースが遅れがちになり、ソフトウェアのバージョンが古いこともあるが、メンテナンスされているパッケージの数が多い。
パッケージ開発システムとして、Debianにより開発されたDeb/Dpkg/Aptを採用している。
特定のデスクトップ環境にも依存せず、さまざまなデスクトップ環境を試すことが出来る。
保守的だが、リリースバージョンごとにパッケージのメンテナンスをきちんとしているため、サーバー用途にもおすすめだ。機能追加の更新は極力行わず、セキュリティと致命的なバグの修正だけを、リリースバージョンごとに更新している。コマンド一発でそれがアップデートされるのは、たくさんのコミュニティのパッケージメンテナーのおかげだ。
組織的にはボランティアによる民主主義のモデルを採用している。また、独自のフリーソフトウェアガイドラインを設けていて、極力フリーではないパッケージは標準では採用していない。対応されているCPUアーキテクチャも多く、システムも柔軟に構築出来る。
Debianが使い辛くて玄人向けだった時代ははるか昔に終わって、今では普通の人間が普通に使える普通のディストリビューションである。また、色々とパッケージに個性や独自性があるものの、それらはインストールした上で自分でカスタマイズすれば変えられる。よって、プログラマを目指す学習者ならば、Debianを導入すべきである。Linuxディストリビューション全体を見ても、一番まともで正しいディストリビューションではないかと思う。ただし、パッケージに新しさが無く、いつまでも古いままであるため、普通に使っていて「何の面白さも無い」ディストリビューションである。

Red Hat Linux/Fedora

Red Hatと言う会社が主に開発しているディストリビューション
Red Hat Linuxと言うものは無くなり、代わりにFedoraと言う最新式のコミュニティベースのディストリビューションRed Hatが母体となって開発し、それを有料サポートのついたRed Hat Enterprise Linux(RHEL)に統合し、安定化させてサポートで儲ける、と言う体制を取っている。
RHELのコード自体はオープンソースで公開されているため、CentOSと言うクローン版もある。企業サーバーにはRHELCentOSがおすすめだ。
Fedoraは、動くか動かないか分からない不安定版・実験版であると同時に、コミュニティ開発による最新式の技術を取り入れた、Linuxの「最新開発版」であると言える。
Red Hatが昔独自に開発した、RPMと言うパッケージ管理システムを採用。このRPMによって、ディストリビューションはパッケージ管理システムを使って開発するのが主流になった。また、依存関係の解決も容易になり、Linuxを使うのが一部の「オタク」だけではなくなり、ディストリビューションのパッケージを誰でも簡単にインストール出来るようになった。
IBMによりRed Hatが買収されたため、これからどうなるのか不安なのがFedoraCentOSである。単なるWebSphereの実行基盤になるとか、AIXという名前に変わるのではないかとか、あるいは本当にLinux無くなるんじゃないか、などといった声もある。

Ubuntu

Debianをベースに、初心者向けで、出来るだけ最新のパッケージと使いやすいデスクトップ環境を取り入れたディストリビューションとして有名。
Linuxディストリビューションとしても、一番使いやすくて初心者向けとして有名で、ユーザーが多い。
Unityと言う独自のデスクトップを採用しているが、フレーバーと言うディストリビューションの公式派生を持っていて、KDEGNOMEXfceやMATEを使うことも出来る。(後日注記:現在ではUnityではなくGMOME 3を採用している。)
Debianの派生のため、比較的たくさんのパッケージをメンテナンスしている。また、Canonicalと言う母体の会社によって、十分にリーダーシップが発揮されていることから、Red Hatとともにオープンソース業界をリードしていく役割を担っている。
Ubuntuも成熟したが、「普通にLinuxを使うならUbuntuしか選択肢がない」という状況が長い間続いてきた。だが、今のLinuxディストリビューションは、Linux Mintをはじめ、「Ubuntu以後の新しいセンスのあるディストリビューション」が増えている。よって、Ubuntuを使うよりも、もっと別のディストリビューションを使った方が面白いだろう。だが、仕事やビジネス、開発、システム管理、あるいはサーバーに使うのであれば、標準的なのはUbuntuである。最近はUbuntuの元になったDebianも改良され、「ほとんどDebianと同じ」になってきている。MriやSnappyのようにCanonicalは良く分からない発想をするため、「Linuxのトレンドと全く違う方向性」を持ったディストリビューションでもある。

openSUSE

昔は、ドイツのSuSEと言う会社が作っていた。Novellと言う会社に買収され、さらにそれもAttachmateに、それもマイクロフォーカスに買収されて、今ではEQTという良く分からないグループに売却されて、「一体誰が作っているの?」という状況。
先進的なKDEの開発で有名だが、NovellXimianと言うGNOMEの会社を買収したことから、GNOMEにも力を入れていた。
最近では、ローリングリリース版(特定のバージョンでリリースするのではなく、常に最新のパッケージにアップデートされる)とバージョンリリース版の両方をリリースしている。
Red Hatのライバル会社で、SUSE Linux Enterpriseと言う企業向け商用サポート版をリリースしている。
openSUSEFedoraのような実験版と言う側面は薄くて、企業が開発していることもあり、信頼性の高い製品になっている。
Linuxカーネルソースコードなどを見ていると、SuSEの会社の社員が開発したコードは意外と多い。企業向けに商用でLinuxを販売した初の会社であり、長らく「アメリカのRed Hat LinuxとドイツのSuSE Linux」の競争によって「商用Linuxの世界」は発展してきた。今ではどちらも体力が無く、一見Linuxは終わったかのように見えるが、裏では小さなディストリビューションがたくさん生まれており、「最盛期はもうはるか昔に過ぎ去ったのに、ようやく今頃使えるようになってきた」というのが2019年のLinuxディストリビューションである。

Gentoo Linux

独自のPortageと言うパッケージ管理システムを搭載したディストリビューション
Gentooとは選択である」と言う標語を掲げている通り、ディストリビューションがお仕着せで「これは標準だが、これは標準ではない」と言うしきたりを決めるのを無くし、ユーザーが独自に自分のディストリビューションを構築する「メタ・ディストリビューション」と言う標語を掲げている。
僕の一番好きなディストリビューション
インストールにはインストーラーは無く、全て手動でディストリビューションを構築するが、Gentoo Handbookと言う「Gentooの教科書」にインストールやシステムの構築方法のことがたくさん書いてあって、勉強になる。「Gentooインストールバトル」とも言われるこの「教科書と戦うインストール」だが、きちんと読めば敗北するわけがないのに敗北した人間が多い。こうした人たちには、GentooをベースにもっとみんなにフレンドリーにしたSabayonというディストリビューションがある。Archで言うManjaroと似ているが、インストーラ付きでバイナリパッケージからインストールできる。
パッケージ管理はソースベースで、BSDportsに近い。そのため、たくさんのCPUアーキテクチャに対応出来る。逆に、LibreOfficeのような巨大パッケージには「コンパイルをいちいちするのが時間がかかる」と言う難点もある。バイナリパッケージが提供されているものもあるが、GentooPortageを使うなら、USEフラグ(コンパイルする時にどのような機能を有効・無効にするかと言うフラグ)をいろいろ設定して、独自コンパイルして使いたいものだ。

Arch Linux

ローリングリリースとシンプル性を両立させたディストリビューション
今までのLinuxが「バージョンごとにリリースする」と言うバージョン制リリースを取っていたのとは逆に、「いつでも最新にアップデートされる」と言うローリングリリースと言うモデルを採用した。
また、Pacmanと言う独自のパッケージ管理システムを採用。そして、「設定ファイルはそのままにし、余計な設定ツールの提供や独自の開発は行わず、それぞれが自分の力で手動設定をする」と言う、ある意味では初心者お断りのようなシンプルなパッケージ管理ポリシーを採用した。
これはとても優れているモデルで、Gentoo Linuxのようなソースベースのパッケージ管理ではなくても、バイナリで、シンプルで、自分で設定することが出来る。ある意味、Linux本来の姿に戻ったような感じである。そして、余計なツールをごてごてに用意するRed HatDebian/Ubuntuのやり方とは一線を画し、とても良い上級者向けのシステムとなっている。
だが、インストーラーもなく、手動でインストールするには、経験と知識が必要だ。初心者は、Manjaroと言う、インストーラーと標準デスクトップ環境のインストールが提供されている派生版があるので、それを使うと良いだろう。

CentOS

RHELクローン。RHELSRPMを独自にリビルドして、フリーなライセンスに基づいて無料のクローン版を配布している。
そもそもRed Hat LinuxRHELに移行した時から、既にフリーソフトウェアRHELクローンはたくさん存在した。White Box Enterprise LinuxScientific Linuxなどがそれに当たる。今では、企業向けのエンタープライズクラスの性能が求められ、Red Hatからのサポートを必要とせず、自分たちの技術で維持する機関向けのLinuxディストリビューションとして、CentOSを使うことが標準的である。「そもそも、CentOSがあるのにRed Hatどう儲けるんや?」という批判や心配の声もあるが、Red Hatは「絶対にストップしてはならない」ような政府や軍、巨大企業向けの責任のある仕事をしていて、「本当にRed Hatにできんのか?」という批判や心配の声もある。REHLの主な利用者として挙げられるのは、宇宙開発のNASAなどである。
ちなみに、Oracle Linuxという派生版があり、これはRed HatではなくOracleが代わりに低価格でサポートする有料のディストリビューション。比較的安価であると同時にOracle DatabaseやWeblogic Serverなどを運用する基盤システムとして利用できる。
後日注記:実際のところ、Red Hatは中小のサーバーや古くなったUNIXのリプレースなどに良く使われている。ミッションクリティカルな領域としては、通信インフラやメインフレームでもRed Hatを使う。こうした分野で、自分で技術力がある会社は、開発部署として本当にCentOSを使う。そのため、ただのコピー品に見えて、社会に本当に必要なエンタープライズOSがCentOSである。

Linux Mint

Mintツールと呼ばれるツールを搭載し、マルチメディアのコーデックを充実させ、標準のソフトウェア環境などを変更した使いやすいディストリビューション。海外で人気がある。

パッケージ管理

Linuxとパッケージ管理

LinuxというOSは、昔から、カーネルだけが単体で配布され、それにGNUやその他のツールを導入しなければ使えなかった。
初期のハッカーは、リーナス・トーバルズとやり取りしながら、そうしたツールの導入を自分で行い、自分の責任でLinuxカーネルを導入し、開発に参加していた。
こうしたLinuxの「配布版」として生まれたのは、Slackwareなどの最初期のLinuxディストリビューションUNIXのシステム管理が分からない人間でも、簡単にLinuxシステム一式を導入し、使うことができた。
だが、さまざまなところからソフトウェアを組み合わせたSlackwareには、「依存関係」と「更新」の問題がある。
依存関係とは、「このソフトウェアをインストールするためには、別途ほかのソフトウェアが必要」であるということ。
更新の問題とは、さまざまなソフトウェアを別々にインストールするため、「最新のセキュリティパッチなどの情報を入手しづらく、自分の手で更新されているかを確認しなければならない」ということ。
パッケージ管理システムは、こうした依存関係と更新の問題を解決し、同時にソフトウェアパッケージを簡単に導入することができる機構であり、WindowsなどにはないLinuxに特有の機構である。
パッケージ管理システムで導入できるソフトウェアパッケージは、依存関係を自動的に解決し、必要なパッケージは追加インストールすることができる。また、パッケージはリポジトリに公開され、新しいパッケージが安定版で入手可能になれば、dnfやaptを用いることで即座に更新することができる。

パッケージ管理システムとは

パッケージ管理システムとは、Linuxで使われるアプリケーションのインストールやアンインストール、そして更新や管理のシステムである。
昔のLinuxでは、ソースコードの入ったtarballをそれぞれのシステムの管理者がコンパイルして、手動でmakeなどのコマンドでインストールしていたが、こうすると、さまざまなソフトウェア配布サイトから集めてきたフリーソフトウェアの更新を自分で把握しなければならないし、依存関係のチェックなどが大変で、一般のユーザーはとても自分ですることは出来なかった。
だが、Red Hatのようなディストリビューションの開発者は、「パッケージ管理システム」というものを作った。RPMでは、そもそものtarballにspecファイルと呼ばれる「インストール方法やソフトウェアの特性(主に依存関係)」を付属し、「パッケージ」という、ソフトウェア構成状態の含まれたコンパイル済みのアーカイブにし、インストールや更新は「パッケージ管理システム」と呼ばれるシステム全体で統一された「機構」によって管理することで、インストールや更新を楽にし、「一部の専門ユーザー(オタク)でなくても、Linuxのさまざまなソフトウェアをきちんと動くように導入出来る」という、画期的なものだった。
今のディストリビューションというのは、ほとんどがこのパッケージ管理システムに基づいている。Red HatRPMのほか、Debianやその派生(Ubuntuなど)のDeb/Dpkgが二大パッケージ管理システムだが、ほかにもGentooPortageやArchのPacmanなどがある。ほかにもたくさん、雨後の竹の子のように増えている。
このパッケージ管理システムというのは、ソフトウェアをパッケージにする代わり、その構成データを全て、.rpmとか.debなどの専用のファイル形式を持つアーカイブにし、そのアーカイブをシステムのrpmなどのコマンドでインストール・管理することになっている。また、ソースパッケージというものもあり、そもそもソフトウェアをビルドしてバイナリにする段階で、ソースパッケージを簡単に自動でバイナリパッケージにすることができるようになっている。
Linuxディストリビューションの開発では、パッケージの取りまとめ作業のようなことをプロジェクトとしてしていて、きちんと全てのパッケージが動くように、システムを安定してバグの無い状態で最新のリリースを出せるように心がけている。だから、DebianのメンテナやRed Hatの従業員は、きちんとOSとしてパッケージが動くことを想定して、diffのパッチを当てたり、カーネルとユーザーランドがきちんと動くように調節を行っている。さまざまなプロジェクトからバラバラにリリースされるソフトウェアを、ひとつのシステムとして動かしているのは、ディストリビュータが頑張ってメンテナンスや開発を行っているからである。それもあって、Linuxは必ずしも、無料であるとは限らないのである。
そして、RPMDebのひとつ上の水準の階層として、yum/dnfやaptのような「パッケージ管理ツール」というものがある。これは、.rpmや.debのようなファイルを、「インターネットから自動でダウンロードして、コマンド一発で依存関係など全ての処理をし、自動で全部のパッケージを更新することができる」というものである。
パッケージをインストールするのをRPMだとすると、そのパッケージをどこかのサーバーが配布しなければならない。Red HatDebianは、これを「リポジトリ」というインターネット上のミラーサーバーに公開している。このリポジトリをシステムに登録し、パッケージ管理ツールでコマンドを打ち込むことで、何ひとつ考えなくてもインストールは完了し、常に最新版に更新することができる。これはMicrosoftのやっている「Windows Update」と同様だが、本当はOSだけではなく「パッケージ全てを一発で更新できる」という特徴がある。
また、リポジトリの設定を変えることでDebianならばstableからsidに「ディストリビューションのバージョンを更新」することができるし、Red Hatでもリポジトリを追加することで「Red Hat以外のサーバーのサードパーティリポジトリ」からパッケージをインストールすることもできる。これはGoogle Chromeのような「一部オープンソースでないアプリケーション」にも適用できる。
ただ、これは二つの知っておくべき点がある。一つは、「パッケージには必ずメンテナが居る」ということ。ボランティアのパッケージのバージョンを上げたりインストールに必要なコマンドをきちんと明記してくれる、善意のメンテナが居るから、Debianのような膨大な数のパッケージも、常にきちんと動く状態になる。これは、商用のディストリビュータ会社が多い理由でもある。会社が金でやるのであれば、全てのRPMを管理する下っ端のプログラマを雇うことが出来る。Fedoraのようなコミュニティのディストリビューションも、メンテナはほとんどが母体となる会社の従業員である。
もう一つの問題は、「パッケージを開発者でもユーザーでもない、第三者が再配布しなければ、パッケージ管理システムは成り立たない」ということである。膨大なパッケージがDebianリポジトリに登録されているものの、それは元の開発者でもなく、使うユーザーでもない、「第三者のボランティア」がやっている。このため、たとえば実際には使ったこともないのにパッケージメンテナになっていたり、あるいは、セキュリティや致命的なバグの修正はマイナーディストリビューションでは遅れることやきちんとやっていないことがある。
だが、これらの問題は最近、FlatpakやSnappyなどの「アプリケーション仮想化ツール」が新しい実験を始めている。ディストリビュータのメンテナがパッケージを提供するのではなく、Windowsフリーソフトのように、ディストリビューションのパッケージ管理システムとは別の、仮想的な導入しやすいパッケージの配布の形態をし、そのパッケージの配布や管理はそれぞれのソフトウェアのプロジェクトが「じかに行う」というものである。また、最近はFlatpakはさらに発展しており、flathubというFlatpak向けのパッケージ集積サイトがある。こうした場所からパッケージを導入することで、システムのパッケージとは別に最新のアプリケーションを簡単に導入できる。詳細はFlatpakを参照のこと。
ただし、パッケージ管理システムは、Linuxだけのものではない。最近はJavaScriptのパッケージ管理システムや、マイナーなところではEmacsのパッケージ管理システムもあるし、Rubyのような日本のプロジェクトでも、同様のパッケージ管理システムのようなものは生まれている。Macにもパッケージ管理システムはあるし、WindowsだってWindows Updateは用意している。Windowsの場合、さまざまなプロジェクトがクローズドソースでプログラムを作っているため、統一されたリポジトリで再配布とするのは難しい。このため、Firefoxだろうが、WinSCPだろうが、あるいはGitだろうが、Windowsの場合はそれぞれのソフトウェアの流儀に従うしかない。これを「手間」だと見るか、あるいは「独立性」と見るかは人それぞれである。Linuxも便利とは言うが、全くクローズドソースなソフトウェアのことは考えていない。そもそもフォトショやイラレのような商用アプリケーションは動かない。それを「動かない」と見るか、「純粋に全て無料であることが保証されていてありがたい」と見るかも、人それぞれである。

依存関係の解決とパッケージ管理システムの乱立の是非

そもそも、パッケージ管理システムの何が良いかと言うと、「依存関係を解決してくれる」ことだ。
さまざまなライブラリやコンポーネントを使うプログラムをインストールしたい場合、あるコンポーネントがなければ、そのプログラムは動作しない。これを依存関係と言う。
これを手動コンパイルでインストールしようとすると、さまざまな複雑な依存関係があらわになって、ディストリビューションを開発したい場合などでは、絶対に動かないようなわけのわからないことになってしまう。
多くのシステムが、依存関係の解決ができないことによって、破壊されてきた。
だが、RPMなどのパッケージ管理システムでは、パッケージの依存関係を計算して、自動的に「これはインストールしても動く」「これはインストールしても動かない」ということを簡単に確認できる。
RPMが生まれたことによって、ディストリビューションの開発が容易になった。一部のオタクやマニアでなくても、動くLinuxシステムを構築することができるようになった。
また、Debianのapt-getのようなパッケージ管理システムのネットワークインストールツールを使って、「必要なパッケージを全部自動でネットワークから取得してインストールしてくれる」ようなツールが生まれた。これによって、firefoxを使う場合は、「apt install firefox」と実行するだけで、面倒なこと全てを自動でやってくれる。オープンソースなので、リポジトリのあるミラーサーバーを経由することで、自分でさまざまなWebサイトにアクセスしてダウンロードしなくても、コマンド一発でリポジトリからダウンロードしてくれる。
この方式の長所はもう一つあって、それは「パッケージ全てを簡単に最新版に保つことが出来る」ということだ。Debianの安定板なら、致命的なバグとセキュリティがfixされたパッケージを、apt update && apt upgradeで簡単に最新版にすることもできる。ほとんどのオープンソースソフトウェアは、リポジトリにパッケージがあるため、お金もかからず、簡単に最新版に出来る。
そして、パッケージのメンテナが見ると、「ソースパッケージ」を使うことで、バイナリのビルドが自動化出来る。この方式はとても画期的で、GentooPortageでは、USEフラグを設定することで、ほとんど自動的にバイナリパッケージをソースパッケージから構築出来る。
もう一つの利点は、システム全体をクリーンに保つことが出来るということ。パッケージの依存関係は、インストール時だけではなく、アンインストール時にも働く。少し前は出来なかった「不要になった依存パッケージのアンインストール」は、最近はどのパッケージ管理システムでも出来るようになった。Fedorayum/dnfなどでは、history機能を使って、その時インストールした全てのパッケージを、全部簡単にundoすることが出来る。システムが壊れる心配もない。
パッケージ管理システムは好評だが、Windowsに比べると、手動で管理する余地が少ないと感じられるかもしれない。Windowsはそれぞれがインストール導入システム(InstallShieldなど)を使っているが、この方式は、個人のフリーソフト作成者などからすると、簡単にインストールしたパッケージをすぐにアンインストール出来るし、.zipなどで配布されている場合は、圧縮ファイルからフォルダを解凍して.exeを実行するだけで簡単にプログラムが実行できる。こうした方式の長所はLinuxでも最近取りいれられていて、AppImageやflatpakやsnappyのようなアプリケーション仮想化システムでは、簡単にアプリケーションイメージをダウンロードしてすぐにインストールできる仕組みを開発している。この方式が上手く働けば、ディストリビューションがわざわざ「第三者が介入して」パッケージをリポジトリに提供しなくても、アプリケーション開発者とユーザーの間で簡単にフリーソフトの配布ができるようになるだろう。
元の話に戻ると、パッケージ管理システムは、雨後の竹の子のようにいくらでも増えている。RPM/Yum (Red Hat), Deb/Apt (Debian), Portage (Gentoo) などの主要なものだけではなく、zypper (openSUSE), Pacman (Arch), マイナーなところではGuixなどいくらでもある。どうでも良いほど増えているが、それは「自分のディストリビューションを作りたい」という一向に増え続けるニーズのためだ。だが、パッケージ管理システムは「とてもたくさんのパッケージを一人でメンテナンスできるわけがない」というところもある。Debianなどの大手ディストリビュータでは可能だろうが、マイナーなところではとても管理しきれず、Vine Linuxのようなディストリビューションは全く管理できていないし、FedoraのようなところではChromiumのような「アップデートしまくるパッケージ」は最初からきちんと管理していない。Linux Mintなどでは、「Ubuntuリポジトリを共有する」という賢い解決策を取っている。こうした意味から言っても、ディストリビューションの乱立のしすぎは、利用者にとってあまり良いことではない。
後日注記:Windowsについて言えば、コントロールパネルのプログラムのアンインストールからパッケージを削除することはできる。だが、たとえばVisual Studioなどをインストールする場合、必要なパッケージが大量にインストールされてしまい、後で消すことができなくなる。消そうとした場合、パッケージを間違えて削除してしまい、結果システムが壊れることがある。Linuxもこれと同じで、パッケージ管理システムがなければ、巨大システムは簡単に、その時点で「一瞬の靄のように」破壊されてしまう。よって、パッケージ管理システムは、サーバーやエンタープライズなどシステムを破壊してはならない場合には必須である。

コマンド一発で全ソフトウェアの安全性が保たれる

パッケージ管理システムとリポジトリのメリットは、「コマンド一発で、システムの(パッケージ管理システムでインストールした)全アプリケーションの安全性が保たれる」ということ。
たとえば、Windowsなどの場合、WindowsのOSのセキュリティホールWindows Updateで修正されても、WinSCPFirefoxまでは修正してくれない。それぞれのアプリケーションを最新にする努力が必要だ。
Linuxでは、その努力は必要ない。ディストリビューションリポジトリセキュリティホールを修正したバージョンをミラーサイトにリリースするため、コマンドを一発実行するだけで、FirefoxからGIMPまで、全てのアプリケーションのセキュリティホールを修正してくれる。これは、オープンソースのなせる業(再配布・修正が可能)である。
これは、サーバーシステムなどでは特にありがたい機能で、ApacheからPHPMySQLまで、全てのコンポーネントを一気にアップデートできる。
だが、これはもろ刃の剣で、システムが破損する可能性を常に持っている。Debianなどでは、セキュリティホールと致命的なバグをアップデートするだけで、ローリングリリースのように、機能が増えAPIの変わった最新のバージョンにすることはないため、比較的安心できる。だが、ローリングリリースのArchや、とにかく最新にしたがるFedoraでシステムを作るのはやめた方が無難だろう。
パッケージの更新は、コマンドラインから行うこともできるほか、aptitudeを使ってメニュー形式でインストールしたり、PackageKitなどを使ってGUIからも行うことが出来る。また、ネットワークからSSHでパッケージ更新をかけることも出来る。他には、cronで定期的に実行する専用のパッケージをインストールすることで、ほとんど何もしないで管理することもできる。
最近は、Dockerという仮想化コンテナも普及している。ホストのLinuxカーネルを共有した上で、いくらでもLinuxのシステムを仮想的にコンテナの上で構築できる。この場合は、Dockerfileにソフトウェア情報を書けば良い。便利な世の中だが、どんどん複雑化しているため、15年前の僕の知識で対応できるかどうかは怪しい。クラウド環境(Amazon EC2など)でサーバーインフラを貸してもらうこともできるだろう。
後日注記:実際にはLinuxでもソースtarballからパッケージをインストールする場合は多く、この場合は自分の手でパッケージを更新しなければならないため、なかなか全自動でシステムを更新し管理するというのは難しい。よって、セキュリティ情報は日ごろから注視しておかなければならないが、Debianなどではメーリングリストなどでセキュリティ関係のMLを購読することで、こうした情報を知ることができる。

RPM

Red Hat系のパッケージ管理システム。

DNF/Yum

Red Hat系の高度なパッケージ管理ツール。

Deb/Dpkg

Debian系のパッケージ管理システム。

Apt

Debian系の高度なパッケージ管理ツール。

zypper

openSUSEのパッケージ管理ツール。

YaST

openSUSEの設定ツール。統合されていて使いやすいと評判。

urpmi

Mandriva Linuxのパッケージ管理ツール。

Portage

Gentoo Linuxのソースベースのパッケージ管理システム。何でもかんでも最適化コンパイルが出来、バイナリ形式ではないため、さまざまなアーキテクチャに対応させやすい。

Pacman

Arch Linuxのパッケージ管理システム。

GNU Guix

Lispによるパッケージ管理システム。

alien

パッケージのフォーマットを変換する。RPM形式をDeb形式にしたりtgz形式にしたりすることができる。

AppImage/Flatpak/Snappy

AppImage/Flatpak/Snappyを使うことで、システムのパッケージとは別に、仮想サンドボックス化されたどのディストリビューションにも入れられる手軽なパッケージを導入できる。パッケージの集約サイトであるflathubやsnapcraftなどを利用することも可能。

Docker Hub

最近では、Dockerというコンテナ型仮想化システムにより、Dockerfileでシステムイメージを作成し、Docker Hubのような場所でイメージを簡単に入手して、docker runでコンテナを起動することができる。
これにより、たとえばMySQLを使いたい場合は、自分で面倒な導入作業や設定作業を行わなくても、Dockerで簡単にコンテナイメージを起動できる。
MySQLコンテナやRailsコンテナを簡単に導入でき、どの環境でも同じ環境で開発が行えるほか、それぞれに仮想マシンを割り当てて、簡単にスクラップ・ビルドができる。

git clone

また、Gitを用いることで、従来ソースパッケージなどを用いて行っていた、「オープンソースの開発への参加」が簡単になった。
ソースコードGitHubなどで公開されている場合、簡単にgit cloneでそれをローカルにコピーできる。コミットするだけで開発でき、プルリクエストすればマージされることも期待できる。
gitやDockerの普及とともに、従来のパッケージ管理システムを使うのではなく、もっと簡単・高度にソフトウェアを導入・管理することが可能になってきている。

ソースからのインストール

まずはREADMEを読もう

ソフトウェアをソースからインストールする時は、まず、READMEやそれに類する文書(INSTALLなど)がtarball(*.tar.gz圧縮ファイル)の中に無いかを確認し、あったらそれを読みましょう。
ソフトウェアをビルド・インストールするための方法がREADMEに書いてあることが多いためです。
ちなみに、Autotoolsで作成されたGNUパッケージでは、以下のようなファイルが含まれていることが多いです。

ファイル名 説明
README 一般的な情報
AUTHORS クレジット
THANKS 謝辞
Changelog 詳細な変更履歴(プログラマー向け)
NEWS 簡単な変更履歴(ユーザー向け)
INSTALL インストール方法
COPYING / LICENSE 著作権・ライセンス情報
BUGS 報告があった既知のバグ

ちなみに、ソースコードなどのファイルはsrcディレクトリに入っていることが多い。ただしそうではなくアプリケーション名のディレクトリに入っている場合もあれば、分野ごとに分かれていたりする場合もあるし、ライブラリだけをlibxxxに入れていることもあったりする。

/usr/localにインストールする場合

ソースコードの入ったtarballのインストールをする場合、Linuxでは慣習的にprefixを/usr/localに指定してインストールします。

$ ./configure --prefix=/usr/local
$ make
$ su -
Password: (rootユーザーのパスワードを入力する)
# make install

/usr/local/binがPATHに入っているかどうかを確認してください。

$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/schwarz/bin

入ってなかった時は、.bash_profileなどに記述をお願いします。

ホームディレクトリにインストールする場合

ホームディレクトリにインストールする場合は、以下のようにします。

$ ./configure --prefix=/home/schwarz/app_name
$ make
$ make install

これで、/home/schwarz/app_nameにプログラムをインストールできます。実行する場合は、相対パスを用いて以下のようにするか、

$ cd /home/schwarz/app_name/bin
$ ./program

あるいは、インストールしたディレクトリのbinディレクトリをPATHに追加します。

/usr/localにサブディレクトリを作る場合

/usr/localにサブディレクトリを作って、/usr/local/mysqlなどにプログラムをインストールすることもできます。管理もしやすいし、あとで削除するかもしれないがシステムとして使いたいプログラムの場合は、これがお勧めです。

共有ライブラリの場合

共有ライブラリの場合、LD_LIBRARY_PATHかLD_LIBRARY_PATH_64にディレクトリを登録するか、/etc/ld.so.confにパスを記述します。記述したあとで、ldconfigコマンドを実行してキャッシュを更新してください。

initとデーモン

SysV init

最近はsystemdにとってかわられてしまったが、昔のシンプルだったごろのSysV initを解説する。
まず、ファイルシステムの方に、起動時に実行するスクリプトが存在する。/etc/rc.d/などにあることが多い。
init.dディレクトリの中に、それぞれのデーモン(コマンドではなく、起動時に実行され、システムで恒常的に実行されるプログラム)を実行させるスクリプトがある。
rc0.dのように、rc[数字].dの中に、それぞれのランレベルごとに実行される、先ほどのスクリプトへの、シンボリックリンクがある。
このスクリプトは、S85httpdのように、実行順(実行の順序)の数字とともにファイル名が付けられている。
ランレベルは以下のようになる。

ランレベル 説明
0 停止
1 シングルユーザモード
2 マルチユーザモード(ネットワークなし)
3 マルチユーザモード(ネットワークあり)
4 未使用
5 マルチユーザモード(GUIログイン)
6 再起動

そして、OSの起動・終了時に/etc/inittabの設定を見て、initと言うプログラムがランレベルによって実行される。

initで終了・再起動

initコマンドとともにランレベルを指定することで、再起動や終了の処理を行うことが出来る。

init 0

halt

と同じで、システムの終了を表す。

init 6

reboot

と同じで再起動を表す。だが、ログインユーザにメッセージを送信するかどうか、という点が違う。基本的にはshutdownコマンドを使うことが推奨される。

デーモンとは

デーモンとは、コマンドによってその時の処理を行うプログラムではなく、システムに常駐して常に実行されるプログラムのこと。
HTTPサーバーデーモン(httpd)などがそれに当たる。httpdは、外部のクライアントに対して、常に応答を待ち、常に実行され得る「サーバー」と呼ばれるプログラムである。
Linuxにおいて、デーモンは主にシステムの起動時に実行され、システムの終了前に停止される。
そのためのスクリプト(デーモンを起動させたり停止させたりする小さなスクリプト)が、/etc/init.dや/etc/rc.d/init.dにスクリプトとして存在し、さらにランレベルごとにrc0.dからrc6.dまでフォルダが存在し、それぞれのランレベルによって、起動スクリプトが配置され、init.dのスクリプト実体にリンクされる、という風になっている。
複雑に見えるが、分かってしまえば単純だ。スクリプトには、start, stop, restartなどの各場合に応じた処理が記載されており、またどのプログラムをシステムの起動時に自動的に起動させたいか、という情報はchkconfigなどのツールで追加・削除して設定する。
(注意:最近のLinuxではsystemdを使っていることに注意。ここでの説明は全て昔のSysV initの説明であり、既に古い。)

デーモンの起動、終了、再起動

デーモンは、起動スクリプトを実行することで起動・停止・再起動・状態確認ができる。また、直接スクリプトを触らずに、serviceコマンドを使う方法もある。デーモンはWindowsなどで良く使われる呼称として、サービスと呼ばれることもある。
基本的に、Apache httpdなどサーバーの設定を変更した場合、サービスを再起動しなければ設定は反映されない。こうした時にこの方法で再起動を実行する。

rc.dスクリプトの例

/etc/rc.d/daemonnameなど

#!/bin/bash

case "$1" in
 start)
   #処理
   ;;
 stop)
   #処理
   ;;
 restart)
   #処理
   ;;
 *)
   echo "usage: $0 {start|stop|restart}"
esac

起動スクリプトの直接の実行

起動スクリプトを直接実行する場合:

/etc/init.d/daemonname start

start(サービスを起動する)、stop(サービスを停止する)、restart(サービスを再起動する)、status(サービスの状態を表示する)がある。

serviceコマンド

serviceコマンドで実行する場合:

/sbin/service daemonname start

init.dのスクリプトと同様に、start、stop、restart、statusがある。
たとえば、Apache httpdを再起動して設定を再度読み込む場合は以下のようにする。

# service httpd restart

/sbinがPATHに入っている場合、コマンドの前の「/sbin/」は必要ない。
現在のLinuxでは、init.dではなくserviceコマンドを主に使う。

systemctl

systemdでは、systemctlコマンドを使ってサービスを起動・停止する。

/etc/rc.conf(BSD方式とGentoo方式)

BSDのrcファイルの方式では、/etc/rc.confという設定ファイルに基づく起動処理を記述する。SysV initに比べて簡素な反面、記述を間違えたり誤ってファイルを削除するとシステムが起動しなくなるという欠点も併せ持つ。
Gentoo Linuxでは、OpenRCという独自の起動処理を行うが、これはBSDと同様に/etc/rc.confをグローバル設定ファイルとしながら、/etc/conf.dや/etc/init.dに設定ファイル・スクリプトを置き、その上でrc-updateコマンドを使って動的に設定を追加・削除することができる。
Gentoo LinuxのOpenRCはとても独自で、多くのディストリビューションがSysV initからsystemdに移った今でも、GentooだけはOpenRCを固持している。これは、OpenRCがとても使いやすく、BSDライクということもあって分かりやすく、そしてGentooの独自の文化の一部になっているからである。

systemd

systemd概要

複雑怪奇だと言って、何かと嫌われているsystemd。僕もそんなに好きではない。並列処理が可能なため速く、サービスの開始・停止などをスクリプトではなく、systemdの標準機能として行える。サービスの設定などはUnitファイルと呼ばれる、シェルスクリプトよりも単純でシンプルな設定ファイルから行える。
柔軟で動的な管理が可能ということだが、いかんせん複雑だ。
Debianから派生したDevuanのように、systemdを取り除いて、さまざまなinitアーキテクチャを選べるようにしたディストリビューションも存在する。
後日注記:現在のマルチコアプロセッサが普通になった64bit CPU環境では、従来の順次起動しかできないSysV initは時代遅れであり、並列処理が可能なsystemdは大幅な起動時間の削減に繋がる。これは悪いことではない。

systemdの意義

僕が感じることとして、systemdはただの複雑さ・相互依存のオンパレードではない。「Linux界の設定・管理の中心的存在」になろうとしているのである。
systemdは、System VやMulticsの失敗を繰り返していると良く批判されるが、systemdのやりたいことは、「Linuxシステム管理で、新しい中心的なリーダー」になろうとしている、ということである。
複雑とは言われるが、systemdのUnitファイルはSysV initよりもシンプルである。これは、シェルスクリプトではなくさまざまなsystemdの機能の下での「設定ファイル」を使うことで、システムアーキテクチャとしての「シンプルかつ高機能性」を目指しているところがある。

モダンなLinuxの管理=systemd

最近のLinuxを見ていると、まるで「Linuxの管理=systemd」である。
今までのLinuxの管理の方法を一掃し、「ディストリビューションの間で違っていたさまざまな管理の手法」は、全てsystemdに置き換わろうとしている。
そして、多くの開発者や管理者も、それを受け入れている。「systemdは確かに巨大なソフトウェアスイートで、Linuxの管理全てを支配するソフトウェアだが、今までのLinuxよりはマシ」ということになろうとしている。
これは必ずしも悪いことではない。今のLinuxの管理はsystemdそのものである。systemdを学んでおけば、Linuxの管理ができるようになる。カーネルやシステムとアプリケーションを繋ぐ「ノリ」の役割は全部systemdにさせる、というのが今の「ナウいLinuxの管理」である。
よく似ているものとして、ネットワークの設定に使うNetworkManagerが挙げられる。Linuxはどんどん作り変えられようとしている。

Unitファイルの命名規則と起動

いまさらだけどsystemdに入門した - 雑なメモを参考に執筆しました。
Unitファイルは、デフォルトの設定が/usr/lib/systemd/systemにあり、変更する場合はここにあるファイルを/etc/systemd/systemにコピーすることで行われる。設定を解除したい時はファイルを削除する。
Unitファイルには、拡張子によってservice(サービス)、target(複数のUnitをグループ化)、mount(ファイルシステムのマウント)、swap(スワップ領域を有効化)、device(デバイス)などがあり、mountとswapは/etc/fstabから自動作成される。deviceはudevがデバイスを認識すると自動作成される。ほかにもsocket、automount、path、timer、snapshot、slice、scopeなどがある。timerはcronのようなジョブスケジューラとして利用できる。
Linuxカーネル起動後、PID=1として/usr/lib/systemd/systemdが起動する。systemdによってUnitの依存関係が解消され、有効にすべきUnitを一覧する。Unitの順序関係に基づいて、Unitを起動し、順序関係を持たないものは並列で起動する。

systemctlコマンド

systemctlコマンドは、enable(有効化)、disable(無効化)、is-enabled(有効・無効の確認)、start(起動)、status(状況の表示)、show(状況の表示2)、stop(停止)、reload(設定の再読み込み)、restart(再起動)と使う。
たとえば、

# systemctl start httpd.service

.serviceは省略できる。

# systemctl start httpd

ネットワーク

ソケット

ソケットはUNIXにおけるファイルAPI(open, write, read, close)と同様のネットワーク通信の実装である。
TCP/IPの下位プロトコルトランスポート層UDP/TCP)の通信が行える。
基本は、複数のソケットが互いに関係を持つと有効になる。一方に書き込むともう一方から出てくる。そのため、ハードウェアやシステム的なことを考えなくても、ファイルのAPIと同様に簡単にネットワーク通信が出来る。
BSDUNIXを起源とするAPIであり、そのためこのソケットのAPIは「BSD socket」などと呼ばれる。
ソケットはファイルとして扱われる。そのため、通常のファイルと同じように、ファイルディスクリプタからストリームとして読み書きできる。

traceroute

tracerouteは、あるホストから別のホストまでのネットワーク経路を表示するコマンド。
ネットワーク経路とはホスト間を接続するルータのことで、経路上にどんなルータが存在し、どれくらいのルータがどのようにネットワークを経由しているかを表示できる。
Windowsではtracertコマンドが同様のコマンドになる。

route

routeは、IPパケットをルーティングするためのルーティングテーブルを表示するコマンド。
Windowsにも同様にrouteコマンドがある。

netstat

netstateは、ホストのネットワークの接続状況や、ソケットやインターフェースごとのネットワーク統計などを表示するコマンド。
ホストが現在実行している接続の一覧やステータスを表示できるほか、IPやTCP/UDP以下の各パケットの統計やエラー状態なども調べられる。
Windowsにも同様にnetstatコマンドがある。
名称は「Network statistics」の略で、ネットワーク接続、ルーティング、ネットワークインターフェース(NIC)の状況や状態を表示できる。
netstatTCP/UDPプロトコルを対象に統計状態を表示する。TCPソケットを表示する「-t」、UDPソケットを表示する「-u」オプションと、多数用意されているオプションを組み合わせて使用する。
主なオプション:

オプション 説明
-I 指定したNICのみ表示(例:-Ieth0)
-a 全てのアクティブなソケットを表示
-c 1秒ごとに更新しつつ表示
-i 全てのNICの状態テーブルを表示
-l 接続待ち(LISTEN)状態のソケットのみ表示
-p ソケットが属するプログラムのPID(プロセスID)とプロセス名を表示
-r ルーティングテーブルを表示
-s プロトコルの統計情報を表示

ifconfig

ifconfigは、Linuxで用いられる、現在のシステムのネットワーク環境の状態確認や設定確認、あるいは手動設定のためのコマンド。
ホストに設置された有線LANや無線LANなどのネットワークインターフェースに対して、IPアドレスサブネットマスク、ブロードキャストアドレスなどの設定をしたり、設定の確認をしたりすることができる。
現在はifconfigは非推奨となり、ipコマンドへと移行が推奨されている。
Windowsではifconfigではなくipconfigコマンドを使う。

ip

メンテナンスが長年滞っていたnet-toolsに代わって、iproute2パッケージが使われるようになった現在のLinuxでは、ifconfigではなくipコマンドを用いる。
arp、ifconfig、netstat、routeなどのコマンドは「レガシーコマンド」とされ、近い将来に廃止される予定。

arp

arpは、ARPテーブルの表示・設定を行うコマンド。ARPテーブルとは、イーサネット通信のために用いられるIPアドレスMACアドレスの対照表のこと。
通常ユーザーでの設定が必要となることは少ないが、OSの設定ミスなどで、イーサネット通信が上手くいかない時に、ARPテーブルの設定に問題がないかどうかの確認に使用する。
Windowsでもarpコマンドを使用できる。

nslookup

nslookupは、DNSサーバに名前解決を問い合わせるコマンド。DNSサーバが正常に動作しているかを調べるためにも使える。
Windowsでもnslookupコマンドを使用できる。

ping

pingは、実際にネットワークに繋がるかを確認するコマンド。IPパケットを実際にホストに発行・送信し、そのパケットが正しく届いて返答が行われるかを確認する。
Windowsでもpingコマンドを使用できる。

高レベルなネットワーク設定システム

ifconfigのような低レベルのネットワーク設定は、強力だが面倒だ。
そのため、もっと高レベルの使いやすいネットワーク設定システムが用意されている。
Red Hatではsysconfig、Debianではifupdownを使う。

NetworkManager

最近は、NetworkManagerを使ってネットワークを設定するのが推奨されている。
以前は/etc/init.d/networkから/etc/sysconfig/*を読んでいた。
RHEL6など、以前のRed Hat系のディストリビューションは/etc/init.d/networkを読んでおり、これが/etc/sysconfig/network-scriptsや/etc/sysconfig/static-routesなどを読んでいた。
RHEL7よりNetworkManagerでネットワーク設定することが推奨されている。
RHEL7のネットワーク設定の方法は、nmcli, nmtui, GNOME コントロールセンター, ファイルを直接編集する, がある。
設定ファイルが/etc/syscnofig/network-scripts/ifcfg-*などになることは相変わらずだが、ファイルを直接編集せずnmcliやnmtuiなどを利用することが推奨されている。

ifupdownについて

ifupdownは、Debianでの高レベルネットワーク設定のデファクトスタンダード

ifup eth0

とするだけでネットワークを立ち上げることができる。
設定ファイルは、/etc/network/interfacesにある。

iptables

ファイアーウォール(パケットフィルタリング)やNAT(ルーティングやアドレス変換)として通信の許可とブロックを行うための、Linuxのネットワーク設定(Netfilter)を設定する技術。CentOS 6などで使われる。
Netfilterはパケットフィルタリングのパッケージで、ネットワークドライバとカーネルとの間でパケットの内容を精査し、設定に応じてパケットを破棄することで不正なパケットの排除を行う。

nftables

ファイアーウォール。Debian 10ではiptablesからnftablesに置き換わる。

SSH

SSHはリモートのマシンにログインする「リモートログイン」ソフトウェア。
リモートのLinuxマシンにログインし、UNIXコマンドを実行したり、パッケージをインストール・更新したり、サービスを起動・停止したり、設定ファイルを編集したりする、「リモート管理」を行うことができる。
Linuxを使う上で、コマンドラインのOSを使うメリットとして言えるのは、「GUIよりも高度なことが簡単にできる」とか「スクリプトで自動化したり、パイプで複数のコマンドを組み合わせることができる」などとよく言われ、コンソール(端末の白黒画面のターミナル)やGUIの端末エミュレータGUIの中でコマンドラインが使えるターミナル)から使うこともできますが、コマンドラインの醍醐味はSSHでリモートのサーバーにログインするなどして、リモートからコマンド操作を行うことだと思います。
たとえばWindows上のTeraTermなどの端末エミュレータから、リモートのLinuxサーバーマシンにログインし、操作を行う。この時、mkdirやcpなどのUNIXコマンドを覚えていると、多くのUNIXコマンドが使える。UNIXコマンドの大きなメリットは、「SSHでリモート操作ができる」ということが多い。
ただし、リモートからログインできるため、セキュリティ管理には注意が必要。昔からのUNIXエンジニアにはrlogin/telnetを使ったログインがお馴染みだが、SSHはそれらよりもセキュリティが高いとされている。
あまり使う頻度は多くないかもしれないが、WindowsからLinuxGUIアプリケーションを起動したい場合は、Cygwin/Xなどが使用できる。僕は使ったことがないので実際は分からないが、Cygwin上のXでもおそらくリモートのXアプリケーションに接続できる(Xはネットワーク透過なクライアント・サーバーシステムである)。
また、リモートデスクトップとしてはVNCと呼ばれるソフトウェアがある。これはリモートのコンピュータを遠隔操作することができ、Windowsなどでも使用できる。

モニタリング

top

topはリアルタイムのモニタリングツール。システムで稼働しているプロセスやスレッドの状況をリアルタイムで表示できる。
「-d 秒数」で更新間隔を、「-p プロセスID」で指定したプロセスIDのみを表示できる。
また対話オプションでは、

コマンド 意味
Space/Enter 更新
q 終了
k 指定したプロセスIDにシグナルを送信
r プロセスIDとNICE値を指定してプロセスの優先度を変更できる。
h ヘルプを表示できる。

その他さまざまな対話オプションがあり、メモリやCPUの利用順に値を並び替えたり、表示・非表示を切り替えたりできる。
[改訂第3版]Linuxコマンドポケットリファレンスを参考に執筆しました。)

vmstatとiostat

vmstatは仮想メモリの統計情報、iostatは入出力デバイスの統計情報を表示する。
topとともに、サーバーのリソースをリアルタイムでモニタリングするのに使える。OSでの実行を待機中のプロセスのキューを表示するのにもvmstatが使える。

共有ライブラリ・ヘッダファイル

lddコマンド

lddコマンドは、引数に指定した実行ファイルが利用している共有ライブラリを表示する。

$ ldd /bin/ls
(lsの依存関係にある共有ライブラリが表示される)

共有ライブラリの検索順序

まず、LD_LIBRARY_PATHあるいはLD_LIBRARY_PATH_64の環境変数から検索される。
次に、/etc/ld.so.confに記述されたパスから検索される。
最後に、通常ライブラリが置かれるパス、/lib (/usr/lib への symbolic link)、/lib64 (/usr/lib64 への symbolic link)から検索される

ldconfig

ldconfigコマンドは、/etc/ld.so.confの情報をOSに伝えるためのコマンド。
/etc/ld.so.conf.d/以下にhoge.confを作ってパスを記述し、ldconfigでキャッシュ(/etc/ld.so.cache)を更新する。

共有ライブラリを作る

Linuxの共有ライブラリを作るためには、PIC (Position Independent Code)となるようコンパイルする。PICでコンパイルするにはgccに-fpicまたは-fPICを渡す。

/usr/includeとヘッダファイル

/usr/includeには、システムのC言語用のヘッダファイルが置かれる。
たとえば、Cのプログラムコードに必ずといって出てくる「#include 」のstdio.hが存在するディレクトリがここ。
標準入出力関数のヘッダファイルは/usr/include/stdio.hに存在する。
C言語で任意のライブラリ関数のAPIを使ったプログラムを自分で書いてコンパイルするためには、関数のプロトタイプ宣言が書かれたヘッダファイルをインクルードしなければならない。
/usr/includeディレクトリが存在しなければ、Cの標準ライブラリ関数や、あるいはどんなライブラリ関数を使ったプログラムも、コンパイルして使うことはできない。
ただし、gccに-Iオプションをつけてコンパイルすると、/usr/include以外のディレクトリを検索対象に追加できる。
また、#include "hoge.h"のようにダブルクオーテーションでヘッダファイルを囲った場合は、/usr/includeでなくプログラムと同じディレクトリからヘッダファイルをインクルードできる)。
だが、一度コンパイルしたバイナリを動かすためには、ヘッダファイルは必要ない。その代わり、ビルドされた共有ライブラリが必要になる。

develパッケージ

-develと名前のついたライブラリのパッケージをインストールすると、/usr/includeにヘッダファイルが展開される。
ほかにもREADMEなど開発向けドキュメントやサンプルプログラムなどがインストールされることもある。
これは、自分でそのライブラリのAPIを使ったプログラムを書いたり、そのライブラリAPIを使ったプログラムをソースコードから「ビルドするために必要」だが、単にそのライブラリを使ったプログラムを「実行するためには必要ない」。

バイスファイル

デバイスドライバ

デバイスドライバは、この世界にあまたあるハードウェアデバイスそれぞれを共有のインターフェースで操作する仕組みで、デバイスドライバが用意されていないハードウェアについてはOSは操作することができない。Linuxカーネルの大部分のコードはデバイスドライバに充てられている。Linuxはプリンターなど一部のデバイスについては今でもドライバが十分ではなく、プリンターについては「ドライバレス」と呼ばれる新しい仕組みも開発されている。
最近はLinuxカーネルX11もモジュールを自動でロードするので、自分でデバイスドライバを導入したり設定したりすることは少なくなっている。組み込みシステム向けにLinuxカーネルを使う場合などは、カーネルを手動コンパイルすることで、必要のないモジュールを全て消去できる。また、リアルタイム向けのパッチを当てることで、プリエンティブルなRTOSの機能(要求が起きてからタスクを実行する時間を最短にする)を実現できる。特に自動車などLinux+Pythonの環境を組み込みでも使いたい場合など(人工知能を乗せるなど)の時は、PC向けの要らない機能(デバイスドライバだけではなくファイルシステムなど)は全部消去させることができる。

ブロック型デバイスとキャラクタ型デバイス

デバイスドライバには、大きく分けてブロック型デバイスとキャラクタ型デバイスがある。
基本的に、ブロック型デバイスというのは、ハードディスクやCD-ROMのような「データ」を扱うためのもので、キャラクタ型デバイスというのは、モデムやプリンタやキーボードやマウスといった「やり取り」を行うためのもの。
ブロック型とキャラクタ型の違いは、「好きな時に好きなところにアクセスできるかどうか」。

  • ブロック型デバイス
    • ランダムに前後してデータを読み書きすることができる。
    • バイスファイルはデータの蓄積として扱われる。
    • ファイルシステムが作成されたハードディスクの場合、ファイルシステムにマウントし、別々のファイルとしてデータを読み書きできる。
    • ハードディスクなどがブロック型デバイスである。
  • キャラクタ型デバイス
    • ランダムに前後してデータを読み書きすることができない。
    • シーケンシャル(順序的)なアクセスだけが可能。
    • バイスファイルはストリームとして扱われる。
    • プリンタやモデムはキャラクタ型デバイスである。

また、このどちらにも当たらないネットワークインターフェースのデバイスドライバがあり、通信に利用する。デバイスファイルからの読み書きはできない。
デバイスドライバによってデバイスがシステムに認識されると、現在のLinuxではudevを用いて/devディレクトリにデバイスファイルが自動作成される。
プログラムがデバイスファイルにアクセスすると、デバイスドライバに対応するI/Oデバイスを用いて、デバイスを直接触ることができる。

バイスファイルを通じてストリームを繋ぐ

Linuxでは、入出力を表現するために、システムに用意されている「デバイスファイル」(スペシャルファイルとも呼ばれる)から、バイト列の読み書きを行うための「ストリーム」をその場その場でつなぐ(生成)ことで行う。
バイスファイルは特別なファイルで、Linuxではudevのような仕組みを用いて、デバイスファイルを/devディレクトリに動的に作成する。このデバイスファイルは、ファイルやディレクトリを表すブロック型デバイスファイルシステムであれば、特定のディレクトリに「マウント」した上で使用する。マウスやキーボードなどのキャラクタデバイスであっても、ストリームからバイト列を操作できる。
バイスファイルにプログラムが直接アクセスした場合、プログラムは対応するI/Oデバイスを用いて、デバイスを直接操作することになる。

CORBA

CORBAとは

GNOMEで使われていることで有名なCORBAだが、そもそもは分散システムでプラットフォームや言語の域を超えてオブジェクト同士がメッセージ通信を行う仕組み。
分散システムでリモートオブジェクトをローカルのように使うことができる。
このようなことをなぜ行う必要があるかといえば、たとえばみんなで地球外生命体の調査を行うために自分のコンピュータのリソースを提供するSETI@homeなどの分散コンピューティングなどがある。
分散コンピューティングの技術は、各種タイプのRPC, COM, CORBA, DCE, JavaRMIなどがある。

要するにPlan 9みたいなもの

GNOMEがCORBAで何をやりたいのかと言うと、ネットワーク上のさまざまな分散オブジェクト(関数やリソース)を一緒にして、「たくさんのコンピュータを一緒にしてひとつのインターフェースで操作する」ということをやりたいのだ。
要するに、Plan 9のような分散OSを、UNIXの基盤の上で実現したい、といった感じである。
あるいは、WindowsLinuxも全部まぜた上で、あらゆる言語を使ってネットワーク上に分散した全てのコンピュータ上でひとつの操作体系からあらゆる場所のリソースを操作したい。
まさにこれは壮大な目標である。
ただ、実際のところは、単なるコンポーネント技術にすぎない。WindowsのCOMと同様の技術であり、「UNIXWindows並みに新しくする試み」であると言える。UNIXのネットワークは化石のようなシステムである。socketを使って相互に通信するだけではなく、CORBAを使うことでネットワーク上の分散システムを高度に実現できる。

CORBAでできること

僕は、CORBAでできることは主に4つあると思う。
1.家庭内あるいは会社内での、ローカルな分散システムの構築。どのパソコンでも共有されたリソースにアクセスできる。
2.さまざまな場所にあるサーバーのサービスと、自分のローカルなアプリケーションを結びつけた利用。HTTPやX11のように、プロトコル的な、サービスを提供するアプリケーションサーバーとクライアントとの間でのやり取りを行う。
3.世界中のたくさんの人々を巻き込んだ、分散・クラスタネットワーク。癌・白血病を解析するUDや地球外生命体を発見するSETI@homeのようにたくさんのコンピュータ資源を用いた分散システム。
4.たくさんのプラットフォームや言語を混在させた上でのネットワーク・コンポーネント再利用システムの構築。WindowsUNIXLinuxを混在させ、Pythonのような新しい言語からCOBOLのような古い言語のシステムをネットワークのたくさんの分散コンピュータから操作するかのようなシステム。
CORBAはこうしたシステムをサーバー・クライアントのコンポーネントシステムとして実現することができる。

別々のマシンがひとつのシステムとして通信する

CORBAやCOMの利点として言えるのが、別々のマシンがひとつのシステムとして通信する、ということ。
これは、ネットワーク接続されたリモートコンピュータの実行形態として、HTTPサーバとHTTPクライアントの関係と違い、コンポーネント・オブジェクトとして通信が可能であると言える。
つまり、HTTPのように、通信プロトコルによって通信するのではなく、ライブラリ関数やクラスインターフェースのような形で、ネットワーク通信によるアプリケーションを利用することができる。

既存システムを再利用するために使う

実際のところ、CORBAは分散システムではあるものの、既存システムの再利用のために使われることが多い。
たとえば、COBOLで組んだ巨大システムを完全にリプレースせず、Javaなどから利用するためにCORBAのコンポーネント再利用技術を用いて、ネットワークインターフェース部分だけを拡張する。
JavaRMIやJavaBeansなども、CORBAと同様の再利用可能なコンポーネント技術である。

D-Bus

Bonoboは、最近はD-Busという新しい仕組みに変わった。D-BusKDE由来のDCOPからの影響で生まれた。LinuxX.OrgでもD-Busを使う。
D-Busはプロセス間通信の仕組みで、メッセージ、バス、オブジェクト、インターフェースを使ってシステム上のさまざまなプログラムと通信することができる。
D-Busでは、dbus-sendというコマンドで、インターフェースを通じたD-Busによる通信ができる。

X11

Linuxデスクトップがなぜ使われないか

Linuxデスクトップがなぜ使われないか。それは、「わざわざWindowsからOSをLinuxに変えるメリットや必要性がない」ということである。
現状のLinuxデスクトップは、ただ「面白そうだから」使ってみようという人であふれており、そうした人々は少しLinuxを試した上で、「Windowsと何も変わらない」と思って、「わざわざLinuxを使う必要性がない」ということに気付いて、定住せずにまだWindowsの元居た古巣に戻ってしまう。
そう、どうにかして、WindowsユーザーをLinuxに「移住」させるには、新しい家として「定住」するに足るメリットを示さなければならない。
多くのアプリケーション、特にAdobe PhotoshopIllustratorのような「使えるアプリケーション」は、Windowsにはあっても、Linuxにはない。あったとしても、知名度が無く、使えるような雰囲気がしないのである。ユーザーも少ない。多くの人がGNOME 3とKDE Plasma 5だけを試して、Windowsに戻る。
だが、僕が思うに、Linuxデスクトップの使いやすさや品質は、年を経るごとに向上していると思う。GNOME 2はWindows XPの劣悪な模倣品だったが、GNOME 3はスマホの画面操作などを取り入れて「スマートなシェル」を提示した。また、KDE 4/Plasma 5も、Windowsっぽかったインターフェースを改め、Windowsよりも美しい統一感のあるデザイナブルなインターフェースになった。
そして、最近では、Cinnamon, MATE, Budgie, Pantheon, Deepinのような新しいデスクトップ環境がどんどん生まれており、UbuntuFedoraの公式フレーバー(最初からデスクトップ環境をカスタマイズして変えてある環境)にも採用されている。そのうち、これらのひとつが流行して、Linuxデスクトップが「きちんと使われて流行る日」は来るのではないかと僕は期待している。
また、LibreOfficeを無料版のMS-Officeとして、「こちらの無料版のOfficeを使いましょう」と言っている人間は、何も分かっていない。パソコンを使う仕事で、MS-Officeの入っていないパソコンが事務用途で使えるわけがなく、どこでもMS-Officeはプリインストールで導入されている。要するに、「WindowsにMS-Officeが入っているのは当たり前」なのである。そのMS-Officeの入ったパソコンをLinuxLibreOfficeに変えるということは、MS-Officeを失うことに等しい。Linuxデスクトップユーザーになることは、LibreOfficeを手に入れたメリットよりも、MS-Officeを失った不利益の方が大きい。だから、単純にLinuxデスクトップは使われないのである。どうにかして、MS-Officeを失った不利益よりも、LibreOfficeを手に入れたメリットの方を向上させれば、いつか使われるものになるだろう。
要するに、今のLinuxは、「無料のものをあげましょう」と言っておいて、有料のすでにあるものを奪っていく行為に等しいのである。ここをどうにかして、有料のWindowsよりも優れたものを与えるようなOSにすれば、Linuxデスクトップは使われる日が来るだろう。

ツールキットとビューの面白さ

XやWindowsに言えることとして、「ツールキットやビューの面白さ」というのがある。
たとえば、昔はファイル一覧を見るのも、コンソールでlsを実行するなど、テキストベースのビューで閲覧するのが普通だった。
grepsedを使ってフィルター処理を行い、bashなどにパイプで渡すなど、「コマンドとテキストで行うから便利な側面」というのも確かにある。
だが、GTK/QtアプリケーションやWindowsアプリケーションは、リストビューやツリービューやアイコンなどの「専門のコントロール」すなわち「ツールキット」を用いてアプリケーションを構築する。ウィンドウにはタイトルバーがつき、大きさや重ね合わせを変えられる。
これは、プログラミングを行う上でも面倒くさい仕組みで、GTKやQtのGUIフレームワークの仕様を覚えなければならず、多くの場合コマンド・テキストベースよりも複雑で理解し辛いプログラムになる。
だが、Windowsの画期的な点とは、こうしたツールキットやビューの面白さにある。インタラクティブにマウスに反応し、さまざまな「細かい作業」のできるGUIツールキットを使ったアプリケーションは、使うのがとても面白いのである。
こうした「ツールキットとビューの面白さ」は、LinuxUNIXにはもともと無かったものだが、X11GTKやQtを使うことで、これを存分に楽しむことができる。特に、GTKやQtはソースコードが公開されているため、「自分でツールキットを作る」というまた別の面白さが存在する。

バイスとの通信とイベント駆動

X11はディスプレイ、キーボード、マウスなどのデバイスを管理し、それぞれの通信を処理して、2Dグラフィックスの「ウィンドウ」をディスプレイに表示し、マウスやキーボードなどでデバイスからの操作や要求があった場合は、「イベント」としてそれらを処理する。
X11の担当範囲はカーネルの担当範囲と重なることがある。特に、グラフィックチップ・グラフィックボードなどの設定は、X11で設定する必要がある。最近は、モジュールによって自動的に読み込まれることが多い。

ネットワーク透過とXサーバー・Xクライアント

X11ではネットワーク透過と呼ばれる、ネットワーク処理をXサーバーとXクライアントの間で行う。これをネットワーク透過と言う。Xサーバーは自分の使うマシンで動作するが、Xクライアントは自分のマシンではなくても、ネットワーク上にあるどのマシンのXクライアントとも、ネットワークと繋いで自分のXサーバーから表示・操作することが出来る。
マウス移動や文字入力などのイベントはXサーバーで処理されて、ディスプレイにマウスカーソルや(システムのフォントを用いた)文字を表示する。また、クリックなどのイベントは個別のXクライアントのウィンドウにイベント駆動で送られる。
Xプロトコルにより、Xはネットワーク透過な通信をXサーバーとXクライアントの間で行う。Xサーバーで発生したイベントは、マウスやキーボードなどのデバイスと、クライアントであるXアプリケーションの間でやり取りされ、その間で通信を行う。
X11のネットワーク透過は、グラフィックス操作におけるネットワーク分散処理を可能にする。これは古い技術だと思われることが多いが、コマンドラインSSHを実行するのと同様に、GUIでの操作や処理において早い段階からネットワーク通信をベースにした設計がなされているという点では、Windowsなどの競合システムよりも優れた点かもしれない。

XlibとGUIツールキット

Xlibは、クライアント向けのライブラリで、Xプロトコルの詳細を知らなくても、XクライアントがXサーバーと通信ができるようになっている。
Xlibでは、イベント駆動としてメッセージループと呼ばれる仕組みを使う。これはWindows APIなどと同等のシステムで、何かのイベントがそのプログラムに常に送られ続ける、というループを条件分岐で処理することで、メッセージを監視・処理することで、1つのループとしてクライアントプログラムを書くことができる。
また、XlibでXアプリケーションを書くことはできるが、Xlibにはボタンやメニューなどの「ウィジェットツールキット」が用意されていない。このため、通常はGTK+やQtのような、Xlibを用いて作られたGUIツールキットと呼ばれるボタンやメニューなどのウィジェットが用意された多重階層のライブラリを使ってウィンドウを表示するGUIプログラムを開発する。

ウィンドウマネージャとデスクトップ環境

X11におけるGUIの操作性は、ウィンドウマネージャと呼ばれるサードパーティのプログラムに任されている。プログラマは独自のウィンドウマネージャを作ることができる。これによって、X11ではどんな操作性を実現したウィンドウマネージャでも自由に開発できる。
また、ウィンドウマネージャはウィンドウの操作を担当するが、Windowsのような近代的なシステムでは、ファイルマネージャや端末エミュレータなどを、統一された操作性で実現する必要がある。また、設定やファイルシステムを仮想化する手段も必要であり、CORBAのようなコンポーネントの利用とその準備も実現する必要がある場合がある。これを統合デスクトップ環境、あるいはデスクトップ環境と呼ぶ。統合デスクトップ環境には、商用UNIXなどで用いられるCDEや、オープンソースKDEGNOMEなどが存在する。言ってみれば、WindowsMacのようなパソコンOSも、その主体となるシステムはデスクトップ環境(Windowsではファイルマネージャを兼ねたExplorerレジストリ・COMなどのGUIシステム)である。

X11の仕組み

X11は、ユーザーのコンピュータの入出力デバイス(マウス、キーボード、ディスプレイなど)を監視するXサーバーと、GUIアプリケーションであるXクライアントが、ネットワーク透過なXプロトコルを使って、要求などの応答を通して成り立っている。(HTTPDとは違い、ユーザーのコンピュータがサーバーで、リモートのプログラムがクライアントである、と言うところに注意が必要。ユーザーはサーバーであるXサーバーの画面を操作しながら、リモートのXクライアントをネットワークで操作する。)
Xlibは、XクライアントがXプロトコルの詳細を知らなくてもXサーバーと通信出来るようにしたライブラリ。Xlibによるプログラミング処理を見ると、Windowsプログラミングのようなメッセージループによるプログラムになる。
だが、普通、Xlibを直接に操作することは無い。ボタンやメニューのようなグラフィックス・ツールキットが用意されていないからである。あらかじめ作られたボタンやメニューを使うためには、GTKやQtなどのツールキットなどを使う。
X11は、最近ではWaylandと言うものにとってかわられようとしている。

ネットワーク透過とはメッセージのやり取り

X11では、ハードウェアを操作しグラフィックを表示するXサーバーと、ウィンドウフォームを描画しGUIプログラムを実行するXクライアントが、「ネットワーク透過」というネットワークプロトコルで繋がっている。
なぜこんな設計にしたのか。それは、僕はウィンドウシステムとウィンドウの間でメッセージをやり取りする上で、それをネットワーク通信にするのが自然だから、だと思う。
ウィンドウシステムの役割とは、大きく3つある。それはハードウェアの操作、グラフィックスの表示、そしてメッセージのやり取りである。
サーバーとしてハードウェアの操作とウィンドウ描画を行うXサーバーと、ウィンドウの内部のグラフィックスの表示を行うXクライアントが、メッセージをやり取りする。このメッセージをネットワーク透過で行うことで、サーバーはSSHのようにネットワークに繋がった他のクライアントとも、「遠隔通信のようにメッセージをやり取りできる」のである。
ただ、これは僕の勝手な意見だから、設計者がこのように考えて設計した、というものではない。僕が勝手に、「X11のネットワーク透過はこんな意味があるのではないか」と考えた、推測にすぎない。

中央処理コンピュータ・X端末のモデルと分散システムとしてのX

実際のところ、X11のネットワーク透過は、端末と中央処理コンピュータが分かれていたごろの名残りであると同時に、一種のネットワークを通じた分散システムであると考えられる。
UNIXの端末のように、Xアプリケーションのプロセスを大きな処理能力のある中央のワークステーションで行いながら、そのプログラムをたくさんのX端末からネットワークを通じて操作することができる。
また、一種の分散システムとして見れば、さまざまなコンピュータのホストにあるXクライアントを、Xサーバーがそれぞれのコンピュータに役割を持たせながら遠隔操作することができる。
これをより発展させたのがWindowsのCOMやGNOMEのCORBAで、さまざまなホストにあるネットワーク上のコンポーネントが連携して、「ネットワーク通信上のさまざまなオブジェクトが相互にメッセージをやり取りしてひとつのシステムとして実行する」ことができる。
CORBAではWindowsのオブジェクトとLinuxのオブジェクトがネットワークで別々の言語で相互に通信することもできる。
後日注記:X11の優れた点は、ひとつのモニターから遠隔地にある複数のコンピュータを操作できるということ。モニターやキーボードがついていないコンピュータでも、X端末から遠隔操作できる。モニターがついているコンピュータはひとつだけで良い。そのひとつのX端末から、ネットワークで繋がった全てのコンピュータを遠隔操作できる。もちろんX11のアプリケーションが入っている必要はあるが、さまざまな場所に分散したコンピュータをひとつのX端末から遠隔操作することで、コンピュータがどこにあったとしてもひとつの端末から遠隔操作し、遠隔地にあるコンピュータシステムを管理することができる。

コマンドとXアプリケーションの違い

コマンドプログラムとXアプリケーションの違いは、コマンドはターミナルに文字を出力し、シェルからコマンドで実行するが、XアプリケーションはXサーバーにウィンドウを表示し、Xサーバーから操作して実行する、ということが異なる。
コマンドプログラムは、文字ベースの入出力で操作が完結しているが、Xアプリケーションは「Xサーバー」を介して実行・操作する。Xサーバーが無ければ動かないし、操作もできない。

ウィンドウマネージャの役割

Xにおいては、「ウィンドウマネージャ」と呼ばれる特別なプログラムが、ウィンドウの操作と実行を管理する。
このウィンドウマネージャの役割は大きく2つ。それは「ウィンドウの管理」と「アプリケーションの実行」である。
X11におけるウィンドウをどのように管理するかという「ウィンドウマネージメント」の機能と、アプリケーションを実行する「ランチャー」の機能を、ウィンドウマネージャは持っている。
X11においてはウィンドウマネージャからXアプリケーションを実行し、ウィンドウマネージャの機能を使って実行されたウィンドウを破棄・表示を切り替えする。
つまり、コマンドラインにおける「ターミナルとシェル」が、X11における「Xとウィンドウマネージャ」となる。
これに加えて、デスクトップ環境では、ファイルマネージャや端末エミュレータなど、さまざまな「GUIアプリケーション」を提供し、一貫した操作法を実現する。

MotifとLinuxGUIツールキット

UNIXにおけるGUI環境では、XサーバーをコアにXlibによるプログラミングを行うが、ここではボタンやスクロールバーのような「ツールキットライブラリ」は提供されていない。
UNIXでは、長らくMotifというGUIツールキットが標準的で、商用のUNIXワークステーションには、プロプライエタリのXとGUIツールキットのMotif、そしてCDEなどのMotifで書かれた統合デスクトップ環境を乗せるのが一般的だった。初期のGIMPもMotifで書かれていた。
だが、最初期のLinuxから見ると、Motifには問題があった。Motifはオープンソースでなく、有償で提供されていたため、Motifで作られたXアプリケーションは、それ自体がフリーでもMotifに依存し、そのため「Motifを購入しなければ使えない」という酷いものだった。
最初期のLinuxX11には標準的なツールキットが無く、Motifに代わるツールキットが必要だった。
標準的なツールキットのないX11に、Trolltechという会社がQtと呼ばれる優れたツールキットを提供した。QtはKDEという「CDEのCをKに変えたデスクトップ」で採用されたが、ここでも問題が起きた。Qtも(当時は)フリーソフトウェアではなかったのである。
これに問題を感じたGNUでは、GNUの協力者でプログラマであるミゲル・デ・イカザにより、QtではなくGIMPGTK+を採用した独自の統合デスクトップが開発された。これがGNOMEである。
Harmonyという「Qtのオープンソース代替」も作っていたGNUだが、GNOMEの方が成功した。GNOMEでは、CORBAを使うことで、WindowsのCOMのようなコンポーネント分散通信システムを作った。これが、商用Linuxディストリビュータなどに「GNOMEを採用させるきっかけ」を与えた。ミゲルは「UNIXをもっとマシなものにしよう」と提唱した。
GTK+はシンプルなC言語のツールキットで、QtがC++を採用しているのとは対照的に、単純なC言語によるツールキットを提供し、C言語オブジェクト指向を行えるGLib・Gobjectという仕組みを採用している。その上で言語バインディングを提供することにより、さまざまな言語で開発が行える。Windowsでも.NETでC#/VBで開発ができるように、GTK+ではC/C++/Python/Ruby/JavaScriptなど、「多くの言語でGUIプログラミングができる」というところが売りである。そのため、RubyistなどにはGNOMEはとても良い環境である。

それぞれのデスクトップが独自に実装するのでは面倒くさい

X11の上でGTK+/GNOMEやQt/KDEを動かすのは、「複雑だ」という人が居る一方で、実際のところ、GUI機能をWindowsのようにカーネルに統合してしまうとサーバーで使う時に困るということと、GNOMEKDEが独自にディスプレイサーバまで実装するのでは面倒くさい、といった感じで、X11だけがディスプレイサーバを実現する、という感じの設計になりました。

色んなところが古臭い

そもそもがUNIXワークステーションOpenVMSで動作することが前提で、本当に古臭い昔の技術です。LinuxのおけるX11はそもそもXFree86プロジェクトをベースとしており、UNIXならX11だよねといったとても昔の技術であるため、色んなところで旧来のコンピュータのさまざまな要件にぶち当たります。

商用UNIXにも搭載できるライセンス

X11商用UNIXにも搭載できる、BSDライセンスと同様のMIT/Xライセンスを採用しており、各種の商用UNIXワークステーションでも動作する。
ただし、GNUはこの点を批判しており、「そもそもは自由だったはずのX11の実装が、商用UNIXではプロプライエタリな独自のバイナリになっており、UNIXユーザーはウィンドウシステムを書き換えたりコピーしたりソースコードを自由に見ることができない」として、「GPLではフリーソフトウェアがフリーでなくなることがない」とGNUは言っている。
だが実際のところX11ソースコードはもともとのオープンなX11ソースコードはMITライセンスで公開・配布されているのであり、開発自体もオープンなコミュニティによって行われているため、「ストールマンの言っていることはおかしい」とされることが多い。たとえばFreeBSDがフリーでなくなることは考えづらく、「わざわざGPLなんかで配布する意味が無い」とされることの方が一般的である。

xorg.confの設定項目

以下はXサーバ設定ファイルxorg.confを設定する - itLifeTipsを参考に執筆しました。

  • Section "section-name"~EndSectionは各セクションを表し、各セクションはエントリ行から成り立つ。エントリはオプション名と1つ以上のオプションから成り立つ。
  • ServerFlags
    • グローバルな設定をし、ServerLayoutの設定で上書きされる。
  • ServerLayout
    • Xサーバで制御される入力・出力用のデバイスを定義する。
    • 1つの出力デバイス(スクリーン)と2つの入力デバイス(キーボードとマウス)を指定する。
    • Screenはモニタを、2つ以上のInputDeviceはマウスとキーボードを表す。
  • Files
    • サーバ用パス。
    • FontPath
      • Xサーバがxfsフォントサーバからフォントを取り出すパスを指定する。
  • Module
    • ロードされるモジュールを指定する。
  • InputDevice
    • 各InputDeviceセクションで入力デバイスの設定をする。
    • Identifier
      • 識別名
    • Driver
      • ドライバ
    • Option
      • オプション。以下のオプションがある。
    • Protocol
    • Device
    • Emulate3Buttons
      • 3ボタンマウスのエミュレート(onにすると2つのボタンを同時に押した時に3ボタンをエミュレートできる)
  • Monitor
    • モニタの設定をする。
    • Identifier
      • 識別名
    • VendorName
      • ベンダ
    • ModelName
      • モデル
    • DisplaySize
      • モニタの表示面積
    • HorizSync
      • 水平同期周波数の幅(kHz単位)
    • VertRefresh
      • 垂直リフレッシュ周波数の幅(kHz単位)
  • Device
  • Screen
    • Deviceセクションが設定するビデオカード上のモニタコネクタを指定する。
    • 各Screenセクションでは、1つのビデオカードを、DeviceセクションとMonitorセクションを参照することにより1つのモニタに結合します。
    • Identifier
      • 識別名
    • Device
      • Deviceセクションの識別名
    • Monitor
      • Monitorセクションの識別名
    • DefaultDepth
      • デフォルトの色の深さを指定する
    • SubSection "Display"
      • 特定の色の深さで利用できるスクリーンモードを指定する。
      • 複数のDisplayセクションを持つことができる。
  • DRI
    • DRI(Direct Rendering Infrastructure)用のパラメータを指定する。

ツールキット

ツールキットとは

ツールキットは「道具箱」という意味で、X11GUIプログラミングを行う際に、Xlibの上で動いてくれるさまざまなGUIの部品(パーツ)のこと。
通常、UNIXではX11の上でMotifのようなGUIツールキットを用いてGUIのアプリケーションを開発する。Moitfはフリーではなかったため、GTK+やQtのようなフリー版のツールキットが開発されている。

ツールキットの一覧

主にIntrinsics (Xt)、Athena widget set (Xaw)、Motif、GTK+、Qt、Tkなどがある。
また、Windows APIのクローンとしてはWine、NeXTSTEPのクローンとしてはGNUstepなどがある。将来的な.NET CoreではWindows.Formsもオープンソースで提供される予定であり、期待が高まっている。

X Toolkit Intrinsics (Xt)

ウィジェットを作成するのに必要な機能を提供するXlibの上位ライブラリ。
特定のウィジェットの実装は、より上位のライブラリ(XawやMotif)で行われる。

Athena widget set (Xaw)

Project Athenaで開発されたX11GUIツールキット。

Motif

商用UNIXで使われる、昔支配的だったツールキット。
初期のGIMPなどは、GTK+で書かれる前はMotifを使用したコードで書かれていた。
スタイルに味があって一部では人気である。

GTK

GIMPによって開発された、本当にフリーなGUIツールキット。
GNOMEで使われており、GLibによってC言語を用いながらオブジェクト指向を行い、さまざまな言語で利用できるラッパーライブラリ(バインディング)を提供する。
このため、C/C++だけではなく、C#JavaPerlPythonRubyJavaScript、Valaなどからも使うことができる。
ただし、それぞれのバインディングに開発状況の差があり、必ずしも安定して使えるとは限らないため、標準的に使われるのはC/C++によるGTK+/GTKmmである。

Qt

Trolltechという会社によって提供されたGUIツールキット。
標準的ツールキットのないLinuxのためのツールキットだったが、残念ながらフリーとは言えなかった。
KDEで使用されたが、Qtがフリーではないため、GNOMEプロジェクトが発足した。
現在では、Qtはオープンソースのライセンスを採用し、名実ともにフリーソフトウェアとなった。
Linuxの他にWindowsでも動くクロスプラットフォームなツールキットとして知られる。
開発に使用できる言語はC/C++のほか、Pythonなど。
テーマやスタイルが表現豊かで美しく、その名の通り「キュートなツールキット」として知られる。なぜか、GTK+はQtと比べてはるかに醜い。

Tk

主にTcl/Tkとして使われることの多いツールキット。
昔のMozillaなどはブラウザ画面の表示にTkスタイルのボタンやテキストボックスのスタイルを採用していた。(当時のMozillaは標準では日本語の太字すら出ない、開発途上のブラウザだった。)

テーマエンジン

GTKやQtなどのGUIツールキットでは、テーマエンジンを搭載しており、テーマを変えることでアプリケーションの見た目を変えることができる。

デスクトップ環境

メタファーと環境の実現

X11のデスクトップ環境について言えることは、「メタファーの実現」である。
メタファーとは隠喩のことで、コンピュータを現実のものに喩えた「デスクトップ」あるいは「ワークスペース環境」を提供する。
GNOMEKDEは、既存のWindowsmacOSのようなデスクトップOSの操作環境と基本的には同一の、デスクトップ環境を構成するGUIアプリケーションをひとまとめに開発しており、一定の共通性のあるルック・フィールでデスクトップを操作できる。
メタファーの実現は重要で、コマンドラインでは「シェルとコマンドとファイル」によって実現されていた「コマンドライン環境」が、GNOMEKDEではファイルマネージャやランチャーやウィンドウマネージャによって全く違う「GUI環境」に変貌する。
LinuxGUIの分野ではコマンドラインほどの目立った成果は得られていないが、そのためにかかる開発のコストや手間はコマンドラインより大きく、さまざまなGUIアプリケーションをウィンドウマネージャや基礎のアーキテクチャ(ライブラリやフレームワーク)の基に実現している。またGNOMEや最近のKDEなど一部の環境はCORBAやD-Busのような分散ネットワークシステムを基盤にしており、Plan 9のように分散ネットワーク上でGUIアプリケーションを実行できる。

GNOME

Linuxで実行出来る巨大なデスクトップ環境の1つ。シンプルで使いやすい、一般ユーザーに分かりやすい操作性と、CORBAを使用したネットワークオブジェクト指向アーキテクチャを提供する。ただし、巨大なコンポーネント指向のデスクトップであるため、昔から動作が遅く「もっさり」しており、またデザインがのっぺりとしていてダサい。動作が遅いだけではなく、何をするにも到達するまでのステップが一息遅い。だが、一般ユーザー、時にパソコン初心者のことを良く考えており、余計なものがなく簡単に使える、シンプルなデスクトップを目指している。
最近ではSunがやっていたように、UNIXワークステーションの環境でもGNOMEが使われることが多くなってきている。GNOMEKDEよりも標準的に採用されることが多い理由は、こうしたUNIXワークステーションベンダーが会社としてGNOMEを支持する傾向が強いからである。なぜか、明らかにKDEの方が優れているのに、馬鹿なGNOMEを標準的に採用する。
だが、GNOMEが決して馬鹿なわけではなく、最近はGNOME 3はWindows 8よりも先んじて投入された、「全画面インターフェース」の先駆けであり、GNOME 3はオリジナル要素が強い。逆にKDEは個性を失い、美しくなったように見えてWindowsと全く同じものになった印象がある。

KDE

Linuxで実行出来るもうひとつの巨大なデスクトップ環境。機能性とQt/C++による整理されたフレームワーク、美しくて使いやすくカッコいいデスクトップ環境が特徴。美しい代わりメモリを食うことで知られており、またGNOMEに比べて不安定なところがある(GNOMEは遅くても起動するが、KDEは起動すらしない場合が多い)。「本当のLinuxのデスクトップ」を目指しているが、Qtを採用しているため、FirefoxのようなGTK+アプリケーションと調和せず、「美しいようでそんなに美しくない」デスクトップ環境である。

CDE

UNIXワークステーションで使われることの多い統合デスクトップ環境。Motifをツールキットとして採用する。KDEはそもそもはこのCDEを模倣して作られた。

Xfce

Xfceは意外と人気がある。僕は、みんなが使う時のことを考えると、UbuntuXfceかMATEを使ってもらうのが一番良いと思う。
昔使っていたところで考えると、本当に軽くて使いやすいのだが、何かがチープで、シンプル過ぎて一人前のデスクトップ環境として使えないような、そんな印象を受ける。
UNIXのメタファーを尊重し、それぞれを単機能で小さなプログラムにする、という発想は、とても良い発想だと思う。

LXDE/LXQt

軽量さを目指しているデスクトップ環境。ただ、僕は機能性を考えるとMATEの方が良いと思う。

Android

Androidはケータイ向けで、僕はスマホで使っていますが、本当はテレビと通信させるなどでも動きます。テレビと通信させる場合は、マウスポインタを使うことも出来ます。

Unity

UbuntuではGNOME 3のGNOME-Shellを拒否し、独自に開発したインターフェースであるUnityを採用していたが、最近はGNOME 3に戻ったようである。

マイナーなカスタムDE

UbuntuのUnityがやったことで知られていますが、GNOMEKDEでもMac風のメニューバーを画面トップに持ってくるインターフェースにしている例が、マイナーディストリビューションで見られるようになりました。
どのディストリビューションだったかは失念しましたが、探してみてください。マイナーなディストリビューションでも、最近は技術力が高く、インターフェースを大胆に変えているものや、Mintのようにさまざまな使いやすいオマケソフトをつけているものが増えています。

Cinnamon, MATE, Budgie, Pantheon, Deepin

最近は新しいデスクトップ環境がどんどん開発されています。CinnamonやMATEのようなGNOME 3の代替・forkだけではなく、Budgie, Pantheon, Deepinなどをディストリビューションがサポートする動きも大きくなっています。
UbuntuではUbuntu BudgieとしてBudgieを公式のフレーバーとして対応し、Fedora 30ではPantheonとDeepinに対応しました。
これからLinuxデスクトップはとても面白くなっていくと思います。もちろん、フレーバーやSpinとして対応していないデスクトップ環境やウィンドウマネージャでも、UbuntuFedoraのパッケージから導入することができます。

X11いろいろ

3ボタンマウスでコピー・ペースト

伝統的なUNIXX11では、Macの1ボタンやWindows/PCの2ボタンではなく、3ボタンマウスを使っていた。
この3ボタンマウスは、現在のホイール用の中ボタンがあるマウスでは、エミュレートして使うことができる。
X11では、伝統的に、選択して右クリックメニューからコピーを選択しなくても、文字列を選択しただけでコピーできる。そして、中ボタンのクリックでペーストができる。
ただし、今ではGNOMEKDEでも右クリックメニューからコピー・ペーストを行うのが一般的である。

X11でも使うのはターミナル

X11でも、UNIXの基本はターミナルです。X11では、端末エミュレータというソフトウェアを使って、X11からコマンドシェルを用いてコマンドを実行することができます。
ただし、アイコンで操作したい、という人は多いでしょう。GNOME/KDEには、ターミナル以外に「ファイルマネージャ」というソフトウェアが用意されています。これは起動時のGNOMEKDEで既に起動しており、ユーザーはデスクトップのアイコンをクリックしたり、ファイルマネージャを新しく起動して深いディレクトリ階層を辿ったりすることができます。
いわば、「WindowsUNIXもどちらの形式の操作もできる両刀使い」です。GNOMEUNIXコマンドラインを上手く使い分けることで、デスクトップLinuxの真価が発揮するでしょう。

GUIWebブラウザがあればLinuxでも何とかなる

また、インターネットも同じで、wgetのようなコマンドとMozillaのようなGUIWebブラウザを使い分けます。現代のパソコンでは、クラウド化が進み、何でもローカルのアプリケーションよりもブラウザから見る場合が増えました。これはLinuxにとって朗報です。というのは、Linuxには優れたアプリケーションが多くなくても、ブラウザのMozilla FirefoxGoogle ChromeなどはWindowsと全く同じように操作することができるからです。僕はLinuxを使ってYouTubeを見ることの多いYouTube利用者です。最近はAndroidからもYouTubeの音楽を良く聴きますが、ネットワークやクラウドが行き着く先は、きっとWindowsよりもLinuxのはずです。

Xサーバーをなぜサーバーと言うか

Xサーバーでは、ローカルのマシンをXサーバーと言い、ネットワーク上のマシンをXクライアントと言います。これは、マイクロカーネル的なOSの考え方に基づいています。マイクロカーネルOSでは、プロセスやメモリ管理やプロセス間通信などを除いて、ファイルシステムやネットワーク、デバイスドライバは、ファイルシステムサーバーのようなデーモンで行います。Xサーバーもこれと同じで、グラフィック専門のマイクロカーネルサーバーのようなものだと考えることができます。

GTK

GTKとは

X11GNOMEで使われるGUIツールキット。ライバルはQt。
C言語オブジェクト指向を行う独自のGLibという仕組みを使いながら、C++だけではなくC#Pythonなどにも対応することで、「ハッカー界の多くの言語」に門を開きながら、ウィジェットとイベント・シグナルをベースとした「オブジェクト指向のツールキット」を提供している。
GNOMEでの標準ツールキット。KDEで使われているQtが当時フリーでは無かったため、GNUによってGNOMEとともに開発された。開発元はPhotoshopキラーとして有名なGIMP

GTKはクラス設計が未熟

GTK/GLibの問題として、クラスやAPIの設計が未熟である、というのが挙げられる。C言語で完結できて、さまざまな言語で開発できるとは言うが、クラスライブラリやAPIの設計が、DelphiBeOSほど美しくない。
MSが.NET、OracleJavaMacCocoaなどで「美しいクラス設計」をしているのとは対照的に、たとえばgpointerのように型名に「g」をつける必要があるなど、「醜くて、使い辛くて、分かりにくくて、美しくない」という特徴がある。
だが、そういう人は、一度GTK#/Monoを試してみよう。LinuxでもGTKとMonoを使うことで、C#/.NETで開発ができる。VMが邪魔だと言う人は、Valaを試してほしい。
GTKはさまざまな言語で開発ができる。特に、PythonRubyで開発できるのは、「Cの関数なんか使いたくないよ」という「高水準な言語オタク」にとってはとても優れた長所である。どんどんC#RubyGNOMEアプリを開発してほしい。GNOMEのネットワーク・オブジェクト・モデルのアーキテクチャは、そうした人々のためにある。

もっとウィジェットを、もっとコンポーネント

僕は、GTKやBonoboなどに言えることとして、もっとウィジェットを用意して、その上でカスタムコントロールコンポーネントをもっとたくさん用意すれば、面白いことに成るのではないかと思います。
たとえば、MS-Wordを簡単に作れるような「ワープロコンポーネント」を用意します。これによって、どんなプログラマでも簡単にコンポーネントを使うだけで、独自の自分のワープロソフトが作れるようになるでしょう。
今のところ、Gnumericのコンポーネントのようなものはあるようですが、僕はもっとGNOMEコンポーネントを用意し、「GUIアプリケーションがたくさん生まれるような土壌」を作り出しても良いと思います。

Glade

Glade

Gladeと呼ばれるGTK用のGUIデザイナーがあります。昔から有名で、ポトペタ(RAD)のGUI操作でXMLのUIデザインファイルを吐いてくれます。
Gladeが吐いたXMLファイルは、libgladeというライブラリを使うことでアプリケーションのインターフェース定義として使うことができる。

VBのようなフォームデザイナー

GladeではVBのように、GUIのデザイン操作でフォームとなるUIをデザインすることができます。
ポトペタでデザインしたUIは、XMLのUIファイルに吐き出すことができ、Gtk.Builderで読み込むことができます。
この時プログラミング言語PythonでもRubyでも対応しているものなら何でも使えます。

Qt

Qt

KDEで採用されている、X11ウィジェットツールキット。昔はこれがオープンソースでなくて、GNOMEと言うもう一つのプロジェクトを作る必要があった。今はオープンソースTrolltechと言う会社で開発されていた。

QtはWindowsでも動く

QtはそもそもクロスプラットフォームC++GUIツールキットとして開発されており、Windowsでも動く。ソースコードコンパイルし直すことで、QtアプリケーションをLinuxからWindowsに移植できる。
特に、Windows APIGUIをやっていると不安だとかうんざりした人におすすめ。旧ボーランドDelphiのように、Windows APIオープンソースオルタナティブとしても利用できる。

GNOME

GNOMEの概要

巨大なデスクトップ環境。GTK+と言うウィジェット・ツールキットをベースに作られている。昔は、シンプルで初心者向けだった。昔のGMONE2を使いたい場合は、MATEをインストールすると良い。
僕の個人的使用感としては、アプリケーションの機能にアクセスするための方法がGNOME 3になってから削られてしまったのが難点。デスクトップのシェル自体は拡張機能を入れることで何とかなるが、アプリケーションのメニューバーをざくっと削除しているため、僕はGNONE 3のアプリケーションは基本的に使わない。僕はいつもMATEをFedoraで使っている。
GNOMEWindowsとの類似性が強いが、そもそもGNOMEコンポーネント技術として採用されたCORBAがWindowsのCOMと同様の技術であるように、最初からWindowsを意識したデスクトップ環境となっている。
だが、インターフェースの特徴などはMac OS X(現macOS)に近く、最近はAndroidのようなタブレットでタッチパネルでタップによって操作されることを念頭に開発されている。
また、シンプルで初心者向けなのを謳っていて、昔から統一的なアイコンやメニューバーなどの機能を分かりやすく、単純にするように作られている。
KDEは統合的要素が強く、それぞれのアプリケーションやコンポーネントが美しく統合されていて、配布もアプリケーションやフレームワーク・ライブラリに応じて配布されているが、GNOMEはそれぞれの要素がバラバラで、それぞれが独立して開発されている印象を受ける。
GNOMEにも、全く良い点が無いわけではない。GNOME 3でインターフェースが独自になって、革新的になった。これからのパソコンのインターフェースを革新していくのは、GNOMEだ。嫌われているのは、GNOME 2がとてもシンプルで使いやすいLinuxの標準GUIだったからだ。
GNOMEの原産地はメキシコである。

GNOMEデスクトップの概要

GNOMEは3から新しくなり、GNOME Shellと呼ばれる独自のインターフェースを備えるようになった。
GNOME Shellは、左上の「アクティビティ」バーを中心に、簡単で分かりやすいインターフェースを備える。
今までの「Windowsと良く似ているUI」ではなく、独自のスマートなUIとして開発されたが、あまり評判は良くない。なぜか、賢いUIなのに使い勝手がとても悪い。だが、エクステンションを入れることで、使い勝手は改善できる。
アプリケーションは、メニューバーや機能をざっくりと削除するなど、大胆なインターフェース設計をしているが、これも評判が良くない。「低機能になった」と言われることが多い。
だが、FirefoxGoogle Chromeなどに見られるように、メニューバーの削除はある意味最近の流行りである。GNOMEの特徴である「シンプルで易しい(初心者向けの)UI」が目標とされている。また、高機能なアプリケーションではメニューバーが存在していることが多い。
UbuntuのUnityなどでは、Mac風の「上にアプリケーションメニューがある」UIをやっているが、Ubuntuは最近GNOME 3に戻った。
また、Mac風のDockを使いたい場合は、エクステンションをインストールしたりすることで実現できる。エクステンションで拡張できるのはある意味画期的で、「どんなUIにもなれるデスクトップ」にはなっている。Avant Window Navigatorなどを入れても良いだろう。
昔のGNOME2が良かった、昔のGNOME2を使いたい、という場合は、MATEと呼ばれるGNOME2のforkが存在する。また、Cinnamonという、GNOME3のままでWindows XPライクなUIを持つ新しいデスクトップ環境も登場している。

メニューバーとタスクバーがなくなった

GNOME 3の開発者は、メニューバーとタスクバーを無くし、アプリケーションの起動やウィンドウの切り替えをアクティビティバーに統合した。
慣れるまでは操作が難しいかもしれないが、慣れるとあまり使いづらくない。
また、拡張機能を入れることで、タスクバーを復活したり、macOS/Windows 10風のDashにすることもできる。メニューバーについては、主要アプリケーションの操作が分かりやすくなったほか、高度な専門的GUIアプリケーションについては引き続きメニューバーを利用できるため、そんなに違和感がない。
また。GNOME-Tweak-Toolを入れることで、最大化ボタンを復活させたり、拡張機能を管理したりすることができる。
一時期GNOME 3に反発してXfceに移っていたリーナス・トーバルズも、GNOME 3が改善されたとしてGNOME 3に戻っている。リーナスは「GNOME-Tweak-Toolを(最初から)含めるべき」と言っている。
GNOME 3の評判はいまひとつだが、中には熱心な愛好家もいて、「画面がすっきりして余計なものがなくなって分かりやすくなった」とか、「拡張機能を入れれば何とか使える」などといった意見もある。

かつては初心者向け・シンプルデスクトップの代名詞だった

今でこそ、独自のモダンでスマートな拡張指向のデスクトップ環境となったGNOME 3ですが、GNOME 2の頃は、シンプルかつ初心者向けの代名詞でした。
アイコンやボタンを大きくして、分かりやすい絵のアイコンを採用し、簡単に使い方の分かる、Windows風のアプリケーションメニューかつMac風のトップバーを採用。上にも下にもバーがあるデスクトップとして有名でした。
この「初心者向け」という哲学には批判もあり、リーナス・トーバルズからも「ユーザーを馬鹿だとみなすGNOMEの姿勢は根本的に誤りである」と言われました。
それでも、標準のデスクトップ環境が初心者向けでシンプルであることは大きな優位性でした。
KDEよりも起動も早く、今でもGNOME 2をforkしたMATEがありますが、MATEは今のデュアルコアの64bitプロセッサで使うと、とても軽いです。
今のGNOME 3も、こうした初心者向け路線の継続である点があります。たとえば、標準のGNOME 3には、アクティビティバーだけがあり、ユーザーは「アクティビティをクリックする」ということが分かれば、あとはアプリケーションのアイコンが大きく表示され、ウィンドウ一覧も最大に表示されるため、分かりやすいのです。慣れるとこちらの方が使いやすいと言われることもあります。
また、GNOMEが標準に選ばれるのは、単に初心者向けなだけではありません。CORBAあるいはD-Busを用いた「分散ネットワークオブジェクトモデル」や、CのGTK APIC++PythonJavaScriptなどへの「言語バインディング」によって、開発の多様性があります。こうした「プログラマにとって賢くて、なおかつ初心者向け」という路線で、KDEと対峙してきたのです。逆に、昔からデザインが醜く、KDEの方がデザインや機能性は高いという弱点もあります。

KDE

KDEの概要

Linuxのデスクトップ環境のもう一つの選択肢。綺麗で豪華な代わり、メモリを食う。Qtと言うC++の美しいウィジェット・ツールキットを利用している。コードはほとんどがC++で書かれている。GNOMEに次いでファンが多い。GNOMEの「G陣営」とは別に「K陣営」と呼ばれている。
KDE 4からガラッと美しくなったが、Trinityと言う昔のKDE 3をforkした集団も存在する。昔から、KDEは使うのにクセがあるが、Windowsに近い。
僕の個人的使用感としては、起動が遅いのと、Fedoraで日本語入力のツールボタンがきちんと動かないのが難点だし、僕はFirefox派なので、あまりKDEを使うことは無い。重くはない(使っていると機敏に反応する)のだが、メモリを食うし、起動が遅い。時々良くアプリケーションが不正終了するなど、不安定な印象も受ける。
KDEは当初からCDEというUNIXの統合デスクトップ環境を模倣して作られている。Konquerorがブラウザとファイルマネージャを兼ねるなどWindowsと良く似ているが、Linuxのそもそもの統合デスクトップ環境としての元祖であり、Linuxを本当に使いたい人間たちが好き勝手に開発している印象を受ける。Sunなどの支持もあって会社のために開発されているところも強いGNOMEとは対照的に、マニアックなアマチュアプログラマが開発している印象を受ける。
GNOMEアーキテクチャ指向であると言われるが、KDEC++とQtとKDEライブラリ・フレームワークを使用したシンプルで強力で、何よりも美しいデスクトップ・GUI環境プラットフォームを開発している。何より、GNOMEよりも使っていて気持ちが良い。GNUとの仲は悪いというが、最近はきちんとQtもオープンソースになっている。
KDEの原産地はドイツである。

KDEデスクトップの概要

KDEGNOMEと並ぶLinuxのデスクトップ環境で、とても綺麗で統合されていることが特徴。
デスクトップとアプリケーションの設計とデザインが上手くされているおかげで、「使っていて気持ちの良いデスクトップ」になっている。
だが、MATEなどと比べると、その巨大さと重さが分かる。特に起動は遅いし、環境によっては不安定だったり、起動すらしないこともある。
美しいのはデスクトップだけではなく、Dolphinなどのファイルマネージャもデザイン的に美しい。
アプリケーションは機能的で、機能がたくさんあるというよりは、一種の「機能美」になっている。どんな機能も簡単にアクセスできて、アプリケーションの機能性が高い。
逆に、必要な機能がなかったり、日本語の環境に対応していないことも多い。昔のKDEは、GNOMEと比べて国際化の水準が低く、日本語で使う場合はGNOMEを使うことが標準だった。
KDE4, KDE Plasma 5の評判は悪くないが、KDE 3をforkしたTrinityというプロジェクトもある。これは、KDE 3の環境があまりにも独自で、ファンが多かったことに起因する。KDE 4からは美しくはなったが、昔のKDE 3のような「Linux的な良さ」がなくなった。ある意味、無個性になったところがある。Trinityは昔のQtを使っているので、日本語の入力などに問題がある(新しい仕組みに対応していない)ため、日本人が使うのには注意が必要。

GNOMEなんかよりはるかに賢い

僕は、ぶっちゃけて言ってしまえば、KDEGNOMEなんかよりはるかに賢いと思います。
GNOMEは迷走と混迷を極めており、標準のデスクトップ環境であるGNOME-Shellには、拡張が可能であること以外、全く何の機能すらありません。
独自に作っていたGTK+/GNOMEアプリケーションは、メニューバーすら無くなって、無価値で低機能な使いづらいアプリケーションになっています。
GNOME-ShellがWindowsのパクリでなく独自のものになってきたのは良いことですが、逆にスマホの低レベルな機能を模倣して、使いづらい全画面でアプリケーションランチャーを表示し、ウィンドウ一覧を表示する機能はバーではなくアクティビティパネルをわざわざクリックしなければならず、とても使いづらいです。
これに比べて、KDEはとても素晴らしい環境です。使いやすく、機能的で、動作の機敏さもあり、また全てのアプリケーションが高度です。
僕は、もしGNOMEが次のバージョンで良いものにならなければ(次のバージョンが出るのかどうかも分かりませんが)、KDELinux界で勝利すると思います。KDEが標準のデスクトップ環境になった時、今のようなアンチXの後ろ向きで自己矛盾なオタクのOSではなく、優れた機能的で素晴らしいデスクトップに、Linuxは変貌するでしょう。
GNOMEが標準だった関係で、GTK+アプリケーションとQtアプリケーションではGTK+アプリケーションの方が多いですが、KDEプロジェクトはアプリケーションも独自に開発しているため、Mozilla Firefoxの代わりにKonquerorを使い、GIMPの代わりにKritaを使うことが可能です(KritaはPhotoshopよりもPainterやSAIに近い)。またCalligra SuiteではLibreOfficeではないものの、共通のOpenDocument Formatを読み書きすることができます。

KDEは巨大そのもの

KDEの欠点として「巨大そのもの」ということが挙げられます。
シンプルなOSというUNIXの哲学を引き継いだLinuxにとって、KDEはまさに「巨大そのもの」です。アプリケーション、フレームワーク、デスクトップまで、全てを一括して開発し、たくさんのサブプロジェクトを持っています。
オープンソースなプロジェクトとして、たくさんのアプリケーションがあり、機能がどんどん増えていくのは魅力的かもしれませんが、C++を使って巨大システムを作っているため、起動も遅く、バグも多く、メモリも食う、そして場合によってはどこかに不具合が必ずあって起動すらしないこともあるのです。
ただし、この巨大システムに慣れてしまえば、KDEはとても使いやすく、高度で、高機能で、同時に分かりやすいです。デザイン的に見ても魅力的で、たくさんのアプリケーションと機能があります。多くの人がGNOMEよりもKDEを愛しています。また、C++とQtを採用しているため、一度起動してしまえば機敏に動き、開発の際にも美しいインターフェース設計ができます。

Xfce

Xfceとは

見た目のかっこよさやカスタマイズ性は十分にあるままで、軽量かつ高速なUNIXのデスクトップ環境を作ろう、という試み。
GNOMEKDEの巨大指向にうんざりした人にお勧めで、一部では「絶対にこの方が(UNIXとして)正しい」というファンが居るデスクトップ環境。リーナス・トーバルズも一時期GNOMEからXfceに乗り換えていた。
ある意味、Linuxのデスクトップ環境は、肥大化・巨大化してWindowsよりも不安定になっている。本当に路線として正しいのは、「UNIXの哲学を体現する」Xfceなのかもしれない。一部では商用UNIXで用いられるCDEに似ているとか。
Thunarという簡素で賢いファイルマネージャも人気。Xfce-Goodiesという軽量アプリケーションのプロジェクトもあり、軽量なWebブラウザのMidoriなどが開発されている。
標準の機能は少ないが、プラグインを導入することで機能を拡張できるため、コアなユーザにも推奨できる。見た目のスタイルを変えられるテーマ機能もある。

MATE

GNOME 2のfork

MATEは、昔からのGNOME 2の操作性を追究して分岐された、GNOME 2のfork(派生版)。
GNOME 2のインターフェースや操作性を追究しながら、GTK+3への対応など、設計やアーキテクチャの面で古くなった部分だけを、GNOME 3の最新版に近づけようとして開発されている。

軽快で多機能でシンプル

昔のGNOME 2は重かったが、MATEはなぜか軽快で安定している。それは、ハードウェアのスペックがここ十数年で大きく進歩したからである。特に、64bit化したCPUや、大きくなったメモリが要因である。
昔のGNOME 2がたくさんの機能を持ちながらシンプルだったように、MATEはとてもシンプルかつ多機能である。それは、標準のファイルマネージャやテキストエディタ、端末やファイルアーカイバなどを使えば分かる。昔のGNOME 2の開発者が頑張っていた通り、シンプルな使いやすい伝統的なメニューとボタンのインターフェースをしている。そして、標準の機能がとても高機能で、メニューバーにはGNOME 3でなくなったたくさんの機能が残っている。

最近のGNOME 3の機能は無い

だが、最近のGNOME 3で見られる、ありえない機能は存在しない。GNOMEパネルはさまざまなCORBAコンポーネントは配置できるが、エクステンションでWindowsと全く同じにはできないし、たとえばオンラインアカウントを登録して、クラウドアプリケーションと通信するような機能は無い。たとえば、Google Driveとの連携機能は設定できない。(ただ、僕の経験から言って、GNOME 3とMATEを共存させた環境で、GNOME 3でオンラインアカウントを設定すると、なぜかMATEでもGoogle Driveと連携できたことはある。そうした何かの機能がある可能性はあるが、僕は良く知らない。)

forkのためにアプリケーションは名前を変更した

MATEのさまざまなアプリケーションは、GNOME 3の同じアプリケーションと区別するために名前変更された。これによって、GNOME 3をインストールしている環境に、そのままMATEをインストールできる。
だが、僕はMATEを使うならば、GNOME 3はインストールせず、MATEだけをインストールすることをおすすめする。これは、アプリケーションメニューがとても散らかって、使い辛いものになるからである。
もちろん、標準のアプリケーションだけではなく、GIMPInkscapeなども最新のものを使いたいが、そういうところがMATEの課題になるだろう。どこまでをGNOME 2のまま残し、どこまでをGNOME 3の仕様に追従するか、という問題がある。

もちろんGNOME 3を使ってもよし

MATEは使いやすいが、それでも、GNOME 2は過去のものである。それこそ、Linuxコマンドラインが優れているせいで、GNOMEが劣っていたからといって、そんなにそれだけで使えないわけではない。GNOME 3をエクステンションでWindows並みに使いやすくして、GNOME端末とMozilla FirefoxGNOME 3の環境を使っているエンジニアや一般ユーザーはたくさん居る。
だが、MATEはMATEの道を切り開くだけである。

Cinnamon

Cinnamon

また、最近はCinnamonというデスクトップ環境も作られている。これは、GNOME 3のアーキテクチャとしながら、GNOMEとは別の道を行くカッコいいデスクトップ環境である。
僕は、昔、Debianの環境でCinnamonを使っていた。Linux Mintよりも軽快に動作し、「今最高の環境はこれだ」と思った。
ただし、Cinnamonは、言ってしまえばWindows XPのパクリである。
「全てのプラットフォームのデスクトップの中で最もユーザーフレンドリーでオールアラウンドである」(Ars Technica)とか、「夢のデスクトップに変更できる」(ZDNet)など好意的な評価が多い。おそらく、Linuxのデスクトップ環境の中で、「Windowsのパクリでも良いのであれば」、最高のデスクトップ環境であると言える。それは、単純にGNOMEの環境をWindows風にしただけで、それだけで最高のデスクトップ環境が簡単に生まれた、ということを意味している。

MATEとCinnamonを使うなら、Linux Mintかも

MATE創立の開発メンバーには、Arch LinuxLinux Mintの開発者が関わっている。特に、MATEやCinnamonを使うのであれば、Linux Mintを使うと良いだろう。僕の試した環境では、Debianよりは重かったが、綺麗で豪華で、使いやすかった。日本語の整備のための情報もネットにあるので、検索して参照してほしい。

X-Apps

CinnamonにはX-Appsが導入されている。これはGNOME Core Applicationsをベースとしたアプリで、MATEやXfceでも動作するように変更されており、伝統的なインターフェースを備える。

仮想化

Docker

Dockerは、今までのホストOSとゲストOSに分かれたVM型の仮想化ではなく、ホストのLinuxカーネルを共有しながら、アプリケーションやミドルウェア・ライブラリを「隔離」することで、コンテナの上で別のマシンを動かす(あたかも別のマシンが動いているかのように実行する)ことができる。
この時、マシンの「イメージ」を作ることができ、環境設定や構成をコード化して別のマシンに簡単に適用したり、Dockerfileとして配布することや、配布されているイメージを簡単に自分のLinuxで動かすこともできる。イメージはWeb上のDocker Hubでも配布されている。
Dockerの利点は、「コンテナ式による軽量さ」「再構築・削除が簡単」「イメージをDockerfileによって作成し、配布したり、環境の簡単な再現が可能」などの利点がある。また、「WordPressを使える環境を作りたい」などといった時に、Docker Hubで専用のイメージを入手すれば、簡単に同じ環境を作ることができる。
Docker Hubを使うことで、Nginxを導入するのも、MySQLを導入するのも、WordPressを導入するのも全部「docker run」コマンドでOK。簡単にDocker Hubから導入できる。

Linuxにおけるコンテナ型仮想化

LXCやDockerなどのコンテナ型仮想化技術では、ホストのLinuxカーネルを共有するため、KVMなどのようなOSの上でOSを走らせることによるオーバーヘッドがゼロに近い。XenKVMに比べて、起動や終了も早く、プロセス実行の効率も良い。
注記:ここに書いた時のにわか知識で執筆したため、「Linuxの上でLinuxが動く」という説明をしていますが、本当は「Linuxカーネルの上でコンテナ型の仮想環境が動く」が正しいです。
DockerはLinuxカーネルを共有しながら、さまざまなLinux環境(仮想マシン)を同時に構築し、動的に作ったり削除したりすることができる。このため、開発環境の上でデプロイする本番環境を作り出して、本番環境でどのようにシステムが動くのかを試すような用途に使える。
システムをインスタンスに作ったり削除したりすることができることで、いついかなる時に必要になっても、迅速に新しいコンピュータ資源を確保できる。Dockerでは、Dockerfileを使うことで、新しいシステムイメージを簡単に作成できる。Kubernetesを使用することで、たくさんのネットワーク資源をあたかもひとつのコンピュータであるかのように仮想化できる。これらの技術により、いついかなる場合にどんなシステムの問題や必要性がでてきても、対応し、拡張し、あるいは改良することができる。

Dockerとコンテナ型仮想化の基本

コンテナ型の仮想環境は、ホストOSのLinuxカーネルを共有した上で、仮想化されたLinuxコンテナ環境(仮想マシン)を実行・実現する。
ファイルやディレクトリ、プロセス、ネットワーク、設定、システム構成などをコンテナでそれぞれの環境に仮想化して、その上でその仮想環境におけるアプリケーションを実行することが出来る。
DockerはLinuxの仮想コンテナ環境。Linuxの上で仮想コンテナを作ることによって、Linuxの上でたくさんのLinux仮想コンテナ環境を走らせることが出来る。
Xenなどの仮想OSとは異なり、Linuxの上でWindowsなどの他のOSを動かすことは出来ない。Linuxの上でLinux仮想環境を動かすことが出来る。
ただし、LinuxLinuxを本当に動かすわけではない。Linuxと言うカーネルは共有しながら、通常のプロセスと同じように、別の環境でコンテナプロセスを動かすことが出来る。
この時、VM型の仮想化に比べて、ネイティブなアプリケーションとほぼ同等の効率で、仮想Linuxコンテナ環境のアプリケーションを実行出来る。
後日注記:実際のところ、「Linuxの上でLinuxが動く」と言うよりも、「仮想マシンとして隔離されたコンテナプロセスが動く」と言った方が正しい。たとえば、仮想マシンとして隔離したMySQLコンテナを動かしたり、隔離したRailsコンテナを動かすことで、「それぞれのサーバーに専用の仮想マシン環境を割り当てる」ことができる。Docker Hubなどを利用すれば、ネットからイメージをダウンロードして、コンテナとしてすぐに起動できる。こうした「隔離」という意味合いが強いため、コンテナ型仮想化のオリジナル的存在であるFreeBSDのjailsは「刑務所」という意味である。

Dockerfile

Dockerでは、システムイメージの構成をDockerfileと言うファイルに記述することで、新しいシステムイメージを簡単に作ることが出来る。Dockerfileにソフトウェアのインストール手順と設定手順を記述することで、どこでも同じシステムを簡単に再構築出来る。

Dockerの利点

Dockerの利点とは、
・それぞれの開発環境で、本番環境と同じ環境を簡単に再現できる。どんな環境でも同じ。ホストがDebianでもUbuntuでも関係なく、コンテナ環境でゲストの環境を再現できる。
・Dockerfileに全てのインフラ+アプリの情報が書かれており、コンテナの状態が保存されるため、間違いが発生しにくい。また簡単・高速にデプロイできる。
・必要のなくなった時点で、簡単にインスタンスを削除できる。インスタンスなイメージの作成・削除ができる。
・設定を間違えたら、元の状態に戻すことができる。ロールバックが簡単。
など、多くが「環境の再現やデプロイの際の管理がしやすくなる」ということです。
特に、たくさんのインフラソフトウェアやインフラシステムが重なり合っている「複雑なシステム」を管理するための助けになってくれます。

Docker Hub

Docker HubはDockerイメージをインターネット上で共有できるサービス。
たとえばCentOSにnode.jsを入れたDockerイメージを共有することで、みんなと一緒に同じ環境を再現することができる。
用途としては、「このようにLinuxをインストールして、こんな必要なソフトを導入して、このアプリケーションを使ってください」といった場合に、そんなことを手動でする必要なく、システム全体をまるっと共有できる。

コンテナはDevOpsと相性が良い

コンテナ型仮想化のメリットは、軽量であることや環境構築の時間短縮もありますが、DevOpsとの相性が良いことが言えます。
DevOpsとは、開発チームと運用チームが協力し合って開発・運用を行っていく手法です。コンテナ型の仮想化を行うことで、環境をさまざまに構築して試験することができます。
デメリットは、ホストのOSと別のOSで仮想化することができないことなど。

VM型に対してコンテナ型は速度が速い

また、VM型の仮想化に比べて、コンテナ型は速度が速く軽量です。
たとえば、サーバの本番環境を開発環境で試したい時に、何度も仮想サーバを立ち上げる必要がある時、VMwareのようなVM型の仮想化を行うよりも、Dockerのようなコンテナ型の方が素早く試すことができます。
これは開発の効率化にとても大きく寄与します。

Kubernetes

Kubernetesは、サーバーが複数台ある時に、簡単にサーバーの規模を大きくしたり、アプリケーションをクラウド上で適切にデプロイすることが出来る技術。
通常、Dockerの実行環境は一台のホストに閉じている。Kubernetesを使うことで、複数のホストがあってホストの外側とやり取りする場合でも、複数のホストから構成される実行環境を「あたかもひとつの実行環境のように」扱うことができる。
また、コンテナを起動する際にもイメージと台数を指定するだけでく、クラスタのどこにコンテナが配置されるかなど、面倒なことは全てKubernetesが自動で面倒をみてくれる。
このため、いくらでも容易にスケールアウトできる。

OpenShift

Red Hatなどが推し進めている、オープンソースで開発されているクラウド環境構築用のフリーソフトウェア
基本的に、OpenShift & OpenStackとDockerを組み合わせて、Ansibleで自動化する、といった風に使う。

OpenStack

OpenStackはNova(コンピュート)、Neutron(ネットワーク、旧称Quantum)、Cinder(ブロックストレージ)、Keystone(認証)、Glance(マシンイメージ管理)、Swift(オブジェクトストレージ)、Horizon(Web管理)などのコンポーネントから構成される。AWSを自分で作れるソフトという感じの位置づけ。

Ansible

サーバを立ち上げる際にインストールや設定を自動化できる構成管理ソフト。
Ansibleを使うことで、SSHで接続したサーバーに、リモートホストミドルウェアのインストールや設定ファイルの更新ができる。
Ansibleはリモートホストの状態を記載した定義ファイルであるPlaybook(YAML形式)を記述する。この時、Rolesと呼ばれる機能を使うことで、Playbookをちょうどいい単位に分割・整理することができる。
Fedora Server 30では、AnsibleのRoles機能をベースにした「Linux System Roles」が実装されており、メール(Postfix)やネットワーク(Network)、セキュリティ(SELinux)といった重要なサブシステムに対してつねに一貫したインタフェースを提供している。コマンドラインの呼び出しよりも容易な構成管理が実現できる。

猫も杓子もDockerとKubernetes

最近のクラウド市場は、猫も杓子もDockerとKubernetesです。
まず、クラウドを作る場合、Amazon EC2に登録して、クレジットカードを登録して従量課金制の契約を結び、OSはサポートが必要ならRHEL、必要ないならUbuntuにして、root権限が得られるためWebサーバやデータベースをインストールします。ApacheやNginx、あるいはNode.js+Reactです。
仮想サーバの構築は、ホストのLinuxの上でDockerとKubernetesを用いて行うため、どんな仮想サーバ向けのOS(注意:Linuxに限る)でも導入できます。インフラのDockerとKubernetesが何から何まで全部やってくれるので、クラウドサーバの運営業者も楽です。DockerとKubernetesの上で動くRHELあるいはUbuntuを導入して、root権限で何でも好きなようにできるのです。
あるいはRed HatUbuntuなどが力を入れているのがOpenStack。これはAWSを自分で作れるという位置づけです。
なぜDockerとKubernetesが流行るのか。それは、単純で簡単で、なおかつ軽量でパフォーマンスが良いからです。手元の開発環境のLinuxマシンで開発し、Docker上の本番環境と同等の試験環境で動くかどうかを試して、開発が終わったら本番環境にデプロイ。これを簡単かつスピーディに行えて、必要なことは全部DockerとKubernetesがやってくれる、というわけです。
また、JavaScript環境がとても優れたものになってきつつある現在、JavaPHPのような従来の言語は必要なくなってきています。サーバ側はNode.js、クライアント側はReact。あるいは、Ruby on RailsDjangoのようなWebフレームワークを使います。
僕も経験が豊富にあるわけではありませんが、最近のLinuxによるWebサービス開発は、そのようにどんどん進歩していて、最新が本当は何なのか、正しい情報は何なのか全くわかりません。僕が書いたこの情報も、ほとんどが書いてすぐウソになってしまいます。ですから、最初からネット上の情報などあてにしないことです。自分でやってみて、駄目なら駄目だと自分で判断し、自分で調べて自分で考えること、それがIT業界の鉄則です。Do-it-yourself、自分以外のものを信じないようにしましょう。

簡単な説明

システムとコマンド

  • コマンドラインやシステム構成
    • 起動とデーモン管理
    • シェル
      • 全てのコマンドはshがforkしてその後にexecで実行される
      • Bash
        • コマンドを実行するための主となるインターフェース
        • 基本的にコマンド名とオプションや引数となるファイル名などをキーボード入力してEnterする
      • Bash Script
        • cron処理からメール送信まで、スクリプトで複数行のコマンドを実行
        • シェルや環境変数の個人的な設定を行うための初期化スクリプト(.bashrcや.bash_profileなど)に使われる
        • バッチ処理のように「いつも使う処理をひとつにまとめて正しく実行する」といった用途にも使える
      • csh
      • zsh
      • エイリアス
        • コマンドの別名
        • よく使うオプションなどを最初から標準にしたい場合などに使う
      • ヒストリ
      • タブ補完
      • シェルのカスタマイズ
    • コマンド例
      • 基本コマンド
        • cd, ls, cat, cp, mkdir, rm, mv, ln, lessなど
      • パイプ・リダイレクト
        • コマンドが出力した内容を別のコマンドの入力として、次々に渡す
        • ファイルと標準入出力の統一(ストリーム)
        • たとえばfind / | grep "2020"とか、sort test.txt | lessなどといったように、「コマンドで処理した内容にさらに処理をかける」と言う風に使う
      • grep, find, sed, awk
        • awkはパイプでduなどと一緒に「1000MB以上のサイズのファイルだけを抽出する」などといった使い方をすると便利
        • findはxargsなどと使うことで、「ファイル一覧を出力して、その中の全ファイルに対して処理をかける」などといった使い方ができる
      • ファイル操作系ツール
        • tar, rsyncなど
        • 圧縮解凍:gzip, gunzip, bzip2, bunzip2, zip
      • テキスト操作系ツール
        • diff, patch, sortなど
        • nl, join, split, csplitなどが地味に使える
        • uniq, seq, wc, head, tail, tac, revなどはパイプで他のコマンドの出力をフィルタリングするのに使うことが多い
      • プロセス操作系ツール
        • ps, killなど
        • 端末の出力を写し取るtee, scriptが使える
        • コマンドの実行状況を見るにはpv, watch
        • コマンドを並列実行させるためにはコマンドの最後に&をつける
      • バイス操作系ツール
        • df, du, ddなど
      • ユーザー・パーミッション・所有権
        • chmod, chown, chgrp
        • useradd, groupaddとadduser, addgroupという紛らわしいコマンドがある
        • 設定ファイルは/etc/passwd, /etc/group, /etc/shadow, /etc/gshadow
        • たとえば/var/www/htmlの所有ユーザーを変更する
        • UNIXパーミッションWindowsにないため最初は難しいが分かってしまえば何とかなる
        • ユーザーを追加した場合、/etc/skelが新しいホームディレクトリを作るためのひな型になる
        • rootユーザーとは、システムの管理者のこと。何でも破壊できるため、間違ってコマンドを実行しないように通常は一般ユーザーでログインし、必要に応じてsuやsudoコマンドでrootユーザーになることが推奨される。
        • su, sudo
      • BusyBox
        • 組み込みなど小容量のデバイスの場合に、基本コマンドをひとつのバイナリに詰め込んで小サイズにする
    • ベースシステム
      • ディレクトリ階層
        • /binは通常のコマンド、/sbinは管理者用のシステムコマンド
        • /binや/sbinはシステムに必須の最低限のコマンドで、/usr/binや/usr/sbinはそれ以外のアプリケーションなどのコマンドやプログラム
        • /usr/localにはソースtarballから自分でビルドした、パッケージ管理とは関係のないプログラムを置く
        • /optにはさまざまなオプションのアプリケーションが入る。たとえばGoogle Chromeのようなクローズドなアプリケーションあるいは追加リポジトリから入れたアプリケーションが入ることが多い
        • Apacheのドキュメントルートなどは、Apacheをどのようにインストールしたかで変わってくる。/var/www/htmlである場合もあれば/usr/local/apache2/htdocsである場合もある。必要に応じて所有者や所有グループを設定しよう
      • ヘッダー
        • プログラムのビルドにはヘッダファイルが必要となる場合がある
        • 単に実行するだけならヘッダーは必要ない。プログラムをコンパイルしたり開発したりする時に必要。
        • 「-devel」パッケージをインストールするとヘッダーファイルが入れられる
      • 共有ライブラリとリンク
        • 全てのプログラムはlibc(libc.so.6)にリンクされる
        • ダイナミックリンクした場合、Linuxのリンクローダ(ld-linux.so.2)が動的にシンボル情報を共有ライブラリにリンクする
        • スタティックリンクはあまり使われていないが、一部の軽量なlibcはスタティックリンクに最適化されていて、組み込み向けに使われる
        • バイナリのリンク情報はlddコマンドで確認できる。
        • ldconfigコマンドやld.so.confで共有ライブラリのパスやキャッシュなどを管理・設定できる。
        • ちなみにプログラムのシステムコール呼び出しはstraceコマンドでトレースできる
      • ファイルシステムとマウント
      • 設定ファイル
        • 設定ファイルは/etcにある
        • /etcには使っていて内容が変化しないファイル、/varには使っていて内容やサイズの変化するファイルを置く
      • ログファイル
        • ログは/var/logにある
        • ユーザーのログイン・認証情報はauth.logにあるので不審なログインがないかチェックしよう
      • スプールファイル
        • 印刷などの時間のかかる処理の時に、一時的に転送データをファイルに書き出し、少しずつ送信するのに使う
      • バイスファイル
        • キャラクタ型デバイス
          • 文字のバイト列としてストリーム表現ができるデバイス
        • ブロック型デバイス
        • ネットワークインターフェース
        • udev
          • ユーザー空間でデバイスファイルを自動で作成するシステム
          • 以前のdevfsがUSBフラッシュメモリなど頻繁に抜き差しを行うホットプラグと相性が悪いため作り直された
      • シンボリックリンク
    • システムロガー
    • cron
      • 定期的に処理を実行する

コンパイラテキストエディタ

ディストリビューションとパッケージ管理

Linuxカーネル

  • カーネルの仕組み
    • プロセス管理
    • メモリ管理
      • 仮想アドレス空間
      • ページングとセグメンテーション
        • メモリはページと呼ばれる小さな単位でカーネルによって管理される
      • プロセスにはテキスト領域(プログラムコード自身が入る領域)、スタック領域、ヒープ領域などが確保される
    • デバイスドライバ
      • OSの中で唯一デバイスコントローラの仕様を知っている
      • Linuxではカーネルの肥大化を防ぐためマイナーなドライバは削除している
    • 割り込み
      • I/O・ディスクデバイスなどハードウェアの処理を待つ間カーネルは別のことをする
      • カーネルが何かしている間にイベントを通知して割り込む
      • ソフトウェア割込み
      • ハードウェア割込み
      • タイマ割込み
    • プロセス間通信
      • 共有メモリ
      • セマフォ
      • メモリマップトファイル
      • パイプ
      • ソケット通信
    • シグナル
      • プロセスの強制終了に使うほか、シグナルをトラップ(捕捉)することでシグナルに応じた処理をプロセスで実行できる
    • 入出力
      • tty(端末のデバイスファイル)
      • もともとはテレタイプ(プリンタと紙テープ)だったが、歴史とともに徐々にモニター(ダム端末やキャラクタ端末など)とキーボードになり、最近はX端末を使うようになった
      • 仮想コンソール
      • ターミナルエミュレータ
    • ファイルシステム
    • ソケット
      • 2つの接続でデータをやり取りする
      • 2つのソケットが相互に接続されると有効になる
      • 片方に書くと、片方から読める
    • カーネルモジュール
    • マイクロカーネル
    • リアルタイム処理
      • リアルタイムOSでは、優先度の高いタスクは優先度の低い他の全てのタスクを後回しにして、必ず決められた時間内に実行する。
      • LinuxではRT-PreemptパッチをあてることでLinuxカーネルをプリエンティブルにできる。
      • 商用のリアルタイムOSにはQNXVxWorksなどがあり、宇宙開発などにも使われている。

X

  • X
    • Xはクライアント・サーバーで動くため、たとえば複数のX端末からひとつの中央ワークステーションに接続したり、たくさんの分散コンピュータにひとつのモニターから接続したりできる
    • イベントメッセージ
    • Xプロトコル、ネットワーク透過
    • Xサーバー・Xクライアント
    • Xlib
      • Xプロトコルの詳細を知らなくても、Xlibを使うことでXアプリケーションが開発できる
      • XlibではWindowsのメッセージループと同じイベントループでプログラムを記述する
    • Motif
      • 昔はMotifがXで標準的で、GIMPももともとはMotifで書かれていたが、Motifはフリーでなかった
    • GTK
    • Qt
      • 昔はKDEで使われていたQtがフリーでなく、Harmony(代替Qtを作るプロジェクト)やGTK/GNOMEを作る必要があった
      • 今はQtもフリーである
      • C++で、美しい見た目を持ち、Windowsなどでも動くクロスプラットフォーム性が売り(一応GTKWindowsで動くが、Qtほど美しくない)
      • PyQt
      • QtRuby
    • ウィンドウマネージャ
      • Blackbox派生
        • Openboxなどが有名
      • Window Maker
      • enlightenment
        • 「ハッと息をのむほど美しい」という豪華なウィンドウマネージャ
        • 高度なライブラリを提供するなど、既にデスクトップ環境に近い
      • twm派生
        • FVWMなどが有名
      • タイル型
        • Linuxにはさまざまなタイル型ウィンドウマネージャがある
      • Windows95
        • JWMはXlibで書かれており、「羽のように軽い」
    • デスクトップ環境など
      • GNOME
        • Linuxの事実上の標準デスクトップ環境
        • GNOME 2まではシンプルかつ簡単なデスクトップ環境を目指しており、言ってしまえば「パソコン初心者向けのデスクトップ環境」だった
        • GNOME 3からはユーザーインターフェースを抜本的に一新し、GNOME-Shellと呼ばれる新しいGUIを採用、アクティビティバーから全ての操作を行うようにし、標準アプリケーションのメニューバーやタスクバーは大胆に削除した
          • デスクトップ環境はデフォルトで高度な機能を提供せず、拡張機能によって自分の好きなデスクトップにカスタマイズすることができる
          • GNOME 3は当初は大不評だったが、今見ると「WindowsのパクリだったGNOME 2に比べて、独自性があっていい」というユーザーも
        • CORBA
          • 分散システム。ネットワーク上の複数のコンピュータにおいて、言語やプラットフォームをまたいでシステムを構築できる
          • たとえば古いシステムを再利用して、プラットフォームが別の環境とネットワークで接続したり、コンポーネントとして再利用したりできる
          • GNOMEではCORBAを使うことで、LinuxWindowsが互いにメッセージをやり取りしたり、GNOMEアプリケーションを複数のホストから構築したり、さまざまなアプリケーションや言語でBonoboコンポーネントを使うことができる
        • D-Bus
          • GNOME 3ではCORBAではなくD-Busが標準になった
          • D-BusLinuxカーネルKDEでも使われているプロセス間通信の仕組みで、CORBAと同じようにインターフェース定義によってそれぞれのプロセスがネットワークで通信できる
        • Gconf, dconf
        • GnomeVfs, GVfs, GIO
          • ネットワーク上のたとえばFTPなどのストレージを、ローカルにあるものと同じように使用できる仮想ファイルシステム
        • GNOMEアプリケーション
        • MATE, Cinnamonなど
          • GNOME 3はメニューバーやタスクバーを廃止したが、これが不評であったためMATEがGNOME 2からforkし、GNOME 3とは別の道を行くCinnamonが開発されている
      • KDE
        • KDE Frameworks
        • Plasma
          • KDE 4以降ではKDEのデスクトップ環境のことをPlasmaと呼ぶ
          • 透明で美しいが、少し不安定で動かないこともある
        • KDEアプリケーション
        • CMake
      • Xfce
        • シンプルで軽量。GNOMEKDEよりもUNIXの本来の哲学に近い
        • Xfce-GoodiesではWebKitを使用したMidoriと呼ばれるブラウザなど、軽量アプリケーションも開発している
      • LXDE, LXQt
        • 軽量だけを目指すデスクトップ環境。仮想環境でも優れたパフォーマンスを発揮する
      • Budgie, Pantheon, Deepinなど
        • 最近は新しいデスクトップがいろいろと開発されており、Budgie, Pantheon, DeepinなどはUbuntuFedoraなどのフレーバー(デスクトップ環境だけを変えたバージョン)にも対応されるなど波に乗っている
    • Wayland

ハードウェア

  • ハードウェア
    • コンピュータの計算原理(リレーとスイッチ)
      • 論理回路(AND、OR、NAND、NOR、XOR)
      • 二進数の演算(加算器)は下桁からの桁上がりを考慮した論理回路(AND, OR, NOT, XOR)によって実現できる
        • 2進数の1ビットの計算は、0+0=0, 0+1=1, 1+0=1, 1+1=10(桁上がりを考慮しなければ0)しかない。これらは人間と同じ頭脳がなくても、機械的論理回路(XORとAND)だけで計算できる。
        • 2進数の1ビットだけの計算を行う加算器を半加算器と呼ぶ
        • 実際は計算は1ビットだけではなく、「下の桁から桁上がりする数」も考慮しなければならない
        • 桁上がりを考慮した加算器は2個の半加算器とORで実現でき、これを全加算器と呼ぶ
      • 負の数は2の補数表現によって実現できる
        • 2の補数とは、2進数で0と1を反転させた数に1を足したもの
        • 同じ数を負数にして足した時に、桁あふれを考慮しなければ、必ず0になる
    • 真空管トランジスタ集積回路(IC)
    • CPUとメモリ
      • CISCRISC
      • 命令サイクル
      • レジスタ
      • パイプライン
        • 複数の命令実行サイクルを行う際に、CPUの命令実行サイクルを1つずつずらして同時に行うことで、処理が高速化する
        • 特に命令の単純なRISCで効果的
      • キャッシュメモリ
        • 遅い主メモリの代わりに、よく使うデータをキャッシュメモリに入れることで、処理を高速化できる
        • キャッシュには、ライトスルー方式(データをキャッシュメモリに書き込む際に主メモリあるいはハードディスクにも同時に書き込む・書かれ終わるまで待つ)と、ライトバック方式(キャッシュに書かれた時点で書き込み完了として次の処理にバックする)がある
      • メモリ管理方式
      • LSIの製造プロセス
      • CPUアーキテクチャ
      • 量子コンピュータ
    • 磁気テープ、磁気ディスク
      • 磁気ヘッドと磁気テープによってデータを記録する
      • 磁気ヘッドから電磁気が流れ、磁気テープに記録される
      • ハードディスクはヘッドがディスクに接していない(空中を移動する)ため高速
      • ヘッド、シリンダ、トラック、セクタ
      • FAT(ファイルアロケーションテーブル)
      • SSD
    • 入出力と端末
    • UNIXでの日本語入力
    • CRTモニター
    • プリンター

互換レイヤー