綺麗に死ぬITエンジニア

Linux必須知識! 最低限知っておくべきLinuxコマンドの基礎

2015-01-23

Linuxを操作する上で、必ず必要な知識の一つが、Linuxコマンドの知識です。

本記事では、Linuxを操作する上で"絶対必要"といえるコマンドの基礎知識を紹介していきます。具体的なコマンドを覚えていく前に、基礎知識をきちんと身につけて、効率的に作業を行えるようにしましょう。

なお、「Linuxって何?」って人は、下の記事にLinuxの概要をまとめているので、読んでみてください。

5分でわかるLinux

また、本記事内でのコマンドの実行環境は、WebブラウザでLinuxの動作をエミュレートしたJavascript PC Emulatorを用いています。紹介するコマンドの入力も出力もすべてその環境でのものです。みなさんも学習の際には、ぜひ使ってみてください。

引数と標準入力と標準出力と標準エラー出力

コマンドは基本動作として、「引数」「標準入力」といった情報から「標準出力」「標準エラー出力」を出すのが一連の流れです。

[コマンド名] [引数] [入出力先の指定]

そしてこれが、コマンド1つの基本的な書式です。「引数」「入出力先の指定」はコマンドによって省略することができます。この状態で[Enter]キーを押すことで、コマンドが実行され、コマンドの動作によって出力が得られます。

例えば、単純にファイルの中身を出力するcatコマンドを用いて説明すると、以下のようになります。

~ # cat /proc/version
Linux version 2.6.20 (bellard@voyager) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-9)) #13 Sun Feb 12 20:21:29 CET 2012

上の例の1行目のcat /proc/versionは、/proc/versionというLinuxカーネルのバージョン情報が格納されているファイルの中身を出力せよ、というコマンドです。この場合、/proc/versionというのが「引数」と呼ばれるパラメータです。

それを入力したことにより、2行目に結果としてLinuxカーネルのバージョン情報が出力されています。この、2行目の出力が「標準出力」となります。

~ # cat /proc/aaaa
cat: can't open '/proc/aaaa': No such file or directory

しかし、上の例の場合は違います。1行目はcat /proc/aaaaとなっていますが、実際には/proc/aaaaというファイルは存在しません。なので、2行目にファイルが開けない旨のエラーメッセージが出力されています。この、2行目の出力が「標準エラー出力」となります。

標準出力標準エラー出力も、どちらも同じように画面に出力されているのだから、違いはないのではないかと思う方もいるかもしれませんが、実は全然違います。

この違いは、リダイレクトやパイプといった、ファイル対コマンドやコマンド対コマンドでのデータのやりとりをするときに、非常に重要になってきます。これが、先ほど述べた「入出力先の指定」となります。

リダイレクト

ではまず、リダイレクトの例を見てみましょう。

~ # cat /proc/version > /tmp/version
~ # cat /tmp/version
Linux version 2.6.20 (bellard@voyager) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-9)) #13 Sun Feb 12 20:21:29 CET 2012

1行目は、「/proc/versionを標準出力に出力してください。ただし、標準出力は/tmp/versionというファイルに変更します。」というコマンドです。簡単に言うと、「/proc/versionの中身を/tmp/versionというファイルに出力してください」ということですが。

このときの、> /tmp/versionの部分が、「入出力先の指定」で、今回の場合、リダイレクトと呼ばれる動作になります。リダイレクトとは、コマンドとファイル(デバイス)間でデータをやり取りすることをいいます。

そして2行目で、1行目で出力された/tmp/versionというファイルの中身を3行目に出力しています。

上の例では少し説明が飛躍しすぎました。基本の基本から話します。

出力には標準出力標準エラー出力があるという話をしました。そして、標準出力には1、標準エラー出力には2という数字が割り当てられています。

デフォルトで何もしなければ、入出力先の指定は、1>/dev/console 2>/dev/consoleという状態になっており、1が標準出力で2が標準エラー出力ですから、標準出力標準エラー出力もコンソール画面(/dev/console)に表示されるような設定になっています。(書き方については、そういうものだと覚えてください)

上の例であった、> /tmp/versionですが、1とも2とも記述されていない場合、1に適用されるルールとなっています。なので、1>/tmp/versionと記述した場合と同じ意味です。

つまり、デフォルトも考慮すると、

~ # cat /proc/version > /tmp/version

は、

~ # cat /proc/version 1>/tmp/version 2>/dev/console

と同じ意味ということになり、標準出力が/tmp/version、標準エラー出力が/dev/console(画面)に表示されるコマンドだということになるのです。

試しに、存在しないファイルを指定して、わざと標準エラー出力をさせると以下のようになります。

~ # cat /proc/aaaa > /tmp/version
cat: can't open '/proc/aaaa': No such file or directory

はい、しっかり画面に表示されましたね。

同じ理屈で、標準エラー出力をファイルに指定することもできます。

~ # cat /proc/aaaa 2>/tmp/error
~ # cat /tmp/error
cat: can't open '/proc/aaaa': No such file or directory

標準出力標準エラー出力を同時に指定することもできます。

~ # cat /proc/version 1>/tmp/version 2>/tmp/error

出力を画面にもファイルにもどこにも出したくないときには、/dev/nullに渡すことで、データを捨てることができます。

~ # cat /proc/version 2>/dev/null

標準出力標準エラー出力を同じものにしたい場合は、特殊な書き方で&を用いることで実現できます。

~ # cat /proc/version 1>/tmp/version 2>&1

上の例での2>&1というのは、2の出力を1と同じものにする、つまり標準エラー出力標準出力と同じものにする、という意味です。上記の例だと、どちらも/tmp/versionに出力されます。

しかし、ここで1点注意すべきことがあります。リダイレクトの処理は、左から順に行われるということです。

つまり、1と2の表記を逆にした場合、動作が変わります。

~ # cat /proc/version 2>&1 1>/tmp/version

先に2>&1がきてしまうと、その時点では1はデフォルトの/dev/consoleですから、2>/dev/consoleとなった後に、1>/tmp/versionとなってしまい、結果的に1>/tmp/version 2>/dev/consoleとなり、1と2は違うものになってしまいます。

同じものを指定する場合、それがファイルなら、更にもう1点注意すべきことがあります。それは、同一ファイルに標準出力標準エラー出力を指定する場合には、&を用いた書き方をしなければならない、という点です。

~ # cat /proc/version 1>/tmp/version 2>/tmp/version

上記の書き方の場合、標準出力標準エラー出力が共になされた場合、どちらかの出力が捨てられる可能性があります。

>によるリダイレクトの指定だと、もし仮に先に/tmp/versionにデータが入っていたとしても、上書きして元のデータを消去してしまう特性があります。つまり、1も2も>で指定してしまうと、どちらかのデータが上書きされて消えてしまいます。

上書きして消さないためにも、&を用いた表記は有用なのです。

なお、>以外にも、>>でリダイレクトを行うこともできます。

こちらの場合は、リダイレクト先に指定したファイルを上書きではなく、ファイルの最後尾にデータを追加していくかたちになります。

~ # cat /proc/version > /tmp/version
~ # cat /proc/version >> /tmp/version
~ # cat /proc/version >> /tmp/version
~ # cat /tmp/version
Linux version 2.6.20 (bellard@voyager) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-9)) #13 Sun Feb 12 20:21:29 CET 2012
Linux version 2.6.20 (bellard@voyager) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-9)) #13 Sun Feb 12 20:21:29 CET 2012
Linux version 2.6.20 (bellard@voyager) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-9)) #13 Sun Feb 12 20:21:29 CET 2012
~ # cat /proc/version > /tmp/version
~ # cat /tmp/version
Linux version 2.6.20 (bellard@voyager) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-9)) #13 Sun Feb 12 20:21:29 CET 2012

上記のとおり、>の場合は上書きされて以前の情報が失われますが、>>の場合は既存のデータの後ろに追加されていきます。

ちなみに、>>を用いてしまえば上書きされることはないため、&を用いた書き方をしなくても同じファイルに1と2の出力先を指定できます。

~ # cat /proc/version 1>>/tmp/version 2>>/tmp/version

まあ、素直に&を用いた表記を覚えたほうがいいでしょう。

>>>は出力をリダイレクトする方法ですが、<<<を用いることで入力をリダイレクトすることも可能です。

~ # cat < /proc/version
Linux version 2.6.20 (bellard@voyager) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-9)) #13 Sun Feb 12 20:21:29 CET 2012

上記のように<を使うことで、入力をリダイレクトし、ファイルの内容から入力することができるようになります。このときの入力を、標準入力といいます。

~ # cat << endl > server
> computer
> software
> linux
> endl
server
computer
software
linux

上記のように<<を使うことで、その後に指定した文字列が登場するまで、キーボードで直接標準入力を指定することができます。上の例ではendlとしてますが、任意の文字列で動作します。

catコマンドの場合は引数で指定することもできますし、標準入力で指定して出力することもできます。

パイプ

リダイレクトでは、標準入力標準出力標準エラー出力の入力元・出力先を切り替えることができますが、コマンドに直接渡すことはできません。

コマンドに直接渡すときには、パイプという機能を使います。

この機能を使うことにより、標準出力を次のコマンドの標準入力にすることができます。

パイプには、入出力先の指定|を使います。

~ # cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 5
model : 4
model name : Pentium MMX
stepping : 3
cache size : 0 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : yes
coma_bug : no
fpu : no
fpu_exception : no
cpuid level : 1
wp : yes
flags :
bogomips : 20.22
clflush size : 32

~ # cat /proc/cpuinfo | grep bug
fdiv_bug : no
hlt_bug : no
f00f_bug : yes
coma_bug : no

grepコマンドは、標準入力引数で指定したファイルから、特定の文字列が含まれる行だけ標準出力するコマンドです。

よって、上記の例(21行目)では、catコマンドでCPUの情報ファイル(/proc/cpuinfo)の内容を標準出力し、それをgrepコマンドが標準入力として受け取り、bugという文字列が含まれる行だけ標準出力する、といった動作になっています。

grepコマンドはパイプで使われるコマンドの代表格なので、覚えておくと何かと便利でしょう。

他には、teeコマンドも、よくパイプで用いられる便利なコマンドです。

~ # cat /proc/cpuinfo | grep bug | tee /tmp/cpu_bugs
fdiv_bug : no
hlt_bug : no
f00f_bug : yes
coma_bug : no
~ # cat /tmp/cpu_bugs
fdiv_bug : no
hlt_bug : no
f00f_bug : yes
coma_bug : no

teeコマンドは、標準入力引数で指定したファイルと標準出力に出力するコマンドです。一般的には画面に表示し、なおかつファイルにも保存したいときに、よくパイプを使って用いられます。

上の例だと、先ほどのbugという文字列が含まれる行だけ抽出されたCPU情報を、画面に表示し、なおかつ/tmp/cpu_bugsというファイルに保存しています。

リダイレクトとパイプとteeコマンドを用いることで、こんなこともできます。

~ # cat > /tmp/test0
this is test.
~ # cat < /tmp/test0 | tee /tmp/test1 | tee /tmp/test2 | tee /tmp/test3 > /tmp/test4
~ # cat /tmp/test0
this is test.
~ # cat /tmp/test1
this is test.
~ # cat /tmp/test2
this is test.
~ # cat /tmp/test3
this is test.
~ # cat /tmp/test4
this is test.

1行目で、「this is test.」 と書かれたテキストファイル/tmp/test0を作成。(catは引数をつけずに実行すると、キーボード入力待ち状態になり、入力した値をそのまま標準出力する。その機能を用いて作成した。)

3行目で、/tmp/test0の内容を標準出力、パイプでteeコマンドの標準入力にし、ファイル/tmp/test1に保存、その内容を更に標準出力……を繰り返し、たくさんのコピーを作成しています。

ね? 面白いでしょう?

パイプとリダイレクトを使えば、たった1行でいろいろなことができるコマンドを記述できるようになります。cronやatなどと組み合わせて使うと効果は絶大ですね。ぜひ、マスターしてください。

複数コマンドの実行

パイプを利用したデータの受け渡しなどを行わずに、複数のコマンドを実行したい場合には、以下に述べる4種類の方法があります。

  • ;の利用
~ # sleep 1 ; cat /proc/version
Linux version 2.6.20 (bellard@voyager) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-9)) #13 Sun Feb 12 20:21:29 CET 2012

;を用いて複数コマンドをつなぐことにより、1つ目のコマンド実行後に2つ目のコマンドを自動的に実行させることができます。

上の例だと、「sleepコマンドにより1秒待機した後、/proc/versionを出力する」という動作になります。実際にコマンドを入力してみると、本当に1秒経過した後に/proc/versionが表示されるはずです。

  • &の利用
~ # sleep 1 & cat /proc/version
Linux version 2.6.20 (bellard@voyager) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-9)) #13 Sun Feb 12 20:21:29 CET 2012

&を用いて複数コマンドをつなぐことにより、1つ目のコマンドを実行後、その終了を待たずに2つ目のコマンドを自動的に実行させることができます。

上の例だと、「sleepコマンドにより1秒待機しながら、/proc/versionを出力する」という動作になります。実際にコマンドを入力してみると、すぐに/proc/versionが表示されるはずです。

  • &&の利用
~ # cat /proc/version && echo "ok!"
Linux version 2.6.20 (bellard@voyager) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-9)) #13 Sun Feb 12 20:21:29 CET 2012
ok!
~ # cat /proc/aaaa && echo "ok!"
cat: can't open '/proc/aaaa': No such file or directory

&&を用いて複数コマンドをつなぐことにより、1つ目のコマンドを実行し、そのコマンドが正常終了すると、2つ目のコマンドを自動的に実行させることができます。

上の例だと、1行目はcatコマンドにより/proc/versionを表示することができ、正常終了したので、次のechoコマンドによりok!の文字が出力されています。3行目はcatコマンドが/proc/aaaaを見つけられないというエラーで終了したため、次のechoコマンドは実行されていません。

  • ||の利用
~ # cat /proc/version || echo "error!"
Linux version 2.6.20 (bellard@voyager) (gcc version 3.4.6 20060404 (Red Hat 3.4.
6-9)) #13 Sun Feb 12 20:21:29 CET 2012
~ # cat /proc/aaaa || echo "error!"
cat: can't open '/proc/aaaa': No such file or directory
error!

||を用いて複数コマンドをつなぐことにより、1つ目のコマンドを実行し、そのコマンドがエラー終了すると、2つ目のコマンドを自動的に実行させることができます。&&と逆です。

上の例だと、1行目はcatコマンドにより/proc/versionを表示することができ、正常終了したので、次のechoコマンドは実行されていません。3行目はcatコマンドが/proc/aaaaを見つけられないと、エラー終了したため、次のechoコマンドによりerror!の文字が出力されています。

まとめ

Linuxコマンドの正しい使い方を知っておくことで効率的に作業できるようになりますし、シェルスクリプトを書く上で必須の知識ですので、Linuxを触る機会のある方は、ぜひマスターしましょう。

基本を制する者が世界を制する。 パブロ・ピカソ

ということで。

筆者について

フリーランスエンジニアとして活動している、「もりやませーた」です。

筆者のTwitterはこちら。記事に関するご意見等はTwitterの方へお寄せください。

その他業務に関するお問い合わせは、こちらのページをご覧ください。

Linux