bash-completionを活用して、manやhelpを見ずに、バシバシ長いコマンドを打つ

# 1. 入力補完機能を使っていますか？

**bash**をはじめとして、多くのシェルやコマンドプロンプトで**入力補完機能**（completion）が提供されている。Windowsでも使える機能だし、ほとんどの人が使っているだろう。

```shell-session:入力補完機能によるファイル名補完の例
$ ls
sample.txt  test1.txt  test2.txt  test3.txt
$ cat s[TAB]キー入力
$ cat sample.txt　　★TABキーを押すと、一致するファイル名が補完される
```

**<font color="blue">そしてRHEL6（2010年代～）あたりからは、ファイル名やディレクトリ名だけでなく、コマンドのオプション入力にも使えるようになっている。**</font>

### 1-1.前提条件

* LinuxやMacOS

### 1-2. TL;DR

* 入力補完機能は使っていたが、Linuxコマンドのオプション入力で使えるのは知らなかった。<font color="red">恥ずかしい…。</font>

# 2. systmctlのオプション長げー問題

ここ数年はRHEL7系をメインに使っているが、長らくRHEL5/RHEL6系を使ってきた。RHEL7系で戸惑うのは`service`コマンドや`chkconfig`コマンドが使えないことだ（一部は互換機能で使える）。

システム構築・運用でよく使うコマンドなので「`chkconfig --list`って、`systemctl`だと何だったっけ…」となりがちである。

**そんなときに役立つのがコマンド・オプションの入力補完機能だ。**

次のように`systemctl`のあとに「TABキー」を入力すると、オプションの一覧を表示できる。

```shell-session
$ sudo systemctl [TAB]キー入力　★systemctlのあとに1スペース入れてからTAB
add-requires           hybrid-sleep           reload-or-restart
add-wants              is-active              reload-or-try-restart
cancel                 is-enabled             rescue
cat                    is-failed              reset-failed
condreload             isolate                restart
condrestart            is-system-running      set-default
condstop               kexec                  set-environment
daemon-reexec          kill                   set-property
daemon-reload          link                   show
default                list-dependencies      show-environment
delete                 list-jobs              snapshot
disable                list-sockets           start
edit                   list-timers            status
emergency              list-unit-files        stop
enable                 list-units             suspend
exit                   mask                   switch-root
force-reload           poweroff               try-restart
get-default            preset                 unmask
halt                   reboot                 unset-environment
help                   reenable
hibernate              reload
```

一覧が表示されれば、こちらのもの。続いて`list-unit-files`を入力すればよい。オプションを入力してる途中も「TABキー」の入力補完は効く。

```shell-session
$ sudo systemctl list-unit-files　★list-unit-filesの途中でもTABの補完が効く
```

**これで`systemctl`も怖くない！　えっへん！**

# 3. bash-completionとは

ファイル名やディレクトリ名の入力補完では無く、コマンドのオプションを補完するのがbash-completionだ。`complete -p`を入力して大量の行が表示されるならば利用できると思っていい。

### 3-1. ディストリビューションごとの状況

Linuxディストリビューションの種類やバージョンによって、標準リポジトリに含まれていないことがある。

* **RHEL6系** ： EPELリポジトリ
* **RHEL7系以降：** 標準リポジトリ
* **Ubuntu 18.04 LTS：** 標準リポジトリ


```shell-session:RHEL9系
$ rpm -q bash-completion
bash-completion-2.11-4.el9.noarch
```

```shell-session:RHEL8系
$ rpm -q bash-completion
bash-completion-2.7-5.el8.noarch
```

```shell-session:RHEL7系
$  rpm -q bash-completion
bash-completion-2.1-6.el7.noarch
```

```shell-session:RHEL6系
$ rpm -q bash-completion
package bash-completion is not installed
```


```shell-session:Ubuntu18.04LTS
$ dpkg -l bash-completion
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
ii  bash-completio 1:2.8-1ubunt all          programmable completion for the b
```

少し古いので現在当てはまるか微妙だが、MacOSの情報はこちら。

* [MacOSでのbash-completion](https://qiita.com/takamario/items/982ddc85a6a924516301)

RHEL7以降やUbuntuでは標準リポジトリに含まれているので「3-3. bash-completionの定義ファイル」に進んでほしい。

### 3-2. RHEL6系OSへのインストール

RHEL6やCentOS 6では、bash-completionをEPELリポジトリからインストールする必要がある。その手順を説明する。

1. EPELリポジトリが有効になっているか確認する。次のように行が存在し、enabledになっていれば利用できる。

```shell-session
$ yum repolist all | grep -i epel
epel                         Extra Packages for Enterprise Linux enabled: 12,586
```

2.上記以外のときは状況に応じてEPELリポジトリを有効にする。

**行はあるがdisabledのとき**

```shell-session
$ sudo yum-config-mangaer --enable epel
```

**行自体がないとき**

```shell-session
$ sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm -y
```

3.次のように「Available Packages」に表示されたときは、インストールされていないが、リポジトリには存在している。

```shell-session
$ sudo yum list bash-completion
Loaded plugins: refresh-packagekit, security, ulninfo
Available Packages
bash-completion.noarch                          1:1.3-7.el6                          epel
```

4.ここまで確認できたらbash-completionをインストールする。

```shell-session
$ sudo yum install bash-completion -y
```

5.bash-completionを有効にするためにログアウト／ログインする。ログアウトする理由は`/etc/profile.d/bash_completion.sh`でbash-completionの定義ファイルを読むためだ。

### 3-3. bash-completionの定義ファイル

bash-completionの定義ファイルは、次のディレクトリ配下に存在する。

* /etc/bash_completion.d/
* /usr/share/bash-completion/completions/

ディレクトリを確認すると大量の定義ファイルがある。このファイルがあるコマンドは、オプションの入力補完ができることになる。

```shell-session
$ ls  /usr/share/bash-completion/completions/ | wc -l
454

$ ls /usr/share/bash-completion/completions/
addpart       fsck.minix      lvextend     raw                  timedatectl
blkdiscard    fsfreeze        lvm          readprofile          tuned-adm
blkid         fstrim          lvmdiskscan  rename               udevadm
blockdev      gapplication    lvreduce     renice               ul
bootctl       gdbus           lvremove     repquota             umount
busctl        getopt          lvrename     resizepart           unshare
bzip2         groupadd        lvresize     rev                  useradd
cal           groupdel        lvs          rpm                  userdel
cfdisk        groupmod        lvscan       rtcwake              usermod
★以下省略
```

### 3-4. 入力補完例いろいろ

先ほどの`systemctl`の例では`list-unit-files`オプションを補完した。それ以外にもハイフン（`-`）やハイフンハイフン（`--`）で始まるオプションも入力補完できる。

```shell-session
$ sudo systemctl -[TAB]キー入力
-a                     --ignore-dependencies  --quiet
--after                --kill-who             -r
--all                  -l                     --recursive
--before               --no-ask-password      --reverse
--defaults             --no-block             --root
-f                     --no-legend            --runtime
--fail                 --no-pager             -s
--failed               --no-reload            --signal
--force                --now                  --state
--full                 --no-wall              --system
--global               -p                     -t
-h                     -P                     --type
-H                     --privileged           --version
--help                 --property
--host                 -q
```

表示まで少し時間はかかるが、サービス名（ユニットファイル名）の途中で「TABキー」を入力すると、一致するサービスの一覧を表示できる。

```shell-session
$ sudo systemctl restart sshd[TAB]キー入力
sshd@                sshd.service
sshd-keygen.service  sshd.socket
```

**sshの場合**

sshでは、`~/.ssh/known_hosts`や`~/.ssh/config`、`/etc/hosts`からホスト名候補を表示できる。

```shell-session:1スペースのあとに[TAB]キー
$ ssh [TAB]キー入力
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.5.1.35 ol7srv.dbprivatenrt01s.work01nrtvcn.oraclevcn.com ol7srv
```

```shell-session:ホスト名の途中で[TAB]キー
$ ssh ol7[TAB]キー入力
ol7ksplice
ol7srv
ol7srv2
ol7srv3
ol7srv-vip.dbprivatenrt01s.work01nrtvcn.oraclevcn.com
```

```shell-session:-oオプションのあとに[TAB]キー
$ ssh -o [TAB]キー入力
AddressFamily=                     IdentitiesOnly=
BatchMode=                         IdentityFile=
BindAddress=                       IPQoS=
ChallengeResponseAuthentication=   KbdInteractive
```

**ここまで来ると何でもありだ。とりあえず「TABキー」を試してみたい。**

定義ファイルを解析すれば、コマンドごとに何ができるかわかる。だけれど数が多いので覚えるのはナンセンスだ。

次のように本来オプションを指定するコマンドなのに、カレントディレクトリのファイルやディレクトリが表示されたときは定義されていない、と覚えた方がいいだろう。

```shell-session
$ sudo yum-config-managar [TAB]キー入力
bash-completion-extras-2.1-11.el7.noarch.rpm
.bash_history
.bash_logout
.bash_profile
.bashrc
.cache/
.config/
.lesshst
sample.txt
.ssh/
```

### 3-5. さらに追加モジュール（RHEL7系のみ）

bash-completionには追加モジュールの`bash-completion-extras`がある。こちらはRHEL7系のEPELリポジトリで提供されているパッケージだ。RHEL6/8/9のEPELでは提供されていない。

1. クラウドではデフォルトでEPELリポジトリが有効になっていることがある。次のコマンドでEPELを確認する。このように表示されたときは、すぐにインストールできる。

```shell-session
$ sudo yum list bash-completion-extras
Loaded plugins: langpacks, ulninfo
Available Packages
bash-completion-extras.noarch          1:2.1-11.el7           ol7_developer_EPEL
```

2.EPELリポジトリがインストールされていないときはインストールする。

```shell-session:RHEL7系
$ sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y
```

```shell-session:AmazonLinux2
$ sudo amazon-linux-extras install epel -y
```

3.bash-completion-extrasパッケージをインストールする。これで終了だ。

```shell-session:
$ sudo yum install bash-completion-extras -y
```

4.パッケージの中身を確認すると300近いモジュールがあり、mysqlやpostgresqlなどもあることがわかる。

```shell-session
$ rpm -ql bash-completion-extras |wc -l
271

$ rpm -ql bash-completion-extras
/usr/share/bash-completion/completions
/usr/share/bash-completion/completions/a2x
/usr/share/bash-completion/completions/aclocal
/usr/share/bash-completion/completions/add_members
/usr/share/bash-completion/completions/alias
/usr/share/bash-completion/completions/alternatives
/usr/share/bash-completion/completions/animate
/usr/share/bash-completion/completions/ant
/usr/share/bash-completion/completions/apropos
/usr/share/bash-completion/completions/arch
/usr/share/bash-completion/completions/arping
★以下省略
```

# 4. まとめ

* **bash-completionを使用すると、コマンド・オプションを入力補完できる**
* **RHEL6系ではEPELからインストールする必要がある**
* **RHEL7/8/9やUbuntuではデフォルトでインストールされていることが多い。少なくとも標準リポジトリには存在する**