CentOS7.1のKUSANAGI自動補完を修正

さくらのVPSでは標準でもOSが色々選べるのが特徴ですが、KUSANAGIを使いたいというリクエストがあり
最近Wordpressなどを入れる機会がなかったので試してみました。

参考にしたのは下記の公式サイトの文書です。
https://kusanagi.tokyo/document/kusanagi-init/

# kusanagi init --nginx

途中、このようにkusanagiというコマンドを使って初期化したり、
プロビジョニングをするという流れでWordpressをインストールできるのですが、bashのタブキーで自動補完をするときに警告が出ていました。

■自動補完時の警告文

(2017/8/15に修正済みの様子です。早い!)
https://kusanagi.tokyo/archives/4063/

(2017/8/14現在)

[root@kusanagi71 ~]# kusanagi -bash: COMP_CWORDS: 誤った配列の添字 
-bash: COMP_CWORDS: 誤った配列の添字
 
autorenewal cert-change fcache httpd init php-fpm provision ssl target warm-up 
bcache configure hhvm https nginx php7 setting status update zabbix

これは、以前にも参考にしたサイトで使っていたスクリプトを使っているはずなのに・・と思ったのですが
CentOS7では厳しくなったのかなと思いまして調査してみることにしました。

まず、これが定義されているのはどこかな?と探してみると
/etc/bash_completion.d/kusanagi
このファイルがありました。

[root@kusanagi71 ~]# cat /etc/bash_completion.d/kusanagi 
#!/bin/bash
 
_kusanagi() {
  local cur prev
  cur=${COMP_WORDS[COMP_CWORD]}
  prev=${COMP_WORDS[COMP_CWORD-1]}
  twoprev=${COMP_CWORDS[COMP_CWORD-2]}
  COMPREPLY=()
  if (( $COMP_CWORD <= 1 )); then
    COMPREPLY=( $(compgen -W 'init provision status warm-up target update nginx httpd hhvm php-fpm php7 bcache fcache configure setting ssl https autorenewal cert-change zabbix' -- $cur) );
  elif [ $COMP_CWORD = 2 ]; then
    if   [ "$prev" = "update" ]; then
      COMPREPLY=( $(compgen -W 'plugin cert' -- $cur) );
    elif [ "$prev" = "fcache" ] || [ "$prev" = "bcache" ] ; then
      COMPREPLY=( $(compgen -W 'on off clear' -- $cur) );
    elif [ "$prev" = "provision" ] || [ "$prev" = "target" ] ; then
                  COMPREPLY=( $(compgen -W $(ls /home/kusanagi)) )
    fi
  elif [ $COMP_CWORD = 3 ] ; then
          if [ "$twoprev" = "update" ] ; then
                  COMPREPLY=( $(compgen -W $(ls /home/kusanagi)) )
          fi
  fi
}
complete -F _kusanagi -o default -o bashdefault kusanagi

COMP_CWORDSが使われているのはこの部分です。

  twoprev=${COMP_CWORDS[COMP_CWORD-2]}

単純にCOMP_WORDSという配列名をCOMP_CWORDSと書き間違えただけのようです。
(localの変数定義にtwoprevが抜けていたので追加もしましたが、警告とは関係ないですね)
確認してみたらなんだーって思ったものですが、実は確認方法に手間取りまして。

■確認方法

NGだった確認方法

# vim /etc/bash_completion.d/kusanagi
# bash /etc/bash_completion.d/kusanagi
# kusanagi update ....

最初はこれで再読み込みされるはず…と思ったのですが、ダメでした。
気が付いたのは、数行コメントアウトしても挙動が変わらなかったりしたところです。

OKだった確認方法

# vim /etc/bash_completion.d/kusanagi
# bash
# kusanagi update ....
# exit

一度新しいbashシェルを起動し、そのうえで確認する形です。
ps auxwwfのツリー表示で見ると、こんな風に見えます。

  \_ sshd: root@pts/1
      \_ -bash
          \_ bash

■最終的に修正した設定

#!/bin/bash
 
_kusanagi() {
  local cur prev twoprev
  cur=${COMP_WORDS[COMP_CWORD]}
  prev=${COMP_WORDS[COMP_CWORD-1]}
  if [ ${COMP_CWORD} -ge 2 ];then
    twoprev=${COMP_WORDS[COMP_CWORD-2]}
  fi
 
  COMPREPLY=()
  if (( $COMP_CWORD <= 1 )); then
    COMPREPLY=( $(compgen -W 'init provision status warm-up target update nginx httpd hhvm php-fpm php7 bcache fcache configure setting ssl https autorenewal cert-change zabbix' -- $cur) );
  elif [ $COMP_CWORD = 2 ]; then
    if   [ "$prev" = "update" ]; then
      COMPREPLY=( $(compgen -W 'plugin cert' -- $cur) );
    elif [ "$prev" = "fcache" ] || [ "$prev" = "bcache" ] ; then
      COMPREPLY=( $(compgen -W 'on off clear' -- $cur) );
    elif [ "$prev" = "provision" ] || [ "$prev" = "target" ] ; then
                  COMPREPLY=( $(compgen -W $(ls /home/kusanagi)) )
    fi
  elif [ $COMP_CWORD = 3 ] ; then
          if [ "$twoprev" = "update" ] ; then
                  COMPREPLY=( $(compgen -W $(ls /home/kusanagi)) )
          fi
  fi
}
complete -F _kusanagi -o default -o bashdefault kusanagi
  local cur prev twoprev
  if [ ${COMP_CWORD} -ge 2 ];then
 
  fi

※これも追加しました。if文は配列の添え字がマイナスになるのを嫌って…ですが冗長ですかねぇ。

以前は.bash_profileに記載していたのですが、記載場所が変わることで違うのかなとか色々余計なことを考えてしまったようです。
こちらも参考になりました。ありがとうございました。
bash なんて書いたことない人が補完関数をとりあえず自作する – Qiita