MS-DOSユーザー（笑）のためのLinuxメモ

# 設計思想
LinuxはC言語と同じ思想で作られている。

C言語は「プログラマは間違わない」という思想で作られている。なので万一間違ったプログラムを作成してしまうと、そのプログラムは容赦なく暴走する。ご指示通りに動作いたしました、というわけである。

Linuxも「オペレーターは間違わない」という思想で作られている。つまり間違うと取り返しのつかないことが多いので注意。例えば、cpコマンドでコピーした先に、すでに同じ名前のファイルがあっても、容赦なく上書きする。無言で上書きする。「オペレーターは間違わない」のだから、最初から上書きしたかったのですよね？というわけである。

# 大文字小文字の区別
大文字小文字は区別される。つまりlsとLSは別である。

MS-DOSではコマンドに使われる文字は大文字でも小文字でも良かった。dirでもDIRでもDirでもdIrでも動作は同じだった。Linuxでは区別されるので注意。

# パスの区切り文字
ファイルパスの区切り文字はMS-DOSで使われていた「\」ではなく「/」なので注意。
むしろ元祖はUNIXの「/」で、それを模したLinuxの方がMS-DOSより元祖ではある。ちなみにコマンドのオプションの指定にLinuxでは「-」を使うが、MS-DOSでは「/」を使う。すでにオプションの指定に「/」が使われていたMS-DOSでは、パスの区切り文字として「/」ではなく「\」が使われることとなった。そのあたりのいきさつは以下のページが詳しい。
https://ascii.jp/elem/000/001/763/1763591/

# pwd
print work directryの略で、カレントディレクトリを表示する。
MS-DOSではcdとだけ入力するとカレントディレクトリを表示したが、Linuxではcdとだけ入力すると別の意味になるので注意。（後述）

# cd
ホームディレクトリに移動するには
~~~bash
$ cd
~~~

ホームディレクトリ配下のworkディレクトリに移動するには（これをチルダ展開と呼ぶ）
~~~bash
$ cd ~/work
~~~

３つ上のディレクトリに移動するには
~~~bash
$ cd ../../..
~~~

ちなみにMS-DOSでは、cd..と間にスペースを空けずに..が書けたがLinuxではエラーとなる。私はいまだにときどき癖で「cd..」と打ってしまって「コマンドが見つかりません」というエラーが表示されてしまう。

-Pオプション
シンボリックリンクの実態の方に移動する。
↓こういうこと。
~~~bash
$ cd -P /bin
$ pwd
/usr/bin
~~~

# ls
ls -lをalias設定したllコマンドの方を頻繁に使ってしまうが、以下のオプションは使用頻度が高いので覚えておく
-l	詳細表示
-a	隠しファイルも表示
-F	ファイル種別を表示（/:ディレクトリ、*:実行可能ファイル、@:シンボリックリンク、なし:通常ファイル）
-1	縦に並べて表示（これはおまけ）

# パス名展開
パス名展開の結果だけを知りたい場合は、echoコマンドを使うと良い。
例: echo *.html

コマンドの引数はパス名展開された後にコマンドへ渡される、というイメージを持っておくとコマンドの書き方を理解しやすい。
~~~bash
$ cp file1 file2 file3 dir1
~~~

上記のコマンドの意味は、例えば、こう書いたのと同じ。
~~~bash
$ cp file? dir1
~~~

つまり、file1とfile2とfile3を、dir1ディレクトリへコピーするということ。
パス名展開する前の方が動作をイメージしやすいということになってしまうが。

# mkdir
深い階層のディレクトリを一気に作成するには-pオプションを使う。
-pは、--parentsの略で、必要に応じて親ディレクトリを作成するという意味。

~~~bash
$ mkdir -p ~/work/report/sample
~~~

なお、MS-DOSでは存在した「md」という「mkdir」の省略形はない。

# touch
空のファイルを作成するのによく利用する。
ファイルがなければ作成し、ファイルがあればタイムスタンプを更新する。
上書きされたり削除されたりしないので安全。

~~~bash
$ touch file1 file2 file3
~~~

# cat
conCATenate（連結する）の略。指定したファイルを連結して標準出力へ出力する。
結果としてMS-DOSのtypeコマンドと同じような動作となる。

~~~bash
$ cat file1
~~~

ファイルを指定しないと、標準入力からの入力を標準出力へ出力する、ということになる。
この際のコマンドの終了方法はCtrl+d

~~~bash
$ cat
abcd
abcd
^d
~~~

# rm
removeの略。ファイルの削除だけでなくディレクトリの削除も可能。
ディレクトリの削除の際には-rオプションを使う。
-rは、--recursiveの略で「ディレクトリとその中身を再帰的に削除する」という意味。

~~~bash
$ rm -r dir1
~~~

上記はそのディレクトリ配下に何があろうとも容赦なく削除するので非常に危険なコマンド。使用する際はディレクトリの中身をよく確認すること。特にWindowsのような「ごみ箱」なるものはないので、間違って削除してしまったら取り返しがつかない。

# rmdir
空のディレクトリを削除する。空ではないディレクトリを削除しようとするとエラーとなる。
ディレクトリの削除をする際は面倒でもrmdirを使うのが安全。

~~~bash
$ rmdir dir1
~~~

# less
ファイルの中身を確認するためにページャーを起動する。
メモリの消費は非常に少ない。ファイルを更新しないので安全。

~~~bash
$ less /etc/bashrc
~~~

起動後の操作は以下
q:終了
j:1行下へスクロール
k:1行上へスクロール
d:半画面下へスクロール
u:半画面上へスクロール
g:ファイルの先頭へ
G:ファイルの末尾へ
/:指定の文字列を下方向へ検索
?:指定の文字列を上方向へ検索
n:次の検索結果に移動
N:前の検索結果に移動
&:指定の文字列がある行のみ表示（&のみの入力で解除）
-N:行番号表示
-n:行番号非表示

# cp
MS-DOSで言うところのcopyコマンド。ただしMS-DOSで言うところのxcopyの機能も持ち、ディレクトリのコピーもできる。その際は-rオプションを使う。-rは--recursiveの略で「再帰的にディレクトリをコピーする」という意味。

~~~bash
$ cp -r dir1 dir2
~~~

# mv
ファイルを移動するコマンドだが、ファイル名の変更にも使える。

~~~bash
$ mv file1 file2
~~~

移動元にディレクトリを指定すると、ディレクトリの移動となる。
cpコマンドと違って-rオプションは必要ない。

~~~bash
$ mv dir1 dir2
~~~

# ln
リンクにはハードリンクとシンボリックリンクがあるが、ハードリンクはリンク先もリンク元も「どちらも本物」というややこしい状況になるので普通は使わない。シンボリックリンクの方が良く使われる。シンボリックリンクの使い方はWindowsのショートカットリンクと同様と思っておいて良い。lnコマンドに-sオプションを付けると、シンボリックリンクを作成できる。
後ろの引数がシンボリックリンクの名前になることに注意。

~~~bash
$ ln -s file1 filelink
~~~

# find
検索対象にワイルドカードを使いたい場合は検索文字列をシングルクォートかダブルクオートで囲む。そうしないとパス名展開になって、引数の数が合わなくなってしまう。

~~~bash
$ find . -name '*.txt' -print
~~~

# locate
ファイル検索コマンド。動作結果はすべてのディレクトリに対してlsして、指定の文字列をgrepしていくイメージ。初期状態ではlocateコマンドはインストールされていないようで、最初にインストールする必要がある。RHEL8なら
~~~bash
$ sudo yum install mlocate
~~~

さらに検索用のデータベースを更新する必要がある。
~~~bash
$ sudo updatedb
~~~

# which
サーチパス（環境変数$PATHに設定されたパス）からコマンドを検索してそのフルパスを表示する。aliasに設定しているコマンドも表示してくれる。

~~~bash
$ which ll
alias ll='ls -l --color=auto'
        /usr/bin/ls
~~~

# vim
忘れがちなカーソル移動コマンド
w: 次の単語の先頭へ
b: 前の単語の先頭へ
0: 行頭へ
$: 行末へ
数G: 数行目へ

Vimでは「コピー＆ペースト」を「ヤンク＆プット」と呼ぶ。なのでコピペはヤンプ（嘘）「カット＆ペースト」は「デリート＆プット」と呼ぶ。デリートやヤンクのコマンドは、よく見るとカーソル移動のコマンドと意味が連動していることがわかる。

d$: カーソル位置から行末までデリート
d0: カーソル位置から行頭までデリート
dl: カーソル位置から1文字デリート（xでも同じ）
dw: カーソル位置から1単語デリート
dgg: カーソル位置からファイル先頭まで削除
dG: カーソル位置からファイル末尾まで削除

なお上記のコマンドは「d」を「y」に変えればそのままヤンクのコマンドとなる。貼り付けは「p」

J: 下の行と連結

なぜこんな変なコマンドが用意されているのかというと、行末の改行をxコマンドで削除できないから。やってみるとわかるが行末の改行は本当にxで消せない（笑）改行の上にカーソルが行かないから。改行の上にカーソルが移動できればいいだけの話ではないかと思ったが、まあその考えは浅はかなのだろう。

u: アンドゥ
Ctrl+r: リドゥ

慣れないと操作をしょっちゅう間違えるのでアンドゥは必須。リドゥのコマンドだけ、なぜかctrlが必要。

検索については、lessコマンドとまったく同じ。置換のコマンドは独特。「abc」を「ABC」に置き換えたいときは以下のコマンドとなる。

~~~
:%s/abc/ABC/g
~~~

「s」と末尾の「g」の意味は以下。

substitute	代わりの
global	広くすべて

以下が詳しい。
https://www.mybluelinux.com/sed-tutorial-how-replace-or-substitute-file-contents/#:~:text=SED%20Tutorial%20-%20how%20replace%20or%20substitute%20file,matching%20occurrences%20in%20the%20line%20would%20be%20replaced

:help
ヘルプを表示できる。ただし初期状態では英語。日本語化する方法は以下が詳しい。
https://qiita.com/shinshin86/items/eb41e4fb513bb4d3e3cd

ちなみに上記の手順はgitをインストールしていないとうまく行かないので注意。

# vimtutor
vimのチュートリアルを起動できる。
~~~bash
$ vimtutor
~~~

# type
コマンドのタイプを調べる。
~~~bash
$ type set
set はシェル組み込み関数です
$ type cp
cp は /usr/bin/cp です
~~~
このコマンドを初めて使った際に、MS-DOSユーザーだった私にとって、まったく予期しない結果が表示されて焦った記憶がある。ちなみにMS-DOSにおけるtypeコマンドはテキストファイルの中身を表示するコマンドで頻繁に使う。手癖になるほどだ。Linuxを使い始めてcatが手になじむまで時間を要した。

dirじゃないのかよ。
typeじゃないのかよ。
pwdってなんだよ。

思わずもらした上記の独り言は、MS-DOSユーザーだったらよくわかるはず。

# alias
エイリアスでないコマンドを実行したいときは先頭に「\」を付ける
例えば、typeコマンドでgrepのエイリアスを確認すると
~~~bash
$ type grep
grep は `grep --color=auto' のエイリアスです
~~~

これを、エイリアスではなく、元々のgrepを実行したい場合は以下のようにする
~~~bash
$ \grep abc sample.txt
~~~

# シェル変数
変数を設定する際「=」の左右にスペースを付けてはいけない。変数名をコマンドとみなしてしまうため。

~~~bash
$ var1='I have a dream.'
~~~

プログラミングに慣れていると、逆に「=」の前後にスペースを入れてしまいそうになるが、bashではそれはNG。

PS1というシェル変数はプロンプトの設定。以下は'[ユーザー名@ホスト名 カレントディレクトリ]$ 'となる設定。
~~~bash
$ PS1='[\u@\h \W]\$ '
~~~

# 環境変数
シェル自体に内蔵しているコマンドを組み込みコマンド、そうでないコマンドを外部コマンドと呼ぶ。
~~~bash
$ type set
set はシェル組み込み関数です
$ type cp
cp は /usr/bin/cp です
~~~
外部コマンドはシェルの外側で実行されるため、シェル変数の値を参照することができない。外部コマンドからも値を参照できるようにした変数を環境変数と呼ぶ。

# printenv
シェルに設定されている環境変数を表示する
~~~bash
$ printenv
SHELL=/bin/bash
HISTCONTROL=ignoredups
HISTSIZE=1000
...
~~~

echoの代わりに環境変数の値を表示することもできる。その際、変数名の先頭に付ける「$」は不要。
~~~bash
$ printenv PATH
/home/ec2-user/.local/bin:/home/ec2-user/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
$ echo $PATH
/home/ec2-user/.local/bin:/home/ec2-user/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
~~~

# export
指定したシェル変数を環境変数にする
~~~bash
$ LESS='--no-init'
$ export LESS
~~~
宣言と値の設定をまとめて書くのが一般的。
~~~bash
$ export LESS='--no-init'
~~~

# bashの設定ファイル
~/.bashrc に書く。
bashrcの「rc」とは、「run commands」の略。以下が詳しい。
https://www.oresamalabo.net/entry/2020/05/02/235959

# ファイルのパーミッション
~~~bash
$ ls -l /bin/cat
-rwxr-xr-x. 1 root root 36320  1月  6  2023 /bin/cat
~~~

上記の結果を見て、以下を瞬時に読み取れなければならない。
+ /bin/catのファイルの所有者は？
root

+ ファイルが所属するグループは？
root

+ ファイルの種類は？
実行可能ファイル

+ ファイルの所有者（rootユーザー）の権限は？
読み取り、書き込み、実行が可能。

+ ファイルの所属グループ（rootグループ）のユーザーの権限は？
読み取り、実行が可能だが、書き込みはできない。

+ ファイルの所属グループ（rootグループ）以外のユーザーの権限は？
読み取り、実行が可能だが、書き込みはできない。

# ディレクトリのパーミッション
ファイルの場合と違う意味になるので注意
r: ディレクトリに含まれるファイル一覧の取得
w: ディレクトリの下にあるファイル・ディレクトリの作成・削除
x: ディレクトリをカレントディレクトリにする

~~~bash
$ ls -dl /etc
drwxr-xr-x. 85 root root 8192 12月 16 12:06 /etc
~~~

（-dはディレクトリのみを表示するようにするオプション）
上記の結果を見て、以下を瞬時に読み取れなければならない。
+ /etcのファイルの種類は？
ディレクトリ

+ ディレクトリの所有者は？
root

+ ディレクトリの所属するグループは？
root

+ ディレクトリの所有者（rootユーザー）の権限は？
ファイルの一覧の取得、
ディレクトリの下にあるファイル・ディレクトリの作成・削除、
ディレクトリをカレントディレクトリにすることが可能。

+ ディレクトリの所属グループ（rootグループ）のユーザーの権限は？
ファイルの一覧の取得、
ディレクトリをカレントディレクトリにすることが可能だが、
ディレクトリの下にあるファイル・ディレクトリの作成・削除はできない。

+ ディレクトリの所属グループ（rootグループ）以外のユーザーの権限は？
ファイルの一覧の取得、
ディレクトリをカレントディレクトリにすることが可能だが、
ディレクトリの下にあるファイル・ディレクトリの作成・削除はできない。

※注意点
ファイルを削除できるかどうかは、そのファイルのパーミッションではなく、そのファイルが置かれているディレクトリのパーミッションで決まる。ファイルのパーミッションを「r--r--r--」に設定して読み取り専用としたつもりでも、そのファイルが置かれているディレクトリのパーミッションが「rwxrwxrwx」であれば、誰でもそのファイルを削除できる。

# chmod
+ シンボルモードの意味
u: 所有者(user)
g: グループ(group)
o: グループでないユーザ(others)
a: すべてのユーザ(all)、ugoのすべて

uが所有者(オーナー)で、oがその他のユーザーというのが非常に紛らわしい。
dir1ディレクトリに対して、すべてのユーザーがファイル作成・削除をできるようにしたい場合、以下のように指定する。

~~~bash
$ chmod a+w ./dir1
~~~

+ 数値モードのパーミッション
3桁の8進数で表す。つまり重みは「421 421 421」例えば「r-x r-- r--」であれば「544」

覚えておいた方が良い数値モードの値
+ 755 (rwxr-xr-x)
他のユーザーに見られても良い実行可能ファイルのパーミッション。他のユーザーに見られても良いディレクトリもこれにあたる。

~~~bash
$ chmod 755 dir1
$ ls -ld dir1
drwxr-xr-x. 3 ec2-user ec2-user 30 12月 14 23:31 dir1
~~~

+ 644 (rw-r--r--)
他のユーザーに見られても良い通常ファイルのパーミッション

~~~bash
$ chmod 644 file1
$ ls -l file1
-rw-r--r--. 1 ec2-user ec2-user 0 12月 14 23:14 file1
~~~

# su -
su だけだと、環境変数やカレントディレクトリを現在の環境を維持したままユーザーだけが切り替わる。su - で切り替えると、スーパーユーザーの環境に初期化されて切り替わる。アプリケーションによってはうまく動作しない場合があるため、通常はsu - で切り替えた方が良い。

~~~bash
$ sudo su -
~~~

# sudo
スーパーユーザー権限でコマンドを実行したい場合、通常はsodoを使用する。su -は、exitするまでスーパーユーザーのままなので、安全上なるべく使わない。

# プロセス
メモリ上で実行状態にあるプログラムのことをプロセスと呼ぶ。

# ps
現在動作しているプロセスを表示する。

~~~bash
$ ps
    PID TTY          TIME CMD
   5068 pts/0    00:00:00 bash
   5188 pts/0    00:00:00 ps
~~~

xオプションで、現在のユーザーのプロセスをすべて表示
fオプションで、親子関係を表示

~~~bash
$ ps xf
    PID TTY      STAT   TIME COMMAND
   5067 ?        S      0:00 sshd: ec2-user@pts/0
   5068 pts/0    Ss     0:00  \_ -bash
   5189 pts/0    R+     0:00      \_ ps xf
   5056 ?        Ss     0:00 /usr/lib/systemd/systemd --user
   5060 ?        S      0:00  \_ (sd-pam)
~~~

なおpsコマンドには、UNIXオプションとBSDオプションとがあり、UNIXオプションにはハイフンを付けるが、BSDオプションにはハイフンを付けない。xfはBSDオプションである。

# ジョブ
シェルから見た処理の単位。プロセスはLinuxカーネルから見た処理の単位で、コマンドごとに生成される。ジョブはコマンドライン全体でひとつ。3つのコマンドをパイプでつないだ以下のコマンドライン入力では、プロセスは３つ、ジョブはひとつとなる。

~~~bash
$ ls -l / | cat -n | less
~~~

# ジョブの切り替え操作
viでファイルを編集しつつ、lsでファイルを確認したり、manでマニュアルを確認したり、またviに戻ったりと、まるでウィンドウを切り替えるかのように操作ができる。

+ ctrl+zでジョブを停止してコマンド入力画面へ
+ jobsコマンドで、現在のジョブの一覧を表示（[]内はジョブ番号で、+マークはカレントジョブ）
~~~bash
$ jobs
[1]+  停止                  man bash
[2]-  停止                  vim ~/.bashrc
~~~

+ fgコマンドで、ジョブをフォアグランドにする。
~~~bash
$ fg %1
~~~

+ 再度ジョブを切り替えたいときは、ctrl+zでジョブを停止

# bg
ctrl+zでジョブを停止させると、そのジョブは動作が止まってしまう。

~~~bash
$ sleep 60
^Z
[1]+  停止                  sleep 60
~~~

bgコマンドで、そのジョブをバックグラウンドで動作させることができる。

~~~bash
$ bg %1
[1]+ sleep 60 &
$ jobs
[1]+  実行中               sleep 60 &
~~~

コマンドの末尾に&を付ければ、最初からバックグラウンドで実行される。
その時、ジョブ番号とプロセスIDが表示される。

~~~bash
$ sleep 60 &
[1] 5594
~~~

# ジョブの終了
+ ctrl+c
フォアグランドのジョブの終了
+ kill %ジョブ番号
バックグラウンドのジョブの終了

# プロセスの終了
+ kill プロセスID

kill -lでkillコマンドのシグナルが確認できる。
~~~bash
$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX
~~~

停止のシグナルは　20) SIGTSTP
ジョブ番号=5のジョブを停止するには以下のkillコマンドとなる。
~~~bash
$ kill -20 %5
~~~

sleepコマンドを複数実行して、ps、jobs、ctrl+z、ctrl+c、killを活用して、ジョブの起動、プロセスの起動、ジョブの一覧、プロセスの一覧、ジョブの再開、プロセスの再開、ジョブの終了、プロセスの終了、をエクササイズしてみると良い。アプリケーションがバックグラウンドで起動させたプロセスにはジョブ番号は付かないので、プロセスIDでの操作も慣れておくと良い。

※プロセス管理は運用では極めて重要。基礎知識と操作に慣れておくこと。