Use fzf to Supercharge Your kubectl Command

First let’s have a look at fzf, a super fast command line fuzzy finder. It’s mostly written in golang and there are so many ways to use it. In this note, I’ll just use it to select a value from a list in a terminal and then return it to next command.

When working with kubernetes, I open need to switch between namespaces in a cluster. The raw kubectl command for this is:

 kubectl config set-context --current --namespace='my-namespace'

But I don’t remember every namespace, do I? If auto-completion of kubectl is available I can double-tab and then get a list of namespaces like this:

This is not quite convenient, not at all. So I created this simple bash function using fzf to speed this up.

#select k8s namespace
function kns() {
  kubectl config set-context --current --namespace=$(kubectl get namespaces --output=jsonpath='{range .items[*]}{.metadata.name}{"\n"}'|fzf)
}

The kubectl get... command in the sub shell above simple output a list of available kubernetes namespaces and then pipe to fzf to make an interactive auto-completion. And then the selected namespace will be passed back to kubectl config ... command to actually set the namespace to current context. The result looks like this:

PS. I’ve put this and other handy shorthand functions here.

Use FZF to Speed Up KUBECTL

FZF is general purpose option selector for Linux command line. By default fzf is an super-upgrade for the ctrl-r command history finder, but it is helpful for almost any scenario where you need to pick 1 item from a list.

Here’s a tiny use case where I use fzf to select a kubernetes namespace and set it as the default namespace, just to save the effort to type --namespace flag everytime when I need to do something not in the default namespace.

#!/bin/bash
function kns() {
cns=$(kubectl get namespaces --output=jsonpath='{range .items[*]}{.metadata.name}{"\n"}'|fzf)
kubectl config set-context --current --namespace=$cns
}

Let me explain the script above step by step:

  1. kubectl get namespaces will list all namespaces currently accessible
  2. --output=jsonpath='{range .items[*]}{.metadata.name}{"\n"}' will only output the name of namespaces and 1 in each line
  3. |fzf to pipe the result from step 2 to fzf, a list will popup and becomes interactive for the user to choose one.
  4. kubectl config set-context --current --namespace=$cns will set the chosen namespace from step 3 as the default namespace

This is very convenient when there are not too many namespaces and when you need to work in different namespaces randomly. 🙂

一起疑点重重的案子告破

今天一早就遇上个难题: 某客户系统无法发送邮件了. 同事追踪了一下日志, 发现是邮件模板渲染程序无权限写某附件的临时文件. 但奇怪的是此文件就是渲染程序自己生成的, 通常能生成文件自然也可以改写. 进一步调查后, 我发现出问题的文件夹是个 NFS 共享文件夹, 而 NFS 服务器端设置了 all_squash, 这解释了文件生成后所有者被更换的原因.

另外一个问题就文件属性, 因为 all_squash 是一直生效的, 所以不可能是问题的直接原因. 文件属性是 rwr-r-, 因此被更换了所有权后原用户就无法再更改了. 而新文件的属性是由 umask 控制的. 再查看一下 umask, 果然, 应该是 002, 看到的却是 022. 这就导致生成的文件属性是 rwr-r- 而不是期待的 rwrwr-.

那么下一步是修改 umask, 但涉及到是将”umask 002″ 放到 .bash_profile 还是 .bashrc 的问题. 原来 .bash_profile 是在登录时生效一次, 而 .bashrc 则是在每个 bash 会话开启时生效. 也就是说, 当我利用 ssh 或者 bash -l 时 .bash_profile 会生效, 而登录后打开一个新的 bash 会话则会调用到 .bashrc. 有趣的是使用 bash -c “command” 运行时, 因为不是互动的会话, 所以 .bash_profile 和 .bashrc 都不会生效. 搞清楚这些区别, 看到 unicorn 服务是以 bash -l 的方式启动的(其实有点奇怪), 因此我把 umask 放在 .bash_profile 里.

修改了 umask 之后, 再重启了 unicorn 服务, 问题解决. 😛

但是是谁修改了 umask 呢? 嫌疑犯依旧在逃…