読者です 読者をやめる 読者になる 読者になる

はじめてUNIXで仕事をする人が読む本 の備忘録 12 UNIX とネットワーク技術

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

お世話になった本

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

第3部 ネットワーク技術編

第12章 UNIX とネットワーク技術

TCP/IP 実装の公開と普及

フルスタックのTCP/IP が初めて実装されたのがUNIX だった。それが今日おけるネットワーク技術の礎になっている。という話。

LAN と WAN

省略

ネットワーク端末としての UNIX

UNIX 互換OS がやはり多いと言える為、今日ではネットワークアプリケーションを利用するためのOSとしては主流となっている。という話。


以上で、第12章 UNIX とネットワーク技術 は終了です。
次回は、第13章 OSI 参照モデル です。

はじめてUNIXで仕事をする人が読む本 の備忘録 11 ソフトウェアライセンス

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

お世話になった本

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

第11章 ソフトウェアライセンス

ライセンスを考慮する理由

ソフトウェアは著作物。著者にはそのソフトウェアに関する排他的な権利が与えられる。ソフトウェアに関して著者に与えられる権利には、そのソフトウェアの利用を他社に許可するというものが含まれている。この条件を記したものがソフトウェアライセンス。
どのような条件で何が使用可能か十分検討が必要らしい。

  • 使用するユーザに制限があるか
    • 使用できるユーザに制限のあるソフトウェアは存在する
  • 使用する目的に制限があるか
    • 使用目的に制限のあるソフトウェアは存在する
  • プログラムの再配布が可能か
    • プログラムの再配布に制限のあるソフトウェアは存在する
  • ソースコードにアクセスすることが可能であるか
    • ソースコードにアクセスすることに制限のあるソフトウェアは存在する
  • 期間に制限があるか
    • 期間に制限のあるソフトウェアは存在する

オープンソースライセンス

商用のプログラムでは、それぞれ個別のライセンスが設定されることがほとんど。
オープンソースライセンスのいくつかを紹介する。

  • Apache Software License
    • BSD License に近いらしい
  • BSD License
    • Berkely Software Distributions (BSD) で使用されていたライセンスらしい
    • いくつかの亜種が存在する
    • GNU GPL などと比較して制約が少ないライセンスとして知られている
  • Common Public License
    • IBM で考案された
    • GNU GPL に似ている点があるため取扱注意
  • GNU General Public License (GNU GPL)
    • Free Software Foundation で考案された
    • このライセンスは伝染性がある
    • 業務で取り扱う際には注意が必要
  • GNU Lesser General Public License (GNU LGPL)
    • Free Software Foundation で考案された
    • GNU GPL より制約が緩くなっている
    • でも業務で取り扱う際には注意が必要
  • MIT License / X11 License
    • MIT で考案された
    • MIT X Consortium で使用されている
    • X Window System のライセンスとして知られている (筆者は知らなかった orz
  • Mozilla Public License

詳しくはググってください。


以上で、第11章 ソフトウェアライセンスは終了です。
次回は、第3部 ネットワーク技術編の第12章 UNIX とネットワーク技術 です。

はじめてUNIXで仕事をする人が読む本 の備忘録 10 ソースコードからのドキュメントの生成

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

お世話になった本

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

第10章 ソースコードからのドキュメントの作成

はじめに

ソースコードからドキュメントが作れると、2度手間もなく、ミスもなく出来ると思うからやってみよう。で出来たのがこの技術。

ドキュメント生成ツールの種類

いっぱい有ります。

  • Doxygen
    • 多言語対応のドキュメント生成ツール
  • Javadoc
    • JDKに付属するドキュメント生成ツール
  • PyDoc
    • Python に付属するドキュメント作成ツール
  • RDoc
    • Ruby に付属するドキュメント生成ツール

最近では言語処理系に標準でドキュメント生成ツールが付属していることが多い。

ドキュメント生成ツールの使用方法

Ruby のRDoc の公式ページの紹介だけします。

rdoc 4.1.1 Documentation


以上で、第10章 ソースコードからのドキュメント作成 は終わりです。
次回は、第11章 ソフトウェアライセンス です。

はじめてUNIXで仕事をする人が読む本 の備忘録 09 バージョン管理システム

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

お世話になった本

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

第9章 バージョン管理システム

バージョン管理システムとは

名前の通り、ファイルのバージョンを管理してくれるありがたい存在。

機能としては

  • 「何の」修正を行ったのかわかる
  • 「誰が」修正を行ったのかわかる
  • 「いつ」修正を行ったのかわかる
  • 「なぜ」修正を行ったのかわかる
  • ファイルを過去の状態に戻せる

バージョン管理システムの種類

代表的なのだけ

バージョン管理システムの使い方

Git だけ見ていく。(一部省略するかも)

Git の利用方法

初期設定

Git のWebページでアカウントを作る。そのアカウントのuser name / user email が覚えておく。

$ git config --global user.name "Lecuture Staff"
$ git config --global user.email lec-staff@example.co.jp

とかね。
保存先は、.gitconfigです。

リポジトリの作成

変更履歴を記録する領域のことをリポジトリと呼ぶ。
リポジトリを作成するには、git initを使う。

$ cd project/sample_project/
$ ls -a
.  ..  sample.pl
$ git init
Initialized empty Git repository in /home/taka/project/sample_project/.git/
$ ls -a
.  ..  .git  sample.pl
$ 

この時点で~/project/sample_project/リポジトリの作業コピーとして扱われる。しかし、自動的にリポジトリに追加されるわけでは無い。

$ git add .

カレントディレクトリ配下の変更のあったファイルをコミットするリストに追加(登録)する。

そして、コミット

$ git add .
$ git commit -m "first commit"
[master (root-commit) 9e21337] first commit
 1 file changed, 4 insertions(+)
 create mode 100755 sample.pl

# 確認するなら以下の通り
$ git log
commit 9e213378f45f636300a7f4ac53b9a599ad275a00
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:29:50 2017 -0500

    first commit

ファイルの編集

ざっくりと、こんな感じ

$ ls -a
.  ..  .git  sample.pl  # 現在のファイルの確認
$ vim sample.pl  # ファイルの編集
$ vim foo.sh  #ファイルの作成と編集
$ git add .  # Git に変更のあったファイルを登録
$ git status  # 現在のステータスを確認。new file とmodified があるのがわかる。
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   foo.sh
#   modified:   sample.pl
#
$ git commit -m "2nd commit"  # コミット
[master 46e533d] 2nd commit
 2 files changed, 4 insertions(+)
 create mode 100644 foo.sh
$ git commit -m "2nd commit"
[master 46e533d] 2nd commit
 2 files changed, 4 insertions(+)
 create mode 100644 foo.sh
[taka@ip-172-31-22-211 sample_project]$ git log -p
commit 46e533d1468c15de15f13b1052b6abe388c4f5a9
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:37:06 2017 -0500

    2nd commit

diff --git a/foo.sh b/foo.sh
new file mode 100644
index 0000000..e65e27d
--- /dev/null
+++ b/foo.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+echo "foo"
diff --git a/sample.pl b/sample.pl
index 9059403..477f4d0 100755
--- a/sample.pl
+++ b/sample.pl
@@ -1,4 +1,5 @@
 #!/usr/bin/perl
 
 print "Hello, World!\n";
+print "Hello, World2!\n";
 

commit 9e213378f45f636300a7f4ac53b9a599ad275a00
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:29:50 2017 -0500

    first commit

diff --git a/sample.pl b/sample.pl
new file mode 100755
index 0000000..9059403
--- /dev/null
+++ b/sample.pl
@@ -0,0 +1,4 @@
+#!/usr/bin/perl
+
+print "Hello, World!\n";
+
$ git status     <============ もう一度確認
# On branch master
nothing to commit, working directory clean  <===== きれいになった。
# 本当はここでgit push origin master とかするんですけどね。

変更の取り消し

git resetを使う。
git reset --head で全ての変更をキャンセル出来る。

$ vim bar.sh
$ cat bar.sh 
#!/bin/bash

$DATE=date
echo $DATE
$ git add .
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   bar.sh
#
$ git reset  <====== これ
$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   bar.sh
nothing added to commit but untracked files present (use "git add" to track)

ファイルの削除

git rmこれは、Git の作業コピーとインデックスから削除するコマンド。
なので、これを実施した後はgit commitが必要。

履歴の確認

git logで履歴の確認が出来る。

 git log
commit 46e533d1468c15de15f13b1052b6abe388c4f5a9
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:37:06 2017 -0500

    2nd commit

commit 9e213378f45f636300a7f4ac53b9a599ad275a00
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:29:50 2017 -0500

    first commit

ちなみに、46e533d1468c15de15f13b1052b6abe388c4f5a9これは、リビジョン識別しといい、Gitは格納しているファイル群をこれで管理している。

ブランチの作成

git branchで現在存在するブランチと、現在利用しているブランチを確認できる。
git branch <branch name> ブランチを作成する。
git checkout <branch name> でブランチを移動する。
ブランチを移動するときは、事前にコミットなどをして、変更を確定させておく必要がある。
また、
git checkout -b <branch name> == git branch <branch name> && git checkout <branch name> である。

$ git branch   # ブランチの存在の確認と、現在のブランチの確認。
* master
$ git branch 1st_branch  # ブランチの作成
$ git checkout 1st_branch  # ブランチの移動
Switched to branch '1st_branch'
$ git branch  # ブランチが作成され、移動している
* 1st_branch
  master
$ git checkout master  # 一度ブランチをマスターに戻してみた
Switched to branch 'master'

$ git checkout -b 2nd_branch  # ブランチの作成と移動を一緒にしている
Switched to a new branch '2nd_branch'
$ git branch  # これでブランチを作成して移動していることが確認できる
  1st_branch
* 2nd_branch
  master

マージ

分岐させたブランチは、統合して両方の変更を含んだものを作成できる。これが、マージである。
頭のいい人はここで気づくかもしれないが、条件を満たせば、衝突が起きる。これが英語そのままConflictである。そのときは、VimEmacsその他で修正する必要がある。

例として、masterブランチと1st_branchで変更を加えて、masterブランチにマージしてみようと思う。

$ git branch
  1st_branch
  2nd_branch
* master
$ vim foo.sh 
$ cat foo.sh 
#!/bin/sh

echo "foo"
echo $HOME

$ chmod u+x foo.sh 
$ ls -l
合計 8
-rwxrw-r--. 1 taka taka 34  2月 24 21:31 foo.sh
-rwxrw-r--. 1 taka taka 69  2月 23 18:36 sample.pl
$ git commit -a -m "modify foo.sh"  <======== git add . + git commit -m である。
[master b03be3f] modify foo.sh
 1 file changed, 2 insertions(+)
 mode change 100644 => 100755 foo.sh
$ 
$ git log
commit b03be3f65437753f4ea30d395e3a8104a88280d9
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Fri Feb 24 21:33:46 2017 -0500

    modify foo.sh

##################
# 1st_branch にて作業
##################
$ git branch
  1st_branch
  2nd_branch
* master
$ git checkout 1st_branch
Switched to branch '1st_branch'  <==== スイッチした
$ git branch
* 1st_branch
  2nd_branch
  master
$ ls -l  <======================= 現在のファイルを確認
合計 8
-rw-rw-r--. 1 taka taka 22  2月 24 21:43 foo.sh
-rwxrw-r--. 1 taka taka 69  2月 23 18:36 sample.pl
$ vim bar.sh  <================== bar.sh を作成
$ cat bar.sh  <================== 中身を確認
#!/bin/bash
echo $PATH
echo $HOME
echo `date +%Y%m%d`

$ chmod u+x bar.sh  <============ 実行権を付与
$ ls -l  <====================== ファイルを確認
合計 12
-rwxrw-r--. 1 taka taka 55  2月 24 21:45 bar.sh
-rw-rw-r--. 1 taka taka 22  2月 24 21:43 foo.sh
-rwxrw-r--. 1 taka taka 69  2月 23 18:36 sample.pl
$ git commit -a -m "create: bar.sh"  <=========== コミット
# On branch 1st_branch
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   bar.sh
nothing added to commit but untracked files present (use "git add" to track)
$ git status <============================= 一応確認
# On branch 1st_branch <=================== 1st_branch
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   bar.sh
nothing added to commit but untracked files present (use "git add" to track)

###################
# master ブランチに移動して、1st_branchをマージ
###################
$ git branch
* 1st_branch
  2nd_branch
  master
$ git checkout master
Switched to branch 'master'
$ git branch  <======================== master ブランチになった
  1st_branch
  2nd_branch
* master

$ git merge 1st_branch -m "marge to master form 1st_branch"   <== マージメッセージ付きマージ
Already up-to-date.

$ git status  <======================== ステータスを見てみよう
# On branch master  <================== master ブランチのステータスを見ている。1st_branch で作成した bar.sh がある
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   bar.sh
nothing added to commit but untracked files present (use "git add" to track)

$ ls -l
合計 12
-rwxrw-r--. 1 taka taka 55  2月 24 21:45 bar.sh  <====== あるぞ!
-rwxrwxr-x. 1 taka taka 34  2月 26 01:04 foo.sh
-rwxrw-r--. 1 taka taka 69  2月 23 18:36 sample.pl

$ git log
commit b03be3f65437753f4ea30d395e3a8104a88280d9
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Fri Feb 24 21:33:46 2017 -0500

    modify foo.sh

commit 46e533d1468c15de15f13b1052b6abe388c4f5a9
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:37:06 2017 -0500

    2nd commit

commit 9e213378f45f636300a7f4ac53b9a599ad275a00
Author: shimesaba-type0 <t.k.shimesaba@gmail.com>
Date:   Thu Feb 23 18:29:50 2017 -0500

    first commit
$

リポジトリの複製

git clone これで、リポジトリそのものを複製できます。

$ git clone sample_project sample_project2
Cloning into 'sample_project2'...
done.
$ ls -l
合計 0
drwxrwxr-x. 3 taka taka 63  2月 26 01:04 sample_project
drwxrwxr-x. 3 taka taka 49  2月 26 01:44 sample_project2 <== コピーできたと思うけど、何かおかしい。。。

変更の受け取り

git pull で、clone 元のリポジトリに変更が合った場合、その変更を受け取ることが出来る。

# 事前にclone 元のsample_project 内で変更を入れておいた。
$ vim foo2
$ chmod u+x foo2 
$ ll
合計 16
-rwxrw-r--. 1 taka taka 55  2月 24 21:45 bar.sh
-rwxrwxr-x. 1 taka taka 34  2月 26 01:04 foo.sh
-rwxrw-r--. 1 taka taka 29  2月 26 02:06 foo2
-rwxrw-r--. 1 taka taka 69  2月 23 18:36 sample.pl
$ git add .
$ git status
$ git commit -m "Update"
[master 5d410b7] Update
 2 files changed, 9 insertions(+)
 create mode 100755 bar.sh
 create mode 100755 foo2
$ ls
bar.sh  foo.sh  foo2  sample.pl

###
# ここから、git pullします。
### 
$ cd ../
$ cd sample_project2
$ ls
foo.sh  sample.pl
$ git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
From /home/taka/project/sample_project
   b03be3f..5d410b7  master     -> origin/master
Updating b03be3f..5d410b7
Fast-forward
 bar.sh | 5 +++++
 foo2   | 4 ++++
 2 files changed, 9 insertions(+)
 create mode 100755 bar.sh
 create mode 100755 foo2
$ ls
bar.sh  foo.sh  foo2  sample.pl

## 同期された!

共有リポジトリの作成

複数人で共有して変更できるリポジトリを作るときに使う。
git init --bare --shared=true で「作業コピーを持たない」、「グループから書き込み可能な」リポジトリが出来る。

しかし、個人的にはWebでリポジトリを作ってGit Clone をすることが多いので、パス。

一度、コマンドで実施してみよう。

$ mkdir sample_shared_project.git
$ cd sample_shared_project.git/
$ git init --bare --shared=true
Initialized empty shared Git repository in /home/taka/project/sample_shared_project.git/
$ ls -la
合計 12
drwxrwsr-x. 7 taka taka 119  2月 26 02:16 .
drwxrwxr-x. 5 taka taka  80  2月 26 02:16 ..
-rw-rw-r--. 1 taka taka  23  2月 26 02:16 HEAD
drwxrwsr-x. 2 taka taka   6  2月 26 02:16 branches
-rw-rw-r--. 1 taka taka 126  2月 26 02:16 config
-rw-rw-r--. 1 taka taka  73  2月 26 02:16 description
drwxrwsr-x. 2 taka taka 242  2月 26 02:16 hooks
drwxrwsr-x. 2 taka taka  21  2月 26 02:16 info
drwxrwsr-x. 4 taka taka  30  2月 26 02:16 objects
drwxrwsr-x. 4 taka taka  31  2月 26 02:16 refs

$ git remote add origin https://github.com/shimesaba-type0/sample_shared_project.git
$ git push origin master
Username for 'https://github.com': shimesaba-type0
Password for 'https://shimesaba-type0@github.com': 
remote: Repository not found.
fatal: repository 'https://github.com/shimesaba-type0/sample_shared_project.git/' not found

not found はわかるけど、remote にadd しようとしてこうなるのはなぜなのだろうか。

相変わらず、手元で初期化して、GitHub にプッシュする方法がわからない。


煮え切らないところでは有りますが、第9章 バージョン管理システムは以上です。
次は、第10章 ソースコードからのドキュメントの作成です。

はじめてUNIXで仕事をする人が読む本 の備忘録 08 UNIX プログラミング環境

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

お世話になった本

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

第2部 プログラミング環境編

第8章 UNIX プログラミング環境

第2部ではUNIX におけるプログラミング環境について解説を行うらしい。

UNIXプログラミング環境の特徴

ツールボックスアプローチ

プログラミング環境には、大別して2つの種類がある。
一つは、統合開発環境。機能は豊富だが、重い。しかし、このように全ての機能を1つのソフトウェアでまとめる方法をキッチンシンクアプローチと呼ぶそうだ。

もう一方は、単機能のソフトウェアを組み合わせて使う方法。必要なものだけ揃えればよかったり、一部だけカスタマイズしたらよくなる。しかし、各ソフトウェアの仕様を一通り理解する必要がある。このように、単機能で実現可能なことを複数の組み合わせで実現したりする方法をツールボックスアプローチという。

UNIX の環境では、ツールボックスアプローチの発想に基づいている。

プログラミング可能なシェル

シェルでプログラミングがかけて幸せだよね。

「1行プログラム」が書ける

わざわざ、エディタを開いて、#!/bin/sh とかしなくても、プロンプトでいきなりコードを書ける。これが早くていい。可読性は捨てることがある。
この技をワンライナーと呼ぶ。

これを芸の道にまで発展させた人たちを、シェル芸人と呼ぶことがある。

オンラインマニュアルがある
  • man
  • GNU info
  • -h, --help

man があるかどうかは、man -k <keyword>で探せる。もし、名前がフルでわかっているなら、これでもいい。man -f passwd

主なコマンドの配置

Ubuntu
コンパイラ GNUコンパイラ /usr/bin/gcc
中略
インタプリタ perl /usr/bin/perl
Python /usr/bin/python
PHP /usr/bin/php
Ruby /usr/bin/ruby
シェル sh /bin/sh
bash /bin/bash
中略
zsh /bin/zsh

代表的なプログラミング言語

注意:コードの書き手によって異なることがあります。

  • C
    • 演算子、データ型、制御構造が豊富
    • 移植性が高い
    • ハードウェア寄りの処理の記述も可能
  • C++
    • C言語の上位互換
    • 言語仕様が豊富。そのため、使いこなすのが難しいとされている。
    • STL (Standard Template Library) を使用したプログラミング
  • Java
  • Perl
    • テキスト検索や抽出に向いている
    • 表記形式はC言語に似ている
    • CGI の開発に使用されることが多い
  • Python
    • 最近は、機械学習とかAI でも使われている
    • 言語仕様が小さい
    • インデントによるブロック構造
  • Ruby
  • Lisp
    • 関数型言語
    • 前置記法
    • 括弧を使用したリスト表現で構成
    • リストで表現されたプログラムはデータとしても扱える
  • アセンブリ言語
    • おおむね機械語と1対1に対応。
    • テキストで機械語相当の処理を記述できる。

開発ツール

  • オンラインマニュアル
  • バージョン管理ツール
  • コンパイラ
  • make
  • リンカ
    • なにこれ?
  • デバッガ
    • 大事

コンパイラ

コンパイル対象の言語で書かれたソースファイルから、実行可能なバイナリを生成するプログラム。
中には、このコンパイラを自作して楽しむ人もいる。

make

ファイルの依存関係やコンパイル、リンクの手順を記述したファイル(Makefile) に基づいて、自動的にこれらの処理を実行するツール。

デバッガ

プログラムの不具合の原因究明に使用するツール。

ソフトウェアデバッガ

OSの支援によりユーザプログラムのデバッグを行うためのツール。
ブレークポイントの設置など。

ハードウェアデバッガ

組み込み開発環境では使えない。そのような場合に、ICEやJTAGデバッガが使用される。
これらのデバッガは直接CPUに対して馳tら着かけることでデバッグを行う。OSが存在しなくても使用できる。

C言語による開発実例

skip

Javaによる開発事例

skip

LL言語による開発実例

Perl

バージョン

 perl -v

This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-linux-thread-multi
(with 34 registered patches, see perl -V for more detail)

Copyright 1987-2012, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

sample.pl

$ whereis perl
perl: /usr/bin/perl /usr/share/man/man1/perl.1.gz

$ vim sample.pl
$ cat sample.pl 
#!/usr/bin/perl

print "Hello, World!\n";

実行権限をつけて実行

$ chmod u+x sample.pl
$ ./sample.pl 
Hello, World!

#!/usr/bin/perlはこう書き直すことも出来る。
#!/usr/bin/env perl こうすると、環境変数PATHに応じて実行されるべきperlコマンドが決定されるので、絶対パスを記述する必要がなくなる。

移植性はよくわからない。なぜなら、100個スクリプトがあって、全てこれで統一されていればいいが、1つだけフルパス指定だった場合、環境移行して、パスが変わったら使えないのが出てくる。可能性がある。


以上で、第8章 UNIX プログラミング環境を終わります。
次回は、第9章 バージョン管理システムに行きたいと思います。

はじめて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 プログラミング環境に入っていきます。

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

はじめてUNIXで仕事をする人が読む本 の備忘録 06 セキュリティ

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

お世話になった本

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

第6章 セキュリティ

UNIX におけるセキュリティ

ユーザの権限の分離がキーワード。

アクセス制限できる項目は以下の通り

  • ファイルの読み・書き・実行・ディレクトリの参照
  • (TCPUDPの) 特権ポートの利用

ACL (Access Control List) は、getfaclsetfacl等のマニュアル参照。

ルート権限の獲得方法

通常一般ユーザでログインする。SSH でリモートログインする場合、ルートユーザでのログインが禁止されている運用がほとんど。なので、ログインしてからルートユーザに切り替える。コマンドは、suコマンド。ルートユーザの権限でコマンドを実行したいときは、sudoでを使う。

su コマンド

su (Substitute User)コマンド。任意のユーザ権限でシェルを実行するコマンド。引数が省略された場合は、ルート権限でルートのシェルを実行。引数に-を与えると、元ユーザの環境(環境変数やカレントディレクトリなど)を引き継がない。

[user@pc ~]$ cd /tmp/
[user@pc tmp]$ pwd
/tmp
[user@pc tmp]$ su    <= 環境を引き継ぐ
パスワード:
[root@pc tmp]# exit
exit
[user@pc tmp]$ su -  <= 環境を引き継がない
パスワード:
[root@pc ~]# 

sudo コマンド

個人的な見解としては、こちらをよく使う。一般ユーザでログインしておきコマンドを実行するときに必要に応じて、コマンドの前にsudoコマンドを書いてあげる。su権限でコマンドを実行することが出来る。

設定はsudoersファイルに記述されている。visudoコマンドで編集できる。visudoコマンドは排他制御される。直接いじるよりこのコマンドを使うほうが良さそう。

sudo -l <user name>でコマンドを実行するユーザを指定できる。

user@pc:~$ sudo bash
[sudo] password for user: 
root@pc:~# 

共通鍵暗号公開鍵暗号

データ本体のセキュリティについて。大きく分けて、共通鍵暗号方式と公開鍵暗号方式がある。
共通鍵暗号は、暗号化と復号化が同じ鍵(共通鍵)を使う。一般的なパスワードの暗号化はこの方式を使う。アルゴリズムは、DES3DESAESなど。
インターネットを経由する通信では、共通鍵をどのように一致させるか問題がある。このため、公開鍵暗号方式が生まれた。アルゴリズムRSAなどがある。

基本的な考え方。
公開鍵暗号方式は、ユーザ一人につき「公開鍵」と「秘密鍵」のペアを持つ。公開鍵は文字通り、インターネットに公開される。秘密鍵はバレちゃダメ。
秘密鍵」で暗号化されたファイルは、「公開鍵」で復号化出来る。「公開鍵」で暗号化されたファイルは、「秘密鍵」で復号化出来る。
これにより、共通で同じ鍵を持つ必要がなくなる。

もし、Aさんが、Bさんに暗号化されたファイルを送りたければ、Bさんの「公開鍵」を使って暗号化し、Bさんに送信する。Bさんは、自分の「秘密鍵」で復号化したら良いわけだ。
これで、ファイルの完全性が証明される。
さらに、Aさんが送ったことを保証したければ、Bさんの「公開鍵」で暗号化したものを、更にAさんの「秘密鍵」で暗号化する。Bさんは、Aさんの「公開鍵」で復号化し、Bさんの「秘密鍵」で復号化する。これで、Aさんから送られたことを保証できる。これを電子署名という。

SSH の応用

SSH 公開鍵認証

  • 公開鍵を作成するとき、パスフレーズと呼ばれる文字列を使う
  • 通信時の認証に用いる公開鍵暗号方式
    • dsa
    • ecdsa
    • rsa
  • 接続先サーバで利用可能な方式を選ぶこと

公開鍵と秘密鍵のペアを作成する方法

コマンド、ssh-keygenを用いる。rsaを用いるときは、ssh-keygen -t rsaで良い。
コマンドを実行すると、ホームディレクトリ配下に、.sshディレクトリができているはず。その配下に、id_rsaid_rsa.pubファイルが出来上がる。

  • id_rsa
    • 秘密鍵
    • 他人に盗まれちゃダメ。
    • 他人に盗まれたら、削除して新しい鍵を作ろう
  • id_rsa.pub
    • 公開鍵
    • おそらく、pubpublicの前3文字だと思う。

公開鍵を接続先サーバの管理者に渡して、追加してもらえばOK。
手元で仮想マシンなどで試す場合は、以下の通りauthorized_keysファイルを作りその中にid_rsa.pubファイルの中身をコピーする。

# まず、ユーザのホームディレクトリに行きます。
$ cd ユーザのホームディレクトリ
$ mkdir .ssh
$ sudo chmod 700 .ssh

# もし、既にユーザのホームディレクトリ配下にid_rsa.pub ファイルがある場合
$ cat id_rsa.pub >> .ssh/authorized_keys

他にも、id_rsa.pubの中身を開いてマウスで選択してコピーして、.ssh/authorized_keysに貼り付けでもいいんですけどね。

ssh-agent

あまりつかったこと無い。
(なぜなら、基本的にパスフレーズを0文字にしているからな!)

毎回長いパスフレーズを入力するのが煩わしい時にこれを使う。最初に一度だけパスフレーズを入力すると、sshコマンド実行時のパスフレーズ入力を省略できる。

$ eval `ssh-agent`
$ ssh-add

ssh-agentを起動。すると、環境情報が出力される。eval環境変数化。シェルの種類は、ssh-agentにより自動判別。
ssh-addコマンドを実行する。パスフレーズが求められ、入力して登録完了。シェルをexitするまでパスフレーズの入力が必要なくなる。
Ubuntu デスクトップでは、ssh-agentが最初から起動している。ssh-addするだけでよい。

scp

SSHによる通信経路を使い、ファイルをコピーできる。
リモートファイルを手元にコピーする場合

$ scp <hostname or IP address>:<path> <手元のpath>

手元のファイルをリモート側にコピーする場合

$ scp <手元のpath> <hostname or IP address>:<path>

-r オプションでディレクトリごとコピーできる。詳細は、manを見てね。

ssh_config設定ファイル

とりあえず、man 5 ssh_configでマニュアルを確認できる。

~/.ssh/configファイルを作成し、各種設定ができる。

  • Host
    • 別名を付けれる。
    • 次にHost の項目を見つけるまでは、当該ホストの設定
  • HostName
    • 接続先ホスト名を指定する
  • User
    • ユーザ名を指定する
  • Port
    • 接続先SSHサーバのポート番号を指定する

Host apple
HostName apple.example.co.jp
User pen
Port 2222

SSH によるポート転送

ポートフォワーディングの話。(セキュリティとは少し離れる)
SSHで暗号化された通信路に、別の接続をのせることができる。これをSSHポートフォワーディングまたは、SSHトンネルなどと呼ぶ。

使いどころ
踏み台サーバにログインしたあと本番サーバにログインするときなど
踏み台サーバ:jump.example.net
接続先サーバ : pen.example.net
目指す動作:jump.example.net にアクセスしたあと、pen.example.net にアクセスする。

$ ssh -L8000 pen.example.net:80 jump.example.net

-Lオプションがリモートへのポート転送オプション
ローカルホストの8000番ポートに接続するとjump.example.net を経由して、pen.example.net:80 に中継されるらしい。

PGP による暗号化、電子署名

PGP (Pretty Good Privacy)

詳細は割愛する。必要なときにまた調べましょう。


以上で、第6章 セキュリティの話は終わりです。
次回から、第7章 Unix システム管理 です。