いますぐ実践! Linuxシステム管理

いますぐ実践! Linux システム管理 / Vol.236 / 読者数:2296名

こんばんは、うすだです。

健康的でない生活を過ごしているからか、ここ数年で、 視力がじわじわと悪化してきました。

健康診断では、それなりの推測力(?)でしのいでいますが、 実感としては遠くがかなりボヤけて見えます。

特に気になるのが、左右のバランスです。
もともと左目の方が視力が悪いのですが、右目との差がついてきたような気がして、 ちょっとドキドキしています。

なるべく使った方がいいのかなと思って、 たまに右目をつぶってみたりもしているのですが、 効果があるのかどうかわかりません。
(ひょっとすると逆効果かも…と思ったりもしています。チキンです。)

というわけで、こうするといいよとかありましたら、 なにかアドバイスをいただけますと誠に幸いです。

オチもなんにもないまま、今回もはりきってまいりたいと思います。

今回のお題 - Bash-Completion で複雑な補完をする

前回は、Bash のビルトインコマンド「complete」を使って、 コマンドの引数の候補を絞った補完の方法をご紹介しました。

Vol.235 - Bash の補完機能を活用する
http://www.usupi.org/sysad/235.html

completeにより、ある程度候補を絞り込んで、 より補完しやすくすることができるようになりました。

ですが、引数によって候補を変えたりなど、よりきめ細かい補完をしたいとき、 素のcompleteだけではなかなか実現しづらいように思います。

そこで今回は、「Bash-Completion」なるものを使って、 かゆいところに手の届く補完を行ってみたいと思います。

Bash-Completion とは?

Bash-Completion とは、Bash の補完機能を拡張するシェルスクリプトの集まりです。

Bash-Completion
http://bash-completion.alioth.debian.org/

大抵のディストリビューションなら、 「bash-completion」パッケージがインストールされていて、 知らない間に使っているはずです。
もし「complete -p」を実行して、わらわらと出力が得られなかったら、 ひょっとすると入っていないかもしれませんので、インストールしてみてください。
(すでに入っているなら、もうあるよと言われるだけですので、 安心して実行してくださいませ。)

  $ sudo apt-get install bash-completion  (Debian系な方)
  # yum install bash-completion           (RedHat系な方)

とりあえず仕組みっぽいところの説明を

いろいろな補完をしてくださる bash-completion ですが、前述の通り、 その実体はシェルスクリプトです。

Bashなどsh系のシェルをお使いであれば、 端末を起動したりログインしたときに「/etc/profile」が実行され、 さらに「/etc/profile.d/」以下のスクリプトが実行されるようになっています。

で、そこにある「bash_completion.sh」が、 「/etc/bash_completion」や「/usr/share/bash-completion/bash_completion」 という長いスクリプトを実行し、有無を言わさず補完の機能を拡張します。

bash_completion では、補完を行うための様々な関数が書かれています。 その関数を「-F」オプションで指定して complete を実行すると、 素敵な補完が行われる、という寸法です。

さらに、「/etc/bash_completion.d/」にある、 個々のコマンドに対する設定ファイル(というかスクリプト)も、 もれなく実行されます。


-F オプションで補完を行う手順自体は、難しくありません。
関数内で、「COMPREPLY」という変数に、配列の形で候補を指定するだけです。

たとえば、以下の配列を代入するだけの関数を定義してみます。

comptest1 () {
    COMPREPLY=( aaa bbb )
}

上記をファイルに記述して、「. ファイル名」を実行してもいいですし、 コマンドラインで上記を直接入力しても構いません。
そして下記のように設定すると、COMPREPLY の値が候補になります。

  $ complete -F comptest1 foo
  $ foo (ここで[TAB]キーを押す)
  aaa     bbb

これでは、-Wオプションで候補を指定するのとたいして変わりません。 ですが、補完されるたびに呼び出されますので、

comptest2 () {
    COMPREPLY=( `date "+%T %r %R"` )
}

なんていうことをすると、現在時刻が候補となりますので、 補完しようとするたびに、刻一刻と値が変わります。

  $ complete -F comptest2 foo
  $ foo (ここで[TAB]キーを押す)
  14:27             14:27:58          午後02時27分58秒
  $ foo (もっかい[TAB]キーを押す)
  14:28             14:28:00          午後02時28分00秒

また、関数の引数には、コマンド名($1)、入力途中の文字($2)、 1つ手前の引数($3)が得られます。
ですので、たとえば、-c オプションの直後なら何かのコマンドを、 それ以外ならファイルを、という補完が簡単にできます。

comptest3 () {
    case "$3" in
    -c)
        COMPREPLY=( start stop restart reload );;
    *)
        COMPREPLY=( `echo $2*` );;
    esac
}

実際に試すと、こんな感じになります。

  $ complete -F comptest3 foo
  $ foo file(ここで[TAB]キーを押す)
  file1     file2     file3
  $ foo -c (ここで[TAB]キーを押す)
  start     stop      restart   reload   status

さらに、「COMP_CWORD」「COMP_LINE」「COMP_POINT」などの変数には、 補完対象の引数の番号、コマンドライン全体の文字、 カーソルの位置などが格納されています。 引数によって補完する内容を変えたりなどは、このあたりの変数を使えばできそうです。


あと、大事なのが、「compgen」というビルトインコマンドです。

compgenコマンドは、指定したオプションや入力途中の文字から、 補完の候補を出力してくれます。オプションは、 completeコマンドのオプションがそのまま指定できます。 (もちろん、「-p」や「-r」は除きます。)
書式を以下に示します。

  compgen [completeと同じオプション] [入力途中の文字]

たとえば、fi で始まるファイルの候補を知りたい場合は、以下のように実行します。

  $ compgen -f fi
  file1
  file2
  file3

実は、前述の例では、候補としては表示されるものの、 補完はされないという中途半端なものでした。
たとえば、最初の例では、以下のように compgen を使うようにすることで、 補完もされるようになります。

comptest1 () {
    COMPREPLY=( `compgen -W "aaa bbb" $2` )
}

-c オプションの例の場合は、以下のようにすればよいでしょうか。

comptest3 () {
    case "$3" in
    -c)
        COMPREPLY=( `compgen -W "start stop restart reload" $2` );;
    *)
        COMPREPLY=( `compgen -f $2` );;
    esac
}

…というわけで、途中から、 前回説明できなかった分を説明しているだけになってしまいました。

無理やりまとめますと、Bash-Completion では、このへんの枠組みを猛烈に駆使して、 いろいろな補完を実現している、という次第です。

まあ使ってみましょう

それでは、気を取り直して、実際の例を見ていきましょう。

まずは、お馴染みの「service」コマンドです。
第1引数にサービス名、第2引数にコマンドを指定して実行します。
確認すると、「_service」という関数を使って補完しているようです。

  $ complete -p service
  complete -F _service service

実際に試すと、第1引数ではサービス名が、第2引数ではコマンドが、 候補に挙がります。すばらしいですね。

  $ service (ここで[TAB]キーを押す)
  NetworkManager  dnsmasq         nfs             rsyslog
  abrt-ccpp       firstboot       nfslock         sandbox
  ...後略...
  $ service httpd (ここで[TAB]キーを押す)
  condrestart   fullstatus    reload        status        
  configtest    graceful      restart       stop          
  ...後略...

実際に _service 関数を眺めますと、 /etc/init.d などにあるサービス名をとってきたり、 起動スクリプトの中からコマンドを引っ張り出してくるといった、 けっこう強気なことをしています。
実際、サービスによって、補完されるコマンドが異なります。

  $ service vmware (ここで[TAB]キーを押す)
  restart    start      status     stop       stoppable
  $ service vboxdrv (ここで[TAB]キーを押す)
  force-reload  setup         status        stop_vms      
  restart       start         stop    

また、/etc/init.d/ などにあるサービスは、bash_completion で、 もれなく complete -F _service されるようになっています。
自力でサービスを追加したときでも、なにもしなくても補完の設定がされますので、 超簡単かつ便利ですね。


もういっこ、残件的な例を、ご紹介します。

前回、MP3なファイル(*.mp3)だけに候補を絞ろうとして、 うまく設定することができませんでした。
ですが、Bash-Completion を使えば、簡単に実現できます。

たとえば、mpg321というコマンドでは、 .mp3で終わるファイルだけが候補に挙がるようになっています。

  $ complete -p mpg321
  complete -F _filedir_xspec mpg321
  $ mpg321 (ここで[TAB]キーを押す)
  dir1/      dir2/      hoge.mp3

前述の bash_completion を見ますと、「_xspecs」という変数に登録した上で、 「_filedir_xspec」関数を指定すればよいようです。
たとえば、mp3nantoka.sh コマンドの引数を、 .mp3 で終わるファイルに限定したければ、以下を実行します。

  $ _xspecs[mp3nantoka.sh]='!*.mp3'
  $ complete -F _filedir_xspec mp3nantoka.sh

bash_completion では、「_install_xspec」という関数を使えば、 上記を一発で行えるのですが、unset されてしまっているため、 利用することができなくなっています。(埋め込んじゃえばできるのですが…。)

おわりに

以上、Bash-Completion による補完の一歩手前的な説明と、 実際の使用例をちょびっと、ご紹介しました。

Bash-Completion のバージョンによって、関数などは大きく変わらないのですが、 中身のコードが異なるため、あまり詳細に踏み込むことは控えておきました。

なかなか歯ごたえのある(?)スクリプトですので、興味のある貴兄は、 中を覗いてみてください。なにかヒントが得られるかもしれませんよ!

宿題の答え

前回の宿題は、

  completeにオプションを複数指定した際の動作を確認してみましょう。

でした。

試してみたところ、基本的には、指定したオプションのどれかに該当すると、 候補になることがわかりました。

たとえば、ユーザとグループの両方を指定した場合、 ユーザとグループの双方とも候補に挙がります。

  $ complete -A user -A group foo
  $ complete -p foo
  complete -g -u foo
  $ foo u(ここで[TAB]キーを押す)
  usbmux    users     usu       utempter  utmp      uuc

-Wオプションでリストを指定した場合も同様です。 指定したリストと他のオプションで指定したモノの両方が候補に挙がります。

  $ complete -s -W "foo bar" foo
  $ foo b(ここで[TAB]キーを押す)
  bar    bootpc  bootps  bgp     biff
  ...後略...

ただし、-Xオプションの場合は別です。-Xオプションは、 他のオプションで候補になったモノの中から、 指定したパターンにマッチした候補を除外します。
たとえば、グループはすべてに対して、 ユーザは u で始まるひとを候補にしたいと思って、 下記のように-Xオプションを指定しても、u で始まるという制限は、 ユーザにもグループにも適用されます。

  $ complete -u -X '!u*' -g foo
  $ foo (ここで[TAB]キーを押す)
  usbmux    users     usu       utempter  utmp      uuc

オプションの指定順序を変えても、特に変わりませんでした。

まあ、そんな特殊なニーズがあるのか、という気もしますが…。

今回の宿題

今回の宿題は、

  第1引数はオプション、第2引数はディレクトリのコマンドの補完を設定
  してみましょう。

です。

自作のコマンドで補完できるようにする必要がある、 などと思って作ってみてください。
オプションは引数なしのものが、いくつか補完できればよいです。

なんとなく歯切れが悪いのは、 一般的なコマンドは Bash-Completion がすでに定義してしまっているからなのでした。

あとがき

先日、住んでいるマンションの総会がありました。

今年度の理事長さんは、マンションをよくしていくため、 住人のみなさんが主体的に参加できるよう、 いろいろ策をねって活動されていました。
その結果、いつになく充実した、こゆい総会となりました。

何事も、言われて受動的にやっていては、それなりの結果しか得られず、 お互いにとってあまりハッピーなことにはなりません。

ですが、面倒くさいこと、苦手なことでも、 どうすればよい結果になるかを自分から考えて、そのための行動を始めれば、 期待以上のモノにたどりつけて、お互いにハッピーになる…可能性が高まります。

いま、仕事でも仕事以外でも、自分の苦手なことをやらざるをえないときが、 ちょくちょく増えてきています。

ああいやだなあ面倒くさいなあ… と思う気持ちはなかなか変えられるものではありません。
ですが、それをすることで周囲に貢献でき、自分の経験値にも反映されるのなら、 後回しにしないでやってみよう…と心がけるようにしています。

 

…ま、その成果がいつ出てくるのかは、さっぱりわかりませんが…。

 

それから、たかだか20戸しかない小さなマンションでも、なにかを決めるとき、 すんなり意見がまとまるなんてことは、そうそうありません。

そのため、事前に説明してわかってもらったり、 ある程度の意見を伺っておいて方向性を見極めておいたりといった、 いわゆる「根回し」が必要であることを、今回学びました。

よく、日本の政治は変わらないとか、なかなか決められないとか言われていますが、 小さなマンションですら決まらないのだから、 相当大変なことなんだろうということが、少しわかったような気がします。

というわけで、自民党を100%支持するわけではありませんが、 安倍政権の方々には、ぜひガンバっていただきたいと思います。

 

…あ、まずお前がガンバれよ、という声が聞こえたような気が…。

 

今回も、ここまで読んでいただき、超ありがとうございました。
次回は、3月3日(日) の未明にお会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」- 仕事が一段落したらガンバります。(死亡フラグが立った?)
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)
http://twitter.com/kuriking/ (栗つぶやき)
http://facebook.com/kuriking3 (栗顔本)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本