Author Archives: Cipher Chen

2019.11.13 星期三 代码工作者

这篇文章写的

2019.11.13 星期三 代码工作者

虽然这么多年来我一直在IT行业,方向从未转变过,甚至专业也一样,一直是一名程序员,但我仍旧认为,
在我刚毕业入行之际,那时的我还远称不上是一名程序员。

我们不能轻易地称一位有写作习惯的人为作家,就像我习惯每天都用文字记录些什么,但你还是不能称我为
作家。因为我很有自知之明,知道自己写的文字值几斤几两,确切地说,是不值几斤几两。对于一位有写作
习惯的人,我们也不能贸然称他为作家。众所周知,一个人即便对于写作有着异于常人的兴趣,以及决心,除非
他写出了一些足够好的文章或书籍,我们才会称之为作家。文章或书籍的数量要求不一,对于天赋异禀之人,
如玛格丽特·米切尔,只一本《乱世佳人》就无人能撼动其在文学史上的地位。而对如今充斥网络的网文作家,
确切地说,我们应该称他们为,网文文字工作者。工作者听起来没有作家段位高,这是必然的,因为文字工作者
卖文章收稿费,是按文章字数来定价的,比如千字一百。这些文章不论内容如何精彩纷呈、立意如何深刻、辞藻
如何华丽,一律按文章总字数来收费。还有类似行业的是翻译。对于一位初级翻译而言,他的稿费同样也是按字数收费的。
只有当这些工作者的努力积攒到由量变产生了质变,成名之后,不再按照字数来收费了,我们才称之为作家或者翻译家。

评估一位程序员的工作是很难量化的,
虽然你可能花了更少时间写代码,甚至花了大量时间重构代码,把以前一千行的文件,优化成了五百行,但除非对
这部分代码有如作者般的了解程度的人,其它人未必能发现这些工作的价值。于是乎,在早期的软件工程领域,
程序员的工作是通过代码行数来量化的。你提交的commit的代码行数越多,那么就认为你的工作输出越大,
绩效考核就越高。这听起来是个笑话,但这个行业可能也就时至目前,才逐渐摒弃了这种评估方法。

大概是2011年底,我已经坚定了自己成为一名程序员的决心。
但我刚入行时就碰到了这些让人“愤愤不平”的绩效考核问题。
当时我也很纳闷,“凭什么要用代码行数这个明显不合理的指标来评估程序员的工作呢?”
直到推人及己时,我才明白这个道理。
所以我称我刚入行时为“代码工作者”,因为我写的代码并未产生出显著的效应。
这时的工作成绩,就像是文字工作者在成长为“作家”前所做的量的积累。
这个时候的代码,更多的是为了锻炼自己的编码技巧,就像钢琴家在成为钢琴家之前所做的数万小时的对琴键的敲击。

而今我早已过了这个“愤愤不平”的问题,不再纠结于程序员的工作量考核是否取决于代码量。
就像任何一个行业的入门新手到顶级专家,都必须经过一定的修炼,经过量变产生质变。
抛弃花里胡哨的技巧,而专注于完成一件“事”,才是一个从业人员职业上的升华。

完成一件“事”,要求有多方面的能力。
以我的工作为例,需要完成方案调研、项目规划、产品形态设计、问题跟踪、人员调配等等。
最后才是编码工作。
所以我不再固执地称自己为一名“程序员”,因为我需要做的远远比一名程序员要做的编码工作要更多。

“Get things done” 才是一项职业的目标。

问题排查:haproxy tcp 长连接没有 failover

这篇文章写的

问题排查:haproxy tcp 长连接没有 failover

现象

客户端 192.168.1.35:1234 和 haproxy 监听的 192.168.1.100:81 端口建立长连接;

haproxy 有两个后端,192.168.1.38:81、192.168.1.29:81,
因为工作在非透明模式,假设这个长连接,是和 192.168.1.29:81 建立的。

客户端长连接建立后,在 haproxy 上能看到两个 keepalive 连接:

# netstat -anpto | grep "\:81" | grep keepalive
tcp        0      0 192.168.1.100:42554     192.168.1.29:81         ESTABLISHED 9943/haproxy     keepalive (30.28/0/0)
tcp        0      0 192.168.1.39:81         192.168.1.35:43620      ESTABLISHED 9943/haproxy     keepalive (30.28/0/0)

这时,可以在 haproxy 上加一个 iptables 规则:

iptables -A OUTPUT -d 192.168.1.29 -m tcp -p tcp --dport 81 -j DROP

来模拟后端宕机的情况。

当 192.168.1.29:81 断开时,haproxy 能快速地检测到后端宕机,并修改状态:

root@i-hv6jj9ay:~# /usr/local/bin/lb-collect 'show status'
lbb-0vo2fiec|UP
lbb-811tmjow|UP
lbb-v8y2j191|UP 1/2
root@i-hv6jj9ay:~# /usr/local/bin/lb-collect 'show status'
lbb-0vo2fiec|UP
lbb-811tmjow|UP
lbb-v8y2j191|DOWN
root@i-hv6jj9ay:~#

但这个客户端的长连接没有正常断开,并且hang住了。

也就是说,haproxy 没有对这种长连接的场景做 failover。

分析

haproxy 的长连接配置,有个隧道超时时间设置,

这个参数,表示长连接的两端,空闲多久后,会被认为是连接已中断。所以也不能改太小。

  • timeout tunnel

    The tunnel timeout applies when a bidirectional connection is established
    between a client and a server, and the connection remains inactive in both
    directions. This timeout supersedes both the client and server timeouts once
    the connection becomes a tunnel. In TCP, this timeout is used as soon as no
    analyser remains attached to either connection (eg: tcp content rules are
    accepted). In HTTP, this timeout is used when a connection is upgraded (eg:
    when switching to the WebSocket protocol, or forwarding a CONNECT request
    to a proxy), or after the first response when no keepalive/close option is
    specified.

    Since this timeout is usually used in conjunction with long-lived connections,
    it usually is a good idea to also set “timeout client-fin” to handle the
    situation where a client suddenly disappears from the net and does not
    acknowledge a close, or sends a shutdown and does not acknowledge pending
    data anymore. This can happen in lossy networks where firewalls are present,
    and is detected by the presence of large amounts of sessions in a FIN_WAIT
    state.

  • on-marked-down

    Modify what occurs when a server is marked down.

    Currently one action is available:

    • shutdown-sessions: Shutdown peer sessions. When this setting is enabled,
      all connections to the server are immediately terminated when the server
      goes down. It might be used if the health check detects more complex cases
      than a simple connection status, and long timeouts would cause the service
      to remain unresponsive for too long a time. For instance, a health check
      might detect that a database is stuck and that there’s no chance to reuse
      existing connections anymore. Connections killed this way are logged with
      a ‘D’ termination code (for “Down”).

      这个参数,默认是disabled的。

      测试发现,对于一个keepalive的长连接,如果backend能够在宕机后的一定时间
      (也就是tunnel timeout)内及时恢复,那么这个长连接是还能够继续的。
      所以这个参数,默认没有配置成enabled

解决

配置 default-server on-marked-down shutdown-sessions

```
default-server on-marked-down shutdown-sessions
server  lbb-811tmjow 192.168.1.29:81 check inter 200 fall 1 rise 1 weight 1
server  lbb-v8y2j191 192.168.1.38:81 check inter 200 fall 1 rise 1 weight 1
```
</code></pre>

或者是配置在某个特定的<code>server</code>里,

<pre><code>```
# default-server on-marked-down shutdown-sessions
server  lbb-811tmjow 192.168.1.29:81 check inter 200 fall 1 rise 1 weight 1
server  lbb-v8y2j191 192.168.1.38:81 check inter 200 fall 1 rise 1 weight 1 on-marked-down shutdown-sessions
```

来确保当一个后端下线时,与这个后端相关的连接都会直接断掉。

参考

问题排查:ssh到CentOS上很慢甚至超时

这篇文章写的

现象

部分线上机器 ssh 到一台跳板的 CentOS 主机时,总是连接不上,但其它客户端是能正常ssh到这台跳板机的。

加上 timeout 之后,发现总是会超时。

root@host:~# timeout 5 ssh root@1.2.3.4 -p 2222
root@host:~#

分析

通过其它地方跳转到CentOS server,抓包分析并查看连接,发现

  1. 其实三次握手已经成功建立连接,但连接建立后,两端在反复的发送接收流量,似乎在传输什么数据或者确认什么信息:
# 前三个包,说明已经完成了握手
22:23:46.194993 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [S], seq 4277261782, win 28690, options [mss 1510,nop,nop,TS val 470231038 ecr 0,nop,wscale 10], length 0
22:23:46.195046 IP 100.67.76.58.EtherNet/IP-1 > 10.16.150.17.53924: Flags [S.], seq 3085339803, ack 4277261783, win 28960, options [mss 1460,nop,nop,TS val 186346509 ecr 470231038,nop,wscale 7], length 0
22:23:46.195133 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [.], ack 1, win 29, options [nop,nop,TS val 470231038 ecr 186346509], length 0
22:23:46.195329 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [P.], seq 1:50, ack 1, win 29, options [nop,nop,TS val 470231039 ecr 186346509], length 49
22:23:46.195348 IP 100.67.76.58.EtherNet/IP-1 > 10.16.150.17.53924: Flags [.], ack 50, win 227, options [nop,nop,TS val 186346510 ecr 470231039], length 0
22:23:46.207342 IP 100.67.76.58.EtherNet/IP-1 > 10.16.150.17.53924: Flags [P.], seq 1:24, ack 50, win 227, options [nop,nop,TS val 186346522 ecr 470231039], length 23
22:23:46.207416 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [.], ack 24, win 29, options [nop,nop,TS val 470231051 ecr 186346522], length 0
22:23:46.207770 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [P.], seq 50:1458, ack 24, win 29, options [nop,nop,TS val 470231051 ecr 186346522], length 1408
22:23:46.208860 IP 100.67.76.58.EtherNet/IP-1 > 10.16.150.17.53924: Flags [P.], seq 24:1664, ack 1458, win 249, options [nop,nop,TS val 186346523 ecr 470231051], length 1640
22:23:46.208945 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [.], ack 1664, win 32, options [nop,nop,TS val 470231052 ecr 186346523], length 0
22:23:46.210745 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [P.], seq 1458:1506, ack 1664, win 32, options [nop,nop,TS val 470231054 ecr 186346523], length 48
22:23:46.221765 IP 100.67.76.58.EtherNet/IP-1 > 10.16.150.17.53924: Flags [P.], seq 1664:1944, ack 1506, win 249, options [nop,nop,TS val 186346536 ecr 470231054], length 280
22:23:46.224305 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [P.], seq 1506:1522, ack 1944, win 35, options [nop,nop,TS val 470231067 ecr 186346536], length 16
22:23:46.264170 IP 100.67.76.58.EtherNet/IP-1 > 10.16.150.17.53924: Flags [.], ack 1522, win 249, options [nop,nop,TS val 186346579 ecr 470231067], length 0
22:23:46.264247 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [P.], seq 1522:1566, ack 1944, win 35, options [nop,nop,TS val 470231107 ecr 186346579], length 44
22:23:46.264264 IP 100.67.76.58.EtherNet/IP-1 > 10.16.150.17.53924: Flags [.], ack 1566, win 249, options [nop,nop,TS val 186346579 ecr 470231107], length 0
22:23:46.264340 IP 100.67.76.58.EtherNet/IP-1 > 10.16.150.17.53924: Flags [P.], seq 1944:1988, ack 1566, win 249, options [nop,nop,TS val 186346579 ecr 470231107], length 44
22:23:46.264416 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [P.], seq 1566:1626, ack 1988, win 35, options [nop,nop,TS val 470231108 ecr 186346579], length 60
22:23:46.264894 IP 100.67.76.58.EtherNet/IP-1 > 10.16.150.17.53924: Flags [P.], seq 1988:2032, ack 1626, win 249, options [nop,nop,TS val 186346579 ecr 470231108], length 44
22:23:46.264984 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [P.], seq 1626:1990, ack 2032, win 35, options [nop,nop,TS val 470231108 ecr 186346579], length 364
22:23:46.271079 IP 100.67.76.58.EtherNet/IP-1 > 10.16.150.17.53924: Flags [P.], seq 2032:2356, ack 1990, win 271, options [nop,nop,TS val 186346586 ecr 470231108], length 324
22:23:46.272353 IP 10.16.150.17.53924 > 100.67.76.58.EtherNet/IP-1: Flags [P.], seq 1990:2626, ack 2356, win 37, options [nop,nop,TS val 470231115 ecr 186346586], length 636
  1. 这时查看 netstat 也能看到连接是 ESTABLISHED
tcp        0     76 100.67.76.58:2222       10.16.150.17:53924      ESTABLISHED 6995/sshd: root [pr  on (0.20/0/0)
  1. 忽然想起ssh还有verbose参数,遂加上,发现如下日志:
root@ap3ar03n03:~# timeout 5 ssh root@100.67.76.58 -p 2222 -v
OpenSSH_7.7p1 Ubuntu-4ubuntu0.1+pitrix1, OpenSSL 1.0.2g  1 Mar 2016
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: /etc/ssh/ssh_config line 55: Deprecated option "useroaming"
debug1: Connecting to 100.67.76.58 [100.67.76.58] port 2222.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: identity file /root/.ssh/id_rsa type 0
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_rsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_dsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_dsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_ecdsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_ecdsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_ed25519 type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_ed25519-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_xmss type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_xmss-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_7.7p1 Ubuntu-4ubuntu0.1+pitrix1
debug1: Remote protocol version 2.0, remote software version OpenSSH_6.6.1
debug1: match: OpenSSH_6.6.1 pat OpenSSH_6.6.1* compat 0x04000000
debug1: Authenticating to 100.67.76.58:2222 as 'root'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256@libssh.org
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ecdsa-sha2-nistp256 SHA256:MTFlctqbVPTZGqzDJbMEzgNUtZ3oKUheYmB45T2tuAc
debug1: Host '[100.67.76.58]:2222' is known and matches the ECDSA host key.
debug1: Found key in /root/.ssh/known_hosts:52
debug1: rekey after 134217728 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: rekey after 134217728 blocks
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic
debug1: Next authentication method: gssapi-keyex
debug1: No valid Key exchange context
debug1: Next authentication method: gssapi-with-mic
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic
...
# 而后一直这样死循环

-vvv能看到,这里在反复重试gssapi-with-mic。于是搜索该关键字,发现不少人也碰到了这个问题,但碰到的没这么严重。

一般都是报登录CentOS时,登录会比较慢,或者有明显的等待,而不会像我碰到的这样,直接就连不上,最后timeout了。

解决

要解决这个问题,有两种解决思路,分别是客户端和服务端:

  1. 客户端

    a. ssh 时,命令行可以加上 -o GSSAPIAuthentication=no 参数;

    b. 或者可以配置在客户端的 /etc/ssh/ssh_config 里。

  2. 服务端

修改 /etc/ssh/sshd_config,把 GSSAPIAuthentication 关掉,并重启 sshd 服务。

# 如果是yes,要改成no。或者直接把这两个配置注释掉即可。
# GSSAPIAuthentication no
# GSSAPICleanupCredentials no

说明

GSSAPI:Generic Security Services Application Program Interface,GSSAPI 本身是一套 API,由 IETF 标准化。
其最主要也是著名的实现是基于 Kerberos 的。一般说到 GSSAPI 都暗指 Kerberos 实现。
GSSAPI 是一套通用网络安全系统接口。该接口是对各种不同的客户端服务器安全机制的封装,以消除安全接口的不同,降低编程难度。

参考

NTP 的一些问题

这篇文章写的

ntp 状态及含义

ntp 又叫 Network Protocol Protocol,是一种通过网络来同步时间的协议。

当在linux里维护自己的NTP server时,通过ntpq命令可以查看当前ntp server的状态。

而linux ntp客户端可以通过ntptime来查看当前ntp的同步情况,通过ntpdate来手动同步时间。

ntpdate

强制同步时间

  1. 如果有ntpd,需要先关闭,再同步
service ntp stop
ntpdate time.nist.gov
service ntp start
  1. 或者是加上 -u 参数
ntpdate -u time.nist.gov
  1. 或者是手动同步
date -u --set='2016-09-20 08:14:17.427319'

ntpq

ntpq -pn
root@owning:~# ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
+193.228.143.14  192.36.143.151   2 u  142  256  317  247.201   20.400  15.036
-202.112.10.37   10.3.8.150       5 u  177  256  373   49.110    5.891   1.191
+61.216.153.106  118.163.81.63    3 u  151  256  377   53.737   -4.461   1.382
*120.25.108.11   10.137.53.7      2 u  215  256  377    7.486    7.879   1.613
-91.189.89.198   17.253.34.125    2 u  215  256  377  402.811  -35.993   9.119
root@owning:~#

输出含义

  • remote and refid: remote NTP server, and its NTP server
  • st: stratum of server
    # from https://serverfault.com/questions/277375/ntpdate-d-server-dropped-strata-too-high
    
    NTP increases the stratum for each level in the hierarchy - a NTP server pulling time from a "stratum 1" server would advertise itself as "stratum 2" to its clients.
    
    A stratum value of "16" is reserved for unsynchronized servers meaning that your internal NTP server at 192.168.92.82 thinks not to have a reliable timesource (i.e. not synchronizing to a higher-level stratum server).
    
  • t: type of server (local, unicast, multicast, or broadcast)

  • poll: how frequently to query server (in seconds)
  • when: how long since last poll (in seconds)
  • reach: octal bitmask of success or failure of last 8 queries (left-shifted); 377 = 11111111 = all recent queries were successful; 257 = 10101111 = 4 most recent were successful, 5 and 7 failed

    最后八次查询(每次查询间隔为poll)的结果。

    这个值非常的 tricky,用了八位的bit,先转换成八进制,再以字符串的方式显示出来。

    00 000 000 -> 0
    00 000 001 -> 1
    00 000 011 -> 3
    00 000 111 -> 7
    00 001 111 -> 17
    00 011 111 -> 37
    00 111 111 -> 77
    01 111 111 -> 177
    11 111 111 -> 377
    
    10 101 111 -> 257
    

    测试发现,当ntp server重启后,值变为 17(即最近四次的query,除去刚启动时的一次,说明启动后间隔poll的三次query都成功),这时remote会加上*。下面是示例。

    # 第三次,reach 是 7。
    Wed Aug 15 11:56:02 CST 2018
     remote           refid      st t when poll reach   delay   offset  jitter
    ==============================================================================
    202.108.6.95    10.6.63.22       2 u   65   64    7   24.777  -15.577   0.082
    
    # 第四次,reach 是 17。
    Wed Aug 15 11:56:03 CST 2018
     remote           refid      st t when poll reach   delay   offset  jitter
    ==============================================================================
    *202.108.6.95    10.6.63.22       2 u    -   64   17   24.327  -15.328   0.209
    
  • delay: network round trip time (in milliseconds)
  • offset: difference between local clock and remote clock (in milliseconds)
  • jitter: difference of successive time values from server (high jitter could be due to an unstable clock or, more likely, poor network performance)

参考

remote 前的符号是什么意思?

NTP源码 查看,是根据查询上游服务器的结果的返回值来决定展示什么符号。

char flash3[] = " x.-+#*o"; /* flash decode for peer status version 3 */

所以得查 RFC1305,才能知道每个符号的具体含义:


' ' 0, rejected 'x' 1, passed sanity checks (tests 1 through 8 in Section 3.4.3) '.' 2, passed correctness checks (intersection algorithm in Section 4.2.1) '-' 3, passed candidate checks (if limit check implemented) '+' 4, passed outlyer checks (clustering algorithm in Section 4.2.2) '#' 5, current synchronization source; max distance exceeded (if limit check implemented) '*' 6, current synchronization source; max distance okay 只有ntp server的remote(upstream)为完全同步时,其它ntp client才能从这个server同步时间。 'o' 7, reserved

参考

from ntp source code

    case MODE_CLIENT:
        if (ISREFCLOCKADR(&srcadr))
            type = 'l'; /* local refclock*/
        else if (SOCK_UNSPEC(&srcadr))
            type = 'p'; /* pool */
        else if (IS_MCAST(&srcadr))
            type = 'a'; /* manycastclient */
        else
            type = 'u'; /* unicast */
        break;

ntptime

[root@node01 ~]# ntptime
ntp_gettime() returns code 5 (ERROR)
  time de9e7743.14f3881c  Thu, May 10 2018 15:46:11.081, (.081841975),
  maximum error 16000000 us, estimated error 16000000 us, TAI offset 0
ntp_adjtime() returns code 5 (ERROR)
  modes 0x0 (),
  offset 0.000 us, frequency -8.823 ppm, interval 1 s,
  maximum error 16000000 us, estimated error 16000000 us,
  status 0x2041 (PLL,UNSYNC,NANO),
  time constant 9, precision 0.001 us, tolerance 500 ppm,
[root@node01 ~]#

如果系统起了 ntpd 服务,手动同步主机时间(date -u --set XXX)后,ntptime 可能会如上错误。

其它

timedatectl

root@owning:~# timedatectl status
      Local time: Thu 2018-05-17 11:59:14 CST
  Universal time: Thu 2018-05-17 03:59:14 UTC
        RTC time: Thu 2018-05-17 03:59:12
        Timezone: Asia/Shanghai (CST, +0800)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
root@owning:~#

问题及排查

问题:ntpdate 同步,报 no server suitable for synchronization found

ntp client 从 ntp server 同步,报错 no server suitable for synchronization found

[root@client ~]# ntpdate -dv -b 192.168.2.61
15 Aug 11:38:35 ntpdate[3123]: ntpdate 4.2.6p5@1.2349-o Fri Jan 26 02:18:05 UTC 2018 (1)
Looking for host 192.168.2.61 and service ntp
host found : bigtable-01
transmit(192.168.2.61)
receive(192.168.2.61)
transmit(192.168.2.61)
receive(192.168.2.61)
transmit(192.168.2.61)
receive(192.168.2.61)
transmit(192.168.2.61)
receive(192.168.2.61)
192.168.2.61: Server dropped: strata too high
server 192.168.2.61, port 123
stratum 16, precision -22, leap 11, trust 000
refid [192.168.2.61], delay 0.02580, dispersion 0.00003
transmitted 4, in filter 4
reference time:    00000000.00000000  Mon, Jan  1 1900  8:05:43.000
originate timestamp: df1e1ebb.39c5652e  Wed, Aug 15 2018 11:38:35.225
transmit timestamp:  df1e1ebb.424aafc4  Wed, Aug 15 2018 11:38:35.258
filter delay:  0.02583  0.02591  0.02580  0.02589
         0.00000  0.00000  0.00000  0.00000
filter offset: -0.03335 -0.03343 -0.03338 -0.03343
         0.000000 0.000000 0.000000 0.000000
delay 0.02580, dispersion 0.00003
offset -0.033386

15 Aug 11:38:35 ntpdate[3123]: no server suitable for synchronization found
[root@client ~]#

从这段输出,stratum 为 16,16 是系统预留值,表明 ntp server 还未完全同步。

192.168.2.61: Server dropped: strata too high
server 192.168.2.61, port 123
stratum 16, precision -22, leap 11, trust 000

在 ntp server 上执行 ntpq -pn,也能发现,ntp server 和 upstream 的时间比较接近,但还没有完全同步(remote 前面没有 * 的标记)。

# ntp server 上检查
[root@server ~]# ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 202.108.6.95    10.6.63.22       2 u   56   64    7   24.749  -23.655   0.091
[root@server ~]#

ntp server 在启动后,需要等几个poll周期(1+3个周期,可以根据reach字段来判断。)之后,才会认为和 upstream 已同步。

[root@server ~]# ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*202.108.6.95    10.6.63.22       2 u   43   64   17   24.478  -23.552   0.092
[root@server ~]#

等 ntp server 同步后,ntp client 重试下,就能同步了。

[root@client ~]# ntpdate -dv -b 192.168.2.61
15 Aug 11:51:56 ntpdate[6619]: ntpdate 4.2.6p5@1.2349-o Fri Jan 26 02:18:05 UTC 2018 (1)
Looking for host 192.168.2.61 and service ntp
host found : bigtable-01
transmit(192.168.2.61)
receive(192.168.2.61)
transmit(192.168.2.61)
receive(192.168.2.61)
transmit(192.168.2.61)
receive(192.168.2.61)
transmit(192.168.2.61)
receive(192.168.2.61)
server 192.168.2.61, port 123
stratum 3, precision -22, leap 00, trust 000
refid [192.168.2.61], delay 0.02580, dispersion 0.00003
transmitted 4, in filter 4
reference time:    df1e21ae.f96502d4  Wed, Aug 15 2018 11:51:10.974
originate timestamp: df1e21dc.2d33be99  Wed, Aug 15 2018 11:51:56.176
transmit timestamp:  df1e21dc.28b5ea58  Wed, Aug 15 2018 11:51:56.159
filter delay:  0.02588  0.02592  0.02580  0.02589
         0.00000  0.00000  0.00000  0.00000
filter offset: 0.017501 0.017394 0.017443 0.017392
         0.000000 0.000000 0.000000 0.000000
delay 0.02580, dispersion 0.00003
offset 0.017443

15 Aug 11:51:56 ntpdate[6619]: step time server 192.168.2.61 offset 0.017443 sec
[root@client ~]#

参考

ARP 浅析

这篇文章写的

ARP 浅析

ARP(Address Resolution Protocol)

网络层(IP 地址)将数据包发送出去时,需要确定链路层地址(MAC),ARP 正是提供这种转换的协议。

ARP 请求寻址

当主机 A(IP 地址为 IP—A)的主机需要和主机 B(IP 地址为 IP-B)通信时,A 会先查询本机的路由表,决定下一跳发往哪里。

如果 IP-B 和 IP-A 在同一个子网,A 会查本机的 ARP 缓存,得到 IP-B 对应的 mac 地址,并将数据包的目标 mac 改为 IP-B 对应的 mac 地址,从对应网卡发出。如果 A 的 ARP 缓存里没有 IP-B 对应的 mac 地址,A 会先发一个 ARP 广播包(broadcast),B 会发一个 单播包(unicast) 响应这个 ARP 包;A 收到这个单播包后,会更新本地的 ARP 缓存,并将数据包发出。

如果 IP-B 和 IP-A 不在同一个子网,A 会将数据包发到路由表里指向的下一跳地址。同样的,发往下一跳地址的过程中,也需要通过 ARP 缓存或 ARP 广播来确定下一跳的 mac 地址。

  1. ARP 只在同一个二层网中使用。
  2. ARP 寻址过程中,发出的请求是广播包,收到的请求是单播包。
  3. 广播包会发送给除本机外的所有其它主机。所以如果 arping 自己的 IP,没有人会回包。

常用命令

  • 主机上抓 ARP 数据包
tcpdump -i eth0 arp -v
  • 查看本机的 arp 缓存
ip neighbour

arp -an
  • 通知更新 ARP caches
arping -U # 发送 ARP REQUEST,更新 ARP caches.

arping -A # 发送 ARP REPLY

常见问题

Q1: 如何判断一个 LAN 中,IP 地址冲突了?
A: 通过 arping。

root@hostA:~# arping -I eth0 -c 1 172.31.20.64
ARPING 172.31.20.64 from 172.31.20.10 eth0
Unicast reply from 172.31.20.64 [03:54:12:D0:40:AF]  0.861ms
Unicast reply from 172.31.20.64 [03:54:12:D1:3B:AF]  0.792ms
Sent 1 probes (1 broadcast(s))
Received 2 response(s)
root@hostA:~#

如果出现如上结果,即有不同 MAC 的回包,说明 IP 地址冲突了。

参考

读《人性的枷锁》有感

这篇文章写的
近来阅读了一些非侦探、非悬疑类的小说,比如《追风筝的人》、《钓鱼的男孩》、《月亮和六便士》、《面纱》、《刀锋》、《人性的枷锁》等等,给了我不少启发。
特别是毛姆的作品,除去作品中精彩的故事情节、锋利的人物形象,故事中总会穿插着一些经典的语句。
尽管我现在已经完全忘记了都是些什么,但这些语句正如绿色植物吸收阳光一样,它们在我大脑中转换、提炼出了一些新的、有趣的想法。
这些想法让我能够跳出自己的世界,以第三者的视角审视自己既有的观念和思维,发现思维盲点。
我总是尝试用理性和逻辑去处理事情,身为一名IT从业人员,这取得了一些成绩,让我的工作更加具备逻辑性。
但如果总是带着理性,以缜密到吹毛求疵的逻辑来进行阅读,这可就失去太多乐趣了。
人们听到文学作品,通常会想到优美、畅快、大快朵颐等等词汇,而这些词汇显然没有绝对的评判标准。
《禅与摩托车维修艺术》里也有类似观点,对于一件作品,比如绘画、音乐、诗歌等等,具备正常鉴赏能力的读者或观众通常能不费力的区分出好作品和坏作品。但真要让他们说出评判标准,这可就太为难他们了。如果美没有统一的标准,那么人们如何能够针对两件作品做出几乎相同的判断呢?如果有,那么美的标准是什么?
这给了我一个反思的思路。文学作品亦如此,要让自己融入其中,忘乎所以,要如欣赏音乐一般,让音乐从自己的内心中流出,内心在不断地涌出那些或冲动、或细腻的情感。

《美丽新世界》Aldous Huxley

这篇文章写的

《美丽新世界》Aldous Huxley

image

孵育中心主任头头是道略带骄傲的介绍着他们是如何经由波式程序来控制着世界人口的数量,并经过一道道复杂的生产线工序,来控制着新生儿的阶层和社会责任。这些工序像极了斯金纳在20世纪的著名心理学实验“斯金纳箱”,这是比巴布洛夫实验更为细致的实验,证明人类(动物)在不断强化下,有可能做出超出意志的行为。在《美丽新世界》中,孵育中心在胚胎期间即有各种强化反应,如通过高温和强 X 光,让这群新生人类对寒冷畏惧厌恶,他们必定会被移送到热带去从事矿工、钢铁工人等工作。 他们扮演着上帝的角色。

“一切制约之目的皆在于:使得人们喜欢他们无可逃避的社会命运。”

“切勿把今日之乐留待明日享受” “进步就是美好” “过去和未来都令我难耐,我吃下一克(索麻)就只有现在”

索麻,猜测具备类似镇定剂的功效,让人心情平稳,感觉麻痹。轻微的毒品药效。使人更容易感到快乐。

“在工作和认知的时候是个成人,涉及感觉欲望时则是个婴孩。” 作者在这里用成人和婴儿做比较,主人公柏纳已经开始意识到,自己失去了一些东西。在正视自己的感觉和欲望方面,大部分孵育人并不够成熟,对感觉欲望的认识极为浅薄,像个婴儿一样。而柏纳开始意识到这点,并尝试去正视感觉欲望。

“这是一种容易使高阶层中较不稳定的心灵消除制约的观念——会使他们失去自己把快乐当做‘至善’的信心,转而相信最终目标是在超越其外的什么地方,在现今人类世界之外的某个地方;相信生命的目的不是在于幸福的保持,而是在于一些意识的增强和锻炼,一些知识的扩大。”

“没有钢铁你就造不出汽车——同理,没有不安定的社会你就造不出悲剧。今天的世界是安定的。人们很快乐,他们要什么就会得到什么,而他们永远不会要他们得不到的。他们富有,他们安全,他们永不生病。 他们不惧怕死亡,他们幸运地对激情和老迈一无所知,他们没有父亲或母亲带来麻烦,他们没有妻子、孩子或者情人来给自己强烈的感觉,他们受的制约使他们身不由己地实实在在行其所当行。假使有什么事不对劲了,还有索麻。”

在美丽新世界中,人类社会依托于科技的极大进步,已实现体格、性格甚至是人格方面的人工塑造。一个人在诞生之初,就被教育着。阶级显而易见的存在,并且每个阶层的人们都被洗脑,接受自己才是这个社会最优越的贵族,自己生而做着自己擅长的事情,且以此为乐。人人都追求着快乐,并且快乐很容易获取,只要服用适量的索麻。新世界主张人人平等,没有独立的个体,“我属于所有人,所有人也属于我”,强调着大众,并以孤独为耻。所有人类都是无性繁殖,性行为如牵手一般正常,一夫一妻制已被唾弃,胎生也是可耻的。

而柏纳和约翰则是这个社会下两个格格不入的人物。

重新装瓶实验是个有趣的实验。将两万两千名正阿尔法放到一个岛上,放任其自知。结果很糟糕,尽管是轮班,从事低级工作的人们总是密谋夺取政权。一帮聪明人在一起,也是成事不足败事有余啊。这或许可以给我们的组织管理一个启发,召集一帮精英完成某个任务,必定需要一个更高级的将领来制约,同样需要一帮不这么精英的人群完成一些不那么高端的任务。

坊间传闻,柏纳在试管中时,被误注射了酒精,导致其正阿尔法的身份,却只有负甘玛的身躯,在这个以身高来辨识阶层的社会,柏纳受尽了背后的屈辱与非议。 约翰是其母亲琳达在意料之外的出生儿,正因为如此,琳达无法在“新世界”里继续生活,而被迫跑到保留区。约翰在这样的环境中长大,一方面保留区的长者传授给他的是古老的文明,接触的也是古老的文明书籍,描绘着当面人们的自由、激情、悲伤与痛楚;一方面是其母亲从新世界到保留区的落差生活,不断对约翰描绘着新世界的“美好”。这两种截然不同的文化冲突在约翰误入新世界后井喷而出。一群群孪生儿像参观动物园一样的来参观这位“野人先生”,他在新世界里应有尽有,唯独缺乏那份孤独和不快乐的感觉。 元首穆斯塔法·蒙德看似高高在上,却无疑只是这个新世界规则的执行者。他贯彻那些规则,让人们永远不会想得到他们得不到的东西,在各种制约和索麻的作用下,可以永远保持快乐,没有任何羁绊。这样的人群才是安定社会的基石。

个人观点

很多人将《美丽新世界》与《一九八四》对比。

著名的评论来自《娱乐至死》里的书评:“乔治·奥威尔曾在《一九八四》中预言人类将会遭受外来压迫,失去自由;赫胥黎则在《美丽新世界》中表达了另一种忧虑:人们会渐渐爱上工业技术带来的娱乐和文化,不再思考。

某种程度上,我并不赞同这段话。

“美丽新世界”中元首穆斯塔法·蒙德最后与野人约翰的对话道出了真相。美丽新世界里看似享受工业技术带来的娱乐和文化,然而这个世界已没有太多能够称之为“人类”的个体了。除了少量的正阿尔法外,其他“人”称之为机器人也不为过。这些行走的肉体不过是工业技术带来的新的维系社会运转的躯体。他们没有过多的思想,没有自我,没有自由,没有苦难,没有欲望和激情。整个美丽新世界已沦落为少数人的世界。

但即便是对于穆斯塔法·蒙德——这个世界的元首而言,他也只是这个社会的一个棋子。他们遵从于看不见的双手制定的规则。任何想要启发人们并给予自由的人物,都会被遣送到所谓的“自由岛”上。元首年轻时做了抉择,留在了这个美丽新世界。从这个角度上看,正阿尔法乃至最高领袖,不过也是这个社会下被制约的人吗?

这个极权社会!这跟《一九八四》又有何区别?

“但现在这个游戏已经进行了很久,如果还不能意识到游戏的结果,就不可原谅了。到了这个时候,如果你还不能意识到技术必然会带来社会变迁,还在坚持技术是中性的,仍然认为始终是文化的朋友,那么你实在是太愚蠢了。”

《娱乐至死》

《信》ひがしのけいご

这篇文章写的

《信》ひがしのけいこ

image

故事发生的背景,甚至在现代社会中,也是很常见的。

哥哥武岛志刚因为早年丧失双亲,过早的出来打工,供弟弟武岛直贵上学和生活。无奈承受不了重体力活,身体毁伤,无力继续养家糊口,供弟弟上大学,而一念偏差,错手放下抢劫杀人罪行。不料弟弟反倒因为背负着杀人犯的弟弟的沉重包袱,无法在社会立足。失去了自己仅有的音乐梦想,无法与心爱的女人长相厮守,甚至于因为此事而被调动职位,原因仅是因为人们无法把握与杀人犯弟弟的安全距离。 这一切像沉重的石头,压在了尚未成年的直贵身上。

志刚几年来坚持不断地给弟弟和受害者家属写信,与其说是为了鼓励弟弟,给受害者家属带去慰藉,倒不如说是为了自我满足。自我满足通常发生在自己内心极度愧疚久久不能释怀而又无所寄托时。

不知是否是刻意,但志刚的来信中并未透露出沉重的口吻,给弟弟的信中总是轻描淡写地记录着监狱生活,慰问弟弟在外的生活状况。像是哥哥通过这与外界的信,将自己内心的愧疚与忏悔全都转嫁到了弟弟和受害者家属身上。弟弟和受害者家属无力也不该持续承受着早该结束的悲剧,却因为这些信,不断提醒着他们,事情还未过去。这股压力压得人们喘不过气来,让人无法继续向前走下去。

社长对直贵说的两番话颇有见地,即便是局外人也未必能洞察地如此透彻。

第一次谈话,社长告诉直贵,人们并不是因为歧视而疏远施害者家属,而是因为人们往往没有足够的经验来处理此种情形,因为不知所以导致保持距离;而对于加害者家属而已,这是在为加害者背负犯罪带来的惩罚,无可厚非

第二次谈话,社长并未给出具体的答案。直贵还是无法明白为何自己坦坦荡荡踏踏实实地生活,依旧会让自己的女儿被他人孤立。社长说,这是因为你选择的是一条最简单最容易的道路。你扒开了自己的伤口,让人们决定是否接纳你。既然如此,理所当然会有人有意无意地伤害到你和你的家人。如果想要保护好家人,必须得走一条更难走的路。

所以直贵最终决定断绝与哥哥的关系。这不是一条简单的路。当总有一天,千方百计隐藏的秘密被发现时,直贵又该如何承受这些?更甚者,一个人如何能够抛弃一个当年为了自己而犯下发错的亲人?当哥哥出狱后,最需要得到的是世上唯一的亲人的鼓励和支持时,直贵又在哪里?这些问题随着这条选择的路走下去,总有一天需要面对。

然而,为了保护家人,直贵还是要继续走下去。

个人观点

《虚无的十字架》描绘犯罪者的自我救赎心理,《信》描绘的是犯罪者家属的心路历程。书中提出的问题值得人们深思,“如果碰到类似问题,我会如何处理”。犯罪者通常一步一步走错,可控因素太多,可以尽量避免。然而对于犯罪者家属而言,有色眼镜却无法避免。相信犯罪者出狱后也会同样面临这些问题。即便不是杀人放火,而是小偷小摸的犯罪,或者是经济犯罪,出狱后再想得到之前的尊重都很难了,几近不可能。但这对于家属而言未免太不公平。

《嫌疑人 X 的献身》ひがしのけいご

这篇文章写的

《嫌疑人 X 的献身》ひがしのけいご

image

读推理小说的乐趣也就在于此,尽管东野圭吾从一开始便似说明了案件细节,故事的发展还是让人疑惑不解。答案只在你不经意间流失的线索中。

个人认为,这本小说经典在于其悬疑部分,也就是推理过程。与《虚无的十字架》不同在于,其反复阅读的过程,会让你对生命有不同的思考,而再次阅读《X》再也没有了恍然大悟的那种感觉,因为答案我们已然知晓。

《虚ろな十字架》ひがしのけいご

这篇文章写的

《虚ろな十字架》ひがしのけいご

image

三条主线,中原道正和滨冈小夜子、井口纱织和仁科史也、仁科史也和花慧,通过某种看似偶然的事件,牵扯到了一起。

小说以“《白夜行》后,东野圭吾最刺痛人心的代表作”介绍,“死刑”这个沉重的十字架对于犯罪者而言是否虚无。

滨冈小夜子在女儿遇害后,尝试着寻找自己内心的避难所。重新走了自己往日的工作,自由撰稿人,主要关注犯下杀人罪的罪犯在监狱生活之后是否有无改变,以及遇害者家属(遗族)能否在往后的生活中找到自己内心的避难所。

调查结果显示,50% 的罪犯在出狱后仍然会因再次犯罪而重回监狱,而10% 的罪犯仍有可能再次杀人。凭什么要用无辜的生命来检验这些杀人犯呢?尽管对杀人犯执行死刑并不能让死者复生,也无法消减遗族的悲痛,但“死刑绝对能避免他们再次伤害他人”。

小夜子深知困扰着井口纱织的事情绝不是这么简单的偷窃罪。当小夜子知晓后深信只有主动背负起这沉重的十字架,向他人坦白,诉诸于世,自己内心才得以放下这个负担。她毅然要求(甚至是胁迫)井口纱织和仁科史也必须向警局自首。

正是这一决定,导致了小夜子的悲剧。 深知“自己是烂人”的町村作造有一个宅心仁厚的女婿,他能够替代自己给女儿稳定幸福的生活,并毫不顾忌地随时向自己敞开家门。做了一辈子的烂人的作造被打动了,他不允许任何人破坏这个宅心仁厚的女婿的生活,他决定用剩下的余生来报答他,也算是弥补了前半生对女儿关爱的缺失。

“我先生用迄今为止的所有人生,弥补在二十一年前犯下的罪。从滨冈女士口中得知这件事时,我第一次了解到这件事。同时,多年来一直感到纳闷的事——为什么这么优秀的人愿意拯救我这种落魄的女人,这个疑问终于有了答案。我先生并不是我儿子的亲生父亲,当年我愚蠢无知,被人欺骗后怀了孕,但我先生视如己出地养育他,还愿意照顾我父亲。这一切都是我先生在赎罪。我父亲在隔壁房间听到滨冈女士的话之后,应该也了解到这件事,所以他想报恩,才会做出那种事。如果当时没有遇见我先生,我现在早就不在人世了,我儿子也不会来到这个世界。我先生或许在二十一年前夺走了一条生命,但他拯救了两条生命。而且,他作为医生也在拯救无数生命。你知道我先生拯救了多少罹患罕见疾病的儿童吗?他不辞辛劳地拯救一个又一个小生命,即使这样,仍然说他没有付出任何代价,没有做任何弥补吗?有多少被关进监狱的人根本没有反省,这种人背负的十字架或许很虚无,但我先生背负的十字架绝对不一样。那是很沉重、很沉重,如山一般的十字架。中原先生,你的孩子曾经被人杀害,请身为遗族的你回答我,被关进监狱,和我先生这样的生活方式,哪一种才是真正的弥补?”

在完全知晓来龙去脉之后,中原和小夜子对于事实所做的完全不一样的决定才是戏剧化的冲突。小夜子固执地认为仁科史也和井口纱织必须自首,而完全看不到他们在二十多年来为年轻时犯下的错误所背负的十字架。中原身为遗族,五年以来一直没有找到应该如何处理类似问题,但“无论你做出什么决定,我都不会有意见。杀人凶手该如何弥补这个问题,应该没有标准答案。在这个案例上,我会把你在苦思后得出的结论视为正确答案”。

个人观点

恕我直言,整个事件看起来是由于一些人的无知、一些人的自负、一些人的不负责任导致的结果

井口纱织和仁科史也在年轻时因为无知,“害怕被长辈知道而挨骂”,两人贸然做出了决定。这个决定在成年人看起来就是个笑话。

蛭川和南并不敬畏生命,不仅如此,他不敬畏自己的生活,比得过且过更糟糕。还未到谈论他的社会责任感,他连对自己都不负责。

具有同样问题的是町村作造。但他运气比蛭川和南好一点,他在晚年时碰到了位“完人”,无条件接纳他的一切,他被感动了,他想尽自己绵薄之力来解决恩人的麻烦事。对于他而言,他想不到更好的办法了。

可笑的是小夜子,始终在努力地寻找标准答案,却自负地认为自己掌握了真理。

另外,作为一名读者,处在上帝视角,一切看起来都是那么容易:)