無標題文檔

记次网桥的 Mac 地址改变导致无法链接的问题

家里的小服务器装的是 ArchLinux,在有次 pacman -Syu 以后发现无法连接了,登录上去以后发现原来是网桥的 Mac 地址没有复制过来,导致路由器无法根据 Mac 地址分配正确的 IP 地址。

# ip link show br0
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether <mac> brd ff:ff:ff:ff:ff:ff
# ip link show eno1
2: eno1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP mode DEFAULT group default qlen 1000 link/ether <mac2> ff:ff:ff:ff:ff:ff

原先的网桥配置如下

$ cat /etc/netctl/bridge
Description="Bridge Connection for KVM"
Interface=br0
IP=no
Connection=bridge
BindsToInterfaces=(eno1)
MACAddressOf="eno1"
## Ignore (R)STP and immediately activate the bridge
SkipForwardingDelay=yes

根据配置上的定义 MACAddressOf="eno1" 为复制 eno1 的 Mac 地址,这样子网桥和网卡的 Mac 地址应该一致才是。不知道为何更新重启以后就无法复制 Mac 地址了。

查看了相关的文档,用换了一种方式绑定网卡的 Mac 地址:

$ cat /etc/netctl/bridge
Description="Bridge Connection for KVM"
Interface=br0
IP=no
Connection=bridge
BindsToInterfaces=(eno1)
#MACAddressOf="eno1"
ExecUpPost="ip link set dev br0 address $(cat /sys/class/net/eno1/address); IP=dhcp; ip_set"
ExecDownPre="IP=dhcp"
## Ignore (R)STP and immediately activate the bridge
SkipForwardingDelay=yes

其中,主要是以下两行

ExecUpPost="ip link set dev br0 address $(cat /sys/class/net/eno1/address); IP=dhcp; ip_set"
ExecDownPre="IP=dhcp"

由于 dhcp 让 hook 去获取了,所以务必设置为 IP=no,否则会重复释放 IP 导致网桥无法建立。以下是相关的参考连接:

技术人员如何做好职级晋升答辩

三月即将过去四月份即将到来,很多公司年后的职级晋升安排即将结束。

同时,晋升的结果也将陆陆续续公布出来。几家欢喜几家愁,晋升成功的同事自然值得祝贺,没有过的同事也不要气馁再接再励。

对于技术人员而言,普遍有个很共通的现象,就是往往过于深入技术,忽略了平时对于沟通等所谓「软性素质」的培养和意识,造成可能无法表现出自己真正能力。下面,说说我对职级晋升的一些认知以及经验。

准备阶段

内容控制

通常来说,职级晋升是对去年整年的总结以及回顾,因此从时间的角度上考虑,答辩的内容应该尽量控制在这一年的区间范围内。当然,如果有项目的时间跨度比较长的,应该说明原因同时更需要说明自我在此项目中起到的作用。

往往,主管也答辩人都会犯一个错误,就是将「认为很厉害」的内容和技术点作为答辩的内容,这往往是有偏差的。答辩的内容选题应该从目标职级的角度出发,从目标职级考虑选送的答辩内容是否适合这个职位。

同时,需要根据答辩的时间(自述通常不会超过半小时)来确定选题的数量。因此,答辩的选题是非常重要的,往往选题错误就造成答辩方向的错误。

PPT 是门面

从 PPT 设计的角度上说,技术人员在这块的问题很有典型性,就是往往会将大段的代码(或者截图)贴到 PPT 上。

这会让评委对于内容方面会造成一定的困扰:首先,答辩过程中评委不可能对这块代码进行 Review;其次,从摘抄的这段代码来说也不能体现答辩者应有的水平。

所以,正确的做法应该是觉得需要感觉贴代码解释的地方,尽量贴流程图或者架构图或者 UML,如果还是感觉说不清楚那么建议考虑要不要简化和突出这块想要表述的内容。

技术人员的 PPT 还有个问题就是有太多的文字,这往往会造成表意不清晰。所以,个人的经验就是如果这个 PPT 超过了 200 个字,那么就应该考虑精简。

对 PPT 设计方面的技巧在这块不铺开讲述,网络上已经有更翔实的内容可以找到。

思路和角度很重要

同样的事情,去使用不同的角度去表述,往往返回的结果是不一样的。对于技术人员而言,很容易犯的错误就是将事物「描述得平淡无奇」。这让评委在答辩过程中感觉不到你在这个项目中起到的作用,以及你对这块事物的理解。

例如,有做业务的同学描述了很多对于整个系统的业务以及架构方面的设计,甚至业务的流程是如何流转。但是,根据评委的判断这是团队行为和输出,在答辩的描述中没有体现出其个人对于这个业务的思考和沉淀,以及起到的作用的影响。

所以,对于做业务的同学往往会觉得可能在技术的角度来看,光技术会觉得不够深入。但,换个角度考虑如果结合你对业务的理解,并融合到技术中输出技术的解决方案,那么高度就会不一样。

排练、排练、再排练

答辩的过程和时间是很紧凑的,因此在正式开始答辩前,进行自我排练是非常有必要的。如果条件允许,建议答辩人的主管都能把关一轮,往往在排练过程中就会发现各种问题:答辩人讲述 PPT 的时间、语速以及表达方式能力,等等。

答辩过程中

情绪控制

紧张的情绪能够毁掉所有,甚至让你说话都不利索,尤其作为「相对内向」的技术人员,这块是相对普遍存在的。因此,在答辩开始之前就应该控制和放松自己的情绪,不要过于紧张。

如果过于紧张,这里有个 Tips 可以考虑下:就是作为答辩人你可以认为这是一场技术交流,你尝试说明自己所做的工作以及出彩的地方,让对方觉得自己「很厉害」。

从评委侧也应该给予正向引导,例如答辩人进场的时候打个招呼寒暄一下,也会起到比较好的效果。

节奏控制

答辩开始需要自我介绍,建议两三句话讲重点,千万不要拖泥带水同时夹带不必要的信息。一个失败的自我介绍可能就会毁了整个答辩,毕竟这是你给评委的第一印象。

像上面说的,如果觉得很紧张,那么自我介绍的时候可以稍微刻意放慢下语速,可能会起到调节的作用。

从自我介绍转入到正题的转场口白要自然,如果控制不好演讲的技巧(也不知道应该说什么),那么万精油的一句「下面,我开始我的工作内容介绍」。

在表述 PPT 过程中语速尽量使用中速,前面说的如果排练过那根据内容以及语速,就能找到很好的平衡点。

其实还有个技巧,如果某个技术点很深入或者需要探讨,可以将这个点当作个包袱先抖出来,留给评委后面提问的时候解答。

评委的意图

需要意识到的一个点就是,评委问的所有的问题都有其含义的。如果你的回答让他抓不到他想要的点,那么你的得分会不一定很高的。

例如,当评委问你「这个系统设计的时候,你当时考虑了哪些方面」?这个问题其实反映出两个点:其一,就是你刚才答辩描述的时候没有讲透彻,或者说深度还不够;其二,评委需要个抓手需要了解你对这块的个人理解。

所以,当你回答这个问题的时候,无论从什么角度出发,千万千万不要再介绍业务和系统本身的内容了!应该从自己对这个系统的理解和沉淀出发去阐述自己的理解,如果能表达有一定的输出以及对同事和团队的影响就更好。

答辩后

关注结果、Review 自己

评委对于答辩者的评价是主观的,但是相对答辩的过程其实是客观的。这话说起来可能会有点矛盾,但从「师以质疑,友以折疑」的角度出发, 评委的评价是需要去深入理解的。

对于个人而言,晋升答辩是对过去工作的总结和评价,而不是代表对于未来工作的期待和展望。无论是自我表达的原因,也可能是评委理解不同的原因,评委对答辩者的评价都是不同的,这块需要个人辩证得去理解。

换个角度上考虑,如果你当晋升答辩是一场面试,那么这将是很好理解的一场过程了,而且这场面试的还能看到「面试官」对于自己的评价,何乐而不为呢?

资源和环境

当我们上升个高度去考虑职级晋升的时候,往往就不可避免得聊到职业规划和发展这个老生常谈的问题。

无论答辩的结果怎么样,我们更应该考虑以后的发展。首先,考虑的是个人对于自我提升这块,满足了自我的期望和要求没有;然后,再考虑公司能够提供的环境,能否有个上升的正向上升空间?

能够回答这两个问题,那么自然而然,对于职级这块的理解和态度也就是水到渠成的事情了。

-- eof --

基于「树莓派」的家庭网络服务

当初组建家庭网络的时候,就考虑到自己的需求:主要是网络存储、以及跑部分比较耗时的「定时任务」,例如爬虫和下载还有部分的数据处理等。

本来考虑部署一台性能相对比较好的服务器去处理,但这样子考虑到部署太过中心化不好管理,同时硬件的成本有些高而且占地的面积太大,因此就暂时被我搁置了。

后来想到 空帷 的朋友圈,使用「树莓派」这个方案相对比较轻量,同时多出来的「树莓派」还可以用来它用,因此考虑使用「树莓派」搭建自己的家庭网络服务。

下面是简单的网络拓扑图,同时主要说明下图中的内容:

网络拓扑图

顺便说下,基于「树莓派」我已经写好了几个 Docker 的镜像,主要是文件管理(Netatalk、Syncthing 等)。可以直接拿来部署使用,不用重复造轮子啦:

  1. https://github.com/mingcheng/raspberry-pi3-syncthing
  2. https://github.com/mingcheng/raspberry-pi3-netatalk

- 未完待续 -

扩展 Helidon 的健康检查模块

Helidon Logo

Helidon 是 Oracle 提供的轻量级的微服务框架,提供了 Router、Microprofile、Security 等必要的组件。相对 Spring Boot 等老牌框架而言,它的优势在于轻量同时源代码简单适合阅读。

由于是新出的框架,所以它的文档还不够完善,有时间需要阅读其代码才能明白具体的使用方式。例如,Helidon 的健康检查这块的文档就写得非常的简单,如果想要扩展按照文档中的例子代码将会写得很混乱。

HealthSupport health = HealthSuport.builder()
    .add(() -> HealthCheckResponse.named("exampleHealthCheck")
                 .up()
                 .withData("time", System.currentTimeMillis())
                 .build())                          
    .build();

实际上,Helidon 的 HealthChecks.healthChecks() 已经提供了三个默认的健康检查的反馈,分别是死锁、磁盘以及内存的状态:

/**
    * Built-in health checks.
    *
    * @return built-in health checks to be configured with {@link io.helidon.health.HealthSupport}
    * @see io.helidon.health.HealthSupport.Builder#add(org.eclipse.microprofile.health.HealthCheck...)
    */
public static HealthCheck[] healthChecks() {
    return new HealthCheck[] {
            deadlockCheck(),
            diskSpaceCheck(),
            heapMemoryCheck()
    };
}

分别看其代码就可以发现,这三个直接调用的方法其实就是 HealthCheck 接口的实现。因此,我们自己也可以按照 Helidon 的方式来实现自定义健康检查的项目,满足本地的具体业务的情况。

例如,下面实现了个显示本地服务器时间以及虚拟机的 UPTIME 的状态:

@Health
@ApplicationScoped
public class LocalTimeCheck implements HealthCheck {

  @Override
  public HealthCheckResponse call() {
    return HealthCheckResponse.named("localtime")
        .withData("upTime", ManagementFactory.getRuntimeMXBean().getUptime())
        .withData("currentTime", System.currentTimeMillis())
        .build();
  }
}

然后,在注册到对应的 HealthSupport 中即可:

HealthSupport health = HealthSupport.builder()
    .add(new LocalTimeCheck())
    .build();

顺便说一句,需要注意下:HealthSupport.add() 里面的回调都是同步执行的。

HealthSupport 默认绑定的路由为 /health,如果需要更改这块则根据源代码的提示,增加 .webContext() 这个方法即可,或者直接将其配置到配置文件中:

HealthSupport health = HealthSupport.builder()
    .webContext("/your-health-check-path")
    // ...

- eof -

在 Xorg 中配置苹果的蓝牙键盘

目前同时有台 MacBook Pro 以及 Thinkpad X1,所以想同时使用苹果的蓝牙键盘链接,碰到了键位映射的问题,所以记录下。这次折腾的主要原因是 Thinkpad 的左下角功能键的键位和苹果键盘是不一致,如图:

Apple Keyboard

最主要是对比 Thinkpad 的 Win(Meta) 键和 Alt 和苹果蓝牙键盘的 Apple 和 Alt 是相反的,如果同时使用会有转换的过程,因此需要转换下键位。

硬件方面链接蓝牙的过程就不复述了,Arch Wiki 中有很详细的说明。我使用的是 bluetoothctl 连接硬件,同时使用 BlueMan 作为 GUI 的前端。同时将 BlueMan 加入到 i3wm 的启动脚本中,能够做到自动链接,方便。

键盘链接成功以后,使用 xinput list 查看对应的 device id:

$ xinput list 
⎡ Virtual core pointer                        id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                  id=4    [slave  pointer  (2)]
⎜   ↳ Synaptics TM3072-003                        id=11    [slave  pointer  (2)]
⎜   ↳ Logitech M570                               id=14    [slave  pointer  (2)]
⎜   ↳ TPPS/2 IBM TrackPoint                       id=12    [slave  pointer  (2)]
⎣ Virtual core keyboard                       id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard                 id=5    [slave  keyboard (3)]
    ↳ Power Button                                id=6    [slave  keyboard (3)]
    ↳ Video Bus                                   id=7    [slave  keyboard (3)]
    ↳ Sleep Button                                id=8    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard                id=9    [slave  keyboard (3)]
    ↳ ThinkPad Extra Buttons                      id=10    [slave  keyboard (3)]
    ↳ Integrated Camera: Integrated C             id=13    [slave  keyboard (3)]
    ↳ Apple Inc. Magic Keyboard                   id=15    [slave  keyboard (3)]

其中,能够看到苹果的蓝牙键盘的 device id 是 15,需要暂时记下这个值。然后使用

$ setxkbmap -option altwin:swap_alt_win -device $DEVICE_ID

就可以测试 Win 键和 Alt 键是否对调成功。顺便说一句,对应的还有个命令可以将 Caps Lock 利用起来:

$ setxkbmap -option ctrl:nocaps -device $DEVICE_ID

这样子 Caps Lock 就映射到 Ctrl 键了。具体更多的设置可以在这里 查看(我是 Arch Wiki 的搬运工 😄)。

这样子还有点不方便的地方,就是每次链接蓝牙键盘的时候都要跑下这个命令,于是还是考虑到使用 udev 脚本去自动化。下面是我的 udev 脚本,可以供参考:

ACTION=="bind", SUBSYSTEM=="hid*", DRIVER=="*apple*", RUN+="/usr/bin/sudo -i -u <user> /<path>/key-mapping.sh"

然后还需要考虑到插入 USB 键盘的情况,这再多加一条规则:

ACTION=="bind", SUBSYSTEM=="usb", ENV{ID_VENDOR}=="Apple*", RUN+="/usr/bin/sudo -i -u <user>  /<path>/key-mapping.sh"

其中,key-mapping.sh 是复制下上面命令的脚本。

然后,将这个命令保存到个 rules 文件中,例如我的文件命名是 90-bluetooth-keyboard-mapping.rules 然后放到 /etc/udev/rules.d

最后,重启 udev 规则 sudo udevadm control -R 即可。

- eof -

我的照片

嗨!我叫「明城」,八零后、码农、宁波佬,现居杭州。除了这里,同时也欢迎您关注我的 GitHubTwitterInstagram 等。

这个 Blog 原先的名字叫 Gracecode.com 、现在叫 「無標題文檔」 。 其实无所谓叫什么名字,作为码农知道取名是件很难的事情。最后想到的这个名字,其实都没啥特别的含义,系统默认的文件名而已。

作为八零后,自认为还仅存点傲娇式的幽默感,以及对平淡生活的追求和向往。 为了免得对号入座和不必要的麻烦,声明本站点所持观点仅代表个人意见,不代表自己所服务公司的立场。

如果您想联系我,可以发我邮件 `echo bWluZ2NoZW5nQGdyYWNlY29kZS5jb20K | base64 -d`

文章

项目