Basic Linux Commands - uchan-nos/os-from-zero GitHub Wiki

MikanOS を実験する際に必要となる基礎的な Linux コマンド、およびその周辺知識について、手短に説明します。

参考文献

さらに詳しく知りたい方のために、参考になりそうな文献をいくつか紹介します。 (uchan はこれらを読んだことがありません。ごめんなさい。)

目次

ls

ディレクトリ内のファイルを一覧するためのコマンドです。 一覧の英語「list」を省略したコマンド名だと思うと覚えやすいでしょうか。

ホームディレクトリで ls と打てば、次のような表示になるでしょう。

$ ls
edk2  osbook  workspace

先頭の $ は入力しませんよ。この $ はプロンプトといって、「ユーザからの入力を待っています」ということを、システム側からユーザへ伝えるための印です。

ls は引数でリストを表示したいディレクトリを指定できます。試しに workspace の中を一覧してみましょう。

$ ls workspace
mikanos

こんな感じに、中に入ってるファイルやディレクトリが表示されれば成功です。

ls はファイルやディレクトリの存在確認でも使います。存在しないファイルやディレクトリを指定するとエラーが表示されることを利用します。

$ ls workroom
ls: cannot access 'workroom': No such file or directory

ls に存在しないパス名を指定すると、このように「cannot access 'パス名'」のような表示がでます。

pwd と cd

pwd は自分の現在地を確認するコマンド、cd は現在地を変更するコマンドです。 それぞれ「Print Working Directory」「Change Directory」の頭文字からなる名前ですね。

「現在地」という概念に初めて触れる方もいるでしょう。GUI での作業では登場しない、CUI 特有の概念です。 英語では「current directory」とか「working directory」などと呼びます。 Linux のシェル上の作業の起点となるディレクトリのことです。

ls コマンドの引数で指定した「workspace」や「workroom」は、実はこの「現在地」を起点とした相対パスだったのです。

pwd で現在地を確認します。

$ pwd
/home/uchan

シェル(ターミナル)を立ち上げた直後はホームディレクトリが「現在地」になっています。 私は Linux のユーザ名として「uchan」を使っているので、上記のように「/home/uchan」と表示されます。

先頭が「/」から始まるパスは「絶対パス」です。 Linux では、すべてのファイルとディレクトリは唯一のディレクトリ「ルートディレクトリ」に属することになっています。 ルートディレクトリは唯一の存在なので名前がありません。 強いて言えば、先頭の「/」がルートディレクトリの名前のようなものです。

/home/uchan は、ルートディレクトリに含まれる home という名のディレクトリに含まれる uchan というディレクトリ、を表します。

ここでクイズです。先ほど ls workspace というコマンドを実行しましたが、これで表示される workspace というディレクトリの絶対パスを答えてください。

答え: /home/uchan/workspace

cd は現在地を変更します。

$ cd workspace

このコマンドを実行すると現在地が /home/uchan/workspace に変更されます。 ls の実行結果が変わることが分かります。

$ ls
mikanos
$ ls workspace
ls: cannot access 'workspace': No such file or directory

先ほどは成功した ls workspace ですが、今回は失敗しています。 なぜなら、現在地を変更したため、ls workspace は /home/uchan/workspace/workspace のファイル一覧を表示しようとしたからです。 もちろんそんなディレクトリは存在しませんので、エラーになったのですね。

ln

ln コマンドはシンボリックリンクを作成します。

シンボリックリンクとは何かというと、Windows でいうショートカットみたいなもので、他のファイルやディレクトリを指し示す特殊なファイルです。 全く別のところにあるファイルやディレクトリを、あたかもその場所にあるかのように見せかけることができます。

本書では $HOME/workspace/mikanos/MikanLoaderPkg を $HOME/edk2/MikanLoaderPkg としてアクセスできるようにするためにシンボリックリンクを作ります。

$ cd $HOME/edk2
$ ln -s $HOME/workspace/mikanos/MikanLoaderPkg ./

これで $HOME/workspace/mikanos/MikanLoaderPkg を指すリンクが $HOME/edk2 の中に作られます。

ln に指定した -s が「シンボリック」なリンクを作るための指定です。 「ハードリンク」という種類のリンクもあるのですが、シンボリックリンクの方が仕組みが分かりやすいのでそっちを採用しています。

ln には 2 つのパス、リンク先とリンク元を指定します。 リンク元に指定した「./」は「現在地」を意味する相対パスです。

作成されたリンクを確認するには ls -l というコマンドを使います。試しに $HOME/edk2 ディレクトリで実行してみてください。

$ ls -l
《中略》
lrwxrwxrwx 1 uchan uchan 44 Jun 12 23:56 MikanLoaderPkg -> /home/uchan/workspace/mikanos/MikanLoaderPkg
《中略》

このように「リンク元の名前 -> リンク先のパス」という形でリンクが表示されます。

Ubuntu の初期設定では、正しくシンボリックリンクを作成できていれば「リンク元の名前」が水色で、「リンク先のパス」が青で表示されるはずです。 リンク先のパスの綴りを間違えたりすると赤く表示されるため、間違いに気付くことができます。

ln コマンドは同じ名前のシンボリックリンクを作成しようとするとエラーになります。 「パス名を間違えていたので直したいな」と思ってコマンドを実行しても、次のような表示になってしまいます。

$ ln -s /どこか他のディレクトリ/MikanLoaderPkg ./
ln: failed to create symbolic link './MikanLoaderPkg': File exists

./MikanLoaderPkg は更新されず、「古いリンク先」を指したままです。 これを解決するためには ln-f オプションを指定するか、rm コマンドでリンクを削除してから、改めてリンクを作ります。

rm

rm コマンドはファイルやディレクトリを削除します。 ln コマンドで作成したシンボリックリンクが誤っている場合の修正にも使えます。

$ rm MikanLoaderPkg

このようにすると、現在地にある MikanLoaderPkg というファイルを削除できます。 削除対象(MikanLoaderPkg)がシンボリックリンクの場合、リンク元が削除されるだけで、リンク先のファイルには一切影響を与えません。

もちろん絶対パスを指定して削除することも可能です。

$ rm /home/uchan/edk2/MikanLoaderPkg

このようにすると、現在地に依存することなく /home/uchan/edk2/MikanLoaderPkg というファイルを削除できます。

rm でディレクトリを削除するには -r オプションを指定します。

$ cd $HOME/workspace
$ rm -r mikanos

これを実行すると mikanos と、その中にあるすべてのファイルとディレクトリが削除されます。

変数

何気なく $HOME という記述を使っていますが、これは何でしょうか。

Linux のシェルでは「$」から始まる文字列は「変数名」です。変数は中に値が設定されていて、その値がその場所に展開されます。

$ ls $HOME/workspace

であれば $HOME の部分に変数の値が展開された後で ls コマンドが実行されます。 つまり、次のように指定したのと同じことです。

$ ls /home/uchan/workspace

ただ、ユーザ名は皆さん違うため、本書に /home/uchan/workspace と埋め込んでしまうと uchan さんだけが実行できる手順になってしまいます。 また、/home/uchan は単純に長ったらしいですよね。 そこで $HOME 変数を使うことで、記述が短くなり、汎用性も上がります。

プロンプトも「$」ですが、これは変数とは無関係です。 細かい説明になりますが、この「$」は現在のモードが「一般ユーザのモード」であることを示します。 「root ユーザのモード」の場合にはプロンプトが「#」に切り替わり、特別なモードであることが分かるようになっています。

echo

echo コマンドは引数を表示するコマンドです。何が嬉しいか分からないかもしれませんが、変数の値を確認するのに便利です。

$ echo $USER
uchan

$USER という変数の値を表示してみました。 Linux を操作しているユーザの名前が表示されます。

変数を含んだコマンドを実行する前に echo で確認する癖を付けると、事故を防げるようになります。

$ echo ln -s $HOME/workspace/mikanos/MikanLoaderPkg ./
ln -s /home/uchan/workspace/mikanos/MikanLoaderPkg ./

このように、変数を展開した状態の「本当に実行されるコマンド」を表示することができます。 変数が意図した値に展開されているかなどを確認してください。

mv

mv コマンドはファイルやディレクトリを移動します。移動を表す英単語 Move の略ですね。

$ mv src dest

という文法で、src で指定したファイルを dest に移動します。 もちろん、src と dest には相対パスでも絶対パスでも指定できます。

例えば、mikanos ディレクトリを間違った場所に作ってしまった後、希望する場所に移動することを考えます。 $HOME/edk2/mikanos に作ってしまったけど、本来は $HOME/workspace/mikanos に作りたかった場合、次のコマンドを実行すれば OK です。

$ cd $HOME/edk2
$ mv mikanos $HOME/workspace/

ファイルやディレクトリを移動できるということは、名前を変えるのにも利用できるということです。 同じディレクトリ内で「移動」すればいいわけですからね。

. と ..

絶対パスと相対パスの概念は pwd と cd で登場しました。 絶対パスはルートディレクトリからのパス、相対パスは現在地からのパスのことでしたね。

相対パスで良く使う特殊な名前として「.」と「..」があります。 「.」は現在地を表す名前、「..」は「1 つ上のディレクトリ」を表す名前です。

例えば、$HOME/edk2/mikanos を $HOME/workspace/mikanos に移動(mv)したい場合、次のように書くことができます。

$ cd $HOME/edk2
$ mv ./mikanos ../workspace/

移動元 ./mikanos を詳しく見てみます。「.」は現在のディレクトリ $HOME/edk2 を表します。したがって ./mikanos は $HOME/edk2/mikanos を表すのです。

移動先 ../workspace/ も詳しく見てみます。「..」は 1 つ上のディレクトリ、つまり $HOME を表します。したがって ../workspace は $HOME/workspace を表します。

mv の最後の「/」

mv ./mikanos ../workspace/ というコマンドにおいて、最後の「/」は書いても書かなくても関係ありません。 mv コマンドは、移動先が実在して、それがディレクトリだということが分かると、その中にファイルを移動してくれます。 つまり $HOME/edk2/mikanos/README.md というファイルは $HOME/workspace/mikanos/README.md に移動されることになります。

ただし、$HOME 直下に workspace というディレクトリが存在しない場合、事情が変わってきます。

$HOME/workspace というディレクトリが無い状態で mv ./mikanos ../workspace/ を実行すると、mikanos ディレクトリが workspace という名前に変更されてしまいます。 結果として $HOME/workspace/README.md というファイル配置になります。

コマンドの成否

Linux のコマンドは、成功した場合は大抵静かに成功します。「成功しました」のようなメッセージは表示されません。 慣れないうちは、本当に成功したのか、あるいは失敗しているのか、区別が付かないこともあるでしょう。

実は簡単な方法で、コマンドの成否を知ることができます。それは echo $? です。

$ ls workroom
ls: cannot access 'workroom': No such file or directory
$ echo $?
2

echo $? とすると、直前に実行したコマンドの成否を確認できます。0 なら成功、0 以外の値なら何らかのエラーが発生していると判断できます。 上記の例では存在しないディレクトリを ls しようとして、エラーになりました。 echo $? の表示は「2」となっていて、コマンドが失敗したことが分かりますね。

$ ls workspace
mikanos
$ echo $?
0

コマンドが成功すると、このように「0」と表示されます。

ちなみに echo が成否を表示するためのコマンドというわけではなく、$? という変数にコマンドの成否が格納されていて、それを echo で表示しているというだけです。 $? は特殊な変数で、Linux のシェルがコマンドを実行するたびに自動的に値を更新してくれます。

echo $? を連続で実行すると、2 回目からは $? の値は「直前の echo $? の成否」で上書きされることに注意してください。

$ ls workroom
ls: cannot access 'workroom': No such file or directory
$ echo $?
2
$ echo $?
0

$? の値はどんどん更新されていきますから、ls workroom の成否を確認するためには「そのコマンドの直後、たった 1 回」しかチャンスがありません。