もじゃ(@s10akir)です。paizaラーニングでプログラミング学習動画制作のアルバイトをしたりバイト中にアニメを見たりしている専門学生です。
最近paizaラーニングで「Linux入門編」が公開されました。やったー!(私はLinuxのオタクです)Linux入門編では、Linuxの特徴であるコマンドライン操作について学べます。
こういったシェルコマンドって、どのような仕組みで動いているのか気になりませんか?(気になるって言ってください!)
今回は、実際に自分でシェルコマンドを作ってみつつ、Linuxでのコマンド実行の流れをざっくり確認してみましょう。
※この記事内では" $ hogehoge "という表記がよく出てきますが、$はターミナルで打つコマンドであるということです。(実際のターミナルに$は入力しません)
なおバイト中にアニメを見ている様子はこちら。
PaizaCloudの環境をつくる
まずはPaizaCloudでコマンドを試せる環境を作りましょう。PaizaCloudは、各種プログラミング言語やフレームワークなどが使えるLinux開発環境をブラウザ上で簡単に使えちゃうクラウドIDEです
無料でも24時間は使えますので、この記事の内容を試す分には十分だと思います。
今回はPaizaCloudに標準でセットアップされているものしか使わないので、このへんのチェックは何もつけずにそのままで大丈夫です。
コマンドって何
まず、Linuxコマンドについてざっくり説明します。と言っても、実は「コマンド」という言葉自体の意味って結構あいまいなんですけど、今回は以下のような機能を持つものとして扱っていきます。
- どこにいても実行できる
- パスの指定が必要ない
具体的には、 cd とか echo とかを想像してもらうとわかりやすいかと思います。
どこにいても実行できる
この「どこにいても」というのは、今いるディレクトリにとらわれないということです。
たとえば $ ./hoge.sh という処理は「今いるディレクトリにある hoge.sh というスクリプトを実行する」というコマンドです。ディレクトリを移動したら、 hoge.sh は一緒についてきてくれるわけではないので、このコマンドは使えなくなってしまいます。
パスの指定がいらない
それなら「(相対パスか絶対パスで)具体的に場所を指定してやればいいじゃん」と思いますよね。
その通りなのですが、ひんぱんに使いたい処理だからコマンドにしたいわけで、いちいち毎回ディレクトリの場所を /home/paiza/Code/script/hoge.sh… なんて打つのは面倒です。
コマンドの仕組み
なぜわざわざ上記のような定義をしたかというと、Linuxコマンドのほとんどは、ただのプログラムに対して「どこにいても呼び出せて」「パスの指定をしなくていい」ように設定しただけのものだからです。(「ほとんどは」なので、一部そうではない特殊なコマンドもあります)
PaizaCloudで使えるUbuntuでは、標準で「bash」というシェル環境が動作しています。
cd や echo といった基本的なコマンドは、この「bashが持っている標準機能の一部」なので、ただの一つのプログラムではありません。
こうした「シェルが持っている機能」を組み込みコマンドと呼び、そうではない「ただのプログラムを便利に呼び出せるようにしたもの」を外部コマンドと呼びます。このへんは、コマンドについて理解するときにちょっとややこしい部分でもあります。
内部コマンド | 外部コマンド |
シェルが持っている機能 | ただのプログラムを便利に呼べるようにしたもの |
「内部コマンドを自作する」というのは、イコール「シェルを拡張しよう!」ということです。そっちはちょっと難度が高いので、普通は「外部コマンド」のほうを自作します
ちなみに $ help を実行すれば、こんな感じでbashの持っている内部コマンドを確認できます。help コマンド自身も、bashの内部コマンドです。
外部コマンドはただのプログラム
外部コマンドは「ただのプログラムを便利に呼び出せるようにしたもの」と言いましたが、「じゃあそのプログラムはどこに保存されてるいの?」ということで、実際のコマンドを例に確認してみましょう。
Linux入門編では sl というジョークプログラムを取り扱いましたので(詳しくは講座を見てね)、今回は別のジョークプログラムを入れてみましょう。
まずはおまじないでございます。
$ sudo apt update
おまじないで終わってしまうのもなんなので説明しておきますが、↑これは「パッケージリスト」を更新するコマンドです。パッケージリストとは、インストールしたいプログラムのカタログみたいなものです。古いカタログを見てても商品が変わっていたり、なくなっちゃってたりすることがありますよね。Linuxの開発コミュニティは非常に活発でして、日々新しいプログラムが作られたり既存のものも更新されたりしているので、パッケージリストは毎回更新することをおすすめいたします。
それでは、 cowsay というプログラムをインストールしてみましょう。
$ sudo apt install cowsay -y
cowsay が何かと言いますと、こんな感じでコマンドライン引数に任意の文字列を引き渡すと牛さんがしゃべってくれちゃうすばらしいプログラムです。(日本語をしゃべらせようとすると吹き出しからはみ出してしまいます。日本語は半角英数字より幅が広いからです)
$ cowsay "meow meow I'm a cow" _____________________ < meow meow I'm a cow > --------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
この cowsay はどこに存在しているのでしょうか?次のコマンドで確認してみましょう。
$ type cowsay /usr/games/cowsay
どうやらUbuntuでは、 /usr/games ディレクトリに入ってるみたいです。確認してみましょう。
$ cd /usr/games $ ls cowsay cowthink
ありました。現在同じディレクトリにいるので、この cowsay を直接実行してみましょう。(ちなみに cowthink はバリエーション違いで、牛さんが任意の文字列を思い浮かべてくれるすばらしいプログラムです)
$ ./cowsay "Hello everyone, I'm Kyoko Kirishima." ______________________________________ < Hello everyone, I'm Kyoko Kirishima. > -------------------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
ちゃんと実行できました。これが本体で間違いないようです。
この cowsay は、Perlというスクリプト言語で書かれているのでそのまま中身も見ることができます。
$ cat ./cowsay
で確認してみましょう。
どうでしょう、なんとなくでも「コマンドというのは要はただのプログラムなんだな」ということが伝わりましたでしょうか?
ちなみに、開発言語によってはコンパイルした時点で人間には読めなくなる場合もありますから(C系やJavaなどがそうです)、必ずしもこのように中身が確認できるわけではありません。
どうして実際の場所を省略できるのか?
前述の通り、 cowsay は /usr/games に入っているので、本来なら $ /usr/games/cowsay や同じディレクトリまで行って $ ./cowsay と実行しなければなりませんよね。なぜどこからでも $ cowsay だけで実行できてしまうのでしょうか?
これは、PATHという環境変数のおかげです。環境変数について、今回は詳しく触れませんがひとまず「環境全体から参照できる変数」という解釈で大丈夫です。
PATHには何が登録されているのか、次のコマンドで確認してみましょう。
$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games:/home/ubuntu/go/bin:/home/ubuntu/.local/bin:/home/ubuntu/.npm-packages/bin
PaizaCloudの環境では、いろいろなディレクトリが登録されているみたいです。先程の /usr/games もありますな。
LinuxだけでなくWindowsのコマンドプロンプトやPowerShellでもそうなのですが、コマンドが入力されると、ざっくり次のような順番で処理が走ります。
1.入力されたコマンドが内部コマンドかどうかを確認する
→内部コマンドだった場合は、そのまま実行して終了
2.内部コマンドじゃなかった場合は、「PATHに登録されたディレクトリに存在するか」を確認する
→PATHに登録されたディレクトリに存在していた場合、それを実行して終了
3.それでも見つからなかった場合は、「そんなコマンドなかったぞい」というエラーを吐いて終了
今回の場合、 cowsay はPATHに登録された /usr/games の中に存在していますから、2の段階で見つかって実行されたというわけですね。
このように、自作のプログラムもPATHに登録された場所に設置すれば、コマンド化してどこからでも実行できるのです。
ちなみにこの「PATHの通った場所に設置すること」や「任意の場所をPATHに追加すること」を俗に「PATHを通す」と言ったりします。
自作のプログラムにPATHを通してコマンドにしてみよう
前置きが長くなりましたが(今までの全部前置きだったのか…)、実際に自作のプログラムをコマンド化してみましょう。
今回は例として、Rubyでルーレットのようなコマンドを作ってみます。
せっかくなのですべての作業をコマンドでやってみましょうかね。
プログラムを書く
まずはRubyのプログラムを書きましょう。
ターミナルを立ち上げた時点ではubuntuユーザのホームディレクトリ /home/ubuntu にいます。プログラムを書いてる時点ではどこでも問題ないので、とりあえずここで続けて大丈夫です。
まずは touch コマンドで新規に空ファイルを作成します。
$ touch roulette
touch はファイルのタイムスタンプを更新するコマンドですが、存在しないファイルを指定した場合は新規にファイルを作ってくれます。
ここでファイル名に .rb をつけていないのがポイントです。コマンド名は省略できないので、 $ roulette.rb って感じで呼び出すのはなんかダサいですよね。(そんなことない?)
次に、この roulette を編集します。これもターミナル上でやってしまいましょう。
おすすめはVimコマンドですが、Vimの操作に自信のない方は nano というエディタも使えます。こちらは常に下側にショートカットキーの説明が出ているので、初心者にやさしいエディタです。
$ vim roulette
もしくは
$ nano roulette
エディタが開いたら、次のようなスクリプトを書いてみましょう。
#! /usr/bin/env ruby puts 'roulette start!' puts "#{ARGV.sample}! デンッ"
Rubyではコマンドライン引数が半角スペース区切りで配列に格納されていて、 ARGV という特殊な変数で参照できます。また、 sample は配列内の要素をランダムに一つ返す Array クラスのメソッドです。
つまりこれは、コマンドライン引数にいくつかワードを与えてやると、ランダムにどれか一つを出力してくれるプログラムです。ちゃんと動くか実際に試してみましょう。
Vimは :wq で、nanoは Ctrl+X -> y -> Enter で保存して終了します。
$ ruby roulette ラーメン 焼きそば パスタ うどん roulette start! うどん! デンッ
無事に動いてそうですね。何度も同じ内容で実行して、ちゃんとランダムになっているかも確認してみてください。bashでは、上下カーソルキーで過去に打ったコマンドを引っ張ってきて再度実行できます。
直接実行できるようにする
次に、Rubyコマンドを指定しなくてもこのプログラム単体で実行できるようにしてみましょう。
そのためには、以下の2つの条件を満たす必要があります。
- shebang が記述されていること
- ファイルに実行権限があること
shebang は、そのスクリプトがどのプログラミング言語で動いてほしいかを定義しているものです。
1行目に書いた
#! /usr/bin/env ruby
がそうですね。
実行権限ですが、新しく作ったファイルは初期設定では許可されていませんから、明示的に許可する必要があります。
今回のコマンドは、誰が実行できても問題ない(管理者専用にしないとマズい的な問題はない)ので、全員が実行できるようにしておきましょう。
$ chmod a+x roulette
このあたりは、Linux入門編でも解説していますのでぜひ見てみてください。
$ ./roulette なんか 適当な ワードたち
で実行できるようになっていればOKです。
PATHを通す
いよいよ、このプログラムがコマンドとして使えるようにPATHを通します!
今回はPATHに場所を追加するのではなく、あらかじめPATHの通った場所に配置します。
$ sudo mv roulette /usr/local/bin
roulette を、PATHが通っている /usr/local/bin の中に移動させました。このディレクトリはシステム全体に関わるところなので、変更を加えるにはスーパーユーザー権限が必要です。そのため sudo を忘れないようにしましょう。
ちなみに、PATHに新しい場所を追加する場合は
$ export PATH=$PATH:追加したい場所への絶対パス
で可能です。ただし、このコマンドでは一時的にしかPATHが追加されないので、ターミナルを閉じれば元に戻ってしまいます。これで試して問題が起きなければ、 .bashrc に追記したり /etc/profile に追記したりして永続化しましょう。
では、満を持してコマンドを実行してみましょう。
roulette は移動させたので、今いるディレクトリにはないはずです。 ls で確認してみましょう。
ターミナルで
$ roulette 関内 三田 中山 蒲田
と入力すると…
はい!無事に私が今日行くラーメン二郎のお店が決まりました。
適当なディレクトリに移動しても実行できるか、ターミナルを開き直しても実行できるかなども試してみましょう。どこでも問題なく動くはずです。
まとめ
というわけで、このように任意のプログラムを「単体で実行できる」ようにして「PATHを通す」とコマンドとして使えるようになります。
Linux環境を使い続けていると、「いつもする一連の処理、コマンド化して楽に使いたいなー」と思うことが増えてくるはずなので、このやり方を覚えておくととっても便利です。
paizaラーニングのLinux入門編では、簡単にプログラムの書けるシェルスクリプトや、慣れれば開発効率が爆上がり&ドヤれる(?)Vimの使い方なども学べます。これをきっかけに、すばらしきLinuxの文化に興味を持っていただけたら幸いです。
今回使用した「PaizaCloud」では、環境構築に悩まされることなく、ブラウザだけで簡単にウェブサービスやサーバアプリケーションの開発や公開ができます。
「paizaラーニング」では、未経験者でもブラウザさえあれば、今すぐプログラミングの基礎が動画で学べるレッスンを多数公開しております。
そして、paizaでは、Webサービス開発企業などで求められるコーディング力や、テストケースを想定する力などが問われるプログラミングスキルチェック問題も提供しています。
スキルチェックに挑戦した人は、その結果によってS・A・B・C・D・Eの6段階のランクを取得できます。必要なスキルランクを取得すれば、書類選考なしで企業の求人に応募することも可能です。「自分のプログラミングスキルを客観的に知りたい」「スキルを使って転職したい」という方は、ぜひチャレンジしてみてください。