Dec 18

xxd, join, and fold 不指定

felix021 @ 2023-12-18 18:04 [随想] 评论(0) , 引用(0) , 阅读(1099) | Via 本站原创
1. Get character count in a line

引用

$ xxd packets | head -n 1 | wc -c
68


2. Join lines

引用

xxd packets | tr -d '\n' && echo


Save the output to local file "packets.xxd".

3. Fold lines and decode

引用

fold packets.xxd -w 67 | xxd -r > packets

Sep 1
2009年在 B 厂实习的时候,人手发一个硬件 token,它有个屏幕,实时显示 6 位 TOTP ,用于登录 relay 机器,再通过 relay 机器登录生产环境的机器。

由于 relay 机器禁用了端口转发等各种 fancy 的能力,所以除了 shell 上的输入和输出外无法实现额外的通信。

好在 SecureCRT 默认支持 zmodem 协议,大家都用 sz/rz 来上传/下载文件,也还算方便。

sz 是基于 zmodem 协议实现的,这个功能在早期的 BBS 上非常实用。

简单说就是,通过发送一个特殊的控制串,告诉 terminal 它想要发送一个文件,支持 zmodem 协议的 terminal 会将后续发送的数据保存到本地文件中。

当然具体的协议细节比较复杂,不是本文重点,就不展开了,详情可参考知乎这位老哥的整理 https://zhuanlan.zhihu.com/p/579720546

继续发散,我们可以想象一下,如果我们实现 2 个程序 A、B:

1. A 通过 ssh 连接到目标机器,打开 B
2. 用 B 的 stdin/stdout 来「模拟」一个 tcp 连接
3. 在这个「tcp 连接」上用 xtaci/smux 实现多路复用
4. 在 A 实现 socks5 的前端(监听),在 B 实现 socks5 的后端(转发)

这样我们就实现了一个穿透了 relay 的代理。

领导:明天去财务处结一下工资,后天不用来了。
Feb 24
Why: kitex framework is using gofumpt as linter in gitlab CI, but goland defaults to use gofmt, which enforces weaker rules.

Procedure:

0. $ go install mvdan.cc/gofumpt@v0.2.0  # or any version as you need

1. Install file watcher plugin in goland settings;

2. Go to settings -> Tools -> File Watchers:

2.1. Click on "+", and choose "go fmt"

2.2. Replace "Program:" to be the full path of your gofumpt binary

2.3. Modify "Arguments:" to be "-w $FilePath$"

2.4 OK & OK again.
Aug 9
遥想第一次听说Google Authenticator已经是 7年前的事情 了,那时候它还托管在 Google Code 上(缅怀)。

说来惭愧,那会儿我就已经用着 SecureCRT 好几年了,就在D厂的时候大家都在用的那个D版。今年终于咬牙买了个正版,突然意识到它的Logon Script可以用来搞这个两步认证,上网搜了一下,已经有大神写好放在 gist 上了,于是抄了一把,略作改动,贴在这里。

注意:
1. 记得要把 SecureCRT session option里 Login Actions → "Display logon prompts in terminal window" 勾上。
2. 这个版本是windows版用的,保存成py文件;用mac版的同学,要看下scrt的脚本引擎是py2还是py3,py3的话,得用原作者这个 gist 里的另一个版本

# $language = "python"
# $interface = "1.0"

import hmac, base64, struct, hashlib, time, json, os

TOTP_KEY = 'YOUR_TOTP_KEY'
YOUR_PASSWD = 'PASSWORD'

def get_hotp_token(secret, intervals_no):
  """This is where the magic happens."""
  key = base64.b32decode(normalize(secret), True) # True is to fold lower into uppercase
  msg = struct.pack(">Q", intervals_no)
  h = hmac.new(key, msg, hashlib.sha1).digest()
  o = ord(h[19]) & 15
  h = str((struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff) % 1000000)
  return prefix0(h)


def get_totp_token(secret):
  """The TOTP token is just a HOTP token seeded with every 30 seconds."""
  return get_hotp_token(secret, intervals_no=int(time.time())//30)


def normalize(key):
  """Normalizes secret by removing spaces and padding with = to a multiple of 8"""
  k2 = key.strip().replace(' ','')
  # k2 = k2.upper()  # skipped b/c b32decode has a foldcase argument
  if len(k2)%8 != 0:
    k2 += '='*(8-len(k2)%8)
  return k2


def prefix0(h):
  """Prefixes code with leading zeros if missing."""
  if len(h) < 6:
    h = '0'*(6-len(h)) + h
  return h


def main():
  tab = crt.GetScriptTab()

  if tab.Session.Connected != True:
    crt.Dialog.MessageBox("Session Not Connected")
    return

  tab.Screen.Synchronous = True
  tab.Screen.WaitForStrings(['[MFA auth]:'])
  vc = get_totp_token(TOTP_KEY)
  tab.Screen.Send("{vc}\r\n".format(vc=vc))
  tab.Screen.WaitForStrings(['Opt>'])
  tab.Screen.Send("relay2\r\n")
  if tab.Screen.WaitForString('password:', 1):
      tab.Screen.Send("{pwd}\r\n".format(pwd=YOUR_PASSWD)) #鄙厂的relay后面还有个relay
  return

main()


REF:
https://gist.github.com/hex-ci/a8c58ac049c4b3a05ef2d6f9d98193c2
Jul 6

关于写作的一点思考 不指定

felix021 @ 2020-7-6 01:07 [随想] 评论(2) , 引用(0) , 阅读(3262) | Via 本站原创
今年开始写公众号,最初是想通过写点东西辅助招聘(真的很缺人)。几篇以后发现效果并不好,但“写作”这件事情却是断断续续坚持下来了。 

这背后有些自觉有意思的思考,希望通过本文做一个梳理和总结。 


写作

如果写技术博客也算写作的话,那我已经写作十几年了。

刚开始啥也不懂,一个简单的知识点(比如ASCII码表)也写一篇,又或者觍着脸从别的博客转载过来,自己还挺开心 —— 看,又多了一篇。

最近几年我意识到,写作其实就是自己和自己对话的过程

在这个过程中,你需要把之前输入的知识串到自己的逻辑链上,从而可以很好地把这些知识内化,变成自己的东西。

在写作时我还常常会发现,很多知识点原来并没有吃透。为了把它们写出来,需要进一步查找资料、学习、夯实。

比如之前发的这篇《踩坑记:go服务内存暴涨》,其中 MADV_ADVISE 和 MADV_FREE 这些知识背后的细节也算是现学现卖的,通过写作把它吃透,加入了自己的知识库。

文章被分享后,常会收到很多建设性的讨论,在这个过程中不仅学习到了他人的知识,还通过和他人的对话进一步强化或修正了自己的逻辑链。

越写收获越多、收获越多越愿意写,这样就形成了一个正反馈循环


视角

在这个过程中,我不断提示自己要注意写作的视角 —— 要充分认识到知识的诅咒。我把它简单理解成“你知道的东西都会觉得简单、不知道的就会觉得难”。

比如快排这个算法,大一的时候我花了很久才想明白它是如何在数组里做原地划分的;而一旦想明白了,就会觉得其实很简单,无非就是两个指针加一个临时变量来回捣腾。

有鉴于此,我们往往是很难完全以新手的视角来看待问题;相信你也注意到,现实中很多高手在实战中很厉害,但是却不擅长教导别人(因此知识的诅咒也称为“专家盲点”)。

这对我的启示是,不要因为觉得某个知识太简单就不写了,实际上越简单的知识能帮到的人越多(所以知识付费大卖的课程往往都是比较简单的课程)。这一点在团队的文档建设中尤其重要。


可读性

另一方面我也在努力提高行文的可读性

首先,在写作时我会尽量避免思维跳跃,如前所述,有很多自己觉得显而易见的知识点,对于新手往往就是不可逾越的鸿沟。

为什么我们在高数课上容易犯困?因为一旦有个知识点没有衔接上,后面的逻辑都变得无法理解;而对于持续输入的无法理解的信息,大脑只能罢工了。

因此我宁愿行文时啰嗦一些,多补充相关细节。

其次,如果不是严肃话题,我会想办法提高内容的故事性,并选用轻松活跃的措辞

人类大脑保留的动物性有两个体现,一是喜欢听故事而不是冗长乏味的逻辑推演,二是喜欢即时反馈(给我一袋瓜子,我能磕一个下午)。

这使得今日头条和抖音这样提供即时满足感的app能够如此大行其道,虽然一鸣同学对ByteDancer的要求都是延迟满足

具体到写作时可以使用一些小技巧,比如在文章中有意识地加入一些段子、表情包、埋包袱,都可以提高阅读体验,从而提升阅读完成率。

为了制造效果,甚至可以考虑植入一些无伤大雅的错误,比如端午节的月饼和中秋节的粽子。 

此外,还要尽量避免大段的文字,以避免对阅读者造成视觉上的压迫感。 

这也就是这句话要换行、以及隔一段起标题的原因。


分歧

禅宗有云:不立文字。

文字是思维的投影,在这个过程中不可避免地,会丢失一些无法用文字描述的信息。

而阅读则是这个投影的逆过程,因各自阅历不同,每个读者又会融入自己的独特见解。

因此读者很可能无法准确了解作者想表达的含义

另一方面,即使读者能够理解,往往也会有自己的不同观点。

因此存在分歧属于正常情况,但随之而来的反馈却往往大相径庭。


建设性的反馈

对于这些分歧,有些人会给出建设性的反馈,通过友好而理性的表述,将自己的疑惑或者反对意见表达出来,并且给出自己的理由。

我喜欢这种反馈 —— 有时对方正确,有时我正确,又或者都有考虑不周的地方,但只要双方都怀着最大的诚意,通过充分的沟通和探讨,也就是建设性的讨论,最终可以达成一致或互相理解。

特别需要注意的是,形而上学的问题并不总能达成一致,讨论双方都应当有这样的预期。

这种问题的特点是,各自的观点或结论不具有可证伪性,比如世界的本质是什么,人生的意义是什么,是否应该凡事都相信科学等等。

还有一些情况,比如“如何面试候选人”,现实中不具备可靠的方法来比较各自的观点的优劣,因此也不具备完全达成一致的基础,讨论中就应注意求同存异,而不是升级为对抗性的说服。


破坏性的反馈

另外有些人倾向于给出破坏性的反馈:一旦感觉和自己理念或逻辑有冲突,就上头开喷。

比如“废话太多,一句话掰开十句话说谁都会”,不考虑作者的用意,只凭自己喜好逞口舌之快;又或者“这个需求就是有病”,不考虑问题的背景和受到的现实约束。

他们试图从自己对文字的理解出发,用居高临下的视角来评论以体现自己的正确,因此也放弃了可能对自己有收获的部分。 

对这种反馈,最好的办法是不去理会,因为不太可能形成建设性的讨论。

还有些稍好,在反馈中会给出详细的意见,但是语气很重,或通篇透露着只有自己掌握了真理的自信。

理性一点看,这种反馈也有所助益。但人毕竟是感性的,在这种情况下,出于被认可的需要和避免自己认知失调,人的本能是进一步的带着情绪的反驳,因此后续讨论很容易会陷入互相攻讦,最终使得双方进一步分道扬镳。

想要克服这种反驳中夹带的情绪,得通过不断的自省和训练来达成。

这一点也是我还需要改善的地方。今年文章尽管都只有两三千字,但我每次都花费几个小时反复推敲措辞,才形成自己满意的版本。

对于轻佻、不负责任的评论,难免引起情绪的波动;但这都是在这条路上成长必然会遇到的,也给我提供了自省和训练的机会,其实也是很有意思的体验。


收尾

所幸禅宗终究是随着文字流传了下来,这也让人对文字的力量更有信心。

最近发出的文章,收到了很多点赞、收藏和感谢,相信这些读者或多或少从中得到了自己想要的内容,这也是我持续写作的一个动力来源。

最后用一句话自勉: 

唯一没有瑕疵的作家是那些从不写作的人。
Feb 15
== 结构化面试 ==

在字节跳动,我们使用结构化面试法来考查应聘者的技能。

所谓结构化,指的是将各种知识技能做好划分,例如编程语言,操作系统,数据库,网络,算法,工程/架构设计,并通过几个面试官之间的多轮交叉面试来考查掌握程度。

这样的面试方法,可以避免某个面试官考察太偏,并充分挖掘候选人的亮点。

== 技能 ==

在具体的面试中,每一个方向都会由浅入深去考查。

以编程语言为例,比如某个应聘者常用语言是Python,我会先考查一些语言的基础特性,例如什么是magic function,__repr__ 和 __str__ 的区别等。

确认候选人对语言的使用掌握符合预期后,再考查候选人对python底层实现的理解,例如展开聊聊python的gc相关知识。

更进一步,可以结合一些具体的应用场景来考查候选人对语言的综合应用能力,例如使用Python的多线程,需要考虑什么,如何提高某些任务中的效率等。

通过这样的综合考察,我避开了所有学过下面这本书的程序员。

点击在新窗口中浏览此图片


== 算法 ==

值得一提的是算法/数据结构,这是字节跳动面试的一大特点,也是网上各面经都会提(tu)到(cao)的。

点击在新窗口中浏览此图片

通常来说每一轮面试都会要求候选人完成一道算法题,现场面试就直接在纸上写,远程面试则是在在线共享编辑的IDE环境里完成。

可能早期常有面试官让候选人手写红黑树,以至于"手写红黑树"已经成为一个内部梗。

点击在新窗口中浏览此图片

实际上难度没有太夸张,通常来说15分钟内完成 Leetcode Medium 级别的题目,就能满足面试要求了(划重点)。

我更倾向于考查操作基础数据结构的题目,关注点放在对代码的掌控力,而不是某个具体的算法。

不过,对于有ACM经历的同学,面试官可能会尝试用 Hard 级别题目来challenge。比如我内推的某同学被问了 manacher's algorithm,可能是和面试官八字不合。

但也不用太担心,毕竟不是谁都像他一样拿了ACM金牌。

点击在新窗口中浏览此图片

== 沟通 ==

候选人的沟通能力也是考查的重点。

例如,在面试中的工程设计题通常是开放式问题,题面往往不是精确的,问题的规模,可能存在的问题,或者可以忽略的一些细节,都可以在前期的沟通中确认,然后再开始设计。

点击在新窗口中浏览此图片

还有,在面试过程中的知识盲点,要注意避免不懂装懂的强行作答,但利用已有知识做出的合理推测则是加分项。两种行为的边界可能有点模糊,这就考验候选人的沟通技巧了。

== 总结 ==

我想要招什么样的候选人?概括而言就是:聪明,勤奋,有潜力。

更具体的,大佬早就讲过了,推荐阅读字节跳动创始人张一鸣的演讲《我面了两千个年轻人,发现混得好的都有这5种特质》:https://www.toutiao.com/i6681549238490366472

== 硬广 ==

最后,我目前在字节跳动的网盟广告业务线(穿山甲),由于业务持续高速发展,长期缺人、不限HC,欢迎踊跃投递:

后端开发(上海):https://job.toutiao.com/s/sBAvKe

后端开发(北京):https://job.toutiao.com/s/sBMyxk

广告策略研发(上海):https://job.toutiao.com/s/sBDMAK

测试开发(上海):https://job.toutiao.com/s/sBUKuh

其他地区、职能线:https://job.toutiao.com/s/sB9Jqk
Jul 4

英语流利说 TED 课程 不指定

felix021 @ 2019-7-4 00:04 [随想] 评论(0) , 引用(0) , 阅读(2512) | Via 本站原创
Apr 24
工作这几年,面试了很多人,也结合了自己工作的经验,有一些心得,但是没有深入地思考过。

正好看到两位大佬的总结,很有共鸣,做个梳理,作为一面镜子,照照自己。



~ 张一鸣:我面了两千个年轻人,发现混的好的都有这5种特质

  @ https://www.toutiao.com/i6681549238490366472

点击在新窗口中浏览此图片


~ 谢熊猫君:如何辨认身边的聪明人?

  @ https://mp.weixin.qq.com/s/jvqMxdHRRBhhWl29fj3RHg

点击在新窗口中浏览此图片
分页: 1/4 第一页 1 2 3 4 下页 最后页 [ 显示模式: 摘要 | 列表 ]