『試して理解 Linuxのしくみ』の実験プログラムをVS CodeのRemote - Containersで動かす

OSのプロセス管理、ソケット、メモリ、仮想化などについて理解を深めるために、『[試して理解]Linuxのしくみ』の実験プログラムを写経している。

手元のマシンがMacBook Proなので、本書で想定されている実行環境のUbuntuを利用するべくVS CodeRemote - Containersという拡張機能をセットアップしたのでポイントなどをまとめておく。

 

 

[Dockerfile詳解]

Remote - Containersの基本はこちらのブログで知った。

www.keisuke69.net

Docker Composeでもいけるらしいが、基本に忠実に今回はDockerfileを利用する。

bufferings.hatenablog.com

 

『試して理解 Linuxのしくみ』の実験プログラムを動かすために利用しているDockerfileは、現在のところ以下のようになっている。今はちょうど第3章を写経しながら読み進めている途中なので、それ以降の章を写経するには足りない設定はあるかもしれないが、第2章で登場したstraceコマンドやmanコマンドなどの基本的なコマンドはこれで利用できる。

FROM ubuntu:latest

RUN sed -i "s@path-exclude=/usr/share/man/*@# path-exclude=/usr/share/man/*@g" \
    /etc/dpkg/dpkg.cfg.d/excludes

RUN apt-get update && \
    apt-get install git binutils build-essential \
        sysstat strace python3 man manpages-dev -y

 

■ straceコマンド

最初は本書の「はじめに」の章で指示されている通り、binutils、build-essential、sysstatの3パッケージをインストールしてリモートコンテナを起動し、実験プログラムの写経を開始した。

ところが、straceコマンドを利用しようすると、次のようなエラーが出てしまった。

$ strace -o ./chap02/build/hello.log ./chap02/build/hello
bash: strace: command not found

 

こちらの記事を参考に、apt-get install straceのコマンドをDockerfileに追加したところ、無事リモートコンテナに接続したVS Codeのターミナル上でstraceコマンドを実行できるようになった。

qiita.com

 

straceで出力されるログをみていると、想像していたよりたくさんのシステムコールが実行されており、Linuxというかコンピューターの奥深さを感じた。

 

■ manコマンド

また、本書の脚注を参考に、個々のシステムコールについてmanコマンドで調べようとすると、straceコマンドのときと同様にコマンドが見つからないというエラーがでた。

$ man 2 write
bash: man: command not found

 

straceコマンドの場合と同じで、apt-get install manコマンドを追加すればいいだろうと思ったが、そうではないらしい。次のようなエラーが出てしまった。

$ man 2 write
man: can't set the locale; make sure $LC_* and $LANG are correct
No manual entry for write in section 2
See 'man 7 undocumented' for help when manual pages are not available.

 

諦めてググると、次の記事を見つけた。どうやらコンテナ内でインストールできる内容に制限があるらしい。

qiita.com

 

Dockerfileに次の行を追加して、manのエントリーを追加できるように修正した。

RUN sed -i "s@path-exclude=/usr/share/man/*@# path-exclude=/usr/share/man/*@g" \
    /etc/dpkg/dpkg.cfg.d/excludes

 

リモートコンテナをリビルドして、man 2 writeコマンドを実行すると、無事マニュアルを確認することができた。

WRITE(2)                                                     Linux Programmer's Manual                                                     WRITE(2)

NAME
       write - write to a file descriptor

SYNOPSIS
       #include >unistd.h<

       ssize_t write(int fd, const void *buf, size_t count);

DESCRIPTION
       write() writes up to count bytes from the buffer starting at buf to the file referred to by the file descriptor fd.
(略)

 

[リモートコンテナ内でHello Worldする]

Dockerfileが用意できたところで、いくつかリモートコンテナ内でコードを動かしてみた。

まずはC言語。以下のコードをhello.cに写経する。

#include >stdio.h<

int main(void) {
    puts("Hello world!");
    return 0;
}

 

その後、VS Codeのターミナルでcc -o hello hello.c && ./helloコマンドを実行すると、無事「Hello world!」の文字列が出力された。

 

Pythonの例も載っていたので、試してみた。

print("hello python")と書かれただけのhello.pyを作成し、python3 hello.pyコマンドを入力すると、「hello python」の文字列が出力された。

 

[なぜLinuxを学ぶのか]

2019年3月に、AWS認定 DevOps エンジニア - プロフェッショナル (DOP -CO1) に合格した。そのあとコミュニティのメンバーで集まって『Effective DevOps』のオンライン輪読会を数ヶ月に渡って実施してきた。

その過程で、devopsという概念が特定の技術スタックに特化したものではないと理解しつつも、もう少し技術的な内容を学びたいと考えていたところ、DevOps Roadmapに出会った。

roadmap.sh

 

流石に最初の「プログラミング言語を何か一つ身につける」は大丈夫だと思ったので、次のステップとして「OSの様々な概念を理解する」ことを直近の目標とした。

 

どうやってこの目標を達成しようか考えていたところ、『Effective DevOps』オンライン輪読会でお世話になった@tadaさんから以下の本を紹介してもらい、こうしてVS Codeで実験プログラムを写経しつつ学んでいる。

 

[まとめ]

  • 『試して理解 Linuxのしくみ』の実験プログラムをVS CodeのRemote - Containers拡張機能で動かすためのDockerfileを書いた
  • straceコマンドを実行して、ハローワールドレベルのプログラムでも多くのシステムコールが利用されていることを学んだ
  • Dockerコンテナに限った話ではないが、Linuxに勝手にパッケージを追加できないよう制御する仕組みがあることを学んだ
  • コードは下記のリポジトリにまとめてある

github.com