macOS 神器 Workflow ,让效率翻倍!

本文涉及的产品
运维安全中心(堡垒机),免费版 6个月
日志服务 SLS,月写入数据量 50GB 1个月
运维安全中心(堡垒机),企业双擎版 50资产 7天
简介: 【Alfred Workflow】放过你的记事本,用EasyAlias来提效

滚动.gif

背景

一起回顾一个大家非常熟悉场景。

上周开发一个需求,开发过程中,我需要登录到服务器上看一下服务运行的日志,确认运行状态或者看一些debug的信息。所以我登录到跳板机,此时我发现我忘了某一台机器的具体名字(通常能记得的人都是天才),所以需要用跳板机提供的 autoget 命令来通过服务器组名来获得机器的列表。

此时我发现我连服务器组名都忘了,所以需要上 eagle eye 上查寻一下组名。这个查询可能得依靠我的记忆打出组名的前缀,通过 eagle eye 给出的补全提示列表来识别出其中那个我需要的组名。

终于我得到了我的组名,为了避免我下次再忘记而不得不再繁琐的查询一遍,我选择把这些结果记录到我的记事本中,方便我下次查找使用。终于我登录了机器,可是不巧我忘了日志记录的位置,我想起某个同事曾经告诉过我日志的路径,于是我查找了与那个同事的聊天记录,找到了这个日志路径。同样为了防止忘记,我又把它记录到了我的记事本中方便下次查找。然后我把日志路径复制粘贴到命令行,我终于可以开始工作了。

昨天我又开发了一个需求,我还需要登录到服务器上看一下服务运行的日志,确认运行状态或者看一些 debug 的信息。所以我登录到跳板机,需要用跳板机提供的 autoget 命令来通过服务器组名来获得机器的列表,我想起了我在记事本中记录了这个内容,于是我打开记事本,搜索了 keyword,在简单的翻找下,我找到了我想要的命令。

进入到机器后,我发现日志的路径我还是没有记住。于是,我再次打开记事本,搜索了另一个 keyword ,再次翻找了一下,找到路径后把它复制粘贴到命令行,我一边粘贴一边想,我要是像在本机的终端环境中,把这些命令写成 bashrc 中的 alias 就好了。我又可以开始工作了。

于是,我的记事本中的内容一般都是这样:

image.png

从上述两次流程的对比中,我们发现记事本已经给我们的工作带来很大的提效了。但是在昨天流程最后我的思考中,我们不难发现,这个提效,还有提升的空间。我认为任何用过 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 的排版:

image.png

通过三个关键字的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

image.png

查找一个alias

image.png

删除一个alias

image.png

如果觉得通过sal设置和dal删除的方式太麻烦,也可以直接编辑~/.easy_alias/alias_conf

image.png

保存文件再查询

image.png

作业

这个 workflow 本身很简单很好实现。本文也希望不仅仅只是一个简单分享,希望能与读者有所互动,所以打算留个回家作业。

可以发现现在 dal 命令现在需要使用者盲打key,而不是像gal这样可以搜索补全。这会给使用者带来一定烦恼。回家作业就是将 dal 命令也改造成像 gal 一样可以搜索补全的形式。

作业下载
EasyAliasPro

总结

让我们回过头看一下我们再开始时面对的问题是否得到了很好的解决。

我们无法改变工作中频繁需要冗长信息的状况,但是我们通过访问剪切板的方式让输入变得简单。
我们用一个文件将这些信息集中在一起,并且通过工具打打提升了我们检索这些信息的效率。
Alfred提供给我们一个在检索并获取这些信息上无需切换窗口,并且操作非常简单的方式。

很高兴,我们很大程度上解决了我们先前提出的这些问题!

最后

今天我又开发了一个需求,我还需要登录到服务器上看一下服务运行的日志,确认运行状态或者看一些debug的信息。所以我登录到跳板机,唤醒了Alfred,输入gal ahostp,并将结果粘贴在命令行获得了机器列表。登上机器后,我再次唤醒Alfred,输入gal alog,并粘贴在命令行中。现在我可以开始工作了。

关注「淘系技术」微信公众号,一个有温度有内容的技术社区~

image.png

相关文章
|
微服务 测试技术 Java
阿里技术专家详解 DDD 系列- Domain Primitive
关于DDD的一系列文章,希望能继续在总结前人的基础上发扬光大DDD的思想,但是通过一套我认为合理的代码结构、框架和约束,来降低DDD的实践门槛,提升代码质量、可测试性、安全性、健壮性。
62255 17
阿里技术专家详解 DDD 系列- Domain Primitive
|
SQL 分布式计算 数据处理
FlinkSQL开发经验分享
FlinkSQL开发经验分享
429 8
|
11月前
|
监控 搜索推荐 开发工具
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
1086 2
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
495 2
基于Redis的高可用分布式锁——RedLock
|
机器学习/深度学习 人工智能 自然语言处理
从人工智能到大模型的演变
本文概述了人工智能从早期的规则基础系统到现代大模型的演变过程,涵盖了符号主义、专家系统、统计学习、深度学习、自然语言处理以及大模型的出现与应用,分析了各阶段的关键技术和面临的挑战,展望了未来的发展方向。
593 3
|
SQL 监控 Java
C3P0数据库连接池
C3P0数据库连接池
368 0
|
关系型数据库 MySQL 数据库
MySQL8.0.36 安装配置教程(保姆级,包含图文讲解,环境变量的配置)适合小白
MySQL8.0.36 安装配置教程(保姆级,包含图文讲解,环境变量的配置)适合小白
|
数据库 开发者 Python
Bottle 究竟藏着何种魔力?带你走进精彩世界,畅享 Web 开发新体验!
【8月更文挑战第31天】Bottle 是一款轻量级 Python Web 框架,以其简洁、灵活和高效著称,让开发者快速上手,自由组织代码,轻松应对从个人博客到企业应用的各种项目。尽管体积小巧,性能却不容小觑,同时拥有丰富的插件生态系统,便于扩展功能。
235 0
|
数据可视化 JavaScript 前端开发
【数据分析与可视化】pyecharts可视化图表讲解及实战(超详细 附源码)
【数据分析与可视化】pyecharts可视化图表讲解及实战(超详细 附源码)
1194 0
|
自然语言处理 安全 网络安全
22LLMSecEval数据集及其在评估大模型代码安全中的应用:GPT3和Codex根据LLMSecEval的提示生成代码和代码补全,CodeQL进行安全评估【网安AIGC专题11.22】
22LLMSecEval数据集及其在评估大模型代码安全中的应用:GPT3和Codex根据LLMSecEval的提示生成代码和代码补全,CodeQL进行安全评估【网安AIGC专题11.22】
413 0