#ライセンスとクレジット
クレジット
https://missing.csail.mit.edu/2020/course-shell/
ライセンス
https://creativecommons.org/licenses/by-nc-sa/4.0/
講義動画
https://youtu.be/Z56Jmr9Z34Q
Todo
途中からインラインコードの記述に変更したため修正が必要
(はじめに)
エンジニアとして,情報系の学生として学習するときにはじめに教えられるのはプログラムやアルゴリズムだと思います.
しかし,そのプログラムを動かすための環境構築やバグの修正,他の問題にある程度を時間をかけることになります.
ここで紹介しているMITの講座は,より効率よく作業するためのエッセンスが説明されています.
これらは,基本的に知っていて当たり前や,学習しながら問題に直面した時に知るような”小技”のような扱いですが,とても重要だと思っています.
先に知っておくだけでも大きく成長に差が出るはずです.
私は,研究室のゼミで新しく入ってくるメンバーに説明するためのスライド資料をこの講座を利用して作成しよう考えました.
そのときに作成した翻訳やメモを公開しようと思います.
ライセンスはすべてMITのもの準拠します.
追記の部分はメモなどで記します.翻訳間違いなどがあれば,指摘していただけると助かります.
#モチベーション
コンピュータ科学者である私たちは,コンピュータが反復的なタスクを支援するのに優れていることを知っている。
しかし、プログラムに実行させる計算と同じように、コンピュータの使用にも当てはまることを忘れている。
私たちは、コンピュータ関連の問題に取り組む際に、より生産性を高め、より複雑な問題を解決することができる膨大な種類のツールを手元で利用することができる。
しかし、私たちの多くはこれらのツールのごく一部を利用しているに過ぎません。
このクラスはこの問題を解決するための試みです。
私たちは、あなたが知っているツールを最大限に活用する方法を教え、あなたのツールボックスに追加する新しいツールをお見せし、うまくいけば、あなた自身でもっと多くのツールを探究する(そしておそらくは構築する)ことへのワクワク感を植え付けたいと思っています。
これは、我々はほとんどのコンピュータサイエンスのカリキュラムから欠落している学期であると信じているものです。
次の項,「Class Structure」は省略しています.
#Topic 1 シェル(Shell)
##シェルとは何か
最近のコンピュータには、コマンドを与えるための様々なインターフェースがある.
架空のグラフィカル・ユーザー・インターフェース、ボイス・インターフェース、さらにはAR/VRまでもインターフェースとしてある.
コンピュータが提供するツールを最大限に活用するためには、昔ながらの方法で、テキストインターフェイスに移行しなければならない.
あなたが手を入れることができるほぼすべてのプラットフォームには、1 つの形または別の形でシェルがあるため,選択するためにいくつかのシェルを持っている.
講義では、Bourne Again Shell、略して「bash」に焦点を当てる.
これは最も広く使われているシェルの一つで、その構文は他の多くのシェルで見られるものと似ています。シェルプロンプト(コマンドを入力することができる)を開くには、最初にターミナルが必要.
お使いのデバイスにはおそらくターミナルがインストールされているか、かなり簡単にインストールすることができる.
メモ
ターミナル「黒い画面のやつです」
##シェルを使ってみる
ターミナルを起動すると,このようなプロンプトが表示される.
missing:~$
これはシェルへのメインテキストインターフェースです.
プロンプトの意味は
- あなたがマシン上にいないこと
- あなたの現在の作業ディレクトリ"current working directory"上にいること
- 現在いるディレクトリが~(ホームディレクトリの略)であること
- $はrootユーザ出ないこと
上記の4つを示している.
プロンプトではコマンドを入力することができる.
最も基本的なコマンドはプログラムを実行すること.
missing:~$ date
Fri 10 Jan 2020 11:49:31 AM EST
missing:~$
ここでは,dataプログラムを実行して,現在の日付と時刻を表示している.
シェルはその後,別のコマンドを実行するか尋ねてくる.
また,引数を指定してコマンドを実行することも可能.
missing:~$ echo hello
hello
この例では,シェルに引数helloを指定してechoプログラムを実行するように命令した.
echoプログラムは単に引数を出力するプログラムです.
シェルはコマンドを空白で分割して解析,最初の単語で示されたプログラムを実行する.
もし,スペースや他の特殊文字を含む引数を提供したい場合
(例えば,ディレクトリの名前が"My Photos")
'や"で引数を囲んで引用する.または,関連する特殊文字だけをエスケープ文字''を使って,'My\ Photos'のようにスペースをエスケープすることで引用可能
しかし,シェルはどうやってdateやechoのプログラムを見つけるのか知っているのでしょうか?
シェルはPythonやRubyのようなプログラミング環境なので,変数や条件式,ループ,関数などがあります.(次の講義で紹介
シェルでコマンドを実行するとき,実際にはシェルが解釈するちょっとしたコードを書いていることになります.
もし,シェルがプログラミングのキーワードにマッチしないコマンドを実行するように要求された場合,シェルは'$PATH'と呼ばれる環境変数を参照して,コマンドが与えられたときにシェルがプログラムを変作するディレクトリをリストアップする.
missing:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
missing:~$ which echo
/bin/echo
missing:~$ /bin/echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
echoコマンドを実行すると
シェルはechoプログラムを実行すべきであると判断,'$PATH'にある':'で区切られたディレクトリのリストから,その名前のファイル(プログラム)を探します.
ファイルを見つけると,実行可能であれば実行する.
指定したプログラム名に対してどのファイルが実行されているかは,'which program'を使用して調べることができる.
また,実行したいファイルのパスをすることで$PATHを完全に回避することができる.
hogehoge@local:~$ which echo
/usr/bin/echo
echoプログラムのフォルダは'/usr/bin/echo'にあることがわかる.
##シェルでのナビゲーション
シェル上のパスは,ディレクトリ区切りのリスト.
LinuxとMacOSでは'/'で区切られ,windowsでは''で区切られている.
LinuxとMacでは,'/'はファイルシステムの"ルート(階層構造の根)",でありすべてのディレクトリとファイルはその下にある.
Windowsではディスクパーティションごとにルートがある(例, C:)
このクラスでは,一般的にLinuxファイルシステムを使用していると仮定している.
'/'で始まるパスは絶対パスと呼ばれる.
それ以外のパスは相対パスです.
相対パスは,現在の作業ディレクトリ(current working directories)からの相対パスで,pwdコマンドで確認でき,cdコマンドで変更できる.
パスの中で,'.'はカレントディレクトリを指し,'..'はその親ディレクトリを指します.
missing:~$ pwd
/home/missing
missing:~$ cd /home
missing:/home$ pwd
/home
missing:/home$ cd ..
missing:/$ pwd
/
missing:/$ cd ./home
missing:/home$ pwd
/home
missing:/home$ cd missing
missing:~$ pwd
/home/missing
missing:~$ ../../bin/echo hello
hello
メモ:
上記の例だとpwdコマンドはルートディレクトリで実行しています.はじめはユーザのhomeディレクトリ上にアクセスすることが多いです.
シェルプロンプトは,現在の作業ディレクトリが何であるかを知らせてくれることに注意してください.
プロンプトを設定することで,有用な情報をいくつか表示させることができます.これは後ほど説明します.
一般的に,プログラムを実行すると ,特に支持がない限り,カレントディレクトリで動作する.
例えば,プログラムは通常そこでファイルを検索して,必要に応じて新しいファイルを作成する.
指定されたディレクトリに何があるかを確認するには,lsコマンドを使用する.
missing:~$ ls
missing:~$ cd ..
missing:/home$ ls
missing
missing:/home$ cd ..
missing:/$ ls
bin
boot
dev
etc
home
...
ディレクトリが第一引数として与えられない限り, lsコマンドは現在のディレクトリの内容を表示する.
ほとんどのコマンドは,動作を変更するために'-'で始まるフラグオプション(値を持つフラグ)を受け入れる.
通常,'-h'または'--help'フラグを指定してプログラムを実行すると,どのようなフラグやオプションが利用可能かを示すヘルプテキストが表示される.
例えば,'ls --help'を実行すると,以下のように表示される.
-l use a long listing format
missing:~$ ls -l /home
drwxr-xr-x 1 missing users 4096 Jun 15 2019 missing
これにより,存在する各ファイルはディレクトリに関する多くの情報が得られる.
最初の行頭'd'はディレクトリがないことを示している.
そして,3つの文字の3つのグループ(rwx) は,ファイルの所有者(missing),所有グループ(users),および他のすべての人が,それぞれ関連する項目についてどのようなパーミッションを持っているか示している.
メモ:
パーミッションは権限です.別の講で説明すると思いますが
ユーザやグループごとにファイルやディレクトリの読み込み,書き込み,実行を制御することができます.
権限を設定するコマンドは'chmod'です.
下記で詳細説明します.
'-'は,与えられたプリンシパル(ユーザの総称?)が与えられたパーミッションを持っていないことを示す.
missing:~$ ls -l /home
drwxr-xr-x 1 missing users 4096 Jun 15 2019 missing
上記では,所有者のみが,ディレクトリを修正(w)すること(その中のファイルを追加/削除すること)が許可されている.
ディレクトリに入るためには,ユーザはそのディレクトリ(およびその親)に対して,"検索"(execute:xで表される)権限を持っていなければならない.
ディレクトリの内容を一覧表示するには,ユーザはそのディレクトリのread(r)パーミッションを持っていなければならない.
ファイルの場合,パーミッションは期待通りです.
(検索できるという意味合いのハズ)
missing:~$ ls -l /home
drwxr-xr-x 1 missing users 4096 Jun 15 2019 missing
最後のグループである"everyone else"のために"x"のパーミッションが設定されていることに注意してください.
そうすれば,誰でもこれらのプログラムを実行することができます.
この時点で知っておくと便利な他のプログラムとしては
- mv (ファイルの名前を変更したり移動したりする)
- cp (ファイルをコピーする)
- mkdir (新しいディレクトリを作成する)
プログラムの引数,入力,出力,あるいは一般的にどのように動作するかについて,より多くの情報が必要な場合は,manコマンドを試してみてください.
manコマンドは引数として,コマンドの名前を受け取り,そのマニュアルページを表示する.
qを押して終了します.
missing:~$ man ls
LS(1) BSD General Commands Manual LS(1)
NAME
ls -- list directory contents
SYNOPSIS
ls [-ABCFGHLOPRSTUW@abcdefghiklmnopqrstuwx1%] [file ...]
DESCRIPTION
For each operand that names a file of a type other than directory, ls displays its name as well as any requested, associated information. For each operand that names a file of
type directory, ls displays the names of files contained within that directory, as well as any requested, associated information.
If no operands are given, the contents of the current directory are displayed. If more than one operand is given, non-directory operands are displayed first; directory and non-
directory operands are sorted separately and in lexicographical order.
The following options are available:
-@ Display extended attribute keys and sizes in long (-l) output.
-1 (The numeric digit ``one''.) Force output to be one entry per line. This is the default when output is not to a terminal.
-A List all entries except for . and ... Always set for the super-user.
-a Include directory entries whose names begin with a dot (.).
-B Force printing of non-printable characters (as defined by ctype(3) and current locale settings) in file names as \xxx, where xxx is the numeric value of the character in
octal.
ー 省略 ー
##プログラムの接続
シェルでは,プログラムに入力ストリームと出力ストリームという2つの主要な「ストリーム」が関連付けられる.
プログラムは入力を読み込もうとするときは,入力ストリームから読み込まれ,何かを表示するときは出力ストリームから表示する.
通常,プログラムの入力と出力は両方ともあなたの端末です.
つまり,キーボードが入力,画面が出力です.
しかし,これらのストリームをリダイレクトすることが可能です.
最も簡単なリダイレクトの形式は< file
とfile >
です.
これらを使うと,プログラムの入力と出力のストリームをそれぞれファイルにリダイレクトすることができる.
missing:~$ echo hello > hello.txt
missing:~$ cat hello.txt
hello
missing:~$ cat < hello.txt
hello
missing:~$ cat < hello.txt > hello2.txt
missing:~$ cat hello2.txt
hello
また,>>
を使ってファイルを追加することもできる.
この種の入出力リダイレクションが最も優れているのは,パイプを使うことです.
|
(パイプ)を使うと,あるプログラムの出力が別のプログラムの入力になるようにプログラムを「連鎖」させることができる.
missing:~$ ls -l / | tail -n1
drwxr-xr-x 1 root root 4096 Jun 20 2019 var
missing:~$ curl --head --silent google.com | grep --ignore-case content-length | cut --delimiter=' ' -f2
219
パイプの活用方法については,別の講義で詳しく説明します.
##汎用性の高い強力なツール
ほとんどのUnixライクなシステムでは,"root"ユーザと呼ばれる,1人のユーザが特別な存在です.
rootユーザは(ほとんどの場合)すべてのアクセス制限の上にいて,システム内のあらゆるファイルの作成,読み込み,更新,削除ができます.
誤って何かを壊してしまうのは簡単なので,通常はrootユーザとしてシステムにログインすることはありません.
その代わり,sudo
コマンドを使用します.
その名の通り,何かをsu
のようにdo(行う)
ことができます.
(略して”スーパーユーザ”または"root"です)
あなたが権限拒否(permission denied error)のエラーを取得するとき,あなたがrootとしてなにかを行う必要があるためです.
しかし,あなたが本当にそのようにしたいと思ったことをダブルチェックすることを意識してください.
rootである必要があることの1つは,/sys
の下にマウントされているsysfs
ファイルシステムに書き込むこと.
sysfs
は多くのカーネルパラメータをファイルとして公開しているので,特別なツールを使わなくてもカーネルをその場でかんたんに再設定できます.
WindowsやmacOSにはsysfsが存在しないことに注意してください.
例えば,ラップトップの画面の明るさは
/sys/class/backlight
そのファイルに値を書き込むことで,画面の明るさを変更することができる.
$ sudo find -L /sys/class/backlight -maxdepth 2 -name '*brightness*'
/sys/class/backlight/thinkpad_screen/brightness
$ cd /sys/class/backlight/thinkpad_screen
$ sudo echo 3 > brightness
An error occurred while redirecting file 'brightness'
open: Permission denied
このエラーは意外と出てくるかもしれません.
結局,コマンドを実行したのはsudo
これはシェルについて知っておくべき重要なことです.
|,>,<
のような操作は,個々のプログラムではなく,シェルによって行われる.
echo
やその仲間たちは|
について「知っている」わけではありません.
彼らは,入力から読み込んで出力に書き込んでいるだけです.
上の例では,シェル(ユーザとして認証されている)は,sudo echo
の出力として設定する前に,書き込み用の明るさファイルを開ことしていますが,シェルはrootで実行していないため,それができません.
この知識を利用して,これを回避することができます.
$ echo 3 | sudo tee brightness
tee
プログラムは/sys
ファイルを開いて書き込みを行うものであり,root
として実行されるので,パーミッションはすべてうまく行きます.
様々なシステムLEDの状態など,/sys
を通して様々な楽しいことや便利なことを制御することができます.
(あなたのパスは異なるかもしれない)
$ echo 1 | sudo tee /sys/class/leds/input6::scrolllock/brightness
##次のステップ
この時点では,基本的なタスクを達成するのに十分なシェルの使い方を知っています.
これで,興味のあるファイルを見つけたり,ほとんどのプログラムの基本的な機能を使うことができるようになるはずです.
次の講義では,シェルを使ってより複雑なタスクを実行したり自動化したりする方法や,便利なコマンドラインプログラムについてお話します.
##演習
-
このコースでは,BashやZSHなどのUnixシェルを使用する必要があります.LinuxやmacOSを使用している場合は,特別なことをする必要はありません.Windowsの場合,cmd.exeやpowerShellを実行していないことを確認する必要があります.Windows Subsystem for Linux(WSL)やLinux仮想マシンを使用して,Unixスタイルのコマンドラインツールを使用することができます.
適切なシェルを実行していることを確認するには,echo $SHELL
コマンドを実行してください.もし/bin/bash
や/usr/bin/zsh
のようなものが表示されたら,それは正しいプログラムを実行していることを意味します. -
/tmp
の下にmissing
という新しいディレクトリを作成します. -
touch
プログラムを探します.man
プログラムはあなたの味方です. -
touch
を使ってsemester in missing
という新しいファイルを作成します. -
そのファイルに以下の内容を1行ずつ書き込んでください.
- 最初の行を動作させるのが難しいかもしれません.
-
Bash
では#
はコメントから始まること,そして!
はダブルクォート("
)文字列の中でも特別な意味を持っていることを知っておくと便利です. -
Bash
はシングルクォート文字列('
)を別の意味で扱います.詳しくはBash
のクォートマニュアルページを参照してください.https://www.gnu.org/software/bash/manual/html_node/Quoting.html
#!/bin/sh
curl --head --silent https://missing.csail.mit.edu
6. ファイルを実行してみてください.つまり,スクリプトのパス(`./semester`)をシェルに入力してEnterキーを押してください.lsの出力をみて,なぜうまくいかないのか理解してください.(ヒント:ファイルのパーミッションビットを確認)
7. `sh`インタプリタを明示的に起動してコマンドを実行し,第一引数にファイル `semester` を与えます.`./semester`では動かなかったのに、なぜこれが動くのでしょうか?
8. `chmod`プログラムを検索してください(例: man chmodを使う).
9. `chmod`を使って, `sh semester`と入力する代わりに `./semester`コマンドを実行できるようにしてください.ファイルが`sh`を使って解釈されることになっていることをシェルはどうやって知っているのでしょうか?詳しくは`shebang`行のこのページを参照してください。https://en.wikipedia.org/wiki/Shebang_(Unix)
10. `|`と `>` を使用して,学期ごとに出力された「最終更新日」をホームディレクトリの last-modified.txt というファイルに書き出します.
11. ラップトップのバッテリーの電力レベルやデスクトップのCPU温度を`/sys`から読み出すコマンドを書いてください.注意: もしあなたが macOS ユーザーなら、OS には `sysfs` がないので、この練習はスキップしても構いません.