# Linux 標準教科書

# Linux とは

  • UNIX --- AT&T, Ken Tompthon, System-V, BSD
  • Linux --- UNIX と似て非なる GPL の OS
  • カーネル --- OS の中核。ハードとソフトの橋渡しをする。
  • ユーザランド --- OS のカーネル以外の部分。コマンドはここで動作する。
  • シェル --- 対話型コマンド入力環境。コマンドの受付、シェルスクリプトの実行が 2 つの大きな役割。

# 基本的なコマンド

# ls

  • -t 最終更新時間で並べ替え
  • -r 逆順
  • ls *.conf ワイルドカード
  • ls ???.conf 文字数指定のワイルドカード

# cp

  • -i interactive
  • -r recursive フォルダも
  • -p 所有者、属性、更新日時などを消さずに保持する

# mv

  • -i
  • -f force 強制的に

# rm

  • -i
  • -f
  • -r

# pwd

カレントディレクトリのパスを表示

# mkdir

  • -p 上位フォルダもあわせて作成

# cat

  • -n 行番号を指定

# less

  • スペース 進む
  • b 戻る
  • / 検索
  • q 終了

# find

find PATH -name FILENAME

# man

コマンドのみならず、システムファイルやカーネルなど様々なもののマニュアルを表示できる

  • man passwd
  • man 5 passwd ジャンルを指定して検索

# touch

  • 最終更新日時を変更する
  • ファイルが存在しない場合は新規に作成する(こちらの目的で使われることが多い)

# head, tail

  • -n 先頭|末尾から n 行分を表示
  • -c 先頭|末尾から c バイト分を表示

tailには特別なオブション-fがある。これを使うとそのファイルをウォッチ(読み込み続けること)できる。ログを読む際などに使う。

# sort

テキストファイルの中身をソートする。

  • -r 逆順でソートする
  • -k n n 列目のデータを使ってソートする(列はスペース区切りで判定される)
  • -n 数値として認識してソートする

# uniq

uniq FILENAME 前の行と重複している行を出力しない

# tr

標準入力からの文字列を置き換える(translate する)

cat SOMEFILE | tr 文字列1 文字列2

例えば

Android
iPhone
Windows Phone

tr on ONすると

ANdrOid
iPhONe
WiNdOws PhONe

になる

# diff

差分を出力する。2 つのファイルを比べたり、パッチを作ったりする時に使う。

  • -c context diff 形式で出力
  • -u unified diff 形式で出力(git と一緒)

# grep

  • ファイルの中からデータを探す。grep ".*\.png$" FILENAME
  • 標準入力からのデータを検索対象にすることもできる。
  • regex が使える
  • -e or 検索をしたいときに使う grep -e ".*\.png$" -e "my.*\.jpg$" FILENAME
  • -i 大文字小文字の違いを無視する
  • -v マッチしない行を選択する

# 正規表現とパイプ

# 標準入出力

  • 標準入力 - デフォルトでキーボード
  • 標準出力 - デフォルトでディスプレイ
  • 標準エラー出力 - デフォルトでディスプレイ

# リダイレクト

標準入出力の向き先を変えること。

  • 1>は標準出力をリダイレクト(1は省略可)
  • 2>は標準エラー出力をリダイレクト
  • &>は標準出力及び標準エラー出力をリダイレクト
  • >&1は標準出力「への」リダイレクト(&1は省略可)
  • >&2は標準エラー出力「への」リダイレクト
# 入力
command < file   # ファイルの内容をコマンドの標準入力に渡す

#-----------------------------------------------------------
# 出力
command >&2      # 標準出力を標準エラー出力にリダイレクト

command > file   # 標準出力をリダイレクト
command >> file  # 標準出力をリダイレクト(追記)
command 2> file  # 標準エラー出力をリダイレクト

command &> file      # 標準出力/エラー出力を同一ファイルにリダイレクト
command &>> file     # 標準出力/エラー出力を同一ファイルにリダイレクト(追記)

command > file 2>&1  # 同上
command >> file 2>&1 # 同上

command > file1 2> file2   # 標準出力,エラー出力を別々のファイルにリダイレクト
command >> file1 2>> file2 # 標準出力,エラー出力を別々のファイルに追加書き込み

# vi エディタ

# コマンド

  • :q 終了
  • :w 保存
  • :wq 保存して終了
  • :q! 保存せずに終了

# 移動

  • w|b ワード送り
  • 0 行頭
  • $ 行末
  • Ctrl-D|U 半ページ送り
  • Ctrl-F|B ページ送り
  • gg 文書頭
  • G 文書末
  • H|M|L ページの上部・中部・下部へカーソルを移動
  • :123 指定行へ移動

# 編集

  • dd|yy カット、コピー
  • 5dd|5yy 複数行カット・コピー
  • p|P 現在の行の後ろ or 前にペースト
  • u カット、ペーストを取り消し

# 検索

  • /文字列 検索
  • n|N 前後の検索結果に移動

# 置換

s は sed の s

  • :123s/old/new 123 行目の最初の old を new に置き換え
  • :123s/old/new/g 123 行目の全ての old を new に置き換え
  • :%s/old/new ファイル全体の最初 old を new に置き換え
  • :%s/old/new/g ファイル全体の全ての old を new に置き換え
  • :%s/old/new/gc ファイル全体の全ての old を new に置き換え(確認つき)

# 管理者の仕事

# グループとユーザ

  • /etc/passwd ユーザの定義を記述するファイル
  • /etc/group グループの定義を記述するファイル
  • /etc/shadow パスワードを記録するファイル

これらのファイルの中身の読み方は本書のセクション 7 を参照すること。

# useradd

ユーザを作成する

  • -c コメントを加える
  • -g プライマリグループを指定
  • -G 補助グループを指定
  • -d ホームディレクトリを指定
  • -s シェルを指定 ログインしないユーザにはnologinを指定する
  • -u ユーザ ID を指定

# usermod

ユーザを変更する。useraddのオプションは全て使える。

  • -l ユーザ名を変更する

# userdel

ユーザを削除する

  • -r ホームディレクトリを削除

# groupadd

グループを追加

  • -g グループ ID を指定する

# groupmod

グループを編集

  • -n グループ名を変更
  • -g グループ ID を変更

# groupdel

グループを削除

# パスワード

昔は/etc/passwdに記録、今は/etc/shadowに記録される。 passwd ユーザ名で設定する。 パスワードがセットされていないユーザはログインできない。

# suコマンド

一時的に他のユーザになる。ユーザを指定しなければ root になる。

  • su ユーザ切替(カレントディレクトリを変えずに)
  • su -又はsu - root ユーザ切替(カレントディレクトリを root のホームディレクトリにする)

# sudoコマンド

一時的に他のユーザ権限でコマンドを実行する。

  • -uオプションでユーザを指定しなければ root になる。
  • sudoできるユーザグループをvisudoコマンドで明示的に指定しておく必要がある。

# ユーザ権限とアクセス権

# 所有者と所有グループ

ファイルの作成者が所有者・所有グループになる。

# chown

所有者を変更する

  • -R ディレクトリ内の全てを再帰的に変更する

# chgrp

所有グループを変更する

  • -R ディレクトリ内の全てを再帰的に変更する

# アクセス権

# chmod

アクセス権を変更する。

# u --- user, g---group, o---other
chmod u+rw-x,go+r-wx SOMEFILE

chmod 600 SOMEFILE

# seduid ビット

これが設定されている場合は、他者が実行したとしても、ファイル所有者の権限で実行される。

chmod u+s SOMEFILE
# -rwSr--r-- 1 root root 0 Nov 19 00:43 idbitfile

# 実行権限も付与されている場合は小文字表記になる
# -rwsr--r-- 1 root root 0 Nov 19 00:43 idbitfile

# setgid ビット

これが設定されている場合は、他者が実行したとしても、ファイル所有グループの権限で実行される。

chmod g+s SOMEFILE
# -rw-r-Sr-- 1 root root 0 Nov 19 00:43 SOMEFILE

# 実行権限も付与されている場合は小文字表記になる
# -rw-r-sr-- 1 root root 0 Nov 19 00:43 SOMEFILE

# sticky ビット

これが設定されているディレクトリ内のファイルは所有者以外は削除できない。

chmod +t SOMEFILE
# -rw-r--r-T 1 root root 0 Nov 19 00:43 SOMEFILE

# 実行権限も付与されている場合は小文字表記になる
# -rw-r--r-t 1 root root 0 Nov 19 00:43 SOMEFILE

# umask

マスク値を表示したり、設定したりする。

デフォルトの値からマスク値を引いた値が、ファイルの権限になる。

例えば、touch は 666 の権限でファイルを作成しようとする。 しかし、マスク値が 022 なので、実際には 644 の権限で作成される。

# 現在のマスク値を表示
umask
# => 0022

touch SOMEFILE1
# -rw-r--r--   1 root  root     0 Nov 19 00:58 SOMEFILE1

# マスク値を000にする。シェル内でのみ有効。
umask 000
touch SOMEFILE2
# -rw-rw-rw-   1 root  root     0 Nov 19 00:58 SOMEFILE2

# シェルスクリプト

# 基本

# シェルの指定

1 行目に#!/bin/bashなどで使用するシェルを指定する。 2 行目以降にコマンドを記述する。

# echo

引数として与えた文字列を標準出力に出力する。

  • -n 改行を出力しない

# 変数

代入は=、参照は$

abc=123
echo $abc
# =>123

配列への代入は[]をつけて行う。参照は${}で行う。

arr[0]=5
arr[1]=6
echo ${arr[1]}
# =>6

# シェル変数

  • シェル変数は、子プロセス(シェルから実行した他のコマンド)には引き継がれない。
  • setで一覧表示(但し環境変数も含む)、unsetで削除する。

# 環境変数

  • 環境変数は、子プロセス(シェルから実行した他のコマンド)にも引き継がれる。
  • envで一覧表示、unsetで削除する。
  • exportで設定する。
export abc # シェル変数abcを環境変数にする
export abc=123 # 環境変数abcを作成し123を代入する

# read

標準入力からデータを読み込んで変数に代入する。

read abc
# 'hello'と入力
echo $abc
# => hello

# 引用符

  • シングルクォート --- 変数を展開せずに文字列になる。
  • ダブルクォート --- 変数を展開したうえで文字列になる。
  • バッククォート又は$() --- 変数を展開したうえで、コマンドとして即時に実行した結果が文字列になる。
filename="READ"

# シングルクォート
echo '$filename' # => $filename
# ダブルクォート
echo "$filename" # => READ
# バッククォート
echo `ls | grep $filename` # => README.md
# $()
echo $(ls | grep $filename) # => README.md

# 引数

$のあとに番号や記号を指定することで引数を取得できる。

./args.sh aaa bbb ccc
# $0 => ./args.sh
# $1 => aaa
# $2 => bbb
# $3 => ccc

# 引数の数を取得する
# $# => 3

# shift

$2$1に、$3$2というふうに、引数の位置を手前に 1 つずつずらす。

# バックスラッシュによる改行

echo "I am a cat. Y
As yet I have no name."

# エスケープシーケンス

直後の 1 文字の扱いを変更する。

echo "I am a cat. \
As yet I have no name."
# => 改行は無効にして出力しない

echo "My name \"IS\" John"
# => 引用符を無効にしてただの文字列として扱う

echo -e "My name \t is \n John"
# => タブや改行を挿入する
#    (`echo`でエスケープ文字を利用するには`-e`オプションの指定が必要)

# sourceコマンド

指定したファイルを読み込んでシェル環境を設定する。例えば、.bashrcの変更を再ログインせずに適用したい際などに使う。

# 条件分岐

# 条件式

条件式はtest又は[]で書く。下記の 2 つは等価である。スペースに注意する。

  • test -f FILENAME
  • test ! -f FILENAME 否定形
  • [ -f FILENAME ]
  • [ ! -f FILENAME ] 否定形

# if

if 条件式; then
# 処理
elif 条件式; then
# 処理
else
# 処理
fi

# 文字列比較

  • [ a = b ] 等しい
  • [ a != b ] 等しくない

# 数値比較

  • [ a -eq b ] 等しい
  • [ a -ne b ] 等しくない
  • [ a -ge b ] a が b 以上
  • [ a -le b ] a が b 以下
  • [ a -gt b ] a が b より大きい
  • [ a -lt b ] a が b 未満

# ファイル属性の確認

  • [ -f FILENAME ] ファイルである
  • [ -d FILENAME ] ディレクトリである
  • [ -e FILENAME ] ファイルが存在する
  • [ -L FILENAME ] シンボリックリンクである
  • [ -r FILENAME ] 読み取り可能である
  • [ -w FILENAME ] 書込み可能である
  • [ -x FILENAME ] ファイルが存在し、実行権限がある
  • [ -s FILENAME ] サイズが 0 より大きい

# 論理積、論理和

[]の外に書くか中に書くかで書き方が異なる。

# 論理積
[ 条件1 -a 条件2 ]
[ 条件1 ] && [条件2]

# 論理和
[ 条件1 -o 条件2 ]
[ 条件1 ] || [条件2]

# case

animal="tiger"

case $animal in
  "dog" )
    echo "string is dog";;

  "cat" | "tiger" ) # 複数条件にしたい場合
    echo "string is cat or tiger";;

  * ) # どの条件にも当てはまらなかった場合
    echo "this is default"
esac

# 繰り返し

# for

for i in 1 2 3 4
do
  echo $i
done

# コマンドの実行結果を処理対象にできる
for i in `ls`
do
  echo $i
done

# while/until

while [ $count -le 10 ]
do
  echo "$count 回目の処理です"
  count=`expr $count + 1`
done

# select

ユーザに選択肢を提示して選ばせる時に使う。

select name in "apple" "orange" "banana"
do
  echo "you selected $name"
done
# ctrl+C を押さない限り永遠に繰り返される

# continue, break

do-doneの中で使う。

  • continue ループの先頭に戻る。
  • break ループを抜けて次に進む。

# サブルーチン

サブルーチン=関数のこと

# `function`は省略可能
function sayHello () {
  echo "hello"
}

# 呼び出し方
sayHello # => "hello"

引数の使い方

sayHello () {
  echo "hello, $1"
}
sayHello John # => "hello, John"

返値の使い方

sayHello () {
  return 123
}
result=sayHello
echo $result # => 123

# tips

# チェーン

  • コマンド1 && コマンド2 --- コマンド 1 が正常終了したらコマンド 2 を実行
  • コマンド1 || コマンド2 --- コマンド 1 が異常終了したらコマンド 2 を実行
[ -x /sbin/ip ] || exit 1
  • コマンド1 && コマンド2 && ... && コマンドN || コマンドY --- コマンドを順に実行する。どこかで異常終了したらコマンド Y を実行する。

# 一時的な環境変数の上書き

実行環境の差によって結果がブレるのを防ぐためによく使われるテクニック。そのコマンドでのみ一時的に変数を書き換える。

[ "$(SOME_VALUE=1 some_command)" = "success" ]

# デバッグ

-xオプションをつけることで、コマンドや変数の中身を表示しながら実行できる。

sh -x ./sample.sh

# ネットワーク

# コマンド類

  • traceroute www.google.co.jp --- 経路確認
  • ip a[ddress] --- ネットワーク設定を表示
  • ip route --- ルーティングテーブルを表示
  • ip route add|del --- ルーティング設定の追加・削除
  • nslookup www.google.co.jp --- IP アドレスの参照
  • nslookup 192.168.11.1 --- IP アドレスからホスト名を逆参照
  • ss -at --- TCP サービスを表示
  • ss -au --- UDP サービスを表示

# DNS

  • /etc/resolv.conf --- DNS の設定
  • /etc/hosts --- 静的な名前解決の設定

# プロセス管理

# プロセス

プロセスとはLinux が実行中のプログラムを管理する単位のこと

  • シェル自身もプロセスである
  • シェルでコマンドを実行すると
    • シェルは子プロセスとして自分の分身を作る(fork)
    • 子プロセスでコマンドが実行される(exec)
    • 子プロセスは、コマンドが終了すると親プロセスに終了を伝えて消滅する

# スケジューリング

  • 厳密には、プロセスは同時に 1 つしか実行されない
  • ラウンドロビン方式のスケジューリング
    • プロセスは待ち行列(Run Queue)で待機する
    • 順番が回ってきたら一定時間(タイムスライス)だけ処理を前にすすめる
    • 次に順番が回ってくるのを待つ
  • FIFO 方式のスケジューリング
  • 優先度は Nice 値によって決まる。nice,reniceコマンドで設定する。

# ジョブ

ジョブとはシェルがプログラムを管理する単位のこと

# バックグラウンドで実行する

# はじめからバックグラウンドで実行する
tail -f &

# 途中でバックグラウンドに移行する
tail -f # Ctrl+Z
bg

# フォアグラウンドへ移行する

tail -f # Ctrl+Z
tail -f # Ctrl+Z
tail -f # Ctrl+Z
tail -f # Ctrl+Z
tail -f # Ctrl+Z

jobs
# [1]    suspended  tail -f
# [2]    suspended  tail -f
# [3]    suspended  tail -f
# [4]  - suspended  tail -f
# [5]  + suspended  tail -f

# 3番をフォアグラウンドジョブにする(どちらでも効果は一緒)
%3
fg %3

# -のついたジョブ(2つ前に操作したジョブ)をフォアグラウンドジョブにする(どちらでも効果は一緒)
%-
fg %-

# +のついたジョブ(1つ前に操作したジョブ)をフォアグラウンドジョブにする(どれでも効果は一緒)
fg
fg %+
fg %%
%+
%%

# ジョブを終了する

kill %%など

# プロセス ID

  • psコマンドでプロセス ID の一覧を取得できる。
    • lオプション 親プロセスを取得
    • eオプション コマンドの後に環境を表示
  • 自身のプロセス ID はecho $$で取得できる

# シグナル

信号の送出によりプロセスを制御する仕組み。

# シグナルの送信方法

  • キー入力(Ctrl+Z 等)
  • killコマンド(kill -TSTP PID)
  • プログラムでkill()関数を呼ぶ
key シグナル番号 シグナル名 意味
Ctrl+C 2 INT 割り込み プロセスは終了する
Ctrl+\ 3 QUIT 強制停止
15 KILL 終了 kill コマンドのデフォルト
Ctrl+Z 18 TSTP 一時停止

# シグナルの補足

trapコマンドでシグナルを補足できる。補足後は、補足した場所の次の行から処理が継続される。

trap 'echo "SIGINTが入力されました"' 2

# top コマンド

実行中のプロセスの状態をダイナミックに表示する

# ファイル管理

# Linux のファイル管理

  • ファイルシステム --- 属性データ、ファイル本体を効率よく管理するための仕組み
  • パーティション --- ハードディスクを区切った単位

# FHS (Filesystem Hierarchy Standard)

ファイルシステムの標準構成。下記のようなふわっとした決まりがある。

  • bin --- 一般ユーザ用プログラム
  • sbin --- システム管理用プログラム
  • etc --- 設定ファイル
  • lib --- 複数のプログラムで共通に使われるライブラリ
  • var --- ログ、データベース、ウェブサイトなどの可変的データ
  • boot --- 起動関連
  • dev --- デバイス
  • home --- ユーザの作業領域
  • tmp --- 一時ファイル

/usr/usr/loaclディレクトリ以下にもほぼ同じ構成のディレクトリがあり、ユーザが独自にインストールするものはここに置くこともある。

# パーティション

  • 基本パーティションと拡張パーティションはあわせて最大 4 つまで作成できる。
  • 拡張パーティションは 1 つだけ作成できる。
  • 拡張パーティションの中に「論理パーティション」をいくつも作成できる。

パーティションの管理はfdiskで行う。詳細略

# ファイルシステム

  • Linux では ext3、ext4 など。ext3 以降ではジャーナリング機能があるため障害に強い。
  • Windows では NTFS,NTFS,exFAT など
  • CD では ISO9660 など

# コマンド

  • df --- 現在マウントされているファイルシステムを表示する
  • mkfs --- パーティションにファイルシステムを作成する
  • e2label --- パーティションに名前をつける

# マウント

  • 1 つ目のディスクを必ずルートディレクトリ(/)にマウントする
  • 複数のディスクを使うときは、既にマウントされているディスクの中のディレクトリに重ねてマウントする

# mountコマンド

# マウントのオプション
# -t タイプ ext3など
# -o オプション rw, roなど
mount /dev/sda1 /target
umount /target

# スワップ領域

mkswap デバイスファイル # スワップ領域の作成
swapon デバイスファイル # 有効化
swapoff デバイスファイル # 無効化

# 自動マウント

自動マウントしたい場合は/etc/fstabに設定を記載する

mount -aで上記に記載した全てのパーティションをマウントできる(ただし swap 領域を除く)

# リムーバブルメディア

mount -t iso9660 -o ro /dev/cdrom /media/cdromなどして使う

# i ノード

  • i ノード番号 --- ext ファイルシステムにおけるファイルを管理するための番号
  • i ノード領域 --- ファイルのディスク上の位置やアクセス権などの情報を保持している領域。i ノード番号で管理する。この領域がなくなると新しいファイルを作成できない。
# iノード番号の確認
ls -i

# iノード領域の確認
df -i

# リンク

# ハードリンク

  • i ノード番号を共有することで実現している
  • ハードリンクを削除しても、同じ i ノードを指すハードリンクの数が 0 にならない限りは、元ファイルは削除されない。
  • i ノードを基礎にしているため、別ファイルシステム(パーテイション)には作成できない
  • ln original_file link_file

# シンボリックリンク

  • 元ファイルの場所を表す擬似的なファイルを作成することで実現している
  • ln -s original_file link_file

# ディスク管理

  • fsck --- ファイルシステムのチェックと修復を行う。対象パーティションはアンマウントしてからチェックをかけることをおすすめ。
  • du --- ファイルやディレクトリの使用量を調べる