Dec
18
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
引用
$ 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 的代理。
领导:明天去财务处结一下工资,后天不用来了。
由于 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.
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 里的另一个版本
REF:
https://gist.github.com/hex-ci/a8c58ac049c4b3a05ef2d6f9d98193c2
说来惭愧,那会儿我就已经用着 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()
# $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
今年开始写公众号,最初是想通过写点东西辅助招聘(真的很缺人)。几篇以后发现效果并不好,但“写作”这件事情却是断断续续坚持下来了。
这背后有些自觉有意思的思考,希望通过本文做一个梳理和总结。
写作
如果写技术博客也算写作的话,那我已经写作十几年了。
刚开始啥也不懂,一个简单的知识点(比如ASCII码表)也写一篇,又或者觍着脸从别的博客转载过来,自己还挺开心 —— 看,又多了一篇。
最近几年我意识到,写作其实就是自己和自己对话的过程。
在这个过程中,你需要把之前输入的知识串到自己的逻辑链上,从而可以很好地把这些知识内化,变成自己的东西。
在写作时我还常常会发现,很多知识点原来并没有吃透。为了把它们写出来,需要进一步查找资料、学习、夯实。
比如之前发的这篇《踩坑记:go服务内存暴涨》,其中 MADV_ADVISE 和 MADV_FREE 这些知识背后的细节也算是现学现卖的,通过写作把它吃透,加入了自己的知识库。
文章被分享后,常会收到很多建设性的讨论,在这个过程中不仅学习到了他人的知识,还通过和他人的对话进一步强化或修正了自己的逻辑链。
越写收获越多、收获越多越愿意写,这样就形成了一个正反馈循环。
视角
在这个过程中,我不断提示自己要注意写作的视角 —— 要充分认识到知识的诅咒。我把它简单理解成“你知道的东西都会觉得简单、不知道的就会觉得难”。
比如快排这个算法,大一的时候我花了很久才想明白它是如何在数组里做原地划分的;而一旦想明白了,就会觉得其实很简单,无非就是两个指针加一个临时变量来回捣腾。
有鉴于此,我们往往是很难完全以新手的视角来看待问题;相信你也注意到,现实中很多高手在实战中很厉害,但是却不擅长教导别人(因此知识的诅咒也称为“专家盲点”)。
这对我的启示是,不要因为觉得某个知识太简单就不写了,实际上越简单的知识能帮到的人越多(所以知识付费大卖的课程往往都是比较简单的课程)。这一点在团队的文档建设中尤其重要。
可读性
另一方面我也在努力提高行文的可读性。
首先,在写作时我会尽量避免思维跳跃,如前所述,有很多自己觉得显而易见的知识点,对于新手往往就是不可逾越的鸿沟。
为什么我们在高数课上容易犯困?因为一旦有个知识点没有衔接上,后面的逻辑都变得无法理解;而对于持续输入的无法理解的信息,大脑只能罢工了。
因此我宁愿行文时啰嗦一些,多补充相关细节。
其次,如果不是严肃话题,我会想办法提高内容的故事性,并选用轻松活跃的措辞。
人类大脑保留的动物性有两个体现,一是喜欢听故事而不是冗长乏味的逻辑推演,二是喜欢即时反馈(给我一袋瓜子,我能磕一个下午)。
这使得今日头条和抖音这样提供即时满足感的app能够如此大行其道,虽然一鸣同学对ByteDancer的要求都是延迟满足。
具体到写作时可以使用一些小技巧,比如在文章中有意识地加入一些段子、表情包、埋包袱,都可以提高阅读体验,从而提升阅读完成率。
为了制造效果,甚至可以考虑植入一些无伤大雅的错误,比如端午节的月饼和中秋节的粽子。
此外,还要尽量避免大段的文字,以避免对阅读者造成视觉上的压迫感。
这也就是这句话要换行、以及隔一段起标题的原因。
分歧
禅宗有云:不立文字。
文字是思维的投影,在这个过程中不可避免地,会丢失一些无法用文字描述的信息。
而阅读则是这个投影的逆过程,因各自阅历不同,每个读者又会融入自己的独特见解。
因此读者很可能无法准确了解作者想表达的含义。
另一方面,即使读者能够理解,往往也会有自己的不同观点。
因此存在分歧属于正常情况,但随之而来的反馈却往往大相径庭。
建设性的反馈
对于这些分歧,有些人会给出建设性的反馈,通过友好而理性的表述,将自己的疑惑或者反对意见表达出来,并且给出自己的理由。
我喜欢这种反馈 —— 有时对方正确,有时我正确,又或者都有考虑不周的地方,但只要双方都怀着最大的诚意,通过充分的沟通和探讨,也就是建设性的讨论,最终可以达成一致或互相理解。
特别需要注意的是,形而上学的问题并不总能达成一致,讨论双方都应当有这样的预期。
这种问题的特点是,各自的观点或结论不具有可证伪性,比如世界的本质是什么,人生的意义是什么,是否应该凡事都相信科学等等。
还有一些情况,比如“如何面试候选人”,现实中不具备可靠的方法来比较各自的观点的优劣,因此也不具备完全达成一致的基础,讨论中就应注意求同存异,而不是升级为对抗性的说服。
破坏性的反馈
另外有些人倾向于给出破坏性的反馈:一旦感觉和自己理念或逻辑有冲突,就上头开喷。
比如“废话太多,一句话掰开十句话说谁都会”,不考虑作者的用意,只凭自己喜好逞口舌之快;又或者“这个需求就是有病”,不考虑问题的背景和受到的现实约束。
他们试图从自己对文字的理解出发,用居高临下的视角来评论以体现自己的正确,因此也放弃了可能对自己有收获的部分。
对这种反馈,最好的办法是不去理会,因为不太可能形成建设性的讨论。
还有些稍好,在反馈中会给出详细的意见,但是语气很重,或通篇透露着只有自己掌握了真理的自信。
理性一点看,这种反馈也有所助益。但人毕竟是感性的,在这种情况下,出于被认可的需要和避免自己认知失调,人的本能是进一步的带着情绪的反驳,因此后续讨论很容易会陷入互相攻讦,最终使得双方进一步分道扬镳。
想要克服这种反驳中夹带的情绪,得通过不断的自省和训练来达成。
这一点也是我还需要改善的地方。今年文章尽管都只有两三千字,但我每次都花费几个小时反复推敲措辞,才形成自己满意的版本。
对于轻佻、不负责任的评论,难免引起情绪的波动;但这都是在这条路上成长必然会遇到的,也给我提供了自省和训练的机会,其实也是很有意思的体验。
收尾
所幸禅宗终究是随着文字流传了下来,这也让人对文字的力量更有信心。
最近发出的文章,收到了很多点赞、收藏和感谢,相信这些读者或多或少从中得到了自己想要的内容,这也是我持续写作的一个动力来源。
最后用一句话自勉:
唯一没有瑕疵的作家是那些从不写作的人。
这背后有些自觉有意思的思考,希望通过本文做一个梳理和总结。
写作
如果写技术博客也算写作的话,那我已经写作十几年了。
刚开始啥也不懂,一个简单的知识点(比如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
在字节跳动,我们使用结构化面试法来考查应聘者的技能。
所谓结构化,指的是将各种知识技能做好划分,例如编程语言,操作系统,数据库,网络,算法,工程/架构设计,并通过几个面试官之间的多轮交叉面试来考查掌握程度。
这样的面试方法,可以避免某个面试官考察太偏,并充分挖掘候选人的亮点。
== 技能 ==
在具体的面试中,每一个方向都会由浅入深去考查。
以编程语言为例,比如某个应聘者常用语言是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
课程结束了,记录一下 Level 7 用到的这些 TED 课程,感觉还不错。
* Level 7
** Unit 1
*** Part 1
On Procrastination
https://www.ted.com/talks/tim_urban_inside_the_mind_of_a_master_procrastinator/transcript
*** Part 2
How Leaders Inspire Us
https://www.ted.com/talks/simon_sinek_how_great_leaders_inspire_action/transcript
*** Part 3
On Endurance
https://www.ted.com/talks/david_blaine_how_i_held_my_breath_for_17_min/transcript
** Unit 2
*** Part 1
Never Ever Give Up
https://www.ted.com/talks/diana_nyad_never_ever_give_up/transcript
*** Part 2
The Boiling River
https://www.ted.com/talks/andres_ruzo_the_mythical_boiling_river_of_the_amazon/transcript
*** Part 3
On Machine Intelligence
https://www.ted.com/talks/zeynep_tufekci_machine_intelligence_makes_human_morals_more_important/transcript
** Unit 3
*** Part 1
Being a Global Citizen
https://www.ted.com/talks/hugh_evans_what_does_it_mean_to_be_a_citizen_of_the_world/transcript
*** Part 2
On Reading Minds
https://www.ted.com/talks/rebecca_saxe_how_brains_make_moral_judgments/transcript
*** Part 3
David and Goliath
https://www.ted.com/talks/malcolm_gladwell_the_unheard_story_of_david_and_goliath/transcript
* Level 8
** Unit 1
*** Part 1
The Math of Love
https://www.ted.com/talks/hannah_fry_the_mathematics_of_love/transcript
* Level 7
** Unit 1
*** Part 1
On Procrastination
https://www.ted.com/talks/tim_urban_inside_the_mind_of_a_master_procrastinator/transcript
*** Part 2
How Leaders Inspire Us
https://www.ted.com/talks/simon_sinek_how_great_leaders_inspire_action/transcript
*** Part 3
On Endurance
https://www.ted.com/talks/david_blaine_how_i_held_my_breath_for_17_min/transcript
** Unit 2
*** Part 1
Never Ever Give Up
https://www.ted.com/talks/diana_nyad_never_ever_give_up/transcript
*** Part 2
The Boiling River
https://www.ted.com/talks/andres_ruzo_the_mythical_boiling_river_of_the_amazon/transcript
*** Part 3
On Machine Intelligence
https://www.ted.com/talks/zeynep_tufekci_machine_intelligence_makes_human_morals_more_important/transcript
** Unit 3
*** Part 1
Being a Global Citizen
https://www.ted.com/talks/hugh_evans_what_does_it_mean_to_be_a_citizen_of_the_world/transcript
*** Part 2
On Reading Minds
https://www.ted.com/talks/rebecca_saxe_how_brains_make_moral_judgments/transcript
*** Part 3
David and Goliath
https://www.ted.com/talks/malcolm_gladwell_the_unheard_story_of_david_and_goliath/transcript
* Level 8
** Unit 1
*** Part 1
The Math of Love
https://www.ted.com/talks/hannah_fry_the_mathematics_of_love/transcript
Apr
24
工作这几年,面试了很多人,也结合了自己工作的经验,有一些心得,但是没有深入地思考过。
正好看到两位大佬的总结,很有共鸣,做个梳理,作为一面镜子,照照自己。
~ 张一鸣:我面了两千个年轻人,发现混的好的都有这5种特质
@ https://www.toutiao.com/i6681549238490366472
~ 谢熊猫君:如何辨认身边的聪明人?
@ https://mp.weixin.qq.com/s/jvqMxdHRRBhhWl29fj3RHg
正好看到两位大佬的总结,很有共鸣,做个梳理,作为一面镜子,照照自己。
~ 张一鸣:我面了两千个年轻人,发现混的好的都有这5种特质
@ https://www.toutiao.com/i6681549238490366472
~ 谢熊猫君:如何辨认身边的聪明人?
@ https://mp.weixin.qq.com/s/jvqMxdHRRBhhWl29fj3RHg