Linuxの基礎
参考文献
シェルとカーネル
コマンドを実行する部分は、Linuxカーネルが担当する。
CPUやメモリなどのハードウェアを管理するとともに、最終的なコマンド実行を処理するプロセス管理も担っている。
なお、Linuxカーネルは直接人間が操作できるようになっていないので、カーネルのインタフェースとなるシェルが仲介役を担ってユーザーからのコマンドを探してカーネルに実行を依頼し、その結果を受けてユーザーの画面に表示する。
プロンプトとコマンドライン
ホスト名やユーザー名から$
や%
までをプロンプト、以降のコマンド入力部分をコマンドラインと呼ぶ。
[user@localhost ~]$ ls
操作方法
カーソル移動
操作 | 内容 |
---|---|
C + b | 後方に1文字分移動 |
C + f | 前方に1文字分移動 |
C + a | 行頭に移動 |
C + e | 行末に移動 |
M + b | 後方に1単語分移動 |
M + f | 前方に1単語分移動 |
文字列操作
操作 | 内容 |
---|---|
C + h | 後方に1文字分削除 |
C + d | カーソル位置の1文字削除 |
C + w | 後方にスペース区切りで1単語分削除 |
C + k | カーソル位置から行末までを削除 |
C + u | カーソル位置から行頭までを削除 |
C + y | 最後に削除した内容を挿入する |
画面ロック
操作 | 内容 |
---|---|
C + s | 画面表示をロック |
C + q | 画面表示のロックを解除 |
コマンド終了、入力のやりなおし
操作 | 内容 |
---|---|
C + c | コマンドの強制終了および、入力途中のコマンドの破棄 |
オプションについて
ロングオプション
--
で始まるオプションをロングオプションと呼ぶ。
他のオプションと重複せずに一意に特定できる範囲まで文字列を省略可能。
# --quote-nameを指定したことになる ls --quote
オプション形式
形式 | 内容 |
---|---|
UNIXオプション | ハイフン付きでオプションを指定。ps -aefなど。 |
BSDオプション | ハイフンなしでオプションを指定。ps xfなど。 |
コピー・ハードリンク・シンボリックリンク
- コピー
ファイルを複製する - ハードリンク
ファイルに複数の名前をつけるイメージで、リンク元と同じ内容がリンク先でも表示される。ファイルの実体は1つだがリンク元を消してもリンク先は正常にリンク元のファイル内容を表示できる。 - シンボリックリンク
リンク元のファイルを参照できる。ショートカットやエイリアスに近い。リンク元が削除された場合、リンク先は正常にリンク元のファイル内容を表示できない。
基本的なコマンド
findコマンド
ファイル・ディレクトリを検索する。指定した位置から再帰的にディレクトリを掘って探してきてくれる。
-type
でファイル種別を絞り込み可能。
指定 | ファイル種別 |
---|---|
-type f | 通常ファイル |
-type d | ディレクトリ |
-type l | シンボリックリンク |
-name
や-iname
(大文字小文字の区別なし)を指定しファイル名で絞り込み可能。
*などのワイルドカードを使用する場合、シェルにパス名展開させないようにシングルまたは、ダブルクオートでオプション引数を囲むこと。
$ find -name '*.txt'
-a
オプションでAND検索が可能。
$ find . -type f -a -name '*.txt' -print
locateコマンド
パスが格納された専用のデータベースから指定ファイル・ディレクトリを検索する。そのため、最初だけ手動でデータベースの更新が必要。
findより高速だが、デフォルトでは1日1回だけデータベースの更新をするため、リアルタイムな検索結果が返ってこない点に注意(すでに存在しないファイルが検索に該当する可能性がある)。
導入後、最初にデータベースを更新
# updatedb
通常locate
はファイルパスのどこかに指定したパターンが含まれていたら、一致したものとしてみなす。
ファイル名だけにマッチさせたい場合は、-b
オプションを使うこと。
$ locate -b python
複数の検索パターンを指定すると、OR検索になる。
$ locate docs document
AND検索を行う場合は、-A
または--all
オプションを使う。
$ locate -A bash doc
manコマンド
manで対象コマンドのマニュアルを参照できる。
$ man cat
対象コマンドがわからない場合、何をしたいかというキーワードがわかればそれでマニュアルを検索できる。
$ man -k copy
セクション番号
マニュアル名称の後ろにある括弧付き数字は、マニュアルのセクション番号であり以下の内容を意味する番号が付与されている。
セクション番号 | 内容 |
---|---|
1 | コマンド |
2 | システムコール |
3 | ライブラリ関数 |
4 | デバイスファイル |
5 | ファイルの書式 |
6 | ゲーム |
7 | そのほかいろいろ |
8 | システム管理コマンド |
9 | カーネルルーチン |
複数のセクションに同じ名前のマニュアルが存在する場合もあるので、明示的にセクション番号を指定しない限り、小さい番号のマニュアルが表示される。
$ man 1 crontab
特定のマニュアルがどのセクションに含まれているかは、-wa
オプションを使う。
$ man -wa crontab
whichコマンド
シェルがどのコマンドを実行するかを知りたい場合に使う。
-a
オプションでコマンドが見つかったすべての場所を表示してくれる。
typeコマンド
対象コマンドが本当にコマンドなのかエイリアスなのかを確認できる。
$ type ls
エイリアスを無視してコマンド実行
エイリアスとなっているコマンドの前に\
もしくは、command
を付与する。
$ command ls $ \ls
変数
シェル変数
bashなどの内部で使用される変数。数値や文字列を保存できる。 値にスペースを含む場合はシングルまたはダブルクオートで囲み、=の左右にスペースをつけないこと。
$ var1='test variable' $ echo $var1
シェル変数には特別な意味をもつものがあり、これらを設定することでさまざまな機能のカスタマイズが行える。
変数名 | 内容 |
---|---|
PS1 | プロンプト設定 |
PATH | コマンド検索パス |
LANG | ロケール |
など。
しかし実行ファイルとしてファイルシステム上に存在する外部コマンドでは、このシェル変数を参照できず、シェル自体に内蔵している組込みコマンドのみ参照ができる。
外部コマンドはいわばシェルの「外側」で実行されるため、このような挙動になっている。
そのため、LANGなどの外部コマンドで常に設定を反映したい変数は環境変数というしくみを利用している。
環境変数
外部コマンドから参照できる変数。
実は特に明示的に指定しなくても変数LANGなどは、自動的に環境変数として設定されている。
以下で環境変数を表示できる。
$ printenv
自分で設定するにはexportコマンドを使用する。
$ export LESS='--no-init'
権限
所属グループ確認
groups
コマンドで自分が所属しているグループを確認できる。
$ groups
パーミッションの記号と意味
ファイルの場合
記号 | 意味 |
---|---|
r | 読み取り |
w | 書き込み |
x | 実行 |
ディレクトリの場合
記号 | 意味 |
---|---|
r | 読み取り(ディレクトリに含まれるファイル一覧の取得) |
w | 書き込み(ディレクトリの下にあるファイル・ディレクトリの作成・削除) |
x | 実行(ディレクトリをカレントディレクトリにする) |
chmodコマンド
ファイルやディレクトリのパーミッションを設定するには、ファイルモードを変更するchmodコマンドを使う。
シンボルモードと数値モードによる指定方法がある。
シンボルモード
以下のように実行する。
$ chmod u+w test.txt
chmodのあとは誰にどのような権限を追加・削除するのかを記載する。
- ユーザー指定
記号 | 意味 |
---|---|
u | オーナー |
g | グループ |
o | そのほかのユーザ |
a | ugoすべて |
記号 | 意味 |
---|---|
+ | 権限を追加 |
- | 権限を禁止 |
= | 指定した権限と等しく |
最後は読み取り、書き込み、実行のrwxを記述する。
たとえば以下ではグループとそのほかのユーザーの権限を読み取りのみにしている。
$ chmod go=r text.txt
シンボルモードは指定したパーミッション以外変化しないため、一部だけを変更したいときに便利。(相対的な指定方法)
数値モード
シンボルモードとは対象的に絶対的な指定方法であり、元のパーミッションにかかわらず新しいパーミッションへ変更するときに便利。
rwxの各パーミッションに数値をあて、その合計値で最終的なパーミッションを決定する。
意味 | 数値 |
---|---|
r | 4 |
w | 2 |
x | 1 |
rwxすべて付与する場合は7、読み取りと実行権限だけを付与する場合は4となる。
chmodにオーナー・グループ・その他ユーザーそれぞれに対する数値を合わせて指定する。
オーナーは読み書き、そのほかのユーザーは読み取りと実行を許可する場合は以下のようになる。
$ chmod 755 text.txt
sudoコマンド
su
コマンドではスーパーユーザーのパスワードを求められたが、sudoではsudo
を実行したユーザーのパスワードを入力する。
su
は一度実行すればexit
で終了するまでスーパーユーザーのままだが、sudo
は一度コマンドを実行すれば元の一般ユーザーに戻る。
sudo
コマンドはどのユーザーにどのコマンドの実行権限を与えるのかを設定でき、それは/etc/sudoersファイルで管理されている。
sudoersファイルは<ユーザ><マシン名>=(<権限>)<コマンド>
の形式で記述し、<ユーザ>
の部分は直接ユーザー名を書くか、%<グループ名>
の形でグループを指定する。
以下はwheelというグループ(システム管理を行うグループ)に属するユーザーは、すべてのマシンですべてのコマンドを実行できるという意味。
%wheel ALL=(ALL) ALL
安易にALL設定をするとスーパーユーザーのパスワードを知らなくても管理者権限を行使できるので注意する。
また、このsudoersファイルは書き方を誤ると、sudoが動作せずにどのユーザーもsudoが使えなくなってしまうので、直接エディタで編集せずにvisudoコマンドを使用すること。
実行すると特にエディタを設定していない場合はVimが立ち上がり、編集内容に文法エラーがある場合は終了しようとしたときに警告してくれます。
このようにvisudoコマンドを経由してsudoersファイルを編集すると文法チェックを行ってくれるので、単にエディタで編集するより安全に作業ができる。
プロセスとジョブ
プロセスとは
メモリ上で実行状態にあるプログラムのこと。
Linuxカーネルはディスクから実行ファイルを読み出してメモリに格納、その内容に従ってCPUがプログラムを実行する。
プロセスとは、Linuxカーネルから見た処理の単位。
システム全体で一意なプロセスIDという識別番号が割り振られている。
デーモン(daemon)とは
ターミナルに接続していないプロセスのこと。
ジョブとは
シェルから見た処理の単位。
シェルのコマンドラインに入力している1行が1ジョブにあたる。
シェル毎にジョブ番号をもっており、複数のターミナルで2つ以上のシェルを同時に使っている場合、ジョブ番号は重複する。
ジョブの状態遷移
コマンドを実行中にほかのコマンドを実行したい場合、C + zで現在実行しているジョブを一時停止できる。
ジョブの一覧を表示するにはjobs
コマンドを実行する。
$ jobs
ユーザーが対話的に操作できるジョブの状態をフォアグラウンドと呼ぶ。
停止状態のジョブをフォアグラウンドにするには、fg
コマンドを使用する。
%
でジョブ番号を指定しないと、カレントジョブ(jobs
コマンドで+が表示されているジョブ)がフォアグラウンドとなる。
$ fg %2
ユーザーが対話的に操作できるジョブの状態をバックグラウンドと呼ぶ。
ジョブを停止すると動作が止まってしまうため、バックグラウンドで動作を継続したい場合は、bg
コマンドを使用する。
%
でのジョブ番号の指定はfg
コマンドと同じ。
$ bg %2
なお、始めからジョブをバックグラウンドで実行したい場合は、コマンドラインの末尾に&
を追加する。
$ cp file1 file2 &
ジョブとプロセスの終了
コマンドがフォアグラウンドの場合は、Ctrl + c
でよい。
バッググラウンドジョブは、kill
コマンドでジョブ番号を指定する。
$ kill %2
プロセスを終了する場合も、kill
コマンドでプロセスIDを指定する。
$ kill <プロセスID>
プロセスを終了できるのはそのプロセスの実行ユーザーのみだが、スーパーユーザーはすべてのプロセスを終了できる。
killコマンド
kill
コマンドはシグナルを送信しており、プロセスはそのシグナルによってさまざまな振る舞いをする。
シグナル名を省略すると、TERM
というシグナルを送信します。このTERMシグナルはTerminateを表している。
シグナルの種類は-<シグナル名>
で指定でき、シグナル番号という数値でも指定できる。
以下は同じTERMシグナルを送信している。
$ kill 4695 $ kill -TERM 4695 $ kill -15 4695
シグナル一覧は-l
オプションで確認できる。
例外的なシグナルとして、TERMシグナルを受け付けなくなった場合に強制終了する手段として、SIGKILLシグナルが存在する。
これはプロセスへシグナルを送らずLinuxカーネルに送り、プロセスの強制終了を促す。
プログラムの種類によって終了時に現在の状態を保存したりなどの必要処理があるが、このシグナルはそれらを行わせずに強制終了してしまうため注意が必要。
標準入出力
リダイレクト
コマンドの実行と結果の経路である標準入出力を変更する機能のことをリダイレクトと呼ぶ。
Linuxではコマンド起動時に"標準的な"入出力チャネルが開かれ、標準入力はキーボード、標準出力と標準エラー出力は端末ディスプレイに通常は割り当てられている。
標準入力をキーボードからファイルに変更(リダイレクト)したい場合は、<
を使用する。
$ cat < /work/file.txt
標準出力を端末ディスプレイからファイルに変更したい場合は、>
を使用する。
$ cat /work/file.txt > log.txt
上記では標準エラー出力は端末ディスプレイに表示される。
標準エラー出力のリダイレクトは以下のように2>
を使用する。
$ cat /work/file.txt 2> log.txt
標準出力と標準エラー出力をまとめる場合は以下。
2>
の標準エラー出力を&1
(標準出力)と同じものへリダイレクトするという意味になる。
$ cat /work/file.txt 2>&1 log.txt
>
を使ってのリダイレクトでは、同名ファイルを指定した場合、元の記載内容が上書きされてしまう。
上書きせずファイル末尾に追記する形でのリダイレクトは、>>
を使用する。
$ cat /work/file.txt >> log.txt $ cat /work/file.txt 2>> log.txt
/dev/nullというスペシャルファイルと呼ばれる特別なファイルを標準入出力で使うと以下のような結果になる。
- 入力先として指定しても何も内容を返さない
- 出力先として指定しても、書き込んだデータがどこにも保存されずになくなる
よくある使い方としては、エラーメッセージだけ確認したいときに標準出力を空にする方法。
$ ls ./work > /dev/null
パイプライン
標準出力を次のコマンドの標準入力として扱うためのしくみ。
$ ls | less
標準エラー出力もまとめてパイプラインに送りたい場合は、2>&1
の記法を使う。
$ ls -l /xxxxx 2>&1 | less
フィルタ
標準入力を入力として受け取り標準出力に出力するコマンドのこと。
# コマンド履歴の先頭10行を出力する $ history | head
代表的なフィルタコマンド
コマンド | 役割 |
---|---|
cat | 入力をそのまま出力する |
head | 先頭の部分を表示する |
tail | 末尾の部分を表示する |
grep | 指定した検索パターンに一致する行だけを表示する |
sort | 順番に並べ替える |
uniq | 重複した行を取り除く |
tac | 逆順に出力する |
wc | 行数やバイト数を出力する |
シェルスクリプトについて
実行方法
シェルスクリプトの先頭に書いてある#
から始まる行はshebang(シバン)という。
スクリプトの実行依頼を受けたLinuxカーネルがこの行を解釈して、#
以降に書いているシェル(/bin/bash
など)をつかってスクリプトファイルに書かれた処理を実行する。
実際には下のようなコマンドラインを、シバンを解釈してから実行するイメージ。
$ ./foo.sh ↓ $ /bin/bash ./foo.sh
シェルスクリプトはsource
コマンドを使ってカレントシェルで実行することも可能。
ただしカレントシェルで設定したエイリアスの影響を受けたり、その逆でシェルスクリプト内に記述されたエイリアスが実行後もカレントシェルの環境に残ったりするので注意が必要。
なお直接ファイル名で実行したり、シェルの引数として実行した場合に起動するシェルは、カレントシェルから読み出された子プロセスであるサブシェルなので、環境変数は引き継がれるがエイリアスなどの設定は引き継がれない。
シェルスクリプト実行時になぜ./
から書き始めるのか
それはシェルがコマンドを実行する際に、コマンドの実体ファイルがあるディレクトリサーチパスに、カレントディレクトリが登録されておらず、コマンドが見つからないためである。
サーチパスにないファイルを実行するには、相対パスか絶対パスでファイルを指定する必要がある。
サーチパスは環境変数PATHで確認できる。
$ echo $PATH
長いコマンドを1行で書く
シェルスクリプトでは複数のコマンドを;
で区切ることにより1行で書ける。
1つのコマンドが長い場合は行末に\
を書くことにより途中で改行できる。これはコマンドラインでも使用可能。
$ echo \ >
この>
からコマンドの続きを書ける。これをセカンダリプロンプトと呼ぶ。
またパイプライン|
の直後にも改行でき、長くなりがちなパイプラインを見やすくできる。
変数の書き方
変数の書き方の注意点
=
の後に空白を挟まない- 変数名はアルファベットと数値と_(アンダースコア)だけ。先頭に数値は使えない。
- 変数展開した後に文字列連結したい場合などは、
${foo}
のように波括弧で区切る。
foo=bar echo ${foo}_baz
- シングルクオート内の変数は展開できない。
あんまり使わないが、ダブルクオートでも\
を使って$
そのものを出力できる。
echo "\$foo"
コマンド置換
コマンド置換について
$(foo)
のようにコマンドを括弧で囲むことでコマンド実行結果を受け取れる。
バッククオートで囲む記法もあるが、開始と終了位置がわかりづらいのと、中でさらにコマンド置換する場合はバッククオートをエスケープする必要があって不便。
コマンドライン引数
シェルスクリプトではコマンドライン引数を、$1,$2...
で受け取れる。
$0
にはシェルスクリプト名が入る。
なお、コマンドライン引数に*
のワイルドカードを使用すると、カレントディレクトリのファイルが展開されてシェルスクリプトに渡る。
引数の個数は、$#
で参照可能。