takashi kono's blog

コーヒーとキーボードと共に何かを記録していくブログ

はじめてUNIXで仕事をする人が読む本 の備忘録 07 UNIXシステム管理

はじめてUNIX で仕事をする人が読む本 の備忘録 07

お世話になった本

この連載ブログを書くにあたり、お世話になった本がこちら。LPICと被っているところもありますが、実務での使い方なんかも扱っており、良書だと思います。

第7章 UNIXシステム管理

UNIX に置ける管理作業

この本によると、UNIXを「使う」だけのユーザであっても、「管理する」知識を持つ必要がある。と言っている。
いろいろ、歴史的な経緯があって、UNIXには2階層のユーザ権限がある。

UID = 0 = root = 管理者
UID >=1 = 一般ユーザ
とはいえ、特別に
1 <= UID < 100 のUID にはアプリケーション固有の権限を当てるシステムもある。

Ubuntu は、rootユーザを明確には見えないようにしている。

起動とシャットダウン

Windows 95 ありがとう。らしい。

ブートローダ

BIOSの初期化が終わったところから話をする。

最初にHDD上のブートセクタ(セクタ0)が読み込まれる
ブートセクタは、512バイトしかないため、すべて格納できない。(難しい)
通常は、第2ステージのブートローダーを読み込んで実行するプログラムが格納されている。

ブートローダーは、ルートパーティションを検索し、カーネルファイルを読み込む。

カーネルをメモリに読み込むと、処理をカーネルのエントリポイントに移す。

カーネル起動後の処理

カーネルが行う処理

  • 内部変数の初期化
  • バイス検出と初期化
  • etc

起動メッセージを見たければ、dmesgコマンドで確認できる。

初期化処理が終了すると、カーネルinitを実行する。
initのパスはカーネルに埋め込まれている。通常は、/sbin/initにある。
initPID1の、最初に作られるプロセスである。(0はカーネル自身)他のプロセスの親になる。

initは、/etc配下にある、rcスクリプトを実行する。

スクリプトのファイル名は、Sまたは、Kで始まる。Sで始まるスクリプトのサービスは、そのランレベルで開始され、Kで始まるサービスは停止される。
ファイルの2文字目と3文字目は2桁の数字で処置の順番を表す。

最近のデーモンなどの起動スクリプトは、/etc/rc.d/配下に置かれる。このスクリプトの実行順序は、/sbin/rcorderで決まる。
rcスクリプトの冒頭のコメントには、スクリプト間の依存関係が記述されている。rcorderはそれを元に、サービスの実行順序を決定する。サービスの起動on/offは/etc/rc.conf内に記述する。

シャットダウン

シャットダウンとは、システムを停止させる際の手続きの総称。とでも言おうか。

とりあえず、コマンド一覧

  • shutdown
    • shutdown コマンドはシングルユーザモードに移行するためのコマンド
    • -h オプションでhalt
    • -r オプションでreboot
    • 引数には、時刻を指定。nowなら即座に
    • X時間後とか、X時とか指定すると、その時間にコマンドが実行される。
  • halt
    • 即座にシステム停止
  • reboot
    • 昔は、syncしてからとかあったらしいが、今は組み込まれているので気にしなくて良い。
    • こういう歴史的経緯を知るのも面白い
  • fastboot/fasthalt
    • 次回起動時のfsck (ファイルシステムチェック)をスキップして再起動するコマンド
    • 現在では、ファイルシステムが正常にunmountされていたら、起動時のfsckは省かれるため、差異はない
    • これ動かれたHDDが4TB とかだったらもう悲しくなるよね。

ユーザーとグループの管理

UNIX に置けるユーザの概念

UNIX はマルチユーザで、UID=0 はrootで、一般ユーザはUIDが1以上

初期のUNIXでは、UIDはshort型(16bit)で、足りなくなった。現在では、UIDはuid_tという型である。

UIDは、ユーザに割り当てられた数字であると同時に、実行中のプロセス属性に割り当てられる数字でもある。プロセスは、UIDに対応するユーザの権限で動作する。

プロセスは、ユーザIDの他に実効ユーザID(Effective UID)という値を持つ。
これは、プロセスの所有者とは別に、どのユーザの権限を持って処理を行うかを表している。
root権限で実効されたプロセスでも、実際の処理にroot権限を必要としない場合は、実効ユーザIDを一般ユーザにしておくことで、不正なコードを受け取り実効されていても、被害を抑えることができる。

反対に、一般ユーザがroot権限を必要とするときも使えるらしいが、個人的には、sudoで済ませたい。

ユーザとグループの管理

ネットワークでの集中管理を行わないシステムでは、ユーザとグループは/etc/配下のファイルで管理される。
/etc/passwdにはユーザ情報が格納されている。パスワード情報は、/etc/shadowに格納されている。

ユーザとグループに関係のあるコマンド

  1. id
    1. ユーザに割り当てられたID番号などを表示する。
    2. manを見ること。
  2. whoami
    1. 実効ユーザIDをログイン名で表示
  3. groups
    1. ユーザが所属しているグループ一覧を表示する
  4. who
    1. 現在システムにログインしているユーザの一覧を表示
  5. finger
    1. ユーザの情報を検索する。他のホスト上のユーザの状態を見れた。しかし、今では無効になっていることが多い。

パッケージ管理

Ubuntu のパッケージ管理

APT を使っている。

  • パッケージを検索する。
    • apt-cache search <package name>
  • パッケージをインストールする
    • apt-get install <package name>
  • パッケージを削除する
    • apt-get remove <package name>
  • パッケージ情報を更新する
    • apt-get update
  • インストールされている全パッケージを最新に更新する
    • apt-get upgrade

APT ではdeb形式のバイナリパッケージファイルを扱っている。ATPで提供されていないアプリケーションでも、deb形式で配布されている場合がある。deb形式のファイルは、dpkgコマンドでインストールする。

APTのパッケージの入手先は、/etc/apt/sources.listに記載されている。このファイルに項目をつかすると、非標準のパッケージ配布サイトを利用することもできる。

FreeBSD のパッケージ管理

今回は、Linux を中心にまとめたいので、FreeBSD はskip します。

TCP/IP ネットワーク管理

ネットワークへの接続

自動設定されるものも多くなってきたが、内部処理を知っておこう。

イーサネットインターフェイスが1つである場合を想定している。

  1. ハードウェアのネットワークインターフェイスを使用可能にし、物理的にネットワークに接続する。
  2. ホスト名とネットワークアドレスを割りあてる。(ネットワークによりDHCPも)
  3. デフォルトゲートウェイを設定する。
  4. 必要なネットワーク設定をブート時に実行できるようにする。
  5. ネットワーク接続をテストする。
  6. 利用しようとしているネットワークサービスを設定し、使用可能にする。

ifconfig によるネットワークインターフェイスの設定

IFの設定には、ifconfigコマンドを使う。
OS によって使える引数が異なっている。

# ifconfig msk0 inet 192.168.1.2 netmask 255.255.255.0

msk0 と名付けられたIFを構成し、指定されたIPアドレスとマスクを割りあてる。

  • 第1引数
    • IF 名。OSにより異なる。
  • 第2引数
    • アドレスファミリ。
  • 第3引数
  • 第4引数
    • ネットマスクを示すキーワードが来る
  • 第5引数
    • netmask を10進数または16進数で指定

ifconfigは古いコマンド。
現在は、ipコマンドを使う方が適切。

デフォルトゲートウェイ

routeコマンドで指定

# route add default gw 192.168.192.1

こちらも、現在では、ipコマンドに置き換わっている。

ルーティングテーブルの表示

netstat -rコマンドを使用する。

スタティックルーティング

# route add -net 192.168.2.0/23 192.168.1.128

192.168.2.0/23 ネットワークへの通信は、192.168.1.128のルータを経由するように設定する。

ブート時の設定

OS起動時に自動的にネットワークインターフェイスの設定を行うためには、以下のファイルに記述する。
Linux(Ubuntu): /etc/network/interfaces

設定の反映方法。
Ubuntu では、/etc/network/interfaces に以下を追加する。

auto eth0
iface eth0 inet static
address 192.168.1.2
netmask 255.255.255.0
gateway 192.168.1.1

静的経路設定。/etc/network/if-up.d/routes を作成し、設定を追加。シェルスクリプトとして実行されるので、実行権限をつけておくこと。

#!/bin/sh
route add -net 192.168.2.0 netmask 255.255.240.0 gw 192.168.1.128

名前解決

ホスト名と対応するIPアドレスに変換すること。または、その逆。
手段。以下のいづれか。

  • /etc/hostsファイルに記載されている対応付けを参照する。
  • DNSサーバと通信し検索を行う。

DNSサーバより先に/etc/hostsを検索する。なので、DNSの設定を上書きしたり、仮想サーバの動作試験などにも活用できる。

127.0.0.1 localhost localhost.example.jp
192.168.1.200 server.example.jp

/etc/resolv.confの例

search example.com
nameserver 192.168.0.2
nameserver 192.168.1.2

search 行は、検索時にドメインを省略した時に、補足するドメインを指定する。nameserver行はDNSサーバを指定する。先に指定したエントリが優先される。

Ubuntu では /etc/resolv.confresolvconf ユーティリティによって自動生成される。
/etc/run/resolvconf/resolv.d.conf へのシンボリックリンクとして配置。
/etc/resolv.confを実ファイルで置き換えることで、resolvconfの起動を抑制するか、/etc/network/interfacesdns-nameservers 192.168.0.2を記述する。

ネームサービススイッチ

ホスト名・パスワードの対応付けは、ローカルからLANないで共有するようになった。
それから、ホスト名に関しては、DNSにより広域分散管理になった。

これらのには、幾つかのシステムが今まで生まれてきた。それらを有効・無効にしたり、検索順序を定義するのが、/etc/nsswitch.confというファイルである。コロンで区切って左辺にデータベース名、右辺に供給元を優先度の高い順番で空白区切りで記述する。

hosts:      files dns myhostname

DNS

ホスト名とIPアドレスを対応させて、問い合わせに対して、応答を返すシステムサービス。
負荷分散や、管理・責任の分割のため、大きなドメインごとに管理者が違う。
近くのDNSサーバがIPアドレスを持っていなければ、どんどん大きいドメインを管理しているDNSに問い合わせし、今度は、該当のホスト名に向かって、どんどん問い合わせていき、最後にIPアドレスを得る。

昔はすべてのホストのIPとホスト名の対応を/etc/hostsで持っていたらしいが、さすがに100台超えたあたりから無理が出たよね。

ドメインツリー

最上位 .
TLD(Top Level Domain) jpcomなど

名前解決の流れ

アプリケーションからの要求に応じて名前解決を行うソフトウェアがリゾルバ。

ゾルバは、/etc/resolv.confに記載されたネームサーバに対して、名前解決の要求を送る。このネームサーバをフルサービスリゾルバと呼ぶ。

例:example.co.jp を名前解決してみる。

  1. スタブリゾルバからフルサービスリゾルバへ名前解決依頼が来る。
  2. フルサービスリゾルバはルートサーバへexample.co.jpIPアドレスを問い合わせる。
  3. フルサービスリゾルバは、ルートサーバからjpドメインが管理していると通知を受け取る。
  4. jpドメインを管理しているサーバへ問い合わせる。
  5. co.jpが管理していると通知を受け取る。
  6. co.jpドメインDNSサーバへ問い合わせを行う。
  7. example.co.jpを直接管理しているネームサーバのIPアドレス(NSレコード)を受け取れる。
  8. example.co.jpを管理しているDNSに問い合わせることで、IPアドレス(Aレコード)が最終的に得られる。

このような動作を反覆検索という。(iterative query)

名前解決クライアント

  • nslookup
  • dig
  • host

サービスの管理

起動ファイル

UNIX でサービスという単語を正確に定義するのは難しいらしい。
カーネルが提供するシステムコールを除くと、プロセスが提供するものを指す。
この本では、rcスクリプトで起動されるものをサービスとしている。

サービスの実行順序(Linux)

LInux でも、FreeBSD でもrcスクリプトを直接実行してのサービス起動・停止が可能。
Ubuntu では、rcスクリプト/etc/init.d/配下に置かれている。
Linux では、serviceコマンドが用意されている。
例えば、以下を実行すると、現在のサービスの稼働状態一覧が出る。

$ service --status-all

トラブルシュート

トラブルシュートとは

稼働中のシステムで、何らかのトラブルの発生後サービス提供状態まで復旧させる作業のこと。

サービスとして稼働中のシステムで障害が起き、自分が不慣れな場合は、先輩や上司に判断を仰いでもらう。自分個人の環境であれば、率先してトラブルシュートしよう。
そして、トラブルの原因特定の調査方法を色々知っていこう。

ログとメッセージの確認

だいたい、ソフトウェアを作っている人たちは頭がいい。なので、ログやメッセージを残す。これをまずは読んでいこう。

自ら試行する

要するに、再現してみる。

プロセスの状態確認

例えば、Webサービスで、かつ、apacheで動作しているのであれば、下のような確認方法がある。

$ ps auwx | grep httpd

psコマンドも色々あるので、man参照。

他にも、

$ service httpd status
$ /etc/init.d/httpd status

などがある。

ifconfig

インターフェースの状態確認
例えば、パケットの送受信数が取得できるので、それを確認するだけでも、死活監視はできそう。

netstat

ネットワークの使用状況を表示
よく使うのは、下記の通り

$ netstat -anp -t
  • -a :接続待ち状態にあるソケットも、接続待ち状態にないソケットも表示する。
  • -n :ホスト・ポート・ユーザーなどの名前を解決せずに、数字のアドレスで表示する。
  • -p :各ソケットが属しているプログラムの PID と名前が表示される。
  • -tTCPのみ表示

netstat -rオプションを使うと、そのホストのルーティング情報を表示する。

lsof

現在稼働中のプロセスがどのファイルをオープンしているかを表示する。
lsofコマンドにより、プロセスが正しいファイルをオープンしているか否かを確認できる。

lsof -iでプロセスがオープンしているポートを調べることも出来る。
netstat -aオプションと似ているが、正しいプロセスが正しいポートをオープンしているか否かが、このコマンドでわかる。

たとえば、http(80)ポートがオープンしているかどうかはnetstat -aではわかるが、そのポートを使っているのがhttpdかどうかはlsofでないとわからない。らしい。

ping

サーバ自身には異常が見つからず、ネットワーク通信上に問題の原因がありそうな場合。そんなときに使う、最初のコマンド。

$ ping <hostname>

ICMP を使うのだが、インターネット上に公開されている機器は、ACLやFWで落とすようにしていることがある。

traceroute

対象となるマシンへの経路をたどって表示する。

$ traceroute <hostname>

しかし、バージョンによっては、下記のようなコマンドになる。

# IPv4
$ tracepath <hostname or IPv4 address>
# IPv6
$ tracepath6 <hostname or IPv6 address>

telnet

元々、ローカルマシンからリモートのマシンに接続する為のコマンドだった。(平文だけどね)
一方、telnetコマンドは接続先ポートを指定して、汎用のTCPクライアントとして使うことも出来る。
リモートマシンのhttpポートに接続したい場合は、

$ telnet <hostname or IP address> [http|80]

tcpdumpwireshark

パケットキャプチャツール。tcpdumpコマンドラインで実行するパケットキャプチャの基本ツール。wiresharkGUIで操作する応用ツール。なんとこの二つ。互換性がある。共通のライブラリ(libpcap)を使っている為である。
wiresharkWindows/macOSに対応しているため、tcpdumpでキャプチャしたデータをwiresharkで確認することが出来る。

大事なのは、すべてのパケットをキャプチャすることより、適切にフィルタリングすること。

解析機能は、tcpdumpよりwiresharkの方が強力。

デバッグ的手法

ソフトウェアの外部的振る舞いを観察するのでは無く、内部の動作や実装を調査する方法。
ソースコードが入手可能なら、ptracestraceなどのデバッグツールを用いて、実行中の内部動作を解析できる。

トラブルシュートまとめ

色々書いてきたら、最後に役立つのは、経験と知識と、両者に裏打ちされた勘らしい。
経験の浅い人が丸一日かかっても解決しなかった問題が、経験豊富な人が見ると2秒でわかることがある。(いいすぎた。)


これで、第7章 UNIXのシステム管理が終了です。
また、第1部 生活環境編も終了です。
次回は、第2部 プログラミング環境編、第8章 UNIX プログラミング環境に入っていきます。

ありがとうございました。