You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

30 KiB

[ Languages: English, Español, Italiano, 日本語, 한국어, Português, Русский, Slovenščina, Українська, 中文 ]

原文のコミット bb0c38c0899339e836c37eead4a9534b06c56662

The Art of Command Line

Join the chat at https://gitter.im/jlevy/the-art-of-command-line

curl -s 'https://raw.githubusercontent.com/jlevy/the-art-of-command-line/master/README.md' | egrep -o '\w+' | tr -d '`' | cowsay -W50

コマンドラインで流れるように操作ができるということは、軽く見られたり他人から理解されないスキルだとみなされることもあるだろう。しかしそのスキルは、明らかにかすぐ分かるようかは問わず、エンジニアとしてのあなたの柔軟性や生産性を改善してくれるものだ。ここでは、Linuxでコマンドラインを使う上で便利だと思ったメモやTipsの数々を挙げてみる。あるものは基礎的だが、非常に詳しいもの、洗練されたもの、曖昧なものもある。このページはそんなに長いものではないが、ここに書いてあることの全てを使ったり思い出すことができれば、かなり詳しくなれるだろう。

ここに書いてあることの多くは、元々Quora書かれていたものが多いが、私よりももっと優れた人たちがすぐに改善案を出すことができるGithubに置くのがよいのではと思った(訳注 : 原文はGithub上にある)。間違いやもっとこうした方がよいという点があれば、イシューを登録するかプルリクエストを送ってほしい!(もちろん、メタ情報の項や既存のプルリクエスト、イシューをまず確認しよう)

メタ情報

対象 :

  • このガイドは、初心者向けでも経験者向きでもある。幅広く(書いてあることは全て重要)、かつ明確で(多くのケースに対して具体的な例を付ける)、そして簡潔(他の場所で見つけられるような重要でないことや脱線したことは省く)であることをゴールにしている。各項目は、多くの場面において必須であるか、他の方法に比べて劇的に時間を節約してくれるだろう。
  • Linux向けに書いている。多くはMacOS(あるいはCygwin)でも使えるが、全部ではない。
  • インタラクティブなBashを使うことを想定しているが、多くの項目は他のシェルやBashのスクリプトでも使えるだろう。

注意 :

  • 1ページ内に収めるために、内容には暗黙的に書かれていることがある。ここで取りかかりを知ったりコマンドが分かれば、詳細をどこかで調べたりするくらいはできるだろう。新しいプログラムをインストールするには、apt-get/yum/dnf/pacman/pip/brew(どれか適したもの)を使おう。
  • コマンドやオプション、パイプを分解して理解する手助けに、Explainshellを使おう。

基本

  • 基本的なBashを学ぼう。実際のところ、man bashは結構簡単に理解できるしそんなに長くないので、これで一通りのことは分かる。それ以外のシェルもよいが、Bashは強力だし、常に使用可能であるという利点もある(自分のPCに入れてしまったと言ってzshやfishなどだけを学んでしまうと、既存のサーバを触らなくてはならない時などに制約が出てしまう)。

  • テキストエディタのどれか最低1つに習熟しよう。ターミナル内で適当にものを書くにあたって他に全く代替品がないという点で、理想的にはVim(vi)がよいだろう(通常はEmacsや高機能なIDEや最新のかっこいいエディタをメインに使っていたとしても)。

  • manでのドキュメントの読み方を知ろう(知りたがりのために書くと、man manでセクション番号が分かる。例えば1は「一般的な」コマンド、5はファイルやそのお作法、8は管理についてといった具合)。aproposでmanページを探そう。コマンドによっては実行可能ファイルではなくBashのビルトインコマンドであることを理解し、helphelp -dでヘルプが見られることを知ろう。

  • ><|を使ったパイプによる入出力のリダイレクションを学ぼう。stdout(標準出力)とstderr(標準エラー出力)を学ぼう。

  • *(または?{...})を使ったファイルグロブ展開、クォーテーション、ダブルクォート"とシングルクォート'の違いを学ぼう(詳しくはこの後の変数展開の項を参照)。

  • &ctrl-zctrl-cjobsfgbgkillなど、Bashのジョブ管理について詳しくなろう。

  • sshについて知るとともに、ssh-agentssh-addを使ったパスワードなしの認証の基本について理解しよう。

  • ファイル管理について。lsls -l(特に、ls -lの各列が何を意味するか理解)、lessheadtailtail -f(またはless +F)、lnln -s(ハードリンクとソフトリンクの違いとそれぞれの利点の理解)、chownchmoddu(ディスク使用量まとめを簡単に見るならdu -sk *)。ファイルシステム管理については、dfmountfdiskmkfslsblk

  • 基本的なネットワーク管理について。ipあるいはifconfigdig

  • 正規表現について詳しく知ろう。grepegrepの色々なフラグも合わせて。-i-o-A-Bといったオプションは知っておいて損はない。

  • apt-getyumdnfpacman(ディストリビューションによって違う)といったコマンドでパッケージを探したりインストールする方法を学ぼう。Pythonベースのコマンドラインツールをインストールするのに、pipも必要だ(後に出てくるいくつかのコマンドはpipでインストールするのが一番簡単)。

日常的に使うもの

  • Bashでは、引数を補完するのにタブを使い、コマンド履歴から検索するのにctrl-rを使う。

  • Bashでは、最後の単語を削除するのにはctrl-w、行頭まで全て削除するにはctrl-uを使う。単語ごとに移動するにはalt-bまたはalt-f、行末まで削除するにはctrl-k、画面のクリアはctrl-l。Bashにおけるデフォルトのキー割り当てを全て見るには``man readline`を参照。たくさん出てくる。例えば、**alt-.**は前の引数を順番に表示し、**alt-***はグロブを展開する。

  • vi風のキー割り当てが好きなら、set -o viを実行しよう。

  • 最近実行したコマンドを確認するならhistoryctrl-rや**alt-.**で用は足りるだろうが、!$(直前の引数)や!!(直前のコマンド)といった省略形もたくさんある。

  • 前のワーキングディレクトリに戻るならcd -

  • 途中までコマンドを入力したけれど心変わりした時は、alt-#を打つと行頭に#が挿入され、コメントとして入力される(ctrl-a#enterでも同じ)。これは後でコマンド履歴から検索できる。

  • xargs(またはparallel)を使おう。非常に強力。行ごとにいくつのアイテムを実行するか(-L)や、並列度(-P)も制御できる。正しく実行されるか定かでないなら、まずxargs echoしてみればよい。-I{}も便利。例えば以下の通り。

   find . -name '*.py' | xargs grep some_function
   cat hosts | xargs -I{} ssh root@{} hostname
  • pstree -pはプロセスツリーを表示するのに便利。

  • pgreppkillで、プロセス名で検索したりシグナルを送れる(-fも便利)。

  • プロセスに送れる色々なシグナルを知っておこう。例えば、プロセスをサスペンドするにはkill -STOP [pid]を使う。全種類見るなら、man 7 signal

  • バックグラウンドプロセスをずっと実行し続けたいならnohupあるいはdisownを使おう。

  • netstat -lntpss -platで、どんなプロセスがリッスンしているか確認しよう(UDPなら-uを付ける)。

  • 開かれているソケットやファイルを見るにはlsofも参照。

  • Bashスクリプトでは、set -xでデバッグ出力を出せる。可能なら厳格モードを使い、エラーが起きたら強制終了するようset -eする。パイプのエラーも厳格に扱うためにset -o pipefailも使おう(これはちょっと微妙かも)。より複雑なスクリプトなら、trapも使おう。

  • Bashスクリプトでは、コマンドのグループを作るのにサブシェル(丸括弧で囲まれた部分)が便利。一時的にワーキングディレクトリを移動するというよくある例。

      # カレントディレクトリで何か実行
      (cd /some/other/dir && other-command)
      # 元のディレクトリで作業続行
  • Bashでは、たくさんの変数展開の種類があることを覚えておこう。変数が存在するかチェックするなら、${name:?error message}。例えば、Bashスクリプトが1つの引数を取る必要があるなら、input_file=${1:?usage: $0 input_file}とだけ書けばよい。算術式の展開は、i=$(( (i + 1) % 5 ))。シーケンスは{1..10}。文字列のトリミングは${var%suffix}${var#prefix}。例えばvar=foo.pdfの時、echo ${var%.pdf}.txtとするとfoo.txtが出力に。

  • コマンドの出力を<(some command)のようにしてファイルのように扱える。例えば、ローカルとリモートのの/etc/hostsを比較するなら以下のようになる。

      diff /etc/hosts <(ssh somehost cat /etc/hosts)
  • cat <<EOF ...のような、Bashの「ヒアドキュメント」を理解しよう。

  • Bashでは、some-command >logfile 2>&1で標準出力と標準エラー出力の両方をリダイレクトできる。コマンドが標準入力に対してファイルハンドルを開きっぱなしにせず、ログインしているターミナルにひもづけておくため、</dev/nullするのもよい習慣。

  • 16進と10進のASCIIテーブルを見るのにman asciiを使おう。一般的なエンコードに関する情報は、man unicodeman utf-8man latin1が便利。

  • スクリーンの分割にscreentmuxを使おう。特に、リモートのSSHセッションをデタッチしたりアタッチし直したりするのに有効。セッション永続化だけの簡単なものならdtach

  • SSHで-Lあるいは-D(まれに-R)を使ったポートトンネルのやり方を覚えておくと便利。例えばリモートのサーバからウェブサイトにアクセスする時など。

  • SSHの設定を少しでも最適化しておくと便利。例えば以下の設定だと、ネットワーク環境による接続断を回避し、圧縮を使用し(帯域の細い回線を使ったscpなどで便利)、ローカルの制御ファイルを指定して同一サーバとのチャネルを多重化する。

       TCPKeepAlive=yes
       ServerAliveInterval=15
       ServerAliveCountMax=6
       Compression=yes
       ControlMaster auto
       ControlPath /tmp/%r@%h:%p
       ControlPersist yes
  • これ以外のSSHオプションはセキュリティ上の問題がある可能性があるため、有効にするには、サブネットごとやホストごとに指定したり、信頼できるネットワーク内でのみ使用するなど注意が必要。StrictHostKeyChecking=noForwardAgent=yesなど。

  • 8進数表現のファイルパーミッションは、システム設定の際に便利だがlsの結果にも出てこず、間違いやすい。以下のようにして取得できる。

      stat -c '%A %a %n' /etc/timezone
  • 何らかのコマンドの出力から、インタラクティブに値を選択したい場合は、 percolを使おう。

  • (gitを使うなど)何らかのコマンドの出力からファイルに関するやり取りをする場合は、fpp (PathPicker)を使おう。

  • カレントディレクトリ(とサブディレクトリ)全体を、ネットワーク内に公開されたWebサーバにするなら、python -m SimpleHTTPServer 7777 (ポート7777で公開。Python 2の場合)あるいはpython -m http.server 7777 (Python 3の場合)。

ファイルとデータの処理

  • カレントディレクトリ以下のファイルをファイル名で探したいなら、find . -iname '*something*'。場所を指定せずにファイル名で検索したいなら、locate somethingをつかおう(ただしupdatedbは最近作られたファイルはインデックスしていないであろうことに注意)。

  • ソースやデータファイルの(grep -rよりも高度な)一般的な検索には、agを使おう。

  • HTMLをテキストに変換するなら、lynx -dump -stdin

  • MarkdownやHTMLなど様々な種類のドキュメントの変換には、pandocを試してみるとよい。

  • XMLを扱わなくてはならないなら、xmlstartletは古いがいいツールだ。

  • JSONにはjqを使おう。

  • ExcelやCSVファイルには、csvkitin2csvcsvcutcsvjoincsvgrepなどが使えるようになる。

  • Amazon S3には、s3cmdが便利で、s4cmdはさらに高速。AWS関連の処理にはAmazon公式のawsが欠かせない。

  • sortuniq、さらにuniqの-u-dオプションを知っておこう。後に出てくるワンライナーも参照。commも確認しておこう。

  • 複数のテキストファイルを操作するのには、cutpastejoinは知っておこう。cutはみんな使っているが、joinは忘れられている。

  • wcを理解し、改行(-l)、文字(-m)、単語(-w)、バイト(-c)それぞれの数え方も知っておこう。

  • 標準入力をファイルと標準出力の両方に出すteeを理解しよう。ls -al | tee file.txtのように使う。

  • ロケールは、ソートの順序(照合順序)やパフォーマンスなど、たくさんのコマンドラインツールに微妙なところで影響することを覚えておこう。多くのLinuxディストリビューションでは、LANGや他のロケール変数はUS Englishのようなローカルな設定になっている。ロケールを変更するとソート順序が変わることに注意しよう。また、国際化(i18n)対応のルーチンはソートやその他の処理を何倍も遅く実行するようになる点も知っておこう。場合(設定の処理や一意性を見つける処理など)によっては、export LC_ALL=Cとしてしまい遅いi18n対応の処理を完全に無視してしまうことも可能だ。

  • 単純なデータ加工のためにawksedの基礎を身につけよう。例えば、テキストファイルの3カラム目の合計を出すなら、awk '{ x += $3 } END { print x }'。これは、Pythonで同じことをやるより3倍速くかつ3分の1の長さで書ける。

  • 1つあるいは複数のファイル内の文字列を直接置き換えてしまうには、

      perl -pi.bak -e 's/old-string/new-string/g' my-files-*.txt
  • パターンにしたがってたくさんのファイル名を書き換えるにはrenameを使おう。複雑なファイル名変更なら reprenも便利だ。
      # バックアップファイルfoo.bakをfooに戻す
      rename 's/\.bak$//' *.bak
      # ファイル名、ディレクトリ名、ファイルの中身全てのfooをbarに置き換える
      repren --full --preserve-case --from foo --to bar .
  • ファイルからランダムな行を抜き出すにはshuf

  • sortのオプションを理解しよう。キーがどのように処理されるのか(-t-k)を知ろう。特に、最初の列だけでソートするには-k1,1とかく必要があり、-k1だと全行を見てソートされるという点に注意。

  • stableな(安定した)ソート(sort -s)は便利。例えば、始めに1列目でソートし、それから2列目でソートするなら、sort -k1,1 | sort -s -k2,2とすればよい。

  • Bashのコマンドライン上でタブを表現する必要がある場合、ctrl-v **[Tab]**を入力するか$'\t' (コピペするなら後者の方がいいかも)。

  • ソースコードにパッチを当てる基本のツールはdiffpatch。diffの統計情報を見るならdiffstatも参照しよう。diff -rだと、ディレクトリ全体に対して実行される。変更点の概要を見るならdiff -r tree1 tree2 | diffstat

  • バイナリファイルなら、単純な16進ダンプを見るのにhd、バイナリエディタにはbvi

  • 同じくバイナリファイルに関して、テキストを抽出したいならstrings(とgrepなどの組み合わせ)。

  • バイナリのdiff(デルタ圧縮)なら、xdelta3

  • テキストエンコーディングの変換はiconvを使おう。あるいはより高度なツールとしてuconvもあり、こちらはUnicodeの高度な処理が可能。例えば以下のコマンドでは小文字に変換しアクセント記号を取り除く(展開してから削除)。

      uconv -f utf-8 -t utf-8 -x '::Any-Lower; ::Any-NFD; [:Nonspacing Mark:] >; ::Any-NFC; ' < input.txt > output.txt
  • ファイルを分割するならsplit(サイズで分割)とcsplit(パターンで分割)。

  • 圧縮ファイルの操作はzlesszmorezcatzgrep

システムのデバッグ

  • Webのデバッグならcurlcurl -lが便利で、wgetも同様、よりモダンなのはhttpie

  • ディスクやCPU、ネットワークのステータスを知るにはiostatnetstattop(あるいはhtopの方がよい)、(一番は)dstat。システムで何が起きているのか素早く知るにはよい。

  • 更に詳しいシステムの全体像を見るには、glancesを使おう。ひとつのターミナル内で、いくつかのシステムレベルの統計情報を表示してくれる。複数のサブシステムを素早くチェックするのに非常に便利。

  • メモリのステータスを知るには、freeあるいはvmstatを実行し、その出力の意味を理解しよう。特に、"cached"の値はLinuxカーネルにファイルキャッシュとして保持されているメモリ量であり、"free"の値を見る際に考慮すべきであることに注意しよう。

  • Javaのシステムのデバッグはまた違う困ったところがあるが、Oracleあるいは他のJVMにも共通しているシンプルなトリックは、kill -3 <pid>でフルスタックトレースとヒープの概要が標準出力あるいはログにダンプされる(世代別GCの詳細も参考程度だが含まれている)。

  • 改良版tracerouteとしてmtrを使ってネットワークの問題を調査しよう。

  • ディスクがいっぱいになっている理由を調べるには、ncduを使うとdu -sh *より時間が節約できる。

  • 帯域を使っているのがどのソケットやプロセスなのかを見つけるには、iftopあるいはnethogsを試そう。

  • ab(Apacheに付属)は、Webサーバのパフォーマンスをざっくりチェックするのに便利。より複雑なテストにはsiegeを試そう。

  • より確実なネットワークのデバッグはwiresharktsharkngrep

  • straceltraceについて知っておこう。プログラムの実行に失敗したりハングしたりクラッシュしたりして、その理由が分からない、あるいはパフォーマンスに関する一般的情報を知りたいなら、このツールが役立つはずだ。プロファイリングのオプション(-c)や起動中のプロセスにアタッチする機能(-p)も覚えておこう。

  • 共有ライブラリをチェックするならlddを覚えておこう。

  • 起動中のプロセスにgdbで接続し、そのスタックトレースを取る方法を知ろう。

  • /proc以下のファイルを使おう。今起こっている問題をデバッグするのには素晴らしく便利だ。例えば、/proc/cpuinfo/proc/xxx/cwd/proc/xxx/ece/proc/xxx/fd//proc/xxx/smaps

  • 過去に何か問題が起きたことの原因を探るなら、sarがとても便利。CPUやメモリ、ネットワークなどの過去の統計情報を見られる。

  • さらに深いシステムとパフォーマンスの分析には、stap (SystemTap)、perfsysdig

  • どのディストリビューションを使っているか確認しよう。多くのディストリビューションではlsb_release -a

  • 何かいつもと違うおかしなこと(大抵ハードウェアかドライバ関連の問題だ)が起きていたら、dmesgを実行しよう。

ワンライナー

コマンドをまとめて使う例をいくつか。

  • sortuniqを使ってテキストファイルの共通部分、結合、差異を求める時に特に便利なのが以下のやり方。abはそれぞれ内容に重複のないテキストファイルとする。この方法は高速で、数GB程度までの任意のファイルサイズで動作する(/tmpが小さなルートパーティションにある場合は-Tオプションをつける必要があるが、ソートはメモリ内で行われるとは限らない)。上述のLC_ALLsort-uオプションも参照のこと。
      cat a b | sort | uniq > c   # cはaとbの和集合
      cat a b | sort | uniq -d > c   # cはaとbの共通部分
      cat a b b | sort | uniq -u > c   # cはaとbの差異
  • コンフィグが含まれている/sys/proc/etc/のようなディレクトリ内の全てのファイルの中身全部を確認するにはgrep . *を使おう。

  • テキストファイルの3列目を全て足し合わせるには以下で(Pythonで同じことをやるに比べて3倍速く3分の1の長さで書ける)。

      awk '{ x += $3 } END { print x }' myfile
  • ファイルツリーのサイズやデータを確認したいなら、以下は再帰的なls -lと同じだがls -lRより見やすい。
      find . -type f -ls
  • 事情が許すならxargsparallelを使おう。行あたりいくつのアイテムを実行するか(-L)や並列度(-P)は制御できるのにも注意。正しく使えているか心配な時には、xargs echoをまずやってみよう。また、-I{}も便利だ。以下の例をみてみよう。
      find . -name '*.py' | xargs grep some_function
      cat hosts | xargs -I{} ssh root@{} hostname
  • Webサーバのログのようなテキストファイルがあり、各行には例えばURLの中に出てくるacct_idのような特定の値が現れるとしよう。acct_idが何回リクエストされているかを集計するには、
      cat access.log | egrep -o 'acct_id=[0-9]+' | cut -d= -f2 | sort | uniq -c | sort -rn
  • このドキュメントからランダムに項目を抜き出すには以下の関数を実行しよう(Markdownをパースし、アイテムを抽出する)。
      function taocl() {
        curl -s https://raw.githubusercontent.com/jlevy/the-art-of-command-line/master/README.md |
          pandoc -f markdown -t html |
          xmlstarlet fo --html --dropdtd |
          xmlstarlet sel -t -v "(html/body/ul/li[count(p)>0])[$RANDOM mod last()+1]" |
          xmlstarlet unesc | fmt -80
      }

目立たないが便利なもの

  • expr: 算術演算、論理演算、または正規表現の評価を実行

  • m4: シンプルなマクロプロセッサ

  • yes: 文字列をたくさん表示

  • cal: いい感じのカレンダー

  • env: コマンドを実行(スクリプト内で重宝する)

  • printenv: 環境変数を表示する(デバッグやスクリプト内での使用に便利)

  • look: 文字列で始まる英単語(またはファイル内の行)を見つける

  • cut pastejoin: データの操作

  • fmt: テキストの段落をフォーマットする

  • pr: テキストをページとカラムにフォーマットする

  • fold: テキストの行を分割

  • column: テキストをカラムあるいはテーブルにフォーマット

  • expandunexpand: タブとスペースの相互変換

  • nl: 行数を表示

  • seq: 数字を表示

  • bc: 計算機

  • factor: 整数を因数分解

  • gpg: 暗号化とファイルのサイニング

  • toe: terminfoのエントリのテーブルを表示

  • nc: ネットワークのデバッグとデータ転送

  • socat: ソケットリレーとTCPポートのフォワーダ(netcatと同等)

  • slurm: ネットワークトラフィックの可視化

  • dd: データをファイルあるいはデバイス間で移動

  • file: ファイルの種類を特定

  • tree: ディレクトリとサブディレクトリをツリーで表示。lsに似ているが再帰的に動く

  • stat: ファイルの情報

  • tac: ファイルを逆から表示

  • shuf: ファイルからランダムに選んだ行を表示

  • comm: ソート済みファイルの行を比較

  • pv: パイプ経由でデータの進行状況をモニタリング

  • hd および bvi: バイナリファイルのダンプと編集

  • strings: バイナリファイルからテキストを抽出

  • tr: 文字の置き換えと操作

  • iconv あるいは uconv: 文字エンコーディングの変換

  • split csplit: ファイルを分割

  • units: 単位の変換と計算。2週間あたりのハロン(訳注 : 長さの単位)からまばたきごとのトゥウィップまで( /usr/share/units/definitions.unitsも参照のこと)

  • 7z: 圧縮率の高いファイル圧縮

  • ldd: 動的ライブラリの情報

  • nm: オブジェクトファイルからシンボルを表示

  • ab: Webサーバのベンチーマーク

  • strace: システムコールのデバッグ

  • mtr: ネットワークデバッグのためのより高機能なtraceroute

  • cssh: ビジュアルな並列シェル

  • rsync: ファイルやフォルダをSSH経由で同期

  • wiresharktshark: パケットキャプチャとネットワークデバッギング

  • ngrep: ネットワーク層のgrep

  • hostdig: DNS名前解決

  • lsof:プロセスのファイルディスクリプタとソケット情報

  • dstat: 便利なシステム情報

  • glances: 高レベルに複数のサブシステムの概要を把握

  • iostat: CPUとディスクの使用状況

  • htop: topの改良版

  • last: ログイン履歴

  • w: 誰がログインしているか

  • id: ユーザやグループの情報

  • sar: システム統計情報の履歴

  • iftop または nethogs: ソケットあるいはプロセスごとのネットワーク使用量

  • ss: ソケットの統計情報

  • dmesg: 起動時とシステムのエラーメッセージ

  • hdparm: SATA/ATAディスクの操作やパフォーマンス確認

  • lsb_release: Linuxディストリビューション情報

  • lsblk: ブロックデバイスの一覧。ディスクとディスクパーティションのツリービュー

  • lshwlspci: RAIDやグラフィックなどを含めたハードウェア情報

  • fortuneddatesl: んー、あー、これは蒸気機関車やZippyの引用句が「便利」だと思うかどうかによる

さらなるリソース

  • awesome-shell: シェルのツールやリソースのまとめ
  • よりよいシェルスクリプトを書くにはStrict mode

免責事項

ごく一部の例外はありますが、コードは誰でも読めるように書かれている。力には責任が伴う。Bashでできるからといって、そうすべき必要があるという意味ではない! ;)

ライセンス

Creative Commons License

このドキュメントはCreative Commons Attribution-ShareAlike 4.0 International Liceneでライセンスされる。