ターミナルから起動するプログラムについて
catプログラムを起動する
例えば、ファイルの中身を見るcatというプログラムを起動してみよう。
ファイル名を引数にとって、ファイルの内容を出力する。
$ cat hello.txt hello, world!!
プログラムの場所
プログラムはどこかになくてはならない。
catはどこにあるのだろうか。
whichプログラムで確認できる。
$ which cat /bin/cat
/bin/catにあるらしい。
プログラムの種類
どういうファイルなのだろうか。
fileプログラムでファイルの概要はわかる。
$ file /bin/cat
/bin/cat: Mach-O 64-bit executable x86_64
コンパイルされたバイナリファイルのようだ。
内容は人間が読んで簡単にわかるものではない。
バイナリファイルというのはこのコンピュータのために作られた、
このコンピュータでしか動かないファイルだ。
だからこそ、このコンピュータは実行のしかたを知っている。
しかし、例えばこの/bin/catファイルをWindowsにコピーして実行してみよう。
Windowsは実行のしかたを知らないのでエラーが出る。
次いでpipプログラムをみてみよう。
$ which pip $ file /usr/local/bin/pip # file `which pip`でも同じ /usr/local/bin/pip: a /usr/local/opt/python/bin/pytho script text executable
script textと表示された。
テキストとバイナリ
pipの中身をみてみよう。
$ head `which pip` #!/usr/local/opt/python/bin/python2.7 # EASY-INSTALL-ENTRY-SCRIPT: 'pip==7.1.2','console_scripts','pip' __requires__ = 'pip==7.1.2' import sys from pkg_resources import load_entry_point if __name__ == '__main__': sys.exit( load_entry_point('pip==7.1.2', 'console_scripts', 'pip')() )
ただのテキストファイルだった。
さきほどのcatのように、このコンピュータ用に作られたバイナリファイルではない。
この内容は人間には読めるけれど、コンピュータにはわからないだろう。
ではpip
プログラムはなぜ動くのだろう?
答えは、テキストファイルの一行目で、
このテキストファイルを解釈できるプログラムを指定しているからだ。
#!/usr/local/opt/python/bin/python2.7
「このテキストはpython2.7というプログラムが解釈し実行するものだ」ということだ。
なのでpip
が実行されるとき、実際には以下のコマンドが実行されているのだ。
$ /usr/local/opt/python/bin/python2.7 pip
このpython2.7というファイルは何者だろうか。
$ file /usr/local/opt/python/bin/python2.7 /usr/local/opt/python/bin/python2.7: Mach-O universal binary with 2 architectures
2つのアーキテクチャに対応していると書かれているが、
基本はこのコンピュータために作られたバイナリファイルだ。
catとpythonの違いはなんだろうか。
それは、catが与えたファイルの内容をそのまま吐き出すのに対し、
pythonは与えたファイルの内容によって動作が全く異なるということだ。
サブプロセスを立ち上げたり、Webサーバーになったりもする。
これは驚くべきことだ。
このようなバイナリファイルをインタプリタ(解釈器・翻訳者)という。
pipを解釈できるのは何もpythonだけではない。
$ php /usr/local/bin/pip
結果は実行してみてのお楽しみ。
プログラムのパス
cat
の場所をわざわざwhich cat
で確認したけど、
どうして/bin/catだけでなくcatでも実行できるのだろうか?
実はcatというコマンドを実行したとき、
最初にcat
という名前に一致したプログラムが実行される。
/bin/というディレクトリも探すディレクトリリストの中に含まれているのだ。
":"で区切られて格納されている。
PATHの内容は以下のコマンドで確認できる。
echo $PATH
これでは見にくいので以下のコマンドでディレクトリが1行ずつ表示される。
$ echo $PATH | python -c 'for line in raw_input().split(":"):print(line)'
これで列挙されるディレクトリにcatがなければ見つけてはもらえない。
プログラムをコマンドとして登録する
/Users/chyka/my_programをmy_program
だけで起動できるようにしてみる。
2つ方法がある。
方法1:my_programがあるディレクトリをPATHに追加する
以下のコマンドで/Users/chykaディレクトリを検索対象にすることができる。
export PATH="${PATH}:/Users/chyka"
このコマンドの意味はスクリプト言語風に書くと、
PATH = PATH + ":/Users/chyka"
だ。
my_program
コマンドが使えるようになっているはずだ。
方法2:検索対象のディレクトリのどれかに追加する
$ echo $PATH | python -c 'for line in raw_input().split(":"):print(line)' ... /usr/local/bin ...
PATHの中にディレクトリならどこでもいいが、
/usr/local/binというディレクトリが含まれているようだ。
ここにmy_programをコピーするとmy_program
コマンドが使えるようになる。
ちなみにシンボリックリンクというものがあり、
わざわざファイルをコピーしなくてもそのディレクトリ以下に存在するかのようにリンクを貼ることができる。
Windowsでいうとショートカットみたいなものだ。
sudo ln -s /Users/chyka/my_program /usr/local/bin/my_program