在linux的权限中, 发现不仅仅有rwx, 还有一个t, 如下所示:

1
drwxrwxr-t   2 shentao shentao       4096  8月 24  2016 test/

t只能加在最后一个组, 也就是其他组的权限中, 他的意思是sticky bit, 表示其他组成员不能对该文件进行删除和重命名操作, 这是为了防止某个文件无意被其他组的成员删除和重命名后导致owner找不到文件.

添加的方式是:

1
chmod o+t test

或者

1
chmod +t test

或者使用数字的方式, 在首位设置1

1
chmod 1775 test

结果如下:

1
2
ll test
drwxrwxr-t 2 shentao shentao 4096 8月 24 2016 test/

移除方式如下

1
chmod o-t test

查看结果

1
2
3
ll test

drwxrwxr-x 2 shentao shentao 4096 8月 24 2016 test/

从这里也能看出, t是比x更高一个级别的权限, 即t包含了可执行权限, 只是不能delete和rename. 其次它与rw也不冲突.

星环讲座: 初识微服务

主讲人: 吴伟

三本书:

  • Building Microservices
  • 微服务: 从设计到部署
  • 微服务设计

大纲:

  1. 什么是微服务
  2. 核心概念
  3. 开源微服务框架
  4. 国内微服务产品

内容:

  1. 什么是微服务: 相互独立微小的组建, 能够相互合作: 在一组小的服务, 独立的进程, 通信机制, 基于业务, 独立部署, 没有集中式管理.
  2. 为什么要做微服务: 单体服务膨胀太大, 代码太多, 开发太慢, 发布速度太慢, 新人学习成本太高.
  3. 微服务目标: 敏捷迭代, 灵活扩展, 服务服用.
  4. 微服务核心概念: api网关, 服务发现, 熔断, 限流, 降级, 配置中心, 自动化部署和测试, 日志监控和分部署追踪, 安全, 服务拆分, 服务接口定义, 有状态服务集群, 无状态服务
    • 服务发现: 怎么找到另一个服务的地址. 通常使用服务中心或者服务代理.
    • api网关: 对外统一接入访问; 内外协议转换(http -> gRPC), 统一认证,监控,负载均衡,缓存; 智能路由: Kong, Nginx Plus, Traefik
    • 服务容错(熔断): 假设错误一定会发生, 想办法把损失降到最小: custom fallback, fail silent, fail fast. 超时与重试, 降级熔断, 连接隔离
    • 配置中心: 程序运行时动态调整行为的能力.
    • 自动化测试部署: CI/CD 改动一行代码能够多久部署成功
    • 服务监控: 系统在做什么, 哪些组建流量比较大, 这个请求在哪个地方失败了, 哪个调用比较慢.
    • 安全:
    • 分布式事务: 每个服务解决一个问题, 要解决一个逻辑上的一致性.

cloud native = container + CICD/devops + microservice

Istio: 一个开源平台去链接, 管理和保障微服务: 分布式微服务代理。

传统代理: 类似于一个线, 任何服务都经过这个代理。

分布式代理: 代理运行在每个应用上,接管应用进出的流量并和统一的控制中心通信获取动态配置。

微服务代理: service mesh: 互连的分布式代理。

Istio:

  1. Pilot: 基于http做流量的;

  2. Mixer: 做数据统计, 授权认证

  3. CA-Auth: 做安全认证

Envoy: 微服务代理。

问题描述

今天在执行一个命令是遇到一个which路径与实际执行不同步的问题, 如下:

1
2
3
4
5
6
7
8
9
shentao@shentao-ThinkPad-T450:~/blog$ which ss-local
/usr/local/bin/ss-local
shentao@shentao-ThinkPad-T450:~/blog$ /usr/local/bin/ss-local -v | grep shadowsocks-libev
shadowsocks-libev 2.5.6 with OpenSSL 1.0.1f 6 Jan 2014
shentao@shentao-ThinkPad-T450:~/blog$ ss-local -v | grep shadowsocks-libev
shadowsocks-libev 3.1.3
shentao@shentao-ThinkPad-T450:~/blog$ /usr/bin/ss-local -v | grep shadowsocks-libev
shadowsocks-libev 3.1.3

which 现实路径是/usr/local/bin/ss-local, 但实际执行的路径却是/usr/bin/ss-local. 查看which的文档, 发现which是按顺序搜索PATH环境变量来查找的:

1
2
shentao@shentao-ThinkPad-T450:~/blog$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/go/bin:/usr/local/go/bin:/home/shentao/gopath//bin:/opt/idea-IC-145.1617.8/bin:/usr/local/go/bin:/home/shentao/gopath//bin:/opt/idea-IC-145.1617.8/bin:/usr/local/go/bin

所以最先在/usr/local/bin中找到.

问题解决

于是去调查了下bash的执行过程和顺序. 得到了答案. https://crashingdaily.wordpress.com/2008/04/21/hashing-the-executables-a-look-at-hash-and-type/

原来在每一次执行过程中shell都会有一个hash table作为cache将调用过的可执行命令存入hash table, 这样再下次调用的时候就可以直接从缓存中读取, 而不用每次去搜索PATH. 我们通过type命令可以查看:

1
2
shentao@shentao-ThinkPad-T450:~/blog$ type ss-local
ss-local is hashed (/usr/bin/ss-local)

可以通过hash命令删除:

1
2
3
shentao@shentao-ThinkPad-T450:~/blog$ hash -d ss-local
shentao@shentao-ThinkPad-T450:~/blog$ ss-local -v | grep shadowsocks-libev
shadowsocks-libev 2.5.6 with OpenSSL 1.0.1f 6 Jan 2014

知识回顾

我们再来回顾下关于bash 的一些知识:

关于bash可以执行的类型

  • Aliases: An alias is a word that is mapped to a certain string, 命令的别名.

    1
    2
    $ alias nmapp="nmap -Pn -A --osscan-limit"
    $ nmapp 192.168.0.1
  • Functions: A function contains shell commands, and acts very much like a small script. 用function定义一个函数:

    1
    function gcc { echo “just a test for gcc”; }
  • Builtins: 内置函数, cd之类的

  • Keywords: Keywords are like builtins, with the main difference being that special parsing rules apply to them. For example, [ is a Bash builtin, while [[ is a Bash keyword. They are both used for testing stuff. [[ is a keyword rather than a builtin and is therefore able to offer an extended test:

    1
    2
    3
    $ [ a < b ]
    -bash: b: No such file or directory
    $ [[ a < b ]]

    第一个< 是重定向, 第二个加了[[的关键词之后 < 成了小于号.

  • Executables: (Executables may also be called external commands or applications.) Executables are commonly invoked by typing only their name. This can be done because a pre-defined variable makes known to Bash a list of common, executable, file paths. This variable is called PATH. 外部命令, 也就是PATH中找到的那些命令

  • Script: 脚本. 比如test.sh

关于bash的搜索顺序总结

bash搜索的顺序是: 当前路径和绝对路径的目录->alias->keyword->function->built-in->Executables, Script(hash)->Executables, Script($PATH)

相关命令

bash, hash, type, which, alias, function

苗艳强,闫学安

ZTE 工程师,主要从事容器相关开源工作,Kubernetes 社区 member, containerd 社区 member

课程详情:

演讲主题:

目前跟 Kubernetes 对接的默认容器运行时是 docker,然而 docker 从 1.12 版本开始加入了 swarm 功能,随着版本的演进,功能越来越庞大,已经成为一个跟 Kubernetes 同级甚至高一级的编排工具,且前不久又宣布在编排测要无缝对接 Kubernetes,因此,docker 作为 Kubernetes 默认容器运行时的位子必将被其他工具代替。本次分享首先简单介绍 Kubernetes 的运行时接口规范,然后着重为大家分享一款新的容器运行时工具 containerd,包括项目介绍,功能组成等,以及使其原生对接 Kubernetes 的插件 cri-containerd。

纲要/提纲:

  1. Kubernetes 容器容器运行时接口(CRI)

  2. containerd 项目介绍

  3. containerd 的 CRI 实现


Containerd的CRI实现
kubelet -> cri-containerd -> containerd

写了一个简单的程序, 想通过外部环境变量传递给程序的全局变量, 这个全局变量又被另一个全局变量使用, 发现另一个变量无法改变, 然后发现一些有意思的golang程序初始化顺序, 需要稍微注意一下.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import (
"fmt"
"flag"
)

var (
// 1
size = flag.String("size", "3", "size")
a = "1"
b = a + "2"
c = b + *size
)

func init() {
// 2
fmt.Printf("%s, %s, %s, %s \n", a, b, c, *size)
a = "2"
b = a + "2"
}

func main() {
fmt.Printf("%s, %s, %s, %s \n", a, b, c, *size)
// 3
flag.Parse()
fmt.Printf("%s, %s, %s, %s \n", a, b, c, *size)
}

输出如下:

1
2
3
4
/home/shentao/.IdeaIC2016.1/config/plugins/Go/lib/dlv/linux/dlv --listen=localhost:34206 --headless=true exec "/tmp/Build initializetest.go and rungo" -- -size=10
1, 12, 123, 3
2, 22, 123, 3
2, 22, 123, 10

注释标记的是实际运行顺序, 先是变量的初始化, 此时size还没传入解析, 所以使用默认值”3”; 其次是调用init函数; 最后是main函数, main函数再进行flag.Parse(), 此时size改变, 但是其他变量不会再变.

在hexo中, 在themes目录下git clone了一个子目录themes/next. git push 到远程仓库后没有看到themes/next中的内容, 也无法git add

1
2
3
4
5
6
shentao@shentao-ThinkPad-T450:~/blog$ git commit -m "fix" themes/next/
On branch master
Changes not staged for commit:
modified: themes/next (modified content)
shentao@shentao-ThinkPad-T450:~/blog$ git add themes/next/*
fatal: Pathspec 'themes/next/bower.json' is in submodule 'themes/next'

当创建一个子git项目是, 项目就叫做git submodule结构, 外部无法对子模块进行控制, 有两种方式(我知道的):
1.

1
2
3
cd themes/next
git add .
git commit

再到外部提交

1
2
3
git add themes/next
git commit
git push
  1. 1
    2
    git rm --cached themes/next  
    git add themes/next

本书评不涉及剧透,请大胆的往下看。
​ 阿加莎的书的特点是将你往某种定势思维上引,然后打破这种定势思维。《无人生还》亦是如此。那么如何排解定势思维呢?这本书在侦破的过程中提供了两个思维。

​ 第一个是排除。即一开始不去想最可能的结果,而是将所有已知的证据放在桌面,然后不断排除所有不可能的结果,最后得到的结果无论多么离谱,都是在已有证据下的唯一结果。

​ 第二个思维是回溯。当我们得到一个唯一结果,或者得不到唯一结果,也就是所有结果都被排除掉,那么只有一种可能就是证据本身是错的,这就是有证人在说谎,或者有人伪造了证据,这时候需要回溯到证据提出的过程中,提供假证据必然要掩盖某个事实,从某个最容易甄别的假证据出发找到一个真事实,通过这个真事实,按照第一个思维,可以继续推倒出其他与之相违背的证据,从而重新得到证据链。

​ 我不禁有一个有意思的理论和想法:如果每个人做的事情都看做一条平面上的直线,那么我们肉眼所能看到的案发现场,就是这所有直线的有且仅有的一个交点。有任何一个人在任何时候说谎,那条直线就会发生偏折,就无法相交于一点,此时为了相交于一点,有两种方法:说更多的慌让直线折回来;让其他人也说谎,找一个新的交点。本书的犯人无疑是后者。但想找一个新的交点何其难,终究被识破。

​ 其实还有第三种方法。昨晚看了《黑镜》最新一季的某一集,女主角与男友因为酒驾撞死了一个男子,然后抛尸。时隔多年男友良心不安想要去告诉被害者家属,女主角将他杀害,而杀害的过程被正在调查车祸的女调查员发现,于是女主角杀害了女调查员,并得知她的家庭,于是杀害了她的所有家人。所以这个方法就是把平面上所有其他直线擦掉,平面上只有一条直线,和一个看起来不相交的点。

在跑自己的golang程序时遇到死锁, 查看stack, 发现一些奇怪的goroutinue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
goroutine 17 [syscall, 12 minutes, locked to thread]:
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2086 +0x1

goroutine 20 [select, 12 minutes, locked to thread]:
runtime.gopark(0xd067b8, 0x0, 0xc738c8, 0x6, 0x18, 0x2)
/usr/local/go/src/runtime/proc.go:259 +0xfd
runtime.selectgoImpl(0xc420022f30, 0xc420022f1c, 0x0)
/usr/local/go/src/runtime/select.go:423 +0x1303
runtime.selectgo(0xc420022f30)
/usr/local/go/src/runtime/select.go:238 +0x1c
runtime.ensureSigM.func1()
/usr/local/go/src/runtime/signal1_unix.go:304 +0x28c
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2086 +0x1

这些goroutine显示: locked to thread, 但上网查找有回复说到, 这并不是一个真正的死锁, 而是正常的goroutine拿线程锁的过程. 可能调用了cgo或者runtime.LockOSThread. 这个问题可以忽略掉, 以防绕进死胡同.

1
2
3
4
5
That is not a deadlock, at least not a deadlock in the Go program.  It 
is normal for a goroutine to be locked to a thread. It can happen
because of cgo, or because the code called runtime.LockOSThread. It
is not a problem. The problem is that the thread has not made any
progress for 214 minutes; what that is depends on what it is doing.

<黑客与画家> 的一些笔记和理解:

  • 什么是黑客: “出于兴趣而解决某个难题, 不管有没有用, 这就是黑客.” 由此可见黑客的核心不在于技术高超, 而在于自我驱动.
  • 什么是创业公司: “经济学的观点就是, 可以让人更快速工作的地方.” 所以当你发现一家公司办一件事情很困难, 那可能是部门或小组太大了, 需要将它继续分割成更小的团队甚至是个人.
  • “大公司的生产效率是小型创业公司的十分之一, 没有任何一家大公司能够做得更好.” 这还是相对于雅虎微软这种高效率的大公司,
  • “乔布斯曾说过, 创业成功的成败取决于最早加入公司的那十个人. 而我<作者>觉得, 是5个.”
  • “创业有两条”潜规则”: 1. 很多事情由不得你. 2. 创业的付出与回报在个体上不成比例.”
  • “创业公司不能有任何防御, 他们必须只有进攻, 要么赢得一切, 要么彻底消失.” 不要在乎竞争对手的诋毁, 抄袭, 恶意竞争, 这都只是他们在拖延你成长的手段, 当你花时间和精力打赢了官司, 你会发现市场已经丢失.
  • “技术的发展在加大贫富差距和收入差距, 但却在减小其他方面的差距.” 例如波音747飞机驾驶员的收入大概是超市收银员的40倍, 这种差距可能大于奴隶社会的奴隶和奴隶主, 但他们在生活质量上可能并没有多大的差距, 一个智能手机就能享受到所有人都能享受到的乐趣.
  • “‘语言只是工具, 其实没什么不同’, 这种观点是不对的”. 语言的不同不仅仅是语法的不同, 更在于思维模式的不同, 使用C会专注内存回收释放, 指针指向, 使用java会关注封装,多态以及各种类之间的组织关系, 使用python会不自然的想方设法让语句更短更优雅, 让类型更加不可见, 让参数更加动态多样, 使用golang会更专注于线程之间的并发效率, 线程间通信的可行性, 服务的扩展性和部署的快捷性. 尽管绝大多数的语言可以做到其他语言也能做到的事情, 但在编写的过程中往往不会去思考其他的问题, 而只关注核心问题, 这就是不同编程语言的带来的思维上的不同. 如果硬要找一个共同点, 那可能就是他们都能够让你在解决某一类问题上特别高效.
  • “但是事实上, 我们的思想可能往往会受限于某些现存的语言, 只采用在这种语言看起来更简单的形式, 他对我们的思想的束缚作用会大得令人震惊. 新语言必须靠你自己去发现, 不能依靠那些让你自然而然就沉下去的思维定势.””他们都满足于自己碰巧用熟了的那种语言, 他们的编程思想都被那种语言主宰了.” 要跳出编程语言的固定思维模式, 知道它们善于解决怎样问题而又不善于解决其它问题, 这样才能不局限于永远使用同一种编程语言解决问题.
  • “你要选择的是最高效的编程语言解决问题, 而不是最流行的, 但一个’优秀’的编程语言如果很长时间都无法流行, 那它就还不够优秀”
  • “如果你想在软件业获得成功, 就使用你知道的最强大的语言, 用它解决你知道的最难的问题, 并且等待竞争对手的经理做出自甘平庸的选择”
  • “先做出原型, 在逐步加工成品, 这种方式有利于鼓舞士气, 因为它使得你随时都可以看到工作的成效. 开发软件的时候, 我有一条潜规则: 任何时候, 代码都必须能够运行.”
  • “做出优秀成果的人, 在做的过程中常常觉得自己做的不够好. 其他人看到他们的成果觉得棒极了, 而创造者本人看到的都是自己作品的缺陷. 这种视角的差异并非偶然, 因为只有对现状不满, 才会造就杰出的成果.”
  • “一心让臣民行善的暴君可能是最专制的暴君. —-C.S.LEWIS (1898-1963, 英国小说家) “
0%