
背景
一起回顧一個大家非常熟悉場景。
上周開發一個需求,開發過程中,我需要登入到伺服器上看一下服務運作的日志,确認運作狀态或者看一些debug的資訊。是以我登入到跳闆機,此時我發現我忘了某一台機器的具體名字(通常能記得的人都是天才),是以需要用跳闆機提供的 autoget 指令來通過伺服器組名來獲得機器的清單。
此時我發現我連伺服器組名都忘了,是以需要上 eagle eye 上查尋一下組名。這個查詢可能得依靠我的記憶打出組名的字首,通過 eagle eye 給出的補全提示清單來識别出其中那個我需要的組名。
終于我得到了我的組名,為了避免我下次再忘記而不得不再繁瑣的查詢一遍,我選擇把這些結果記錄到我的記事本中,友善我下次查找使用。終于我登入了機器,可是不巧我忘了日志記錄的位置,我想起某個同僚曾經告訴過我日志的路徑,于是我查找了與那個同僚的聊天記錄,找到了這個日志路徑。同樣為了防止忘記,我又把它記錄到了我的記事本中友善下次查找。然後我把日志路徑複制粘貼到指令行,我終于可以開始工作了。
昨天我又開發了一個需求,我還需要登入到伺服器上看一下服務運作的日志,确認運作狀态或者看一些 debug 的資訊。是以我登入到跳闆機,需要用跳闆機提供的 autoget 指令來通過伺服器組名來獲得機器的清單,我想起了我在記事本中記錄了這個内容,于是我打開記事本,搜尋了 keyword,在簡單的翻找下,我找到了我想要的指令。
進入到機器後,我發現日志的路徑我還是沒有記住。于是,我再次打開記事本,搜尋了另一個 keyword ,再次翻找了一下,找到路徑後把它複制粘貼到指令行,我一邊粘貼一邊想,我要是像在本機的終端環境中,把這些指令寫成 bashrc 中的 alias 就好了。我又可以開始工作了。
于是,我的記事本中的内容一般都是這樣:
從上述兩次流程的對比中,我們發現記事本已經給我們的工作帶來很大的提效了。但是在昨天流程最後我的思考中,我們不難發現,這個提效,還有提升的空間。我認為任何用過 shell 的 alias 的同學都會認同我的觀點:如果上述流程能用alias來記錄這些冗長的指令,我們就不用麻煩記事本了不是嗎?
可是跳闆機是公共資源,有嚴格的使用規範。具體伺服器又是容器化部署,每次部署都會是一個新的容器,是以在目前的bashrc上寫下什麼并沒有用。或許我們能尋找一個新的途徑來實作這個需求。
問題
讓我們從背景中總結我們正在面臨的是哪些問題:
1、工作中存在非常多冗長難記的資訊,需要我們在各個場景反複輸入。
2、這些冗長的資訊來源分散,查找起來非常麻煩耗時。
每次需要輸入時等要通過額外的操作,頻繁切換聚焦的視窗來擷取這些資訊。
3、這些問題雖然各自都占用了我們為數不多的時間和精力,但因為場景小而頻繁,當乘以次數後,這些消耗也變得非常可觀,并且非常影響我們的工作體驗。
思考
讓我們思考一下當我們想要使用 alias 的時候我們實際想要的是什麼?我以個人的經驗來總結,大概是以下幾點:
1、用一個很短的短詞來替代一個需要高頻輸入的很長的句子。
2、用一個更好記的詞替代一個難記易忘的句。
3、配置的成本可控,使用的成本很低。
我們品一品1、2兩點,其本質就是一個字典,由短語為key,長句為value。這個是我們程式員的好朋友了,我們可以簡單的通過一個檔案就能實作這份配置。事實上,我們使用記事本記錄,其實本質也是在使用字典的特性。而第三點,讓我瞬間想到使用 Alfred 的 Workflow 這個Mac上的神器。關于 Alfred 此處不做介紹,不知道或者想要了解的同學可以移步
官網。
設計
其實針對我們已經給出的需求,我們非常容易就可以得出一個設計思路。我們可以固定一個檔案路徑儲存一個檔案,這個檔案以一種簡單的格式或方式儲存一個字典。編寫一個 alfred 的 workflow 來解析這個檔案形成一個 Map ,并通過搜尋和比對 key 來快速的擷取 value ,而擷取 value 最有效的方式就是把 value 輸出到系統的剪切闆中。
考慮到 Mac 和 Alfred 的使用使用者并不全是工程師,我們選擇記錄字典的格式最好越簡單越好。是以我計劃以普通的文本格式,每一行為一個鍵值對,第一個空格前的短詞為 key ,第一個空格後的内容為 value 。直接讓使用者建立指定路徑的檔案并通過編輯檔案的方式來管理的形式确實可以被一部分使用者所接受,但是為了能面對更多使用者,我認為以 workflow 的方式在增删字典的内容也同時是需要支援的。這樣不想關心具體實作、不願接觸文本檔案的使用者同樣可以無感使用。
最後我給這個 workflow 取名為 EasyAlias。
實作
來看一下 workflow 的排版:
通過三個關鍵字的Alfred指令,分别實作設定alias(sal, set alias),删除alias(dal, delete alias),查找(gal, get alias)。
其中sal和dal使用簡單的keyword輸入,而gal為了使用Alfred通過的展示候選清單和搜尋比對的能力,而使用了Script Filter作為輸入。三者都通過shell調用了一個實作主要功能的python腳本easy_alias.py,通過傳入不同的action參數來區分行為。
sal:
python easy_alias.py set {query}
dal:
python easy_alias.py del {query}
gal:
python easy_alias.py show {query}
cat filter.output
easy_alias.py
# coding=utf8
import sys
import json
from os import listdir, makedirs
from os.path import isfile, join, exists, expanduser
base_path = expanduser("~/.easy_alias")
file_name = "alias_conf"
file_path = join(base_path, file_name)
alias_map = dict()
def init():
if not exists(base_path):
makedirs(base_path)
if not exists(file_path):
open(file_path, 'w').close()
def get_key_and_value(text):
seqs = text.strip().split(' ')
if len(seqs) < 2:
return None, None
key = seqs[0];
value = reduce(lambda x, y: x.strip() + ' ' + y.strip(), seqs[1:])
return key, value
def get_alias_map():
with open(file_path, 'r') as f:
for line in f.readlines():
k, v = get_key_and_value(line)
if k == None or v == None:
continue
alias_map[k] = v
def set_alias():
if len(sys.argv) < 3:
return
text = sys.argv[2].strip()
k, v = get_key_and_value(text)
if k == None or v == None:
return
alias_map[k] = v
def del_alias():
if len(sys.argv) < 3:
return
key = sys.argv[2].strip()
new_content = ""
if key in alias_map:
alias_map.pop(key)
def show_alias():
items = list()
for k, v in alias_map.iteritems():
d = {
"uid": k,
"type": "default",
"title": k,
"subtitle": v,
"arg": v,
"autocomplete": k,
"icon": {
"type": "fileticon",
"path": "icon.png"
}
}
items.append(d)
show = {"items": items}
with open('filter.output', 'w') as f:
f.write(json.dumps(show))
def write_map_to_file():
file_content = ''
for k, v in alias_map.iteritems():
file_content += k + ' ' + v + '\n'
with open(file_path, 'w') as f:
f.write(file_content)
if __name__ == '__main__':
init()
get_alias_map()
action = sys.argv[1]
with open(join(base_path, 'logs'), 'a') as f:
f.write(str(sys.argv) + '\n')
if (action == 'set'):
set_alias()
if (action == 'del'):
del_alias()
if (action == 'show'):
show_alias()
write_map_to_file()
效果
設定一個alias
查找一個alias
删除一個alias
如果覺得通過sal設定和dal删除的方式太麻煩,也可以直接編輯~/.easy_alias/alias_conf
儲存檔案再查詢
作業
這個 workflow 本身很簡單很好實作。本文也希望不僅僅隻是一個簡單分享,希望能與讀者有所互動,是以打算留個回家作業。
可以發現現在 dal 指令現在需要使用者盲打key,而不是像gal這樣可以搜尋補全。這會給使用者帶來一定煩惱。回家作業就是将 dal 指令也改造成像 gal 一樣可以搜尋補全的形式。
作業下載下傳 EasyAliasPro總結
讓我們回過頭看一下我們再開始時面對的問題是否得到了很好的解決。
我們無法改變工作中頻繁需要冗長資訊的狀況,但是我們通過通路剪切闆的方式讓輸入變得簡單。
我們用一個檔案将這些資訊集中在一起,并且通過工具打打提升了我們檢索這些資訊的效率。
Alfred提供給我們一個在檢索并擷取這些資訊上無需切換視窗,并且操作非常簡單的方式。
很高興,我們很大程度上解決了我們先前提出的這些問題!
最後
今天我又開發了一個需求,我還需要登入到伺服器上看一下服務運作的日志,确認運作狀态或者看一些debug的資訊。是以我登入到跳闆機,喚醒了Alfred,輸入gal ahostp,并将結果粘貼在指令行獲得了機器清單。登上機器後,我再次喚醒Alfred,輸入gal alog,并粘貼在指令行中。現在我可以開始工作了。
關注「淘系技術」微信公衆号,一個有溫度有内容的技術社群~