Bash有一项很有用的功能,就是当你在终端输入一个命令后,按两下 <TAB>
就会列出该命令支持的所有可能参数.
接下来,我会展示如何为一段python脚本也赋予这项能力. 而且, 该解决方案要足够的通用. 使得他能自动适应对python脚本选项或配置文件所做出的改动.
该脚本接受两种类型的参数. 一类是以’–’开头的标志,一类是从chef脚本中取出来的主机名称.
假设该脚本名为 show.py
- 它的作用是显示某主机的信息. 它的使用方法为:
show.py szymon
其中 szymon
为我的LG的名字, 是从我的chef节点定义文件中抽取出来的.
该脚本还支持许多的其他参数,例如:
show.py --cpu --memory --format=json
脚本支持的参数有两种格式: 一种是简单的字符串,还有一种是以–开头的参数
为了让该python脚本支持bash补全,首先需要先写一个简单的python脚本来列出所有的chef node名称.
#!/usr/bin/env python
from sys import argv
import os
import json
if __name__ == "__main__":
pattern = ""
if len(argv) == 2:
pattern = argv[1]
chef_dir = os.environ.get('LG_CHEF_DIR', None)
if not chef_dir:
exit(0)
node_dirs = [os.path.join(chef_dir, "nodes"),
os.path.join(chef_dir, "dev_nodes")]
node_names = []
for nodes_dir in node_dirs:
for root, dirs, files in os.walk(nodes_dir):
for f in files:
try:
with open(os.path.join(root, f), 'r') as nf:
data = json.load(nf)
node_names.append(data['normal']['liquid_galaxy']['support_name'])
except:
pass
for name in node_names:
print name
然后还需要一种方法来获取python脚本支持的所有选项. 我们可以通过下面这行代码实现:
$LG_CHEF_DIR/repo_scripts/show.py --help | grep ' --' | awk {'print $1'}
最后通过一个简单的bash脚本来整合上面两个脚本.
_lg_ssh()
{
local cur prev opts node_names
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts=`$LG_CHEF_DIR/repo_scripts/show.py --help | grep ' --' | awk {'print $1'}`
node_names=`python $LG_CHEF_DIR/repo_scripts/node_names.py`
if [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
COMPREPLY=( $(compgen -W "${node_names}" -- ${cur}) )
}
complete -F _lg_ssh show.py
最后,我们只需要在当前bash session中使用source命令加载该文件即可. 因此,我把下面这行添加到 ~/.bashrc
中.
source $LG_CHEF_DIR/repo_scripts/show.bash-completion
至此,只要在终端中按两下 <TAB>
就会列出所有的补全选项了.
$ show.py <tab><tab> Display all 42 possibilities? (y or n) ... and here go all 42 node names ... </tab></tab> $ show.py h<tab><tab> ... and here go all node names beginning with 'h' ... </tab></tab> $ show.py --<tab><tab> .. and here go all the options beginning with -- ... </tab></tab>
该实现最大的好处在于,任何对python script的修改或chef node名称的修改,都会自动反映出来.