山西11选5的玩法有什么:文章 – 伯乐在线 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net Fri, 18 Jan 2019 13:28:47 +0000 zh-CN hourly 1 https://wordpress.org/?v=4.5.16 Vim 命令合集 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114641/ //www.brhi.net/114641/#respond Fri, 18 Jan 2019 13:07:28 +0000 //www.brhi.net/?p=114641 本文整理了常用的 Vim 命令,欢迎补充。

Vim 命令合集,首发于山西十一选五手机版。

]]>
山西11选5的玩法有什么:命令历史

以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令。

启动vim

在命令行窗口中输入以下命令即可

vim 直接启动vim

vim filename 打开vim并创建名为filename的文件

文件命令

打开单个文件

vim file

同时打开多个文件

vim file1 file2 file3 …

在vim窗口中打开一个新文件

:open file

在新窗口中打开文件

:split file

切换到下一个文件

:bn

切换到上一个文件

:bp

查看当前打开的文件列表,当前正在编辑的文件会用[]括起来。

:args

打开远程文件,比如ftp或者share folder

:e ftp://192.168.10.76/abc.txt

:e \\qadrive\test\1.txt

vim的模式

正常模式(按Esc或Ctrl+[进入) 左下角显示文件名或为空
插入模式(按i键进入) 左下角显示–INSERT–
可视模式(不知道如何进入) 左下角显示–VISUAL–

导航命令

% 括号匹配

插入命令

i 在当前位置生前插入

I 在当前行首插入

a 在当前位置后插入

A 在当前行尾插入

o 在当前行之后插入一行

O 在当前行之前插入一行

查找命令

/text  查找text,按n健查找下一个,按N健查找前一个。

?text  查找text,反向查找,按n健查找下一个,按N健查找前一个。

vim中有一些特殊字符在查找时需要转义  .*[]^%/?~$

:set ignorecase  忽略大小写的查找

:set noignorecase  不忽略大小写的查找

查找很长的词,如果一个词很长,键入麻烦,可以将光标移动到该词上,按*或#键即可以该单词进行搜索,相当于/搜索。而#命令相当于?搜索。

:set hlsearch  高亮搜索结果,所有结果都高亮显示,而不是只显示一个匹配。

:set nohlsearch  关闭高亮搜索显示

:nohlsearch  关闭当前的高亮显示,如果再次搜索或者按下n或N键,则会再次高亮。

:set incsearch  逐步搜索模式,对当前键入的字符进行搜索而不必等待键入完成。

:set wrapscan  重新搜索,在搜索到文件头或尾时,返回继续搜索,默认开启。

替换命令

ra 将当前字符替换为a,当期字符即光标所在字符。

s/old/new/ 用old替换new,替换当前行的第一个匹配

s/old/new/g 用old替换new,替换当前行的所有匹配

%s/old/new/ 用old替换new,替换所有行的第一个匹配

%s/old/new/g 用old替换new,替换整个文件的所有匹配

:10,20 s/^/??? /g 在第10行知第20行每行前面加四个空格,用于缩进。

ddp 交换光标所在行和其下紧邻的一行。

移动命令

h 左移一个字符
l 右移一个字符,这个命令很少用,一般用w代替。
k 上移一个字符
j 下移一个字符
以上四个命令可以配合数字使用,比如20j就是向下移动20行,5h就是向左移动5个字符,在Vim中,很多命令都可以配合数字使用,比如删除10个字符10x,在当前位置后插入3个!,3a!<Esc>,这里的Esc是必须的,否则命令不生效。

w 向前移动一个单词(光标停在单词首部),如果已到行尾,则转至下一行行首。此命令快,可以代替l命令。

b 向后移动一个单词 2b 向后移动2个单词

e,同w,只不过是光标停在单词尾部

ge,同b,光标停在单词尾部。

^ 移动到本行第一个非空白字符上。

0(数字0)移动到本行第一个字符上,

<HOME> 移动到本行第一个字符。同0健。

$ 移动到行尾 3$ 移动到下面3行的行尾

gg 移动到文件头。 = [[

G(shift + g) 移动到文件尾。 = ]]

f(find)命令也可以用于移动,fx将找到光标后第一个为x的字符,3fd将找到第三个为d的字符。

F 同f,反向查找。

跳到指定行,冒号+行号,回车,比如跳到240行就是 :240回车。另一个方法是行号+G,比如230G跳到230行。

Ctrl + e 向下滚动一行

Ctrl + y 向上滚动一行

Ctrl + d 向下滚动半屏

Ctrl + u 向上滚动半屏

Ctrl + f 向下滚动一屏

Ctrl + b 向上滚动一屏

撤销和重做

u 撤销(Undo)
U 撤销对整行的操作
Ctrl + r 重做(Redo),即撤销的撤销。

删除命令

x 删除当前字符

3x 删除当前光标开始向后三个字符

X 删除当前字符的前一个字符。X=dh

dl 删除当前字符, dl=x

dh 删除前一个字符

dd 删除当前行

dj 删除上一行

dk 删除下一行

10d 删除当前行开始的10行。

D 删除当前字符至行尾。D=d$

d$ 删除当前字符之后的所有字符(本行)

kdgg 删除当前行之前所有行(不包括当前行)

jdG(jd shift + g) ? 删除当前行之后所有行(不包括当前行)

:1,10d 删除1-10行

:11,$d 删除11行及以后所有的行

:1,$d 删除所有行

J(shift + j)  删除两行之间的空行,实际上是合并两行。

拷贝和粘贴

yy 拷贝当前行

nyy 拷贝当前后开始的n行,比如2yy拷贝当前行及其下一行。

p? 在当前光标后粘贴,如果之前使用了yy命令来复制一行,那么就在当前行的下一行粘贴。

shift+p 在当前行前粘贴

:1,10 co 20 将1-10行插入到第20行之后。

:1,$ co $ 将整个文件复制一份并添加到文件尾部。

正常模式下按v(逐字)或V(逐行)进入可视模式,然后用jklh命令移动即可选择某些行或字符,再按y即可复制

ddp交换当前行和其下一行

xp交换当前字符和其后一个字符

剪切命令

正常模式下按v(逐字)或V(逐行)进入可视模式,然后用jklh命令移动即可选择某些行或字符,再按d即可剪切

ndd 剪切当前行之后的n行。利用p命令可以对剪切的内容进行粘贴

:1,10d 将1-10行剪切。利用p命令可将剪切后的内容进行粘贴。

:1, 10 m 20 将第1-10行移动到第20行之后。

退出命令

:wq 保存并退出

ZZ 保存并退出

:q! 强制退出并忽略所有更改

:e! 放弃所有修改,并打开原来文件。

窗口命令

:split或new 打开一个新窗口,光标停在顶层的窗口上

:split file或:new file 用新窗口打开文件

split打开的窗口都是横向的,使用vsplit可以纵向打开窗口。

Ctrl+ww 移动到下一个窗口

Ctrl+wj 移动到下方的窗口

Ctrl+wk 移动到上方的窗口

关闭窗口

:close 最后一个窗口不能使用此命令,可以防止意外退出vim。

:q 如果是最后一个被关闭的窗口,那么将退出vim。

ZZ 保存并退出。

关闭所有窗口,只保留当前窗口

:only

录制宏

按q键加任意字母开始录制,再按q键结束录制(这意味着vim中的宏不可嵌套),使用的时候@加宏名,比如qa。。。q录制名为a的宏,@a使用这个宏。

执行shell命令

:!command

:!ls 列出当前目录下文件

:!perl -c script.pl 检查perl脚本语法,可以不用退出vim,非常方便。

:!perl script.pl 执行perl脚本,可以不用退出vim,非常方便。

:suspend或Ctrl – Z 挂起vim,回到shell,按fg可以返回vim。

注释命令

perl程序中#开始的行为注释,所以要注释某些行,只需在行首加入#

3,5 s/^/#/g 注释第3-5行

3,5 s/^#//g 解除3-5行的注释

1,$ s/^/#/g 注释整个文档。

:%s/^/#/g 注释整个文档,此法更快。

帮助命令

:help or F1 显示整个帮助
:help xxx 显示xxx的帮助,比如 :help i, :help CTRL-[(即Ctrl+[的帮助)。
:help ‘number’ Vim选项的帮助用单引号括起
:help <Esc> 特殊键的帮助用<>扩起
:help -t Vim启动参数的帮助用-
:help i_<Esc> 插入模式下Esc的帮助,某个模式下的帮助用模式_主题的模式
帮助文件中位于||之间的内容是超链接,可以用Ctrl+]进入链接,Ctrl+o(Ctrl + t)返回

其他非编辑命令

. 重复前一次命令

:set ruler?  查看是否设置了ruler,在.vimrc中,使用set命令设制的选项都可以通过这个命令查看

:scriptnames  查看vim脚本文件的位置,比如.vimrc文件,语法文件及plugin等。

:set list 显示非打印字符,如tab,空格,行尾等。如果tab无法显示,请确定用set lcs=tab:>-命令设置了.vimrc文件,并确保你的文件中的确有tab,如果开启了expendtab,那么tab将被扩展为空格。

Vim教程
在Unix系统上
$ vimtutor
在Windows系统上
:help tutor

:syntax 列出已经定义的语法项
:syntax clear 清除已定义的语法规则
:syntax case match 大小写敏感,int和Int将视为不同的语法元素
:syntax case ignore 大小写无关,int和Int将视为相同的语法元素,并使用同样的配色方案

Vim 命令合集,首发于山西十一选五手机版。

]]>
//www.brhi.net/114641/feed/ 0
能从远程获得乐趣的 Linux 命令 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114638/ //www.brhi.net/114638/#respond Sun, 13 Jan 2019 14:32:53 +0000 //www.brhi.net/?p=114638 使用这些工具从远程了解天气、阅读资料等。

能从远程获得乐趣的 Linux 命令,首发于山西十一选五手机版。

]]>

使用这些工具从远程了解天气、阅读资料等。

我们即将结束为期 24 天的 Linux 命令行玩具日历。希望你有一直在看,如果没有,请回到开始,从头看过来。你会发现 Linux 终端有很多游戏、消遣和奇怪之处。

虽然你之前可能已经看过我们日历中的一些玩具,但我们希望每个人都遇见一个新事物。

今天的玩具(实际是玩具集合)有点不同。到目前为止,我主要是想把重点放在那些独立的玩具上,并且完全可在开源许可下使用。但是我从读者那里得到了一些很好的建议,利用开源工具远程访问一些开源或者不开源的东西。今天,我将介绍其中的一些。

第一个是经典之作:使用 Telnet 观看星球大战的 ASCII 演绎版本。你的系统可能已经安装了 Telnet,因此你只需运行:

$ telnet towel.blinkenlights.nl

我第一次看到它是十年之前,因此我对于它还存在有点惊奇。如果你还没看过,请留出一点时间看一下。你不会后悔的。

接下来,Opensource.com 的撰稿人 Manuel Dewald 提出了一种从终端获取当地天气的方法。它很简单,你只需安装 curl(或者,wget)。

$ curl wttr.in

最后,在假期中虽然你可以从命令行 Web 浏览器浏览你喜欢的网站(包括 Opensource.com),但有一些我最喜欢的网站可以通过专用客户端更轻松地浏览。其中两个是 Reddit 和 Hacker News,有人推荐给我一些它们的客户端,你可能也想尝试,它们都使用开源许可。我尝试过 haxor-news (Hacker News) 和 rtv (Reddit),它们都还不错。

 

 

能从远程获得乐趣的 Linux 命令,首发于山西十一选五手机版。

]]>
//www.brhi.net/114638/feed/ 0
5 款 Linux 街机游戏 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114636/ //www.brhi.net/114636/#respond Fri, 11 Jan 2019 12:50:36 +0000 //www.brhi.net/?p=114636 本文首先介绍 Linux 开源游戏中的街机类型游戏,在之后的文章中,我将介绍桌面和卡牌游戏,解谜游戏,竞速游戏,以及策略模拟游戏。

5 款 Linux 街机游戏,首发于山西十一选五手机版。

]]>

长久以来,游戏都是 Linux 的软肋。近些年,Steam、GOG 等游戏发布平台上不少商业游戏都开始支持 Linux,这对于 Linux 的游戏生态来说是件好事,但是我们能在这些平台上玩到的游戏通常是不开源的商业作品。当然,这些游戏在一个开源的操作系统上运行,但对于一个开源提倡者来说这似乎还不够纯粹。

那么,我们能找到既自由开源又能给玩家带来完整游戏体验的优质游戏吗?当然!虽然绝大多数的开源游戏很难和 3A 商业游戏大作竞争,但仍然有不少各种类型的开源游戏,不仅内容有趣而且直接可以通过几大 Linux 发行版本库中直接安装。

本文首先介绍 Linux 开源游戏中的街机类型游戏,在之后的文章中,我将介绍桌面和卡牌游戏,解谜游戏,竞速游戏,以及策略模拟游戏。

太空?;鶤stroMenace

太空?;?/a> 是一个近现代太空背景下的滚动页面射击游戏??⒊跗谒且桓霰赵从蜗?,但它的代码和素材而后以开源许可证发布了。游戏玩法和大多数此类游戏大同小异,但它有质量极高的 3D 画面。飞船和武器升级可以通过击杀敌人所获得的点数购买。游戏的难度可以选择,因此适合新手以及想要追求挑战的硬核玩家。

安装太空?;?,你只需要在终端下运行以下指令:

  • Fedora 用户: dnf install astromenace
  • Debian/Ubuntu 用户: apt install astromenace

坦克战役Battle Tanks

坦克战役 是一个俯瞰式视角的快节奏坦克战斗游戏。玩家可以选择三种不同的陆地坦克,操纵其在地图上前行,收集道具并且尝试炸飞敌军。它有四种游戏模式,死亡竞赛(又称“死斗”)、团队死斗、夺旗模式和合作模式。死斗和夺旗模式下,分别有 9 张地图可供玩家选择,合作模式则有 4 张。该游戏支持分屏本地双人游戏,以及在线多人竞技。游戏节奏很快,默认一次战役仅 5 分钟,因此,坦克战役十分适合想要利用零碎时间快速来一局的玩家。

安装坦克战役,你只需要在终端下运行以下指令:

  • Fedora 用户: dnf install btanks
  • Debian/Ubuntu 用户: apt install btanks

火星M.A.R.S.

火星 是一个自上而下的太空射击游戏,游戏机制类似传统街机游戏 “爆破彗星Asteroids”。玩家在操控一个太空船的同时向敌方射击并躲避敌军的弹幕射击。游戏有标准的死斗和团体死斗模式,除此之外也有更新鲜的比赛形式 —— 例如在一个模式下,玩家需要控制一个球使其进入敌方母星。该游戏支持本地多人游戏,但遗憾的是不支持多人联机。该游戏的开发更新似乎已经停止,所以该游戏之后增加联机模式的几率很小,但就算没有联机支持,这个游戏仍然值得一试。

安装火星,你只需要在终端下运行以下指令:

  • Fedora 用户: dnf install marsshooter
  • Debian/Ubuntu 用户: apt install marsshooter

不存在之球Neverball

不存在之球 的游戏灵感来源自世嘉的 “超级猴子球Super Monkey Ball” ,玩家需要将一个球在 3D 球场上运动起来,但是玩家控制的不是球,而是球场。游戏任务是在规定的时限内,收集足够多的金币从而打开该关卡的出口并且将小球落进该洞中。游戏可以调整难度,从休闲到难以超乎想象,可以适应不同的玩家需求。该游戏支持键盘/鼠标以及控制杆操作。

安装不存在之球,你只需要在终端下运行以下指令:

  • Fedora 用户:dnf install neverball
  • Debian/Ubuntu 用户:apt install neverball

超级 TuxSuperTux

超级 Tux 是继任天堂超级马里奥后的一款 2D 的平台跳跃游戏。Linux 的吉祥物企鹅 Tux 代替了马里奥,而鸡蛋对应着马里奥系列中的蘑菇能力提升。当 Tux 获得了鸡蛋得到了能力提升,它便可以收集花朵,而花朵可以带来新的附加特殊能力?;鹧婊ㄔ诠乜ㄖ凶钗<?,收集了火焰花的 Tux 可以掷出火球。除此之外,冰冻花/空气花/土地花也在游戏的程序中。收集星星的能力提升能使 Tux 暂时变得隐形,就如同马里奥系列游戏。该游戏最基础的一组关卡,冰之岛也有 30 关之多,因此游戏的内容和流程和超级马里奥系列一般长。SuperTux 还有一些附加关卡,例如三个额外奖励小岛、一个森林之岛、一个万圣节岛、一个孵化处,以及很多测试关卡。SuperTux 有一个自带的关卡编辑器,所以玩家可以创建他们的原创关卡。

安装超级 Tux,你只需要在终端下运行以下指令:

  • Fedora 用户:dnf install supertux
  • Debian/Ubuntu 用户: apt install supertux

如果我没有在上文中提及你最喜欢的开源街机游戏,欢迎在评论中分享。

有关作者

Joshua Allen Holm – 是 Opensource.com 的社区协调者之一。他的主要兴趣有数字人文、学术开放以及公开教育资源。你可以在 GitHub、GitLab、LinkedIn 和 Zotero 上找到他??梢酝ü?holmja@opensource.com 联系到他。

 

5 款 Linux 街机游戏,首发于山西十一选五手机版。

]]>
//www.brhi.net/114636/feed/ 0
“三次握手,四次挥手”你真的懂吗? - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114633/ //www.brhi.net/114633/#respond Wed, 09 Jan 2019 02:03:01 +0000 //www.brhi.net/?p=114633 作为程序员,要有“刨根问底”的精神。知其然,更要知其所以然。这篇文章希望能抽丝剥茧,还原背后的原理。

“三次握手,四次挥手”你真的懂吗?,首发于山西十一选五手机版。

]]>
记得刚毕业找工作面试的时候,经?;岜晃实剑耗阒馈?次握手,4次挥手”吗?这时候我会“胸有成竹”地“背诵”前期准备好的“答案”,第一次怎么怎么,第二次……答完就没有下文了,面试官貌似也没有深入下去的意思,深入下去我也不懂,皆大欢喜!

作为程序员,要有“刨根问底”的精神。知其然,更要知其所以然。这篇文章希望能抽丝剥茧,还原背后的原理。

什么是“3次握手,4次挥手”

TCP是一种面向连接的单播协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的“连接”,其实是客户端和服务器的内存里保存的一份关于对方的信息,如ip地址、端口号等。

TCP可以看成是一种字节流,它会处理IP层或以下的层的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放在TCP头部。

TCP提供了一种可靠、面向连接、字节流、传输层的服务,采用三次握手建立一个连接。采用4次挥手来关闭一个连接。

TCP服务模型

在了解了建立连接、关闭连接的“三次握手和四次挥手”后,我们再来看下TCP相关的东西。

一个TCP连接由一个4元组构成,分别是两个IP地址和两个端口号。一个TCP连接通常分为三个阶段:启动、数据传输、退出(关闭)。

当TCP接收到另一端的数据时,它会发送一个确认,但这个确认不会立即发送,一般会延迟一会儿。ACK是累积的,一个确认字节号N的ACK表示所有直到N的字节(不包括N)已经成功被接收了。这样的好处是如果一个ACK丢失,很可能后续的ACK就足以确认前面的报文段了。

一个完整的TCP连接是双向和对称的,数据可以在两个方向上平等地流动。给上层应用程序提供一种双工服务。一旦建立了一个连接,这个连接的一个方向上的每个TCP报文段都包含了相反方向上的报文段的一个ACK。

序列号的作用是使得一个TCP接收端可丢弃重复的报文段,记录以杂乱次序到达的报文段。因为TCP使用IP来传输报文段,而IP不提供重复消除或者保证次序正确的功能。另一方面,TCP是一个字节流协议,绝不会以杂乱的次序给上层程序发送数据。因此TCP接收端会被迫先保持大序列号的数据不交给应用程序,直到缺失的小序列号的报文段被填满。

TCP头部

tcp header

源端口和目的端口在TCP层确定双方进程,序列号表示的是报文段数据中的第一个字节号,ACK表示确认号,该确认号的发送方期待接收的下一个序列号,即最后被成功接收的数据字节序列号加1,这个字段只有在ACK位被启用的时候才有效。

当新建一个连接时,从客户端发送到服务端的第一个报文段的SYN位被启用,这称为SYN报文段,这时序列号字段包含了在本次连接的这个方向上要使用的第一个序列号,即初始序列号ISN,之后发送的数据是ISN加1,因此SYN位字段会消耗一个序列号,这意味着使用重传进行可靠传输。而不消耗序列号的ACK则不是。

头部长度(图中的数据偏移)以32位字为单位,也就是以4bytes为单位,它只有4位,最大为15,因此头部最大长度为60字节,而其最小为5,也就是头部最小为20字节(可变选项为空)。

ACK —— 确认,使得确认号有效。
RST —— 重置连接(经??吹降膔eset by peer)就是此字段搞的鬼。
SYN —— 用于初如化一个连接的序列号。
FIN —— 该报文段的发送方已经结束向对方发送数据。

当一个连接被建立或被终止时,交换的报文段只包含TCP头部,而没有数据。

状态转换

三次握手和四次挥手的状态转换如下图。
tcp connect

为什么要“三次握手,四次挥手”

三次握手

换个易于理解的视角来看为什么要3次握手。

客户端和服务端通信前要进行连接,“3次握手”的作用就是双方都能明确自己和对方的收、发能力是正常的。

第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。

第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。
从客户端的视角来看,我接到了服务端发送过来的响应数据包,说明服务端接收到了我在第一次握手时发送的网络包,并且成功发送了响应数据包,这就说明,服务端的接收、发送能力正常。而另一方面,我收到了服务端的响应数据包,说明我第一次发送的网络包成功到达服务端,这样,我自己的发送和接收能力也是正常的。

第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接收、发送能力,服务端的发送、接收能力是正常的。
第一、二次握手后,服务端并不知道客户端的接收能力以及自己的发送能力是否正常。而在第三次握手时,服务端收到了客户端对第二次握手作的回应。从服务端的角度,我在第二次握手时的响应数据发送出去了,客户端接收到了。所以,我的发送能力是正常的。而客户端的接收能力也是正常的。

经历了上面的三次握手过程,客户端和服务端都确认了自己的接收、发送能力是正常的。之后就可以正常通信了。

每次都是接收到数据包的一方可以得到一些结论,发送的一方其实没有任何头绪。我虽然有发包的动作,但是我怎么知道我有没有发出去,而对方有没有接收到呢?

而从上面的过程可以看到,最少是需要三次握手过程的。两次达不到让双方都得出自己、对方的接收、发送能力都正常的结论。其实每次收到网络包的一方至少是可以得到:对方的发送、我方的接收是正常的。而每一步都是有关联的,下一次的“响应”是由于第一次的“请求”触发,因此每次握手其实是可以得到额外的结论的。比如第三次握手时,服务端收到数据包,表明看服务端只能得到客户端的发送能力、服务端的接收能力是正常的,但是结合第二次,说明服务端在第二次发送的响应包,客户端接收到了,并且作出了响应,从而得到额外的结论:客户端的接收、服务端的发送是正常的。

用表格总结一下:

视角 客收 客发 服收 服发
客视角 一 + 二 一 + 二
服视角 二 + 三 二 + 三

四次挥手

TCP连接是双向传输的对等的模式,就是说双方都可以同时向对方发送或接收数据。当有一方要关闭连接时,会发送指令告知对方,我要关闭连接了。这时对方会回一个ACK,此时一个方向的连接关闭。但是另一个方向仍然可以继续传输数据,等到发送完了所有的数据后,会发送一个FIN段来关闭此方向上的连接。接收方发送ACK确认关闭连接。注意,接收到FIN报文的一方只能回复一个ACK, 它是无法马上返回对方一个FIN报文段的,因为结束数据传输的“指令”是上层应用层给出的,我只是一个“搬运工”,我无法了解“上层的意志”。

“三次握手,四次挥手”怎么完成?

其实3次握手的目的并不只是让通信双方都了解到一个连接正在建立,还在于利用数据包的选项来传输特殊的信息,交换初始序列号ISN。

3次握手是指发送了3个报文段,4次挥手是指发送了4个报文段。注意,SYN和FIN段都是会利用重传进行可靠传输的。

三次握手

三次握手

  1. 客户端发送一个SYN段,并指明客户端的初始序列号,即ISN(c).
  2. 服务端发送自己的SYN段作为应答,同样指明自己的ISN(s)。为了确认客户端的SYN,将ISN(c)+1作为ACK数值。这样,每发送一个SYN,序列号就会加1. 如果有丢失的情况,则会重传。
  3. 为了确认服务器端的SYN,客户端将ISN(s)+1作为返回的ACK数值。

四次挥手

四次挥手

  1. 客户端发送一个FIN段,并包含一个希望接收者看到的自己当前的序列号K. 同时还包含一个ACK表示确认对方最近一次发过来的数据。
  2. 服务端将K值加1作为ACK序号值,表明收到了上一个包。这时上层的应用程序会被告知另一端发起了关闭操作,通常这将引起应用程序发起自己的关闭操作。
  3. 服务端发起自己的FIN段,ACK=K+1, Seq=L
  4. 客户端确认。ACK=L+1

为什么建立连接是三次握手,而关闭连接却是四次挥手呢?

这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方是否现在关闭发送数据通道,需要上层应用来决定,因此,己方ACK和FIN一般都会分开发送。

“三次握手,四次挥手”进阶

ISN

三次握手的一个重要功能是客户端和服务端交换ISN(Initial Sequence Number), 以便让对方知道接下来接收数据的时候如何按序列号组装数据。

如果ISN是固定的,攻击者很容易猜出后续的确认号。

ISN = M + F(localhost, localport, remotehost, remoteport)

M是一个计时器,每隔4毫秒加1。
F是一个Hash算法,根据源IP、目的IP、源端口、目的端口生成一个随机数值。要保证hash算法不能被外部轻易推算得出。

序列号回绕

因为ISN是随机的,所以序列号容易就会超过2^31-1. 而tcp对于丢包和乱序等问题的判断都是依赖于序列号大小比较的。此时就出现了所谓的tcp序列号回绕(sequence wraparound)问题。怎么解决?

/*
* The next routines deal with comparing 32 bit unsigned ints
* and worry about wraparound (automatic with unsigned arithmetic).
*/
static inline int before(__u32 seq1, __u32 seq2)
{
    return (__s32)(seq1-seq2) < 0;
}

#define after(seq2, seq1) before(seq1, seq2)

上述代码是内核中的解决回绕问题代码。__s32是有符号整型的意思,而__u32则是无符号整型。序列号发生回绕后,序列号变小,相减之后,把结果变成有符号数了,因此结果成了负数。

假设seq1=255, seq2=1(发生了回绕)。
seq1 = 1111 1111 seq2 = 0000 0001
我们希望比较结果是
 seq1 - seq2=
 1111 1111
-0000 0001
-----------
 1111 1110

由于我们将结果转化成了有符号数,由于最高位是1,因此结果是一个负数,负数的绝对值为
 0000 0001 + 1 = 0000 0010 = 2

因此seq1 - seq2 < 0

syn flood攻击

最基本的DoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应。syn flood属于Dos攻击的一种。

如果恶意的向某个服务器端口发送大量的SYN包,则可以使服务器打开大量的半开连接,分配TCB(Transmission Control Block), 从而消耗大量的服务器资源,同时也使得正常的连接请求无法被相应。当开放了一个TCP端口后,该端口就处于Listening状态,不停地监视发到该端口的Syn报文,一 旦接收到Client发来的Syn报文,就需要为该请求分配一个TCB,通常一个TCB至少需要280个字节,在某些操作系统中TCB甚至需要1300个字节,并返回一个SYN ACK命令,立即转为SYN-RECEIVED即半开连接状态。系统会为此耗尽资源。

常见的防攻击方法有:

无效连接的监视释放

监视系统的半开连接和不活动连接,当达到一定阈值时拆除这些连接,从而释放系统资源。这种方法对于所有的连接一视同仁,而且由于SYN Flood造成的半开连接数量很大,正常连接请求也被淹没在其中被这种方式误释放掉,因此这种方法属于入门级的SYN Flood方法。

延缓TCB分配方法

消耗服务器资源主要是因为当SYN数据报文一到达,系统立即分配TCB,从而占用了资源。而SYN Flood由于很难建立起正常连接,因此,当正常连接建立起来后再分配TCB则可以有效地减轻服务器资源的消耗。常见的方法是使用Syn Cache和Syn Cookie技术。

Syn Cache技术

系统在收到一个SYN报文时,在一个专用HASH表中保存这种半连接信息,直到收到正确的回应ACK报文再分配TCB。这个开销远小于TCB的开销。当然还需要保存序列号。

Syn Cookie技术

Syn Cookie技术则完全不使用任何存储资源,这种方法比较巧妙,它使用一种特殊的算法生成Sequence Number,这种算法考虑到了对方的IP、端口、己方IP、端口的固定信息,以及对方无法知道而己方比较固定的一些信息,如MSS(Maximum Segment Size,最大报文段大小,指的是TCP报文的最大数据报长度,其中不包括TCP首部长度。)、时间等,在收到对方 的ACK报文后,重新计算一遍,看其是否与对方回应报文中的(Sequence Number-1)相同,从而决定是否分配TCB资源。

使用SYN Proxy防火墙

一种方式是防止墙dqywb连接的有效性后,防火墙才会向内部服务器发起SYN请求。防火墙代服务器发出的SYN ACK包使用的序列号为c, 而真正的服务器回应的序列号为c’, 这样,在每个数据报文经过防火墙的时候进行序列号的修改。另一种方式是防火墙确定了连接的安全后,会发出一个safe reset命令,client会进行重新连接,这时出现的syn报文会直接放行。这样不需要修改序列号了。但是,client需要发起两次握手过程,因此建立连接的时间将会延长。

连接队列

在外部请求到达时,被服务程序最终感知到前,连接可能处于SYN_RCVD状态或是ESTABLISHED状态,但还未被应用程序接受。

tcp queue

对应地,服务器端也会维护两种队列,处于SYN_RCVD状态的半连接队列,而处于ESTABLISHED状态但仍未被应用程序accept的为全连接队列。如果这两个队列满了之后,就会出现各种丢包的情形。

查看是否有连接溢出
netstat -s | grep LISTEN

半连接队列满了

在三次握手协议中,服务器维护一个半连接队列,该队列为每个客户端的SYN包开设一个条目(服务端在接收到SYN包的时候,就已经创建了request_sock结构,存储在半连接队列中),该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。

目前,Linux下默认会进行5次重发SYN-ACK包,重试的间隔时间从1s开始,下次的重试间隔时间是前一次的双倍,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s, 总共31s, 称为指数退避,第5次发出后还要等32s才知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 63s, TCP才会把断开这个连接。由于,SYN超时需要63秒,那么就给攻击者一个攻击服务器的机会,攻击者在短时间内发送大量的SYN包给Server(俗称SYN flood攻击),用于耗尽Server的SYN队列。对于应对SYN 过多的问题,linux提供了几个TCP参数:tcp_syncookies、tcp_synack_retries、tcp_max_syn_backlog、tcp_abort_on_overflow 来调整应对。

参数 作用
tcp_syncookies SYNcookie将连接信息编码在ISN(initialsequencenumber)中返回给客户端,这时server不需要将半连接保存在队列中,而是利用客户端随后发来的ACK带回的ISN还原连接信息,以完成连接的建立,避免了半连接队列被攻击SYN包填满。
tcp_syncookies 内核放弃建立连接之前发送SYN包的数量。
tcp_synack_retries 内核放弃连接之前发送SYN+ACK包的数量
tcp_max_syn_backlog 默认为1000. 这表示半连接队列的长度,如果超过则放弃当前连接。
tcp_abort_on_overflow 如果设置了此项,则直接reset. 否则,不做任何操作,这样当服务器半连接队列有空了之后,会重新接受连接。Linux坚持在能力许可范围内不忽略进入的连接??突Ф嗽谡馄诩浠嶂馗捶⑺蛃ys包,当重试次数到达上限之后,会得到connection time out响应。

全连接队列满了

当第三次握手时,当server接收到ACK包之后,会进入一个新的叫 accept 的队列。

当accept队列满了之后,即使client继续向server发送ACK的包,也会不被响应,此时ListenOverflows+1,同时server通过tcp_abort_on_overflow来决定如何返回,0表示直接丢弃该ACK,1表示发送RST通知client;相应的,client则会分别返回read timeout 或者 connection reset by peer。另外,tcp_abort_on_overflow是0的话,server过一段时间再次发送syn+ack给client(也就是重新走握手的第二步),如果client超时等待比较短,就很容易异常了。而客户端收到多个 SYN ACK 包,则会认为之前的 ACK 丢包了。于是促使客户端再次发送 ACK ,在 accept队列有空闲的时候最终完成连接。若 accept队列始终满员,则最终客户端收到 RST 包(此时服务端发送syn+ack的次数超出了tcp_synack_retries)。

服务端仅仅只是创建一个定时器,以固定间隔重传syn和ack到服务端

参数 作用
tcp_abort_on_overflow 如果设置了此项,则直接reset. 否则,不做任何操作,这样当服务器半连接队列有空了之后,会重新接受连接。Linux坚持在能力许可范围内不忽略进入的连接??突Ф嗽谡馄诩浠嶂馗捶⑺蛃ys包,当重试次数到达上限之后,会得到connection time out响应。
min(backlog, somaxconn) 全连接队列的长度。

命令

netstat -s命令

[root@server ~]#  netstat -s | egrep "listen|LISTEN" 
667399 times the listen queue of a socket overflowed
667399 SYNs to LISTEN sockets ignored

上面看到的 667399 times ,表示全连接队列溢出的次数,隔几秒钟执行下,如果这个数字一直在增加的话肯定全连接队列偶尔满了。

[root@server ~]#  netstat -s | grep TCPBacklogDrop

查看 Accept queue 是否有溢出

ss命令

[root@server ~]#  ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN     0      128 *:6379 *:*
LISTEN     0      128 *:22 *:*

如果State是listen状态,Send-Q 表示第三列的listen端口上的全连接队列最大为50,第一列Recv-Q为全连接队列当前使用了多少。
非 LISTEN 状态中 Recv-Q 表示 receive queue 中的 bytes 数量;Send-Q 表示 send queue 中的 bytes 数值。

小结

当外部连接请求到来时,TCP??榛崾紫炔榭磎ax_syn_backlog,如果处于SYN_RCVD状态的连接数目超过这一阈值,进入的连接会被拒绝。根据tcp_abort_on_overflow字段来决定是直接丢弃,还是直接reset.

从服务端来说,三次握手中,第一步server接受到client的syn后,把相关信息放到半连接队列中,同时回复syn+ack给client. 第三步当收到客户端的ack, 将连接加入到全连接队列。

一般,全连接队列比较小,会先满,此时半连接队列还没满。如果这时收到syn报文,则会进入半连接队列,没有问题。但是如果收到了三次握手中的第3步(ACK),则会根据tcp_abort_on_overflow字段来决定是直接丢弃,还是直接reset.此时,客户端发送了ACK, 那么客户端认为三次握手完成,它认为服务端已经准备好了接收数据的准备。但此时服务端可能因为全连接队列满了而无法将连接放入,会重新发送第2步的syn+ack, 如果这时有数据到来,服务器TCP??榛峤荽嫒攵恿兄?。一段时间后,client端没收到回复,超时,连接异常,client会主动关闭连接。

“三次握手,四次挥手”redis实例分析

  1. 我在dev机器上部署redis服务,端口号为6379,
  2. 通过tcpdump工具获取数据包,使用如下命令

tcpdump -w /tmp/a.cap port 6379 -s0
-w把数据写入文件,-s0设置每个数据包的大小默认为68字节,如果用-S 0则会抓到完整数据包

  1. 在dev2机器上用redis-cli访问dev:6379, 发送一个ping, 得到回复pong
  2. 停止抓包,用tcpdump读取捕获到的数据包

tcpdump -r /tmp/a.cap -n -nn -A -x| vim -
(-x 以16进制形式展示,便于后面分析)

共收到了7个包。

抓到的是IP数据包,IP数据包分为IP头部和IP数据部分,IP数据部分是TCP头部加TCP数据部分。

IP的数据格式为:
ip head
它由固定长度20B+可变长度构成。

10:55:45.662077 IP dev2.39070 > dev.6379: Flags [S], seq 4133153791, win 29200, options [mss 1460,sackOK,TS val 2959270704 ecr 0,nop,wscale 7], length 0
        0x0000:  4500 003c 08cf 4000 3606 14a5 0ab3 b561
        0x0010:  0a60 5cd4 989e 18eb f65a ebff 0000 0000
        0x0020:  a002 7210 872f 0000 0204 05b4 0402 080a
        0x0030:  b062 e330 0000 0000 0103 0307

对着IP头部格式,来拆解数据包的具体含义。

字节值 字节含义
0x4 IP版本为ipv4
0x5 首部长度为5 * 4字节=20B
0x00 服务类型,现在基本都置为0
0x003c 总长度为3*16+12=60字节,上面所有的长度就是60字节
0x08cf 标识。同一个数据报的唯一标识。当IP数据报被拆分时,会复制到每一个数据中。
0x4000 3bit 标志 + 13bit 片偏移。3bit 标志对应 R、DF、MF。目前只有后两位有效,DF位:为1表示不分片,为0表示分片。MF:为1表示“更多的片”,为0表示这是最后一片。13bit 片位移:本分片在原先数据报文中相对首位的偏移位。(需要再乘以8 )
0x36 生存时间TTL。IP报文所允许通过的路由器的最大数量。每经过一个路由器,TTL减1,当为 0 时,路由器将该数据报丢弃。TTL 字段是由发送端初始设置一个 8 bit字段.推荐的初始值由分配数字 RFC 指定。发送 ICMP 回显应答时经常把 TTL 设为最大值 255。TTL可以防止数据报陷入路由循环。 此处为54.
0x06 协议类型。指出IP报文携带的数据使用的是哪种协议,以便目的主机的IP层能知道要将数据报上交到哪个进程。TCP 的协议号为6,UDP 的协议号为17。ICMP 的协议号为1,IGMP 的协议号为2。该 IP 报文携带的数据使用 TCP 协议,得到了验证。
0x14a5 16bitIP首部校验和。
0x0ab3 b561 32bit源ip地址。
0x0a60 5cd4 32bit目的ip地址。

剩余的数据部分即为TCP协议相关的。TCP也是20B固定长度+可变长度部分。

字节值 字节含义
0x989e 16bit源端口。1161616+81616+1416+11=39070
0x18eb 16bit目的端口6379
0xf65a ebff 32bit序列号。4133153791
0x0000 0000 32bit确认号。
0xa 4bit首部长度,以4byte为单位。共10*4=40字节。因此TCP报文的可选长度为40-20=20
0b000000 6bit保留位。目前置为0.
0b000010 6bitTCP标志位。从左到右依次是紧急 URG、确认 ACK、推送 PSH、复位 RST、同步 SYN 、终止 FIN。
0x7210 滑动窗口大小,滑动窗口即tcp接收缓冲区的大小,用于tcp拥塞控制。29200
0x872f 16bit校验和。
0x0000 紧急指针。仅在 URG = 1时才有意义,它指出本报文段中的紧急数据的字节数。当 URG = 1 时,发送方 TCP 就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍是普通数据。

可变长度部分,协议如下:

字节值 字节含义
0x0204 05b4 最大报文长度为,05b4=1460. 即可接收的最大包长度,通常为MTU减40字节,IP头和TCP头各20字节
0x0402 表示支持SACK
0x080a b062 e330 0000 0000 时间戳。Ts val=b062 e330=2959270704, ecr=0
0x01 无操作
0x03 0307 窗口扩大因子为7. 移位7, 乘以128

这样第一个包分析完了。dev2向dev发送SYN请求。也就是三次握手中的第一次了。
SYN seq(c)=4133153791

第二个包,dev响应连接,ack=4133153792. 表明dev下次准备接收这个序号的包,用于tcp字节注的顺序控制。dev(也就是server端)的初始序号为seq=4264776963, syn=1.
SYN ack=seq(c)+1 seq(s)=4264776963

第三个包,client包确认,这里使用了相对值应答。seq=4133153792, 等于第二个包的ack. ack=4264776964.
ack=seq(s)+1, seq=seq(c)+1
至此,三次握手完成。接下来就是发送ping和pong的数据了。

接着第四个包。

10:55:48.090073 IP dev2.39070 > dev.6379: Flags [P.], seq 1:15, ack 1, win 229, options [nop,nop,TS val 2959273132 ecr 3132256230], length 14
        0x0000:  4500 0042 08d1 4000 3606 149d 0ab3 b561
        0x0010:  0a60 5cd4 989e 18eb f65a ec00 fe33 5504
        0x0020:  8018 00e5 4b5f 0000 0101 080a b062 ecac
        0x0030:  bab2 6fe6 2a31 0d0a 2434 0d0a 7069 6e67
        0x0040:  0d0a

tcp首部长度为32B, 可选长度为12B. IP报文的总长度为66B, 首部长度为20B, 因此TCP数据部分长度为14B. seq=0xf65a ec00=4133153792
ACK, PSH. 数据部分为2a31 0d0a 2434 0d0a 7069 6e67 0d0a

0x2a31         -> *1
0x0d0a         -> \r\n
0x2434         -> $4
0x0d0a         -> \r\n
0x7069 0x6e67  -> ping
0x0d0a         -> \r\n

dev2向dev发送了ping数据,第四个包完毕。

第五个包,dev2向dev发送ack响应。
序列号为0xfe33 5504=4264776964, ack确认号为0xf65a ec0e=4133153806=(4133153792+14).

第六个包,dev向dev2响应pong消息。序列号fe33 5504,确认号f65a ec0e, TCP头部可选长度为12B, IP数据报总长度为59B, 首部长度为20B, 因此TCP数据长度为7B.
数据部分2b50 4f4e 470d 0a, 翻译过来就是+PONG\r\n.

至此,Redis客户端和Server端的三次握手过程分析完毕。

总结

“三次握手,四次挥手”看似简单,但是深究进去,还是可以延伸出很多知识点的。比如半连接队列、全连接队列等等。以前关于TCP建立连接、关闭连接的过程很容易就会忘记,可能是因为只是死记硬背了几个过程,没有深入研究背后的原理。

所以,“三次握手,四次挥手”你真的懂了吗?

参考资料

【redis】https://segmentfault.com/a/1190000015044878
【tcp option】https://blog.csdn.net/wdscq1234/article/details/52423272
【滑动窗口】https://www.zhihu.com/question/32255109
【全连接队列】//jm.taobao.org/2017/05/25/525-1/
【client fooling】 https://github.com/torvalds/linux/commit/5ea8ea2cb7f1d0db15762c9b0bb9e7330425a071
【backlog RECV_Q】//blog.51cto.com/59090939/1947443
【定时器】https://www.cnblogs.com/menghuanbiao/p/5212131.html
【队列图示】https://www.itcodemonkey.com/article/5834.html
【tcp flood攻击】https://www.cnblogs.com/hubavyn/p/4477883.html
【MSS MTU】https://blog.csdn.net/LoseInVain/article/details/53694265

“三次握手,四次挥手”你真的懂吗?,首发于山西十一选五手机版。

]]>
//www.brhi.net/114633/feed/ 0
从软件工程的角度解读任正非的新年公开信 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114605/ //www.brhi.net/114605/#respond Tue, 08 Jan 2019 05:52:57 +0000 //www.brhi.net/?p=114605 软件工程就像一个国家的农业,是最基础的设施!

从软件工程的角度解读任正非的新年公开信,首发于山西十一选五手机版。

]]>
近日任正非的公开信《全面提升软件工程能力与实践,打造可信的高质量产品》刷屏了,作为一个软件工程专业科班出身的软件开发从业者,自然是引起了我(@宝玉xp)的好奇。仔细阅读之下确实让我大吃一惊,看似八股官方文,但细看之下是作者对于软件工程的理解确实非常深刻,各种专业术语信手拈来,比喻恰到好处。

我对华为的研发其实一直挺好奇的,从传统的硬件公司,到现在软硬件齐头并进,华为手机销量都已经超过了苹果,可见华为的软硬件研发实力早已是全球领先了。公开信中的这一句:

二十年前的 IPD 变革,重构了我们的研发模式,实现了从依赖个人、偶然性推出成功产品,到制度化、持续地推出高质量产品的转变。

也揭示了华为的软件研发能做到领先水平的原因。

华为是在 1999 年开始从 IBM 引进 IPD 的,到今年 2019 年正好 20 年,在过去的 20 年里,IPD 帮助华为从游击队变成了正规军,研发队伍从几千人到几万人,软件产品也覆盖到手机操作系统、应用、云服务。

我对 IPD 是不甚了解的,只知道 IPD(Integrated Product Development,集成产品开发)是一种产品开发方法,但如果说软件产品的开发方法,我是比较熟悉的,那就是软件工程么!

任正非发出的这封信的大背景也很特殊,2018 年中美贸易战开始,中兴、华为首当其冲成为美国开刀的对象,跟风站队的澳大利亚、新西兰、英国也跳出来抵制华为,说华为不安全,可能含有间谍软件,窃听国家机密,这帽子一扣是很难扯清的!这就是为什么整封信从标题开始,一共 17 次提到两个关键字:“可信”。

只有让客户觉得华为的产品“可信”,华为才能尽快走出这场?;?,那么怎么才能做到可信?

如果你是餐厅老板,有人造谣你的厨房脏乱差,员工上完厕所不洗手,你怎么办?最好的办法自然是用先进的管理流程,并且让整个做菜的过程尽可能公开透明。

所以信中有这样一句话:

我们要转变观念,追求打造可信的高质量产品,不仅仅是功能、特性的高质量,也包括产品开发到交付过程的高质量。

要转变观念,不再只认结果的质量,还要追求过程质量了!而如何追求过程质量呢?那就是要:“全面提升软件工程能力和实践

如果信到此为止,也就是个普通官方八股文了。领导们么,可不就是喜欢指个大方向,说你们要用软件工程,要实施软件工程,至于怎么用,那是你们的事情,毕竟做领导的哪有几个真的懂软件工程的,难得的是这封信居然有很多具体怎么做的内容。

软件项目管理金三角

先看这一句:

我们各级管理者和全体员工都不得以进度、功能、特性等为理由来降低可信的要求,确??尚诺囊笤谥葱泄讨胁槐湫?。

振聋发聩呀同志们,热泪盈眶呀!生活中多少次:三个月的项目老板说你一个月就要给我做完;做到一半的项目,PM 说这个功能很重要,我们要加上去。最终怎么办?牺牲质量呗!又想要马儿跑得快又想要马儿不吃草,天底下哪有那么好的事情!

软件工程里面早就告诉我们了:时间、范围、成本这三个要素直接决定了产品的质量!

?希望各位老板别光学乔布斯,也学学任正非!

程序开发

2018年底程序员被裁的不少,很多程序员开始担忧起前景来,其实如果你能做到这下面要求的应该是不担心被裁的!

我们要从最基础的编码质量做起,视高质量代码为尊严和个人声誉。代码就像是高楼大厦的一砖一瓦,没有高质量的代码,可信的产品就是空中楼阁。我们要优化并遵循公司各种编程规范,遵从架构与设计原则,熟练使用各种编程库和API,编写出简洁、规范、可读性强、健壮安全的代码。

这一段是说给我们程序员看的,这其实也是对程序员的基本要求,大家看看自己,看看身边,真能做到的有多少?像我一样觉得自己还做的不够好的,咱还是努力学习吧,多练练,多用点心肯定更没问题的。

架构

说完程序员开始说架构师了:

我们要深刻理解架构的核心要素,基于可信导向来进行架构与设计。

看到没有,又提到可信了,架构设计的时候,别再天马行空,啥新酷用啥,啥流行用啥,一定要“可信导向”,架构设计目标先搞清楚!

再是细节:

在确??尚诺那疤嵯?,要在性能、功能、扩展性等方面做好权衡;慎重地定义我们的??橛虢涌?,真正做到高内聚与低耦合;我们要遵循权限和攻击面最小化等安全设计原则,科学设计??橹涞母衾胗虢涌?,提升安全性;低阶架构与设计要遵循高阶的架构与设计原则,在充分理解原有架构与设计的情况下,持续优化;我们要熟悉各种设计模式,重用公共成熟组件和服务,避免重复劳动。

“高内聚与低耦合”,“权限和攻击面最小化”,“??橹涞母衾胗虢涌凇?,“重用公共成熟组件和服务”……道理我都明白,做到可不容易!

技术债务

华为这些年高速发展,早些年为了追求速度肯定也没少走捷径,这些年下来也肯定没少欠技术债务,现在也是一个从追求速度到追求质量转型的契机。所以信中说完架构开始讲技术债务了:

我们要重构腐化的架构及不符合软件工程规范和质量要求的历史代码。我们知道,再好的架构,其生命力也是有限的。随着时间的推移、环境的变化以及新技术、新功能特性的引入,架构也会腐化。面对腐化了的架构,要毫不犹豫地去重构它。同时主动以可信设计原则为导向,去重构不符合软件工程规范和质量要求的历史代码,提升软件架构的生命力。

我们都知道,没有万能的架构,只有适合当时需求,当时技术条件和人员的架构,时间推移了很多架构就满足不了要求了,就需要重构了!作为80后,小时候其实生活挺艰苦的,那时候我们穿衣服都讲究的是:“新三年,旧三年,缝缝补补又三年”,架构也一样嘛,不满足需求我们先修修补补,真要重构挑战还是不小的,但是不去做它会一直成为发展的一个障碍,这封信也算是推了一把:“面对腐化了的架构,要毫不犹豫地去重构它?!?,当然你重构,也不要忘记“可信”这个根本目标:“同时主动以可信设计原则为导向”。

其实Google在这方面已经走在前面了,一直鼓励重写代码,任何软件每隔几年就重写一遍,这样可以优化代码,采用最新技术,去掉一些没有价值的功能,最重要的是让新员工得到锻炼,保持高昂的斗志。不知道这点是不是华为在像Google学习!

安全

这些年,互联网发展很快,但是安全事故却层出不穷:开房记录被泄漏、密码被泄漏、比特币被盗……这暴露出业界其实对安全是不够重视的,所以信中也不止一次提到安全问题:

公司已经明确,把网络安全和隐私?;ぷ魑镜淖罡吒倭??!?/p>

“我们要深入钻研软件技术,尤其是安全技术?!?/p>

“我们要遵循权限和攻击面最小化等安全设计原则,科学设计??橹涞母衾胗虢涌?,提升安全性”

“编写出简洁、规范、可读性强、健壮安全的代码。

要打造一个“安全”的软件,就是首先要有安全意识,然后要懂安全技术,在整个开发过程中要从架构设计、代码方方面面去注意。

技术是工具

这些年开发界一直有些不好的风气,就是都认为自己的技术是最牛的,写后端的看不上前端的,用angular的看不上vue,写PHP的认为自己的语言是全世界最好的,开发的还看不上测试的。但是信中这一句话不要忽视呀:“软件技术是我们打造产品的基本工具”,技术只是工具,只是我们用来打造产品的工具!

“技术是否先进,技术选择是否合理,将决定我们软件的高度;”,技术的选型,不仅看的是不是先进,还要看是不是适合当前产品项目,并不是什么什么新酷就用什么!

“我们要深入学习架构与设计、编码、测试、安全、可用性、性能、维护性、体验等技术,并科学运用这些技术?!?,既然技术只是工具,那么我们就没必要给自己设置各种技术壁垒障碍。如果开发就只学编码,测试就只学测试,认为安全那应该是搞安全的事,这样的话是非常不利于团体协作的,每个人都在一个领域能有深入的钻研,同时对其他领域有一定了解,对个人,对团队是非常有利的一件事。这样也不需要DevOps这种为了兼顾开发、测试、运维三种角色而存在的工种!

一致性

我们做软件开发的都知道,也看过很多段子:从客户的需求,到最终的实现,总是差别很大;我们在项目初始的时候制定了很多规范,却总是不了了之,难以执行;我们良好的设计,在编码实现的时候,因为赶进度、开发人员偷懒等各种原因绕开设计,抄近路,最后设计和编码无法一致……

一致性在软件开发领域一直都是理想美好而现实却很残酷,信中也提到:

我们要遵守过程的一致性。遵守适用的法律法规、遵循业界共识的标准、规范,确保规范到实现的一致性、代码到二进制的一致性。架构要符合架构原则,设计要遵循设计模式,代码要符合编程规范,最终做到需求与实现一致,达成各项对客户的承诺。我们只有脚踏实地做好每一步,才能真正打造出可信的高质量产品。

无论这个目标有多难,但是从“遵守过程的一致性”开始,在每个阶段都去做到一致性,“脚踏实地做好每一步”,还是有希望做到,“真正打造出可信的高质量产品”。

改变习惯

在实施软件工程的过程中,有两个难题,一个就是转变思想,另一个就是改变习惯了,这种改变的过程也一定是很痛苦的。

为此,我们要改变行为习惯,追求精品。我们要开放透明、积极和勇于揭示问题并主动推动改进。软件开发是一种创造性和艺术性的工作,需要充分发挥我们的聪明才智和潜力。我们要改变只重视功能结果、不重视代码质量的行为习惯,要严格遵守软件工程规范;改变被动的修修补补;改变碎片化知识获取,主动去学习提升并贡献经验、代码,形成共享知识库。我们需要改变的行为和习惯还有很多,对绝大多数人来讲都将是一个痛苦的转变过程,会脱一层皮,但我相信大家能够迎接这种挑战。

从事软件开发工作越久,恐怕养成的坏习惯就越多,信中列的几条都很有代表性:

  • “只重视功能结果、不重视代码质量”
    “功能实现完了就完事了,质量那是QA的事”,这种坏习惯不改质量是很难有保障的
  • “不遵守软件工程规范”
    软件工程的各种规范不是约束,也不是摆设,而是实实在在为了团队整体更好的协作。对于定好的规范,要严格执行,不合理的规范,也要提出来一起改进。
  • “被动的修修补补”
    为了能继续凑合,继续修修补补,而没有考虑重构改进,也是一个不好的习惯。
  • “碎片化知识获取,不主动去学习提升”
    在现在的信息时代,碎片化的知识获取是容易的,但是像软件工程这种知识,仅仅通过碎片化的学习还是不够的,必须的主动的,系统的去学习,虽然这个过程会很辛苦,但是是非常有必要的。
  • “不愿意贡献经验、代码,不去形成共享知识库”
    很多人不愿意去分享知识和经验,有的是因为太懒,有的是觉得没什么好处。但是分享本身就是一个学习和提升的最好手段!知识库这种事不仅是对别人,对自己也是一个特别好的过程。
    想象下你新加入一个团队,如果这个团队有很好的知识库,你可以通过知识库很快的上手工作,同样的,如果你把你的经验写到知识库,后面的新人也可以受益你的贡献!

“软件工程”和“质量工程”需要依靠架构技术

“软件工程”和“质量工程”需要依靠架构技术,而不是依靠CMM和QA管理流程。一切工程问题,首先要思考能否通过技术解决,当前技术无法解决的问题,暂时由管理手段代劳,同时不停止寻找技术手段。

所有的涉及到人的管理最终都要归结到人管理还是制度管理的问题上,软件项目管理也不例外,如果过多的依赖于人的管理,那么项目经理的职责就太重了,优秀的项目经理本身就是稀缺资源,最终会变成一个瓶颈。

所以通过架构技术和工具,把管理流程落实下来是一个非常好的方式。有两个例子可以很好的说明这点。

早些年软件项目团队是非常庞大的,各个服务庞大??榻裘?,所以管理成本很高,后来微服务这种架构提出后,将大的服务拆成小的服务,整个组织也从大项目部门拆分成各个小组,各小组可以独立更新维护。

另一个例子是以前单元测试和代码审查还有自动部署很难执行,后来借助源代码管理工具和CI(Continuous integration,持续集成)工具,就可以很容易的进行代码审查、并且可以确保单元测试测试跑通过后才进行部署。这一点其实信中也有体现:

我们将全面强化以Committer角色为核心的代码审核和提交机制,代码经过更加严格和系统的审核才能合入版本。为此我们将建立一支更高水平的Committer角色群体,负责软件架构的看护、代码的审核和提交,整体保障合入代码的高质量。我们要变革考核机制,要让架构设计好、代码写得好的人脱颖而出,对编程能力不满足要求的人给予帮助和培训。但任何人如果编写的代码长时间不能合入版本,将会被团队抛弃。

软件工程就像一个国家的农业

软件工程就像一个国家的农业,是最基础的设施!

很感动,这些年软件工程被提起的其实不多,大家关注的更多是各种新酷的技术,而对于这种软件开发最基础的理论视而不见?;褂腥艘惶岬饺砑こ?,就马上说软件工程不是银弹。软件工程从来不说自己是银弹,就像现代医学,也不会号称自己包治百病,只会不断改进,对症下药!

希望这封信能带动软件工程在国内的更多发展,也希望我这篇浅显的文章能帮助大家更好的理解一些软件工程的概念。

从软件工程的角度解读任正非的新年公开信,首发于山西十一选五手机版。

]]>
//www.brhi.net/114605/feed/ 0
追思杰出的 Linux 内核开发者李少华 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114630/ //www.brhi.net/114630/#respond Tue, 08 Jan 2019 05:45:47 +0000 //www.brhi.net/?p=114630 李少华是我们这一辈 Linux 内核开发者之中的杰出代表,应该说是目前华人圈最优秀和最重要的 Linux 内核开发者之一,他除了是内核子系统 MD(软raid)的维护者之外,在块设备层、I/O 调度器、NVMe、内存管理、电源管理等领域都做出了非常重要的工作。

追思杰出的 Linux 内核开发者李少华,首发于山西十一选五手机版。

]]>
2018 年最后一天,我在商场溜娃,忽然看到少华妻子的朋友圈提到李少华于 12 月 28 日离开了我们。我知道少华前阵子身体不好但有好转,这心痛的消息来得太突然,眼泪一下就出来了。家人也发现了我忽然情绪低沉,我忍不住眼泪颤抖的说“少华走了”。

李少华是我们这一辈 Linux 内核开发者之中的杰出代表,应该说是目前华人圈最优秀和最重要的 Linux 内核开发者之一,他除了是内核子系统 MD(软raid)的维护者之外,在块设备层、I/O 调度器、NVMe、内存管理、电源管理等领域都做出了非常重要的工作。他的代码和对内核的改进,融合在整个内核在 IO 和存储站的方方面面,真的是通过很具体的工作,贡献了正能量,让这世界变得更美好了些许。

和少华家人联系后得知,在最后的时候,少华还时不时的提起“我有了一个新的想法”,“这段代码路径还可以再优化改进”。这是一个多么纯粹的人,对系统软件技术充满的虔诚的纯真的热爱,我心想恐怕也只有这般专注,才能成为一个改变世界的人。很多人活一辈子,恐怕也没有少华这三十几年来的闪亮和耀眼。一辈子活成这样,从个人来说,没有遗憾,是我们心目中的英雄!

我和少华最直接的工作交集,我印象最深的有两件事情。

第一件事情是我在解决 MD raid1在 NVMe SSD 上的读写性能瓶颈时,少华认为我的修改可能会在多层 MD 设备堆叠的时候引入死锁,而我认为不会。我们在邮件列表里来回讨论了很多次,他指导我来理解MD代码中的一些细节,最终我们发现 MD raid1 在发射 IO 的时候会从另外一个 raid1d() 线程来处理,所以不会在 generic_make_request() 里面发生死锁,少华鼓励我“这是很好的讨论”,然后接受了我的 patch。而后来少华还发现了我的 patch 里的其他问题,直接就修掉了。在少华的帮助下,除了我们将 MD raid1 的读性能提升了好几倍之外,我也对 MD 的基本原理有了更深刻的认识。

第二件事情是有用户报告 MD raid0 在 NVMe SSD 上做 trim 的时候时间非常久,我自己测试在 15T 的 NVMe raid0 设备上格式化 xfs 文件系统(加trim)需要 300 多秒,绝大多数时间都用在 trim 这里了,这是很不正常的。少华分析这是因为 raid0 会将上层发来的 discard bio 按照 stripe 大小做切分,然后再发送到 raid0 组成的不同硬盘上去,所以当 raid0 容量比较大的时候,原本的一个 discard bio 可能会被切分成几百甚至上千万个小 bio 来处理,这性能一下就降低了。

我们的思路是将切分后的 bio 再根据每一个 raid0 的组件设备拼接起来,最后可以组成连续的一个或者极少数几个 bio,然后再将拼接后的bio发送到每一个组件设备上去,这样就可以降低几百万个 bio 了。我先写了一个很复杂的 patch,来准确的将所有切分的 bio 按照每个设备一个 bio 的方式拼接起来。虽然拼接出来的 bio 最少,但是代码非常难读懂。少华后来做了一个实现,大概几十行代码,做了一个次优化版本:

raid0_handle_discard()核心代码片段raid0_handle_discard()核心代码片段

少华的代码,通过一个很优雅的循环,就完成了将分布在不同组件设备上的 bio 的拼接,并且在绝大多数通常情况下,拼接效果和我的复杂代码一样,速度还更快!最后我测试出来,少华的这个代码可以将在 raid0 上格式化 xfs 文件系统的速度从 300 多秒降低到 20 多秒。当我阅读少华的 patch 时,心中充满的欣赏和愉悦,能看到一段更优雅和高效的代码,真的是非常愉悦的事情,而且这种好心情可以持续很久,每每想起都会觉得开心。

再后来我接手了 bcache 子系统的维护工作,和少华一起密切合作的机会就少了很多。但我一直在关注他在内核里的工作,看到他继续在做的很多优秀的工作。非常切合实际的说,少华是为 Linux 内核做贡献的最杰出和最重要的中国人之一,从全球华人的范围来看他的工作重要性也能够进入前 20 位。而他还这么年轻,还不到 40 岁,实在是我们这辈人之中的璀璨明星,能和他一起工作是我的骄傲和荣幸!

在写这些文字的时候,不禁回想起从最初认识少华,那时他在 Intel OTC 我在 SUSE Labs,他在做性能相关,我在做文件系统。然后2009 年我们在 CLSF[1] 会议上第一次见面,然后 2010 年他和其他 Intel 朋友一起帮忙在 Intel 紫竹园区举行第二届 CLSF。再后来他离开了 Intel 去了存储领域创新独角兽公司 Fusion IO,在 PCIe SSD、IO 调度器和块设备层做了大量的优秀工作。在我加入阿里组建淘宝内核组的时候,他已经决定去 Facebook 内核团队,和 Jens Axboe、Chiris Mason、Tanjun Heo 等国际顶级内核黑客一起工作,很遗憾没有机会和他做同事。少华一直是我们这一批人中最耀眼最杰出的极少数几个人。我在 2016 年遇到参加 Kernel Summit 的 Tanjun Heo 的时候,他特意反复几次的提到,少华非常优秀,在块设备层做了很多优秀的工作。能够被顶级黑客这样评价的人,少之又少,而我认识的国人之中大概也就两三个人吧。当时我意识到,经过长期不懈的努力工作,在 Linux 内核开发领域,少华已经跻身全球最好的 IO 栈开发者之列了。

从 git log 里看到少华的大量的贡献,我感觉到少华虽然人离开了我们,但是他的代码,仍然散发着他的才华,继续在为世界做贡献。在今后的工作中,我们还会继续阅读他的代码,就像和他在谈心,对于熟悉他的人而言,这虽然心酸,也是和老朋友对话的最好的方式。而我也知道,他的代码以及他所维护的 MD 子系统,在工业届被广泛应用。譬如现在火热的 PD-1/PD-L1 生物制药领域,通过大数据的方式来分析 DNA 特征,其中的信息处理系统中 Linux 内核和高性能 IO 栈肯定被广泛地使用到了。少华虽然离开了我们,他为这个世界留下的贡献,仍然在为创造更美好的世界发挥价值。

我们都会离开这个世界,或早或晚,命不在长短而在价值,活得有价值是很幸运的。很痛心少华过早离开了我们,但我也很羡慕他的人生活出了精彩,他自己的不懈奋斗为这操蛋的世界带来了更多的光亮。这光亮,对家人对朋友,都是鼓励和激励,让我们继续在这操蛋的世界里,为更好的世界努力不懈,也享受生活中点滴的幸福。感激少华,你短暂的一生所创造的温暖和快乐,让我感受到这世界多一点的善意和希望。

CLSF[1]: China Linux Storage, Memory management & File system Workshp

追思杰出的 Linux 内核开发者李少华,首发于山西十一选五手机版。

]]>
//www.brhi.net/114630/feed/ 0
在 Linux 上使用 tarball - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114628/ //www.brhi.net/114628/#respond Mon, 07 Jan 2019 12:57:28 +0000 //www.brhi.net/?p=114628 Tarball 提供了一种在 Linux 系统上备份和管理一组文件的通用方法。请按照以下提示了解如何创建它们,以及从中提取和删除单个文件。

在 Linux 上使用 tarball,首发于山西十一选五手机版。

]]>

Tarball 提供了一种在 Linux 系统上备份和管理一组文件的通用方法。请按照以下提示了解如何创建它们,以及从中提取和删除单个文件。

“tarball” (LCTT 译注:国内也常称为“tar 包”)一词通常用于描述备份一组选择的文件并将它们打包在一个文件中的一种文件格式。该名称来自 .tar 文件扩展名和 tar 命令,它用于将文件打包到一个文件中,有时还会压缩该文件,使其在移动到其它系统时更小。

tarball 通常用于备份个人或系统文件来创建存档,特别是在进行可能需要撤消的更改之前。例如,Linux 系统管理员通?;嵩诟挠τ弥按唇ò幌盗信渲梦募?tarball,以防必须撤消这些更改。从 tarball 中解压文件通常比在备份中搜索文件快。

如何在 Linux 上创建 tarball

使用如下命令,你可以在单条命令中创建 tarball 并压缩它。

$ tar -cvzf PDFs.tar.gz *.pdf

其结果是一个压缩文件(gzip 压缩的),其中包含了当前目录中的所有 PDF 文件。当然,压缩是可选的。一个稍微简单的只是将 PDF 文件打包成未压缩 tarball 的命令:

$ tar -cvf PDFs.tar *.pdf

注意,选项中的 z 将文件变成压缩的。 c 表明创建文件,v(详细)表示你在命令运行时需要一些反馈。如果你不想查看列出的文件,请忽略 v。

另一个常见的命名约定是给压缩的 tarball 命名成 .tgz 而不是双扩展名 .tar.gz,如下所示:

$ tar cvzf MyPDFs.tgz *.pdf

如何从 tarball 中解压文件

要从 gzip 压缩包中解压所有文件,你可以使用如下命令:

$ tar -xvzf file.tar.gz

如果使用 .tgz 命名约定,该命令将如下所示:

$ tar -xvzf MyPDFs.tgz

要从 gzip 包中解压单个文件,你可以执行几乎相同的操作,只需添加文件名:

$ tar -xvzf PDFs.tar.gz ShenTix.pdf
ShenTix.pdf
ls -l ShenTix.pdf
-rw-rw-r-- 1 shs shs 122057 Dec 14 14:43 ShenTix.pdf

如果未压缩 tarball,你甚至可以从 tarball 中删除文件。例如,如果我们想从 PDFs.tar.gz 中删除我们上面解压过的文件,我们会这样做:

$ gunzip PDFs.tar.gz
$ ls -l PDFs.tar
-rw-rw-r-- 1 shs shs 10700800 Dec 15 11:51 PDFs.tar
$ tar -vf PDFs.tar --delete ShenTix.pdf
$ ls -l PDFs.tar
-rw-rw-r-- 1 shs shs 10577920 Dec 15 11:45 PDFs.tar

请注意,我们在删除 ShenTix.pdf 后,缩小了一点 tarball 文件占用的空间。如果我们想要,我们可以再次压缩文件:

$ gzip -f PDFs.tar
ls -l PDFs.tar.gz
-rw-rw-r-- 1 shs shs 10134499 Dec 15 11:51 PDFs.tar.gzFlickr / James St. John

丰富的命令行选项使得 tarball 使用起来简单方便。

 

在 Linux 上使用 tarball,首发于山西十一选五手机版。

]]>
//www.brhi.net/114628/feed/ 0
微软变了!招程序员的流程完全改了 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114610/ //www.brhi.net/114610/#respond Sat, 05 Jan 2019 11:42:51 +0000 //www.brhi.net/?p=114610 微软真的是变了!

微软变了!招程序员的流程完全改了,首发于山西十一选五手机版。

]]>
【伯乐在线导读】:在微软新 CEO?萨蒂亚·纳德拉的领导下,微软试图改革公司文化,让整个公司朝着同一个方向发展。为此,微软在 2016 年开始研究「替代面试框架(Alternative Interview Framework)」。这是一种在开发部门进行面试的新方式,目的是减少偏见,更好地测试求职者在工作中实际需要的技能。该团队首先在自己身上测试了面试过程,并在过程中不断改进。

本文作者约翰·蒙哥马利(John Montgomery)是微软项目管理合伙人,他也是新面试流程的负责人。本文写于 2018 年 12 月 15 日,原标题:《Rethinking how we interview in Microsoft’s Developer Division | 对微软开发者部门招聘流程的反思》。以下是伯乐在线的译文:


 

几年前,我有了一系列的顿悟。我刚刚和团队讨论了我们将如何改变项目经理的角色。少关注待办事项,多关注业务;少强调“知道”,多强调“学习和质疑”;更多地关注与客户一对一的接触,而不是聚合数据。我们想把能帮助我们改变这种文化的人带到团队中,但我们仍然在问同样的面试问题,使用同样的面试风格。所以反思了我们是如何面试候选人的,并想出了一些适合我们的方法。

新面试流程我们已经用了一段时间了,我认为有必要分享一下我们所做的,以及学到的东西。

第?1 个顿悟:我们仍然在问一些过时(和无效)的面试题

第一个顿悟是我首次从程序员转为项目经理之后,我们注意到,我们仍然在问过去 10 年或更长的时间里一直在问的面试题。如果我们想寻找能够将不同技能和观点的新人带入团队,那些面试题就没有意义了。(补充:我在微软工作时,我们还在问为什么下水道井盖是圆的,一架波音 747 飞机能装满多少个乒乓球,以及如何反转一个链表。在微软工作的 20 年中,我还没有编写代码来反转链表,或用任何类型的球堆满波音 747。)

不仅如此,有时两个面试官会无意中问同样的基本问题。即使在协调面试题的时候,面试官之间也是共享着相同的面试题目录。有些基于行为的面试题并不可怕,但我们并没有特别有效地运用它们。

 

第 2 个顿悟:并不是人人都能在快节奏、高压力的环境中超常发挥

第二次顿悟是在一次会议上。点子冒出来的很快,与会者听着对方的话语,试图把自己的想法融入谈话,我们很快就做出了一些重大决定。至少,我确信这将是一件大事。(我当时被一个客户问题分散了注意力,我正与客户经理和工程团队一起解决客户的问题。这是另一个故事。)不管怎么说,这次会议已经达到了高潮,其中一位与会者,我团队中的一名 PM,他非常聪明,也很安静。他说,“我只是在网上搜索有关我们主题的信息,是的,这个想法行不通?!彼奶缺日庖?。但让我顿悟的是,并不是所有人都能在那些快节奏的头脑风暴会议中出色表现。很多人(包括我)更喜欢坐着喝杯咖啡,看看数据,试着把事情想清楚。更重要的是,在我的职业生涯中,几乎没有任何一次我们做出重大决定的时候,没有不是离开一段时间,然后用新的眼光、新的数据和新的客户研究来处理点子。

但大多数面试都是快节奏的,那些你从未遇到过的问题,你能有多快地解决?

 

第 3 个顿悟:观察新人工作能力的最佳方式,是和他们一起工作

在我和一些工程团队谈论他们是如何将新人带入他们团队的时候,第三个顿悟冒出来了??⒄卟棵抛隽撕芏嗫垂ぷ鳎?NET Core、VS?Code、TypeScript 等等。作为面试过程的一部分,我们开发团队已经开始与应聘者一起解决某个问题或特性。这就是候选人在和团队一起合作,解决实际问题的过程。

把点子写下来,然后迭代

既然“写作就是思考”,我就给自己写了一封电子邮件,讨论我们团队面试流程能有什么样的变化。然后我把自己的想法分享给团队成员,我们开始迭代。 Karen Ng、Amanda Silver、Cindy Alvarez、Nathan Halstead、Anthony Cangialosi、Jeff McAffer、Jessica Rich、Travis Lowdermilk 等成员参与了测试、迭代和测试。

当我们准备推出新面试流程时,我们从很小的地方开始,然后继续学习、迭代,然后扩展。现在,这个新流程(我们称之为“另类面试框架”,因为我们中没有人特别擅长命名事物)是我们的标准实践。我们不断地完善和学习,它对我们非常有效。

下面是我们做的一些不同的事情。

1、提前分享面试

首先,我们要提前几天让候选人知道面试日是什么样的,我们要解决什么样的问题。我们给他们时间去做研究和思考。这并不是说每天上班都是件惊喜的事,那么面试为什么要这样呢?

2、用真实的问题

其次,我们采用了团队正在努力解决的一个实际问题,比如:提高满意度、增加留存率、促进服务或特性的使用。事实上,这是我们正在解决的一个真正的问题,这有助于促进合作对话。

3、候选人可以查阅资料

第三,我们让候选人能拿到与正式员工相同的资料。在面试过程中,他们可以自由上网或搜索更多数据。我们经常向候选人提供我们的客户研究、使用数据、设计和模型——几乎我们所有的一切。

4、让面试更有互动性

我们不是简单地向求职者提问题。面试官和求职者要一起解决问题,所以我们就把求职者当同事看待,一起来解决特定的实际问题。

5、遵循单一场景/问题

第五,我们在面试日都遵循一个单一的场景/问题,带领求职者过一遍类似 PM 会经历的过程,从客户或业务问题开始,理解客户待完成的工作要,设计解决方案,将解决方案交到客户手中,最终让客户使用并爱上它。每次面试都侧重于这一流程中的某一不同的阶段。

6、两个面试官

第六,我们为面试官配对。与一对一的面试不同,我们每次面试都从团队中挑选两个人。我们的最初动机是培养更多的面试官,但有两个面试官在一起还有其他好处。与多个合作者的谈话,不仅更有活力,而且让我们有机会从多个角度观察同一场面试谈话。并不是每个人对同一场面试谈话都有同样的看法,所以,它给了我们一种方法来检查在相同谈话中的无意识偏见。

7、把反馈留到最后

面试官之间的反馈,我们把保留到面试日结束之时。我们希望每位面试官只根据他们谈话的优点来判断候选人,而不是根据他们之前面试官的意见。我们告诉面试官,不要向别人暗示他们是否倾向于推荐我们雇佣某人。他们把候选人交给下一轮面试官,并总结我们在上一环节中学到的东西。在面试日结束的时候,每个面试官同时提出他们的建议,并解释相应理由。

8、总结面试流程的优缺点

第八,在每次面试循环的最后,我们不仅要讨论我们在面试中所学到的东西,还要讨论在面试过程中哪些有用,哪些没用。我们再把这些反馈重新应用到面试流程中,流程会变得更好。

 

关于新的面试流程,我或许忘了一些,但上述 8 个方面是最重要的。

我们学到了什么?

嗯,我们担心候选人会紧张。面试日有两个面试官和候选人在一起,有真实的问题,还有真实的数据。几乎每个候选人都主动反馈说,新面试流程是独一无二的,真正帮助他们了解我们的业务和团队。即使是那些没有收到录用通知的求职者,也喜欢新的面试流程,明白我们为什么没有录用他们。

不断优化面试流程

我们发现还是有不少要改进的地方。例如,我们 PM 团队是非常有技术性的。许多 PM 将代码?check in 生产产品。这对我们来说是有意义的:我们面试流程的「客户」是开发者,因此拥有来自于创建软件的那种客户理解,是很有帮助的。但在这个过程中,我们并没有很好地深入了解应聘者的技术技能。因此,我们增加了一个面试环节,以进行更技术性的互动。

后勤

我们了解到,相对标准面试流程,新流程的一些相应准备工作真心不容易。举个例子,由于求职者正在处理同样的问题,并在白板上写下他们以后需要的东西,我们需要为求职者保留一个专门的空间(会议室或?Focus Room),面试官会去找求职者。

(补注:Focus Room 是一个消除压力的环境,可以帮助你在缓解压力的同时传递信息。)

面试过程的成本不菲

我们了解到面试是“昂贵的”?!懊看瘟礁雒媸怨?,我们的时间和人力投入翻了一番,大大增加了日程安排的复杂性?!比欢?,在最初对费用有些抱怨之后,团队中的每个人都开始看到了好处,就像团队中有更多的人见到了我们潜在的新员工。所以,我们愿意付出这些代价。

最终,招聘流程的目标是把优秀的人员带入团队或公司——确保他们是合适的,会成功,并为他们创造良好的经验,他们才会想要加入。我们和其他几家西雅图的大型科技公司都向一位求职者提供了竞争性的工作机会,她特别选择了我们的团队,因为她非常喜欢这个过程。她碰巧成为了我们在早期实验阶段的候选人之一,她还在这里上班,做的很好。其他很多候选人也类似。所以我说,我们的新面试流程表现的很好。我们仍在学习,但到目前为止,新面试流程的成果已超过我们的预期。

微软变了!招程序员的流程完全改了,首发于山西十一选五手机版。

]]>
//www.brhi.net/114610/feed/ 0
cat 命令的源码进化史 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114591/ //www.brhi.net/114591/#respond Thu, 03 Jan 2019 14:53:08 +0000 //www.brhi.net/?p=114591 在不断变化,日新月异的计算机领域,过往的知识和软件都被淘汰了吗?通过我们最熟悉的 cat 命令行,作者想像你说明的是,现在看来很陈旧的,三四十年前的想法与概念,在很多时候都融入到了你现在计算机上安装了的应用程序里,而很多程序比你想象的要古老的多。

cat 命令的源码进化史,首发于山西十一选五手机版。

]]>
cat-command-linux

有一次,我跟我的亲戚有一场争论,是关于读一个计算机科学的学位是否值得。当时是我在大学里面临是否选择计算机科学专业的时候。我姑姑和一个表哥认为我不该选。他们觉得会编程当然是个既有用又合算的事情,但是他们也坚信,计算机科学更新太快了,当下学到的知识会很快被淘汰掉。所以最好是选一门编程的课程,然后主修经济或者物理这种基本知识一辈子都适用的专业。

我并不相信他们的理论,并且选择了主修计算机专业(抱歉了姑姑和表哥?。┢涫挡荒芽闯?,为什么常人会认为计算机科学,或者软件工程这样的专业,每几年就会更新换代。先是诞生了私人计算机,然后是网络,手机,机器学习……科技永远在变化,那么其潜在的技术原理当然也在变化了。当然,最让人惊讶的是,这些基础技术原理,其实基本没变。我相信大部分人要是知道他们计算机中重要软件到底有多老,肯定会震惊。我并不是说软件的表面,毕竟我自己用的最多的火狐浏览器,两周前才更新过。但是如果你打开帮助手册查看?grep?之类的工具,你会发现它的上一次更新还是在 2010 年(至少 Mac 系统是这样)。grep?的初代诞生于 1974 年,那时候的计算机时代好比侏罗纪。现如今,人们(以及程序)在工作中仍然要依赖 grep 做很多事情。

我姑姑和表哥把计算机科技想象成一系列沙滩上的城堡,涨潮时潮水抹去旧的城堡,更加华丽的新城堡又会被建成。其实在现实中的很多领域,我们都是不断地在现有的程序基础上进行迭代。我们也许会时不时的修改这些程序来避免软件崩溃,但是除此之外这些程序不需要额外的维护。grep?是一个简单的程序,它所解决的问题现在也有意义,所以它至今还存在。很多应用程序的编写都起始于一个很高的角度,就像是在金字塔顶端的基础上构建,而金字塔本身是由曾经解决问题的答案所建成的。现在看来很陈旧的,三四十年前的想法与概念,在很多时候都融入到了你现在计算机上安装了的应用程序里。

我想仔细研究一个这样的老程序,看看它从诞生到现在到底被修改了多少次,这肯定很有趣。我想用?cat?这个最简单的 Unix 工具来作为例子。Ken Thompson 在 1969 年开发了初代?cat。如果我跟别人说我计算机里有个 1969 年的程序,这准确吗?cat?在这几十年里到底经历了几次迭代?我们计算机里的程序到底有多古老?

幸好有这个代码仓库,我们可以清晰地了解到,从 1969 年以来,cat?是如何进化的。我接下来会主要聚焦于我自己 Macbook 上?cat?程序的历史实现方式。你会看到,cat?历史从最初的 Unix 版本,到现在的 Mac 版本,这个程序被重写了比你预想的还要多的次数,但是最终它所实现的功能几乎跟五十年前一模一样。

Unix实验版本

1969 年,Ken Thompson 和 Dennis Ritchie 开始在 PDP 7 上开发 Unix。这是在 C 语言出现之前,所以早期的 Unix 程序都是用 PDP 7 上用汇编语言开发的。他们使用了专门针对于 Unix 的汇编版本,因为 Ken Thompson 开发了自己的汇编编译器,他在 PDP 7 出厂商DEC 提供的编译器基础上添加了新的功能。Thompson 的改进文档在初始?Unix 编程手册中有收录,在?as 编译器条目下面。

cat?的初代实现使用了 PDP 7 汇编语言。我有添加一些注释来解释每行命令,但是除非你明白 Thompson 编写汇编编译器的一些扩展,不然这个程序还是很难理解。这里有两个重要的点。第一,字符?;?可以被用于分隔同一行的声明语句。根据 sys 指令的描述,?;?通常被用于在同一行使用系统调用参数。第二,Thompson 添加了数字 0-9 用于支持“暂存标记”。这些标记可以被整个程序重用,这就像 Unix 编程手册所描述的,“对于程序员思维和汇编语言字符空间的缩减优化”。从手册中,你可以使用?nf?来表示下一个标记?n,用?nb?来表示上一个标记?n。举个例子,如果你有个标记为?1:?的代码块,你可以从相距很远的下方代码中使用?jmp 1b?来往上跳回标记代码。(但是你不能往下跳到标记代码,除非你使用jmp 1f。)

关于初代?cat?最有意思的是,它包含了两个我们熟知的名字,分别是一个标记为是一个标记为?getc,和一个标记为?putc?的代码块,这表示这俩名字要比标准 C 语言库都要历史久远。初代?cat?实际上包含了这两个方法的实现。这样的实现方式使得输入字符可以被写入缓冲区,也就是说,读和写不需要以单个字符为单位完成。

初代?cat?并没有存在很久。Ken Thompson 和 Dennis Ritchie 成功劝说了贝尔实验室帮他们购入了一台 PDP11,以便于他们对 Unix 系统进行扩展与提高。PDP 11 使用的是一种不同的指令集,因此他们不得不重写?cat。对于?第二代?cat?代码我也加了注释。第二代使用了针对于新指令集的新版汇编助记符,也利用了 PDP 11中不同的地址模式。(那些源代码中的括号和 $ 符号,是被用来指代不同的地址模式的。)但是?cat?第二代中也同样使用了初代中的?;?和暂存标记,这些功能一定是在 PDP 11 中移植?as?时被保留了下来。

cat?的第二代源代码远比初代要简洁很多。第二代也更加的”Unix-y”,因为它不再需要一串文件名作为命令参数,而是与如今的?cat一样,在没有参数的情况下,从?stdin?读取输入。对于二代?cat,你也可以使用参数来指定从?stdin 读取输入数据。

1973 年,为了准备发布第四版 Unix,很大一部分 Unix 系统都用 C 语言重写了一遍。但是 C 语言版本的?cat?在 Unix 发布后过了一段时间才出现。第一个 C 语言版本的?cat?只出现在第七版 Unix 系统中。这个实现方法非常值得一读,因为它非常简单明了。与其他版本比较,这一版最能作为代表?cat?的 K&R C 语言教育演示版本。这段程序的核心就是如下两行:

while ((c = getc(fi)) != EOF)
    putchar(c);

当然还有更多的代码,但是除了这两行以外,剩下的逻辑更多的是在确保用户不会同时读写同一个文件。另一个有意思的地方是,这个版本的?cat?只认得一个标记,-u。这个?-u?标记可以被用于关闭输入输出缓冲区,不然?cat?会默认缓存 512 字节。

伯克利软件套件/BSD

在第七版之后,Unix 催生了各种各样的衍生品。MacOS 是基于 Darwin 系统的,而 Darwin 是基于伯克利软件套件(BSD),因此 BSD 是我们最感兴趣的 Unix 分支。BSD 最初是作为Unix附加功能的软件合集,但是它最终成为了一个完整的操作系统。BSD似乎一直在用cat的初代版本,一直到第四版 BSD 发布为止。第四版 BSD 也就是 4BSD,它添加了对于新标记的支持。4BSD 版本的?cat?能明显的看出是初代的衍生品,不过它添加了一些新的函数用来实现用新标记触发的功能。4BSD 文件系统的命名方法是基于?fflg?这个变量的,fflg?用于标记指令的输入是从文件,还是?stdin?读取的。继?fflg?之后,nflg、bflg、vflg、sflg、eflg?和?tflg?也被用于记录程序中的标记是否被用到。这些命令行标记是?cat?添加的最后一批标记;如今至少在 Mac 系统中的?cat?命令行手册有列出来这些标记。4BSD 是在 1980 年发布的,所以这一系列的标记有 38 岁了。

cat?最后一次被重写是为了 BSD Net/2,这主要是为了避免软件许可证问题,因此所有 AT&T Unix 衍生代码都被替换为了新代码。BSD Net/2 在 1991 年发布。最后一次重写是由 Kevin Fall 完成的,Kevin Fall 于 1988 年毕业于伯克利,之后他花了一年的时间在计算机系统研究院(CSRG)工作了一年。Fall 告诉我,用 AT&T 代码写的 Unix 工具集列表被挂在了 CSRG 的一面墙上,员工们被告知可以选择感兴趣的工具重写。Fall 选择了?cat?和?mknod。在如今 Mac 系统的默认?cat?版本中,Fall 的名字排在开发者名单前列。他所编写的?cat,虽然是个很简单的程序,但是直到今年还有数百万的用户在使用。

Fall 所写的?cat?源代码比我们之前看到的版本要长许多。除了支持?-??帮助标记,这一版并没有添加新的功能。理论上来说,这一版代码与 4BSD 版本非常相似。代码之所以长,是因为 Fall 分开了“旧版”和“新版”的逻辑?!熬砂妗笔堑湫偷?cat;它一个字符一个字符的输出?!靶掳妗钡?cat?包括了 4BSD 命令行选项。这样的分割很有道理,但是使得代码在第一眼看上去比实际复杂很多。代码的最后有个华丽的错误处理方程,这也增加了代码长度。

MacOS

2001 年,苹果公司发布了 Mac OS X 系统。这次发布对于苹果公司来说非常重要,因为他们花了很多年,走了不少弯路,为了研发能够取代存在了很多年的旧版 Mac OS 系统。苹果公司内部曾经有过两次研发新系统的尝试,但是最终都没能成功;后来,苹果收购了史蒂夫·乔布斯的公司 NeXT,他们公司开发了一款名为 NeXTSTEP 的,基于面向对象编程框架的操作系统。苹果决定使用 NeXTSTEP 作为Mac OS X 的基础。NeXTSTEP 的一部分是基于 BSD 开发的,所以用 NeXTSTEP 作为 Mac OS X 的基础,同时也给苹果系统带来了 BSD 代码风格。

新发布的第一版 Mac OS X中包含了来自 NetBSD 项目的?cat?代码实现。NetBSD 项目如今仍在不断开发中,它最初是来自 386BSD 的分支。而 386BSD 是直接基于 BSD Net/2 的。所以 Mac OS X 上的?cat?就是 Kevin Fall 所写的?cat。唯一变化的是,Kevin Fall 写的错误处理函数?err()?被替换成了?err.h?中的?err()。err.h?是 BSD 基于 C 语言标准库的扩展。

NetBSD 版本的?cat?在不久之后被 FreeBSD 版本取代了。根据维基百科,苹果从 Mac OS X 10.3 (Panther)开始,使用 FreeBSD 来取代 NetBSD。但是 Mac OS X 版本的?cat,根据苹果的开软发布记录,一直到 2007 年发布 Mac OS X 10.5 (Leopard) 才被取代。苹果为了发布 Leopard 而引进的?FreeBSD 的实现版本一直被沿用到了今天。从 2007 一直到 2018 年,这一版没有做过任何升级或者改变。

所以说 Mac OS 中的?cat?是古老的。实际上?cat?的出现,比 2007 年的正式发布时间还早两年。2005 年的改动,在 FreeBSD 的Github 镜像中可以看到,是?cat?被移植到 Mac OS X 之前 FreeBSD 版的最后一次更新。所以 Mac OS X 中?cat?实际上有 13 年的历史了,它并没有与 FreeBSD 的?cat?进行同步更新。这里有过一个辩论,软件到底被改动过几次才算是一个新的软件呢;就?cat?这个个例来看,它的源代码从 2005 年开始就完全没有改变过了。

如今 Mac OS 系统中的?cat?与 Fall 在 1991 年为 BSD Net/2 所写的版本并没有太多不同。最大的不同是添加了一个新的函数用来支持 Unix 上的套接字。一个 FreeBSD 的开发者认为 Fall 所写的?raw_args()?函数应该与?cook_args()?合并为一个函数?scanfiles()。除此之外,最核心的部分还是 Fall 的代码。

我问过 Fall,有几百万苹果用户在使用你所写的?cat,还有很多程序直接或者间接依赖?cat,对此你有什么感想。如今已经是顾问兼最新版 TCP/IP 协议合作者的 Fall 表示,人们对他开发?cat?的经历如此的感兴趣,让他觉得非常惊讶。Fall 曾经在计算领域工作过很久,并且有过很多有影响力的项目经历。但是似乎人们对于他在 1989 年开发?cat?的那六个月更加感兴趣。

百岁程序

纵观历史上各种伟大的发明,计算机的历史并没有很久。我们仍然在使用有着百年历史的照片和胶卷。但是计算机软件是另外一个类别——目前仍属于高新科技。至少现在的软件是这样。随着计算机产业日渐成熟,我们会不会有一天发现,我们在使用有着百年历史的软件呢?

计算机硬件最终也会更新换代,现在的软件想必是没法跑在一个世纪以后的硬件上。也许高级语言设计的进步,也会导致在将来没有人会使用 C 语言,而?cat?也会被其他的语言重写。(不过 C 语言已经存在了五十年了,估计短期内也不会被取代。)不考虑以上这些的话,不如我们就一直用现在这版?cat?吧。

我认为,cat?的历史告诉我们,在计算机科学领域有一些思想是非常耐用的。实际上,对于?cat,它的代码和思想都是很多年前出现的。要说我计算机中的cat是1969年的其实并不准确。但如果说我计算机中的?cat?是 1989 年 Fall 开发的,就准确多了。很多软件都很古老。也许我们不能单纯的认为计算机科学和软件开发是不断更新换代的领域。我们所开发的系统都是基于历史基础的。在某些时候,我们在开发新代码的同时,也需要去花时间去理解和维护历史代码。

cat 命令的源码进化史,首发于山西十一选五手机版。

]]>
//www.brhi.net/114591/feed/ 0
救命!我的电子邮件发不到 500 英里以外! - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114589/ //www.brhi.net/114589/#respond Sat, 29 Dec 2018 14:09:46 +0000 //www.brhi.net/?p=114589 这是一个听起来几乎不可能的事情……我甚至有点后悔将它发到网上,因为它在一个会议上成了一则著名的酒后故事。

救命!我的电子邮件发不到 500 英里以外!,首发于山西十一选五手机版。

]]>

这是一个听起来几乎不可能的事情……我甚至有点后悔将它发到网上,因为它在一个会议上成了一则著名的酒后故事。这个故事略有改动,以?;す适轮械娜宋?,以及忽略了一些无关的细节使之更有趣一些。

几年前,当我接到统计系主任的电话时,我正在从事维护校园电子邮件系统的工作。

“我们从部门发送电子邮件时遇到了问题?!?/p>

“有什么问题?” 我问。

“我们不能发送超过 500 英里的邮件,”主任解释说。

“咳咳”,我被我喝的拿铁呛了一口,“您再说一遍?”

“我们不能发送距这里超过 500 英里的邮件,”他重复道。 “实际上,更远一点,是 520 英里,但不能更远了?!?/p>

“嗯……电子邮件真的不会这样,通常,”我说,试着让我的声音听起来不那么慌乱。我不能和一个系主任说话时显得慌乱,即使是一个像统计系这样的相对没钱的院系。?“是什么让你觉得你不能发送邮件超过 500 英里?”

“这不是我认为的,”主任有点急躁地回答道。 “我们首先注意到了这种情况是几天前?!?/p>

“你等了几天?” 我打断他,带点颤音说道。 “这段时间你一直你不能发送电子邮件?”

“我们可以发送电子邮件。只是不超过 ——”

“—— 500 英里,我知道,”我接过他的话,“我知道了。但为什么没有你早点打电话呢?”

“好吧,我们没有收集到足够的数据来确定发生了什么,直到现在?!泵淮?,这是统计系的主任?!安还茉趺此?,我请了一位地理统计学家研究它 ——”

“地理统计学家……”

“—— 是的,她制作了一张地图,显示了我们发送电子邮件能够达到的半径略超过 500 英里。在那个半径范围内有零星的几个无法到达的目的地,但我们永远不能发送比这半径更远的电子邮件?!?/p>

“我明白了,”我说,把头埋在我的手中。 “这是什么时候开始的?几天前,你说过,但是那时你的系统做了什么改变?”

“嗯,服务顾问来给我们的服务器打了补丁,并重新启动了它。但我打电话给他,他说他没有碰过邮件系统?!?/p>

“好的,让我来看看,我稍后会给你回电话,”我说。我简直觉得我在做梦,这不是愚人节。我试着回想是不是有人恶作剧报复我。

我登录了他们系的服务器,并发送了一些测试邮件。在北卡罗来纳州的三角研究园( Research Triangle Park),我自己的帐户的测试邮件顺利投递。发往里士满、亚特兰大和华盛顿的也是如此。发往普林斯顿(400 英里)的另一个邮件也正常。

但后来我尝试向孟菲斯(600 英里)发送电子邮件,失败了。波士顿,失败了。底特律,也失败了。我拿出了我的地址簿,开始试图缩小它的范围。纽约(420 英里)工作,但普罗维登斯(580 英里)失败了。

我开始怀疑自己是不是疯了。我试过给住在北卡罗来纳州的朋友发电子邮件,但他的 ISP 在西雅图。谢天谢地,它失败了。如果问题与收件人的地理位置有关,而不是他的邮件服务器,我想我要哭了。

已经确定!虽然令人难以置信,但所报告的问题是真实的、可重复的,我看了一下 sendmail.cf 文件。它看起来很正常。事实上,它看起来很熟悉。

我把它与我主目录中的 sendmail.cf 做了个对比。它没有被改过 —— 这是我写的 sendmail.cf。 而且我相当确定我没有启用某种 “FAIL_MAIL_OVER_500_MILES” 选项。我不知所措,我 telnet 到 SMTP 端口。 服务器愉快地回复了 SunOS sendmail 的横幅消息。

等一下……一个 SunOS sendmail 的横幅消息?当时,即使 Sendmail 8 已经相当成熟,Sun 公司在其操作系统中装的仍然是 Sendmail 5。作为一名优秀的系统管理员,我已经对 Sendmail 8 进行了标准化。并且作为一名优秀的系统管理员,我编写了一个 sendmail.cf,它使用了 Sendmail 8 中提供的很长的、具有自我描述意义的选项和变量,而不是 Sendmail 5 中使用的那种神秘的标点符号式配置选项。

这个细节一下子又回到了起点,我再次被我现在已经冷掉了的拿铁咖啡渣呛了。 当服务顾问“对服务器打补丁”时,他显然升级了 SunOS 的版本,并且这样做降级了 Sendmail。这次升级会将 sendmail.cf 单独留下,即使它现在是错误的版本。

事实上,Sendmail 5 —— 至少是 Sun 所带的版本,是有一些调整的 —— 它可以处理 Sendmail 8 的 sendmail.cf,因为大多数规则在那时保持不变。但新的长配置选项 —— 它被视为垃圾,并跳过。 并且 sendmail 二进制文件编译时没有针对其中大多数设置默认值,因此,在 sendmail.cf 文件中找不到合适的配置,它们被设置为?0。

被设置为 0 的配置之一是连接到远程 SMTP 服务器的超时选项。 一些实验证明,在具有典型负载的特定机器上,0 超时将在稍微超过 3 毫秒的时间内中止连接调用。

当时我们校园网络的一个奇怪的特点是它是 100% 交换的。传出的数据包不会出现路由器延迟,直到命中 POP 服务器并到达远端的路由器。因此,连接到附近网络上的轻负载的远程主机的时间实际上主要取决于到目的地的光速的速度,而不是偶然的路由器延迟。

这让我有点晕,我在我的 shell 中输入:

$ units
1311 units, 63 prefixes

You have: 3 millilightseconds
You want: miles
* 558.84719
/ 0.0017893979

“500 英里,或者稍微多一点点?!?/p>

救命!我的电子邮件发不到 500 英里以外!,首发于山西十一选五手机版。

]]>
//www.brhi.net/114589/feed/ 0
计算机科学自学指南 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114573/ //www.brhi.net/114573/#respond Sat, 22 Dec 2018 14:08:16 +0000 //www.brhi.net/?p=114573 如果你是一名自学工程师或者是一名软件集训课程毕业的学生,有些计算机科学基础课程是你必须要补齐的,本文介绍了几个领域最佳的教材和在线视频

计算机科学自学指南,首发于山西十一选五手机版。

]]>
如果你是一名自学工程师或者是一名软件集训课程毕业的学生,有些计算机科学基础课程是你必须要补齐的。幸好,你通过互联网就能获得世界顶级的CS(计算机科学)课程。

其实网上有很多学习资源但它们良莠不齐,你需要不是什么“200+免费在线课程”列表而是如下问题的答案:

你应该学习哪门课程?为什么?

每门课程最好的书籍或者视频,讲座是什么?

我写这篇文章的目的就是尝试对于这些问题给出的明确答案:

使用建议的书籍或者视频讲座来学习以下的九门科目,最好是书籍和讲座都仔细的研究一下,可以不严格按照列出的顺序来。每一门科目都需要花上100-200小时来研读,然后在你的职业生涯中对于最热爱的方向进行反复重温。

主题 为什么学习它 推荐书籍 推荐视频
编程 别做那些连“递归”是什么都搞不懂的程序员 Programs Brian Harvey’s Berkeley CS 61A
计算机体系结构 如果你基础薄弱,不知道计算机是如何运行的,那些你学会的所谓“高层”技能不过是空中楼阁 计算机组成与设计硬件/软件接口 Berkeley CS 61C
算法和数据结构 如果你不能很好的使用随处可见的数据结构(例如栈、队列、树和图),你是无法解决复杂问题的 Steven Skiena’s lectures
计算机数学 计算机科学实际上是应用数学的一个分支,学好数学让你更具竞争力 《Mathematics for Computer Science》 Tom Leighton’s MIT 6.042J
操作系统 你编写的大部分代码是通过操作系统运行的,所以你需要知道它们是如何交互的 Operating Systems: Three Easy Pieces Berkeley CS 162
计算机网络 互联网是个了不起的发明,只有理解它的原理,才能发挥它的威力
计算机网络(第4版)
Stanford CS 144
数据库 对于很多程序来说,数据是其核心,但是很少有人真正理解数据库系统是如何运行的 Readings in Database Systems Joe Hellerstein’s Berkeley CS 186
编程语言和编译器 如果你理解语言和编译器是如何运行的,你就能编写更好的代码并轻松学会新的语言 编译原理 技术与工具 Alex Aiken’s course on Lagunita
分布式系统 近年来,大部分系统已经发展成为分布式系统 Distributed Systems ?

为什么要学习计算机科学

有两种软件工程师:一种人对于电脑科学有很好的理解从而去从事挑战性的、富有创造力的工作。另外一种人仅仅熟悉一些高级工具,对其原理持得过且过的态度。

两者都叫做软件工程师,而且两者在早期的职业生涯中可能领着同样的薪水。但是第一种工程师,不管他从事的是商业工作,还是突破性的开源工程,都会由于他的技术领导力或者杰出的个人贡献一点一点成长成一名对于编程更加痴迷而且待遇更高的工程师。

第一种工程师可以通过常规手段或者在职业生涯中不断学习来加深对于计算机科学的理解深度。第二种工程师通常停留在表面,学习具体的工具或者技巧而不是其中的基础,当前流行什么技术,他们就仅仅捡起新的技能学习一下。

近些年来,越来越多的人进入软件领域工作,但是本质上计算机科学的毕业生数量是没有改变的。第二种工程师的供应过量开始导致他们的就业机会变少而且导致他们离企业中令人感觉充实的工作更远。不管你是努力要成为第一种工程师或者仅仅是保险起见地想找到更多的工作,学习计算机科学是唯一一种可靠的途径。

课程指南

编程

大多数大学的计算机编程课程通常以“入门类”计算机的课程开始。这些课程最好是不仅仅针对于初学者,而且对于第一次学习编程,基本概念和编程模型不是很熟悉的人也有所启发的。

对于这种介绍的内容的我们给出的标准建议是经典的计算机程序的结构与解释,在网络上能找到很多这样的资料,它们可能是电子书或者是MIT的一系列讲座视频。这些讲座都很不错,但是我们的视频推荐的实际上是伯克利的一门课程:Brian Harvey 的 SICP?讲座?,这个系列的课程比起MIT的讲座更精炼而且对于入门者更具有针对性。

我们推荐观看完至少前三章节的SICP(《计算机程序的构造和解释?》)并且做完相应训练。额外地,可以在 exercism 进行一些编程训练。

image

如果你觉得SICP太难,我们推荐《程序设计方法(中文版)|?How to Design Programs》这本书。如果你觉得它太简单,我们推荐《Concepts, Techniques, and Models of Computer Programming 这本书。

计算机体系结构

硬件是平台 – Mike Acton(Insomniac Games的工程总监) (收看他在 CPP 大会上的演讲)

计算机结构–有的时候被称为“计算机系统”或者“计算机组织”–是了解程序外表下计算机运行的第一步。根据我们的经验,这是自学软件工程师最容易忽略的地方。

《计算机系统要素》The Elements of Computing Systems,也被称为“从与非门到俄罗斯方块”。这是一本让你对于计算机中的每一个零件是怎么工作的有一个整体的理解的雄心勃勃的书。每个章节涉及到建立整体系统中一个小的部分,从写基本的逻辑门到HDL,到CPU和汇编语言,一直到完成一个俄罗斯方块应用程序。

elements-computing-systems

我们推荐阅读书的前六章节并且完成相关的工程。这会提高你对于计算机结构和运行的软件之间关系的理解。

这本书的前半部分(和它的全部工程)在 Nand2Tetris 网站上可以免费获得。在?Coursera 课程网站上你也可以找到它们。

为了保证课程简单并吸引人,Nand2Tetris 舍弃了深度。特别是现代计算机结构中两个很重要的概念:流水线(pipelining)和内存层级(memory hierarchy),在书中都没有提及。

当你觉得看Nand2Tetris已经很简单了,我们下一个建议是Patterson和Hennessy合著的《计算机组成与设计硬件/软件接口》Computer Organization and Design——一本杰出的现代经典书籍。不是书中所有的部分都很重要;我们建议跟随Berkeley的CS61C 课程——(Great Ideas in Computer Architecture),作为特殊读物。讲座的笔记和实验环境都是在线的,而且可以在在这个归档链接回看讲座。

算法和数据结构

只有一个方法是我一直以来广泛推荐的—编码前首先要思考 — Richard Hamming

我们根据几十年的通识来看,熟悉通用的算法和数据结构是计算机科学教育中最重要的方面之一。这是一个训练一个人解决问题的通用能力的方式,而且这种能力还可以迁移到其他领域的学习。

这个领域有很多优秀的书籍,但是我们最喜欢的是Steven Skiena的《算法设计手册》The Algorithm Design Manual 。他显然喜欢这东西而且也迫不及待地想帮助你学习数据结构和算法。这是令人耳目一新的变化,我们认为这本书相对于被更多人所推荐的Cormen, Leiserson, Rivest & Stein 或者 Sedgewick 的书来说更好。后两本书有些太过于引经据典,对于想通过阅读来解决问题的人来说并不是一个好的选择。

skiena

对于那些更喜欢讲座视频的人来说,我们推荐Skiena的讲座. 我们也喜欢Tim Roughgarden的课程,在斯坦福的MOOC平台或者Coursera上面可以获得。你喜欢 Skiena 还是 Roughgarden 的讲课风格就是你的个人喜好问题了。

说到练习,我们倾向于让学生在Leetcode上面解决问题。LeetCode上面的问题都比较有趣而且有答案和讨论。这上面还可以通过解决各大软件公司广泛应用的技术问题来帮助你测试你的进步。我们建议解决你学习的时候解决大约随机100道LeetCode上面的问题。

最后,我们强烈推荐《怎样解题》这本书,它针对如何解题进行了精彩绝伦和独特的讲解,既适用于数学也适用于电脑科学。

polya

计算机科学领域的数学

如果人们不认为数学是简单的,那么他们一定没有体会过人生的艰难 — John von Neumann

在某些方面,计算机科学是应用数学的一个扩展。虽然许多软件工程师忽略了这一点,我们建议你去学习它。好好学习数学会给你比那些不学习它们的人巨大的竞争优势。

和CS最相关的数学领域是“离散数学”,离散是连续对立面。是微积分之外的一系列的有趣的应用数学的主题。从大体上说,尝试学会全部范围的“离散数学”是没有意义的。更现实一点的做法是对于逻辑学,组合学和概率学,集合论,图论和一些数论告知密码学有一个了解。对于计算机图像学和机器学习来说,线性代数也是一门值得学习的课程。

我们建议从László Lovász的讲座学起. 这一系列开始学习离散数学。Lovász 教授让学习的内容变得直观生动,比起拘谨的文字,这更利于你学习。

接下来,我们推荐《Mathematics for Computer Science》, 它是MIT同名课程的讲义。讲座课程的视频也是免费的,而且是我们推荐的离散数学的视频课程。

线性代数,我们建议从 Essence of linear algebra 系列开始学习,接着是Gilbert Strang的书籍视频。

操作系统

《操作系统概念》Operating System Concepts)(恐龙书)和《现代操作系统》Modern Operating Systems?)是经典的操作系统的书籍。这两本书的写作方式都饱受争议,而且为了鼓励你去购买新版,这些长达1000页的书每几年就会添加一些内容。

Operating Systems: Three Easy Pieces》这本书是一本比较好的可供选择的线上免费读物。我们特别喜欢书的结构和它经典的练习题。

ostep

读完这本书,我们推荐你去探索一种特定的操作系统的设计方式,比如那些书名中有系统名字的书籍,比如 《Lion‘s commentary on Unix》、《The Design and Implementation of the FreeBSD Operating System》,还有 Mac OS X Internals.

巩固你对于操作系统的理解很好的方式是去读一个小的内核并且添加功能。xv6 是一个不错的选择,它是 Unix V6 和 ANSI C 和 X86 的接口,MIT专门有一门课程就是讲这个的。OSTEP(之前提到的)这本书有一个 XV6 的实验附录,里面都是充满潜力项目的好点子。

计算机网络

你不能够通过凝视水晶球来预见未来。因特网未来会变成什么样,取决于如今人类如何去塑造它 — Bob Kahn

考虑到很多软件项目都是基于web服务器和客户端的,计算机网络变成计算机科学中一门有实用价值的学科。系统学习过该课程的自学学生发现他们终于理解了围绕了伴随它们很多年的术语,概念,协议等等。

关于这个主题我们最推荐的书是:《计算机网络》Computer Networking: A Top-Down Approach)。书中的小工程和实验都很好,值得一做。我们非常喜欢它们提供的?Wireshark labs。

对于那些喜欢视频课程的人,我们推荐斯坦福MOOC平台上的《Introduction to Computer Networking course》。

学习网络的好处不仅仅在于做小的实验而且对于工程来说也有很大的好处??赡苌婕暗降挠校阂桓鯤TTP的服务器,一个UDP协议的聊天软件,一个迷你的 TCP 协议栈,一个代理或者负载平衡器,还有分布式的哈希表等等。

数据库

对于自学者来说,学习数据库系统会比学习其他花费更多的时间。这是一个相对较新的(即1970年代后期)的研究领域。比起写书,许多潜在的杰出教科书作者更愿意去加入或者创办一家公司。

在这种情况下,我们建议自学者放弃教科书而去学习伯克利的Joe Hellerstein的数据库课程,看完课程再去阅读论文。

对于初学者有一篇论文比较推荐的是:《Architecture of a Database System》,它高屋建瓴地讲解了关系数据库管理系统是如果工作的这一问题。它会为你未来的学习提供一个有用的纲要。

Readings in Database Systems这本书,又被称为数据库红皮书、是一本Peter Bailis、Joe Hellerstein和Michael Stonebraker编辑地论文集。对于那些理解了CS 186内容的人来说,红皮书是你的不二之选。

如果你坚持要使用一本引导性的教科书,我们推荐Ramakrishnan 和Gehrke的《数据库管理系统》Database Management Systems,对于更优秀的学生,Jim Gray的传统课程《Transaction Processing: Concepts and Techniques值得一看,但是我们不建议把它当成入门书。

不编大量的代码是不能很好的巩固数据库的理论的,CS 186的学生往Spark中添加功能,这是一个很有意义的工程。但是我们建议仅仅是从头写一个简单的关系数据库管理系统。功能可能不是很丰富,但是即使每一个部分都涉及到一些基本功能也很有启发性。

最后,数据模型是一个数据库使用中被忽略和没有被重点学习的方面。我们对于这个课题建议的书籍是:《Data and Reality: A Timeless Perspective on Perceiving and Managing Information in Our Imprecise World

语言和编译器

Don’t be a boilerplate programmer. Instead, build tools for users and other programmers. Take historical note of textile and steel industries: do you want to build machines and tools, or do you want to operate those machines? — Ras Bodik at the start of his compilers course

大部分程序员学习如何使用一门编程语言,然而大部分的计算机科学家则学习这门语言本身。这给了计算机科学家比起程序员很明显的优势。他们的知识能够更好的泛化,他们能比简简单单地掌握一门语言的更加深入和快速的理解一门新语言的操作。

经典的教科书《编译原理 技术与工具》(?Compilers: Principles, Techniques & Tools)通常又被称为“龙书”。不幸的是,这本书并不适合自学者,它比较适合教师从中选出1-2个章节并在课堂上讲授。这本书是有必要看的,你可以挑选里面的主题,最好再有个师傅指导你。

如果你选择在自学中使用龙书,我们推荐你一系列门视频讲座,然后再沉浸在对于龙书的研究中。我们推荐的在线课程是:Alex Aiken 的讲座,你可以在斯坦福大学的幕课平台上观看。

也有可以替代龙书的教材:Terence Parr写的《编程语言实现模式》Language Implementation Patterns,它更适合那些工作中使用类似特定领域语言的小众语言的有经验的编程者,它显得更加实用。当然,为了达到这个目的它也删去了一些有价值的理论。

对于工程实践,我们推荐你写一个编译器,你可以选择像COOL这种简单的教学语言或者你感兴趣的一门语言。如果你觉得太难,你可以参考Make a Lisp,你可以参考它作为开始。

分布式系统

计算机的数量增长了,它们的分布也更广了。企业之前会购买越来越大型的主机,但是现在大家更倾向于在很多机器上分布式的运行多个小型的应用程序。分布式系统研究的就是这样的技术,这一技术变得越来越重要了。

我们建议的自学教科书是 Maarten van Steen 和 Andrew Tanenbaum 的《Distributed Systems, 3rd Edition》。 针对于之前的版本做了很大的改进,而且作者慷慨地把书放在了网上共享。由于分布式计算是一门变化很快的领域,所以没有教科书可以很好的涵盖所有的内容。但是Maarten van Steen的书是我们读过的所有书中最好的书。

研究生在线课程?MIT’s 6.824 也是一个不错的选择,但可惜视频中的音质不太好,而且不清楚这些视频是不是都被授权过。

尽管有参考书或者其它的资源,但学习分布式系统是绝对要读论文的。链接中有一个很好的清单,而且我们十分推荐你从Papers We Love 上面下载论文到本地学习。

 

译注:本文提到的大部分书籍,中英文版已归档至该豆列

计算机科学自学指南,首发于山西十一选五手机版。

]]>
//www.brhi.net/114573/feed/ 0
在 Linux 命令行上拥有一头奶牛 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114570/ //www.brhi.net/114570/#respond Fri, 21 Dec 2018 14:55:20 +0000 //www.brhi.net/?p=114570 使用 cowsay 实用程序将牛的话语带到你的终端输出。

在 Linux 命令行上拥有一头奶牛,首发于山西十一选五手机版。

]]>

使用 cowsay 实用程序将牛的话语带到你的终端输出。

欢迎来到 Linux 命令行玩具第四天。如果这是你第一次访问这个系列,你可能会问自己,什么是命令行玩具。我们也在考虑这一点,但是一般来说,这可能是一个游戏,或者任何简单的娱乐,可以帮助你在终端玩得开心。

你们中的一些人会见过我们之前的选中的各种玩具,但是我们希望至少有一个对每个人来说都是新的。因为几乎所有我告诉他这个系列的人都已经问过它了,所以今天的选中的玩具是必须提及的。

你也不会认为我们会在不提及 cowsay 的情况下完成这个系列,对吧?

cowsay 是一个神奇的实用程序,它将文本作为 ASCII 艺术牛的讲话文本输出。

你可能会发现 cowsay?打包在你的默认存储库中,甚至可能已经安装了。对我来说,在 Fedora,像这样安装:

$ sudo dnf install -y cowsay

然后,用 cowsay 调用它,然后是你的消息。也许你想到昨天我们谈到的 fortune 应用 连接起来。

$ fortune | cowsay
 _________________________________________
/ If at first you do succeed, try to hide \
\ your astonishment.                      /
 -----------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

就这样!cowsay 还有点小变体,称为 cow 文件,通??梢栽?/usr/share/cowsay 找到 ,要查看系统上可用的 cow 文件,请在 cowsay 之后使用 -l 。然后,用 -f 试试其中之一。

$ cowsay -f dragon "Run for cover, I feel a sneeze coming on."
 _______________________________________
/ Run for cover, I feel a sneeze coming \
\ on.                                   /
 ---------------------------------------
      \                    / \  //\
       \    |\___/|      /   \//  \\
            /0  0  \__  /    //  | \ \    
           /     /  \/_/    //   |  \  \  
           @_^_@'/   \/_   //    |   \   \ 
           //_^_/     \/_ //     |    \    \
        ( //) |        \///      |     \     \
      ( / /) _|_ /   )  //       |      \     _\
    ( // /) '/,_ _ _/  ( ; -.    |    _ _\.-~        .-~~~^-.
  (( / / )) ,-{        _      `-.|.-~-.           .~         `.
 (( // / ))  '/\      /                 ~-. _ .-~      .-~^-.  \
 (( /// ))      `.   {            }                   /      \  \
  (( / ))     .----~-.\        \-'                 .~         \  `. \^-.
             ///.----..>        \             _ -~             `.  ^-`  ^-_
               ///-._ _ _ _ _ _ _}^ - - - - ~                     ~-- ,.-~
                                                                  /.-~

我对 cowsay 的真正不满是,我今天没有足够的时间来为牛的挤奶 —— 一语双关。牛排价格太高了,我只是开个玩笑。

更严重的是,我已经完全忘记了 cowsay 直到我在学习 Ansible 的剧本时再次遇到它。如果你碰巧安装了 cowsay,当你运行Ansible 的剧本时,你会从一队奶牛那里获得输出。例如,运行这个剧本:

- hosts:
? ? - localhost
? tasks:
? ? - action: ping

可能会给你以下信息:

$ ansible-playbook playbook.yml
 __________________
< PLAY [localhost] >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

 ________________________
< TASK [Gathering Facts] >
 ------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

ok: [localhost]
 _____________
< TASK [ping] >
 -------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

ok: [localhost]
 ____________
< PLAY RECAP >
 ------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

localhost                  : ok=2    changed=0    unreachable=0    failed=0

cowsay 在 GPLv3 许可证下可用,您可以在 GitHub 上找到 它的 Perl 源代码。我也见过其他语言的版本,所以可以看看其他变体;例如,这是 R 语言版。用你选择的语言实现你自己的版本可能是一项有趣的编程学习任务。

既然讲完了 cowsay,我们可以去更绿色的牧场了。

你有希望我来介绍的喜欢的命令行玩具吗?这个系列的排期大部分都填好了,但我还有一些空位方。在下面的评论中让我知道,我会来看看。如果有空间,我会尝试把它包括进去。如果没有,但是我收到了一些好的意见,我在结尾提及。

看看昨天的玩具,如何给你的 Linux 终端带来好运,明天再来看看另一个!

 

在 Linux 命令行上拥有一头奶牛,首发于山西十一选五手机版。

]]>
//www.brhi.net/114570/feed/ 0
Linux 搜索文件和文件夹的 4 种简单方法 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114561/ //www.brhi.net/114561/#respond Wed, 19 Dec 2018 12:49:07 +0000 //www.brhi.net/?p=114561 Linux 管理员一天都不能离开搜索文件,因为这是他们的日?;疃?。

Linux 搜索文件和文件夹的 4 种简单方法,首发于山西十一选五手机版。

]]>

Linux 管理员一天都不能离开搜索文件,因为这是他们的日?;疃?。了解一些搜索的东西是不错的,因为这能帮助你在命令行服务器中工作。这些命令记忆起来不复杂,因为它们使用的是标准语法。

可以通过四个 Linux 命令啦执行此操作,每个命令都有自己独特的功能。

方法 1:使用 find 命令在 Linux 中搜索文件和文件夹

find 命令被广泛使用,并且是在 Linux 中搜索文件和文件夹的著名命令。它搜索当前目录中的给定文件,并根据搜索条件递归遍历其子目录。

它允许用户根据大小、名称、所有者、组、类型、权限、日期和其他条件执行所有类型的文件搜索。

运行以下命令以在系统中查找给定文件。

# find / -iname "sshd_config"
/etc/ssh/sshd_config

运行以下命令以查找系统中的给定文件夹。要在 Linux 中搜索文件夹,我们需要使用 -type 参数。

# find / -type d -iname "ssh"
/usr/lib/ssh
/usr/lib/go/src/cmd/vendor/golang.org/x/crypto/ssh
/usr/lib/go/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ssh
/etc/ssh

使用通配符搜索系统上的所有文件。我们将搜索系统中所有以 .config 为扩展名的文件。

# find / -name "*.config"
/usr/lib/mono/gac/avahi-sharp/1.0.0.0__4d116c78973743f5/avahi-sharp.dll.config
/usr/lib/mono/gac/avahi-ui-sharp/0.0.0.0__4d116c78973743f5/avahi-ui-sharp.dll.config
/usr/lib/python2.7/config/Setup.config
/usr/share/git/mw-to-git/t/test.config
/var/lib/lightdm/.config
/home/daygeek/.config
/root/.config
/etc/skel/.config

使用以下命令格式在系统中查找空文件和文件夹。

# find / -empty

使用以下命令组合查找 Linux 上包含特定文本的所有文件。

# find / -type f -exec grep "Port 22" '{}' \; -print
# find / -type f -print | xargs grep "Port 22"
# find / -type f | xargs grep 'Port 22'
# find / -type f -exec grep -H 'Port 22' {} \;

方法 2:使用 locate 命令在 Linux 中搜索文件和文件夹

locate 命令比 find 命令运行得更快,因为它使用 updatedb 数据库,而 find 命令在真实系统中搜索。

它使用数据库而不是搜索单个目录路径来获取给定文件。

locate 命令未在大多数发行版中预安装,因此,请使用你的包管理器进行安装。

数据库通过 cron 任务定期更新,但我们可以通过运行以下命令手动更新它。

$ sudo updatedb

只需运行以下命令即可列出给定的文件或文件夹。在 locate 命令中不需要指定特定选项来打印文件或文件夹。

在系统中搜索 ssh 文件夹。

# locate --basename '\ssh'
/etc/ssh
/usr/bin/ssh
/usr/lib/ssh
/usr/lib/go/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ssh
/usr/lib/go/src/cmd/go/testdata/failssh/ssh
/usr/lib/go/src/cmd/vendor/golang.org/x/crypto/ssh

在系统中搜索 ssh_config 文件。

# locate --basename '\sshd_config'
/etc/ssh/sshd_config

方法 3:在 Linux 中搜索文件使用 which 命令

which 返回在终端输入命令时执行的可执行文件的完整路径。

当你想要为可执行文件创建桌面快捷方式或符号链接时,它非常有用。

which 命令搜索当前用户而不是所有用户的 $PATH 环境变量中列出的目录。我的意思是,当你登录自己的帐户时,你无法搜索 root 用户文件或目录。

运行以下命令以打印 vim 可执行文件的完整路径。

# which vi
/usr/bin/vi

或者,它允许用户一次执行多个文件搜索。

# which -a vi sudo
/usr/bin/vi
/bin/vi
/usr/bin/sudo
/bin/sudo

方法 4:使用 whereis 命令在 Linux 中搜索文件

whereis 命令用于搜索给定命令的二进制、源码和手册页文件。

# whereis vi
vi: /usr/bin/vi /usr/share/man/man1/vi.1p.gz /usr/share/man/man1/vi.1.gz

 

Linux 搜索文件和文件夹的 4 种简单方法,首发于山西十一选五手机版。

]]>
//www.brhi.net/114561/feed/ 0
学会这两件事,让你成为 Git 老司机 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114551/ //www.brhi.net/114551/#comments Tue, 18 Dec 2018 15:34:25 +0000 //www.brhi.net/?p=114551 “我在提交中犯了个错误,我如何修正它?”,“我的提交历史一团糟,我该如何让它更整洁?”如果你曾经有上述问题,那么这篇文章很适合你。这篇文章介绍了一个让你成为 Git 老司机的清单。

学会这两件事,让你成为 Git 老司机,首发于山西十一选五手机版。

]]>

  • 我在提交中犯了个错误,我如何修正它?
  • 我的提交历史一团糟,我该如何让它更整洁?

如果你曾经有上述问题,那么这篇文章很适合你。这篇文章介绍了一个让你成为 Git 老司机的清单。

我在提交中犯了个错误,我该怎么办?

情景 1

假设你已经提交了一堆文件,并发现输入的提交信息实际上并不清晰。现在你要更改提交消息。为此,你可以使用 git commit --amend

git commit --amend -m “New commit message”

场景 2

假设你要提交六个文件,但你最终错误地只提交了五个文件。你可能认为可以创建新提交并将第六个文件添加到该提交。

这种方法没错。但是,为了保持整洁的提交历史,如果你可以以某种方式将此文件加入到你之前的提交本身,那岂不是更好?这也可以通过 git commit --amend 完成:

git add file6
git commit --amend --no-edit

--no-edit 表示提交信息不会更改。

场景 3

无论你何时在 Git 进行提交,提交都会附上作者名称和作者电子邮箱。通常,当你第一次配置 Git 时,就需要设置作者和电子邮箱。你无需担心每次提交的作者详细信息。

也就是说,对于特定项目,你可能希望使用不同的电子邮箱 ID。你需要使用以下命令为该项目配置电子邮箱 ID:

git config user.email “your email id”

假设你忘记配置电子邮箱,并且已经完成了第一次提交。amend 命令也可以用于更改先前提交的作者消息??梢允褂靡韵旅罡奶峤坏淖髡咝畔ⅲ?/p>

git commit --amend --author "Author Name <Author Email>"

注意事项

应该仅在本地仓库使用 amend 命令。在远端仓库使用 amend 命令会制造大量混乱。

我的提交历史一团糟,我该如何处理?

假设你正在处理一段代码。你知道代码大约需要十天完成。在这十天内,其他开发人员也将提交代码到远程仓库。

将本地仓库代码与远程仓库代码保持同步是个很好的做法。这在你拉取请求时会避免许多合并冲突的操作。因此,你应该每两天从远程仓库中拉取一个变更。

每次将代码从远程仓库拉取到本地仓库时,都会在本地操作中创建新的合并提交。这意味着你的本地历史提交记录会有大量的合并提交,这会让审阅人员头大。

上面是历史提交记录在本地仓库中的显示方式。

如何让历史提交记录看起来更整洁?

这就需要用到 rebase 了。

什么是变基(rebase)?

举个🌰。

此图显示了发布(release)分支和功能(feature)分支中的提交。

  1. 发布分支有三个提交:Rcommit1、Rcommit2 和 Rcommit3。
  2. 你在发布分支中仅有一个提交(即 Rcommit1)时,创建了功能分支。
  3. 你已向功能分支添加了两个提交。它们是 Fcommit1 和 Fcommit2。
  4. 你希望从发布分支提交到功能分支中。
  5. 你可以使用变基来完成该操作。
  6. 让发布分支命名为 release,让功能分支命名为 feature。
  7. 可以使用以下命令进行变基:

git checkout feature
git rebase release

变基

当执行变基时,你的目标是确保功能分支从发布分支获取最新代码。

变基命令尝试逐个添加每个提交,并检查冲突。这听起来是不是有点头大?

让我画个图帮助理解。

这显示了变基内部实际做的事情:

第 1 步

  1. 运行该命令的那一刻,功能分支指向发布分支的头部。
  2. 现在,功能分支有三个提交,Rcommit1、Rcommit2 和 Rcommit3。
  3. 你可能想知道 Rcommit1 和 Rcommit2 发生了什么?
  4. 提交仍然存在,将在下面步骤中使用。

第 2 步

  1. 现在 Git 尝试将 Fcommit1 添加到功能分支上。
  2. 如果没有冲突,则在 Rcommit3 之后添加 Fcommit1;
  3. 如果存在冲突,Git 会通知你,你必须手动解决冲突。解决冲突后,使用以下命令继续变基:

git add fixedfile
git rebase --continue

第 3 步

  1. 一旦添加了 Fcommit1,Git 将尝试添加 Fcommit2。
  2. 同样,如果没有冲突,则在 Fcommit1 之后添加 Fcommit2,并且变基成功。
  3. 如果存在冲突,Git 会通知你,你必须手动解决。解决冲突后,使用第 2 步提到的相同命令。
  4. 整个变基完成后,你会发现功能分支有 Rcommit1、Rcommit2、Rcommit3、Fcommit1 和 Fcommit2。

注意事项

  1. 变基和合并(merge)在 Git 中都很有用。两种并无优劣之分。
  2. 在合并的情况下,你将有个合并提交。在变基的情况下,不会像合并提交那样有额外的提交。
  3. 一种最佳的实践是一分为二。使用远端仓库中的最新代码更新本地仓库时,请使用变基。在处理拉取请求,以将功能分支和发布分支或主分支合并时,请使用合并。
  4. 使用变基会更改历史提交记录(使其更整洁)。但话虽如此,改变历史提交存在风险。因此,请确保永远不要对远程存储仓库的代码使用变基。始终仅对本地仓库代码使用变基,来更改历史提交记录。
  5. 如果对远端仓库进行变基,会制造许多混乱,因为其他开发人员无法识别新的历史记录。
  6. 此外,如果在远端仓库上完成变基,则当其他开发人员尝试从远端仓库中拉取最新代码时,就可能会出问题。所以,我再重申一遍,变基总是仅在本地仓库中进行。😃

恭喜

你现在是个 Git 老司机了。😃

在这篇文章中,你了解到:

  • 修改提交记录
  • 变基

这两个都是非常实用的概念。探索 Git 的世界,继续学习吧。

学会这两件事,让你成为 Git 老司机,首发于山西十一选五手机版。

]]>
//www.brhi.net/114551/feed/ 2
神奇的 Linux 命令行字符形状工具 boxes - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114549/ //www.brhi.net/114549/#respond Sun, 16 Dec 2018 13:08:05 +0000 //www.brhi.net/?p=114549 本文将教你如何在 Linux 命令行终端中使用 boxes 工具绘制字符形状图形来包装你的文字让其更突出。

神奇的 Linux 命令行字符形状工具 boxes,首发于山西十一选五手机版。

]]>

本文将教你如何在 Linux 命令行终端中使用 boxes 工具绘制字符形状图形来包装你的文字让其更突出。

现在正值假期,每个 Linux 终端用户都该得到一点礼物。无论你是庆祝圣诞节还是庆祝其他节日,或者什么节日也没有,都没有关系。我将在接下来的几周内介绍 24 个 Linux 命令行小玩具,供你把玩或者与朋友分享。让我们享受乐趣,让这个月过得快乐一点,因为对于北半球来说,这个月有点冷并且沉闷。

对于我要讲述的内容,可能你之前就有些了解。但是,我还是希望我们都有机会学到一些新的东西(我做了一点研究,确??梢苑窒?24 个小玩具)。

24 个 Linux 终端小玩具中的第一个是叫做 boxes 的小程序。为何从 boxes 说起呢?因为在没有它的情况下很难将所有其他命令礼物包装起来!

在我的 Fedora 机器上,默认没有安装 boxes 程序,但它在我的普通仓库中可以获取到,所以用如下命令就可安装:

$ sudo dnf install boxes -y

如果你在使用其他 Linux 发行版,一般也都可以在默认仓库中找到 boxes。

boxes 是我真正希望在高中和大学计算机课程中就使用的实用程序,因为善意的老师要求我在每个源文件、函数、代码块等开头添加一些特定外观的备注信息。

/***************/
/* Hello World */
/***************/

事实证明,一旦你需要在框内添加几行文字,并且格式化的将它们统一风格就会变得很乏味。而 boxes 是一个简单实用程序,它使用 ASCII 艺术风格的字符形状框来包围文本。其字符形状默认风格是源代码注释风格,但也提供了一些其他选项。

它真的很容易使用。使用管道,便可以将一个简短问候语塞进字符形状盒子里。

$ cat greeting.txt | boxes -d diamonds -a c

上面的命令输出结果如下:

? ? ? ?/ ? ? ? ? ?/ ? ? ? ? ?/
? ? ///\/ ? ?///\/ ? ?///\/
?///\///\///\///\///\///\/
//\///\///\///\///\///\///\
\/// ? ? ? ? ? ? ? ? ? ? ? ? ? ?/\//
?/ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/
?/ ? ? ?I'm wishing you all a ? ? ? /
//\ ? ? joyous holiday season ? ? ?//\
\// ? ? and a Happy Gnu Year! ? ? ?\//
?/ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/
?/ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/
//\/ ? ? ? ? ? ? ? ? ? ? ? ? ? ?///\
\///\///\///\///\///\///\//
?/\///\///\///\///\///\///
? ? /\/// ? ?/\/// ? ?/\///
? ? ? ?/ ? ? ? ? ?/ ? ? ? ? ?/

或者玩点更有趣的,比如:

echo "I am a dog" | boxes -d dog -a c

不要惊讶,它将会输出如下:

? ? ? ? ? __ ? _,--="=--,_ ? __
? ? ? ? ?/ ?." ? ?.-. ? ?"./ ?
? ? ? ? / ?,/ ?_ ? : : ? _ ?/` 
? ? ? ?  ?`| /o ?:_: ?/o |__/
? ? ? ? ?`-'| :="~` _ `~"=: |
? ? ? ? ? ? ` ? ? (_) ? ? `/
? ? ?.-"-. ?  ? ? ?| ? ? ?/ ? .-"-.
.---{ ? ? }--| ?/,.-'-., ?|--{ ? ? }---.
?) ?(_)_)_) ?_/`~-===-~`_/ ?(_(_(_) ?(
( ? ? ? ? ? ? ?I am a dog ? ? ? ? ? ? ? )
?) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (
'---------------------------------------'

boxes 程序提供了很多选项 用于填充、定位甚至处理正则表达式。你可以在其 项目主页 上了解更多有关 boxes 的信息,或者转到 GitHub 去下载源代码或者贡献你自己的盒子形状。说到此,如果你想给你的提交找个好点子,我已经有了一个想法:为什么不能是一个节日礼物盒子?

? ? ? ? ?_ ?_
? ? ? ? /_/_
?________/_/_______
| ? ? ? ///\ ? ? ? |
| ? ? ?/// ?\ ? ? ?|
| ? ? ? ? ? ? ? ? ? ?|
| ? ? "Happy pull ? ?|
| ? ? ? request!" ? ?|
|____________________|

boxes 是基于 GPLv2 许可证的开源项目。

你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。即使要介绍的小玩具已经有 24 个了,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。

你可以通过 Drive a locomotive through your Linux terminal 来查看明天会介绍的命令行小玩具。


 

神奇的 Linux 命令行字符形状工具 boxes,首发于山西十一选五手机版。

]]>
//www.brhi.net/114549/feed/ 0
关于 top 工具的 6 个替代方案 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114546/ //www.brhi.net/114546/#respond Tue, 11 Dec 2018 12:55:00 +0000 //www.brhi.net/?p=114546 我并不会说它们比 top 更好或者可以完全替代 top,但多了解一些类似的工具总是好的。

关于 top 工具的 6 个替代方案,首发于山西十一选五手机版。

]]>
在 GitHub 和 GitLab 上,不断有来自世界各地的开源应用程序和工具涌现。其中有全新的应用程序,也有针对现有各种被广泛使用的 Linux 程序的替代方案。在本文档中,我会介绍一些针对 top 工具(也就是命令行任务管理器程序)的替代方案。

top 工具的替代方案

在本文中,将会介绍以下 6 种 top 工具的替代方案:

  1. Htop
  2. Vtop
  3. Gtop
  4. Gotop
  5. Ptop
  6. Hegemon

如果后续有更多类似的工具,原作者会在原文进行更新。如果你对此有兴趣,可以持续关注。

Htop

htop 是一个流行的开源跨平台交互式进程管理器,也是我最喜欢的系统活动监控工具。htop 是对原版 top 工具的扩展。它最初只是用于 Linux 系统,后来开发者们不断为其添加对其它类 Unix 操作系统的支持,包括 FreeBSD 和 Mac OS。htop 还是一个自由开源软件,它基于 ncurses 并按照 GPLv2 发布。

和原版的 top 工具相比,htop 工具有这些优势:

  • htoptop 启动更快
  • htop 支持横向滚动和纵向滚动浏览进程列表,以便看到所有的进程和完整的命令行
  • top 工具中进行杀死进程、更改进程优先级这些操作时,需要输入进程 ID,而在 htop 工具中则不需要输入
  • htop 中可以同时杀死多个进程
  • top 中每次输入一个未预设的键都要等待一段时间,尤其是在多个键组成转义字符串的时候就更麻烦了

在很多 Linux 发行版的默认软件仓库中,都带有了 htop。

在基于 Arch 的操作系统中则可以执行以下命令来安装 htop

$ sudo pacman -S htop

在基于 Debian 的操作系统使用以下命令:

$ sudo apt install htop

在使用 RPM 软件管理的操作系统使用以下命令:

$ sudo dnf install htop

或者

$ sudo yum install htop

在 openSUSE 系统中:

$ sudo zypper in htop

用法

不带任何参数执行 htop 时,会显示如下画面:

$ htop

从图上可以看出,htop 会在界面顶部显示内存、交换空间、任务总数、系统平均负载、系统正常运行时间这些常用指标,在下方则和 top 一样显示进程列表,并且将进程的 ID、用户、进程优先级、进程 nice 值、虚拟内存使用情况、CPU 使用情况、内存使用情况等信息以多列显示出来。如果你想详细了解这些数据的含义,可以在这里阅读参考。

top 不同的是,htop 支持对不同的操作使用专有的按键。以下列出一些用于与 htop 交互的快捷键:

  • F1、h、?:进入帮助界面。
  • F2、Shift+s:进入设置界面。在设置界面中可以配置仪表板界面顶部显示哪些数据,以及设置颜色方案、显示列、显示顺序等等多种参数。
  • F3、/:在进程列表中进行搜索。
  • F4、\:进入筛选模式。输入一个字符串,筛选出包含这个字符串的进程。进入筛选模式后再按一次 F4 或者 ESC 可以退出筛选模式。
  • F5、t:切换默认显示模式和树型显示模式,在树型显示模式下按 + 可以查看子树。
  • F6、<、>:依次按照进程 ID、用户、进程优先级、进程 nice 值、CPU 使用率、内存使用率排序显示。
  • F7、]:提高所选进程的优先级。
  • F8、[:降低所选进程的优先级。
  • F9、k:杀死所选进程??梢杂? / 键选择不同的进程并按 F9 杀死进程。
  • F10、q: 退出 htop

以上这些快捷键都在 htop 界面底部显示。

需要注意的是,这其中有一些快捷键可能会与已有的快捷键发生冲突。例如按 F2 之后可能没有进入 htop 的设置界面,而是开始了对终端窗口的重命名。在这种情况下,你可能要更改一下快捷键的设置。

除了以上列出的快捷键以外,还有一些带有其它功能的快捷键,例如:

  • u 可以选择显示某个用户的进程。
  • Shift+m 可以按照内存使用量对进程列表排序。
  • Shift+p 可以按照 CPU 使用量对进程列表排序。
  • Shit+t 可以按照进程启动时间对进程列表排序。
  • CTRL+l 刷新界面。

htop 的所有功能都可以在启动后通过快捷键来调用,而不需要在启动的时候带上某个参数。当然,htop 也支持带参数启动。

例如按照以下方式启动 htop 就可以只显示某个用户的进程:

$ htop -u

更改界面自动刷新的时间间隔:

$ htop -d 10

看,htop 确实比 top 好用多了。

想了解 htop 的更多细节,可以查阅它的手册页面:

$ man htop

也可以查看它的项目主页GitHub 仓库。

Vtop

vtoptop 工具的另一个替代方案。它是一个使用 NodeJS 编写的、自由开源的命令行界面系统活动监视器,并使用 MIT 许可证发布。vtop 通过使用 unicode 中的盲文字符来绘制 CPU 和内存使用情况的可视化图表。

在安装 vtop 之前,需要先安装 NodeJS。如果还没有安装 NodeJS,可以按照这个教程进行安装。

NodeJS 安装完毕之后,执行以下命令安装 vtop

$ npm install -g vtop

安装好 vtop 就可以执行以下命令开始监控了。

$ vtop

显示界面如下:

如上图所示,vtop 界面和 top、htop 都有所不同,它将不同的内容分别以多个框的布局显示。另外在界面底部也展示了用于与 vtop 交互的所有快捷键。

vtop 有这些快捷键:

  • dd :杀死一个进程。
  • 、k:向上移动。
  • 、j:向下移动。
  • 、h :放大图表。
  • 、l:缩小图表。
  • g :跳转到进程列表顶部。
  • Shift+g :跳转到进程列表底部。
  • c :以 CPU 使用量对进程排序。
  • m :以内存使用量对进程排序。

想要了解更多关于 vtop 的细节,可以查阅它的项目主页或者 GitHub 仓库。

Gtop

gtopvtop 一样,都是一个使用 NodeJS 编写、在 MIT 许可下发布的系统活动监视器。

执行以下命令安装 gtop

$ npm install gtop -g

然后执行以下命令启动:

$ gtop

显示界面如下:

gtop 有一个优点,就是它会以不同的颜色来显示不同的???,这种表现形式非常清晰明了。

主要的快捷键包括:

  • p:按照进程 ID 对进程排序。
  • c:按照 CPU 使用量对进程排序。
  • m:按照内存使用量对进程排序。
  • q、Ctrl+c:退出。

想要了解更多关于 gtop 的细节,可以查阅它的 GitHub 仓库。

Gotop

gotop 也是一个完全自由和开源的图表式系统活动监视器。顾名思义,它是在受到 gtopvtop 的启发之后用 Go 语言编写的,因此也不再对其展开过多的赘述了。如果你有兴趣了解这个项目,可以阅读《gotop:又一个图表式系统活动监视器》这篇文章。

Ptop

有些人对 NodeJS 和 Go 语言的项目可能不太感冒。如果你也是其中之一,你可以试一下使用 Python 编写的 ptop。它同样是一个自由开源的、在 MIT 许可下发布的系统活动监视器。

ptop 同时兼容 Python2.x 和 Python3.x,因此可以使用 Python 的软件包管理器 pip 轻松安装。如果你没有安装 pip,也可以参考这个教程进行安装。

安装 pip 之后,执行以下命令就可以安装 ptop

$ pip install ptop

又或者按照以下方式通过源代码安装:

$ git clone https://github.com/darxtrix/ptop
$ cd ptop/
$ pip install -r requirements.txt # install requirements
$ sudo python setup.py install

如果需要对 ptop 进行更新,可以这样操作:

$ pip install --upgrade ptop

即使你不执行更新,ptop 也会在第一次启动的时候提示你是否需要更新到最新的版本。

现在可以看一下启动 ptop 后的界面。

$ ptop

就像下面这样:

ptop 的快捷键包括以下这些:

  • Ctrl+k:杀死一个进程。
  • Ctrl+n:按照内存使用量对进程排序。
  • Ctrl+t:按照进程启动时间对进程排序。
  • Ctrl+r:重置所有数据。
  • Ctrl+f:对进程进行筛选,输入进程的名称就能够筛选出符合条件的进程。
  • Ctrl+l:查看所选进程的详细信息。
  • g:跳转到进程列表顶部。
  • Ctrl+q:退出。

ptop 还支持更改显示主题。如果你想让 ptop 更好看,可以选择你喜欢的主题??捎玫闹魈獍ㄒ韵抡庑?/p>

  • colorful
  • elegant
  • simple
  • dark
  • light

如果需要更换主题(例如更换到 colorful 主题),可以执行以下命令:

$ ptop -t colorful

使用 -h 参数可以查看帮助页面:

$ ptop -h

想要了解更多关于 ptop 的细节,可以查阅它的 GitHub 仓库。

Hegemon

hegemon 是一个使用 Rust 编写的系统活动监视器,如果你对 Rust 感兴趣,也可以了解一下。我们最近有一篇关于 hegemon文章,想要详细了解的读者不妨阅读。

总结

以上就是关于 top 工具的 6 个替代方案。我并不会说它们比 top 更好或者可以完全替代 top,但多了解一些类似的工具总是好的。你有使用过这些工具吗?哪个是你最喜欢的?欢迎在评论区留言。

 

关于 top 工具的 6 个替代方案,首发于山西十一选五手机版。

]]>
//www.brhi.net/114546/feed/ 0
正则表达式的隐藏陷阱,你都了解么? - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114536/ //www.brhi.net/114536/#comments Thu, 06 Dec 2018 15:55:18 +0000 //www.brhi.net/?p=114536 想不到,一行不起眼的正则表达式,竟然会让你的CPU挂死,这个正则表达式的陷阱你遇到过吗?

正则表达式的隐藏陷阱,你都了解么?,首发于山西十一选五手机版。

]]>
几天前,一个在线项目的监控系统突然报告了一个异常。在检查了相关资源的使用率后,我们发现 CPU 利用率接近 100%。然后,我们用 Java 附带的线程转储工具导出了这个异常相关的堆栈信息。

我们发现,所有堆栈信息都指向一个名为 “validateUrl” 的方法,它在堆栈上有超过 100 个错误消息。通过检查代码,我们发现该方法的主要功能是验证 URL 的合法性。

一个正则表达式是如何导致如此高的 CPU 利用率的呢?为了重现这个错误,我们提取了关键代码,并进行了简单的单元测试。

public static void main(String[] args) {
    String badRegex = "^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\\\/])+$";
    String bugUrl = "//www.fapiao.com/dddp-web/pdf/download?request=6e7JGxxxxx4ILd-kExxxxxxxqJ4-CHLmqVnenXC692m74H38sdfdsazxcUmfcOH2fAfY1Vw__%5EDadIfJgiEf";
    if (bugUrl.matches(badRegex)) {
        System.out.println("match!!");
    } else {
        System.out.println("no match!!");
    }
}

当我们运行上面的示例时,资源监视器显示,一个名为 Java 的进程 CPU 利用率已经飙升到 91.4%。

现在我们几乎可以判断,正则表达式是导致 CPU 利用率飙升的原因。

所以,让我们聚焦于正则表达式:

^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\/])+$

这个正则表达式看起来并没有什么异常。它可以分为三部分:

第一部分用于匹配 httphttps 协议。 第二部分用于匹配 www. 字符。第三部分用于匹配剩余字符。我盯着这个正则表达式看了很久,也没发现什么大问题。

事实上,Java 用来处理正则表达式所用的 NFA 引擎是引起高 CPU 利用率的关键。当进行字符匹配时, NFA 会使用一种称为“回朔法”(backtracking)的方法。一旦发生回溯,所花费的时间将变得非常长??赡苁羌阜种?,也可能长达数小时。所需时间的长短取决于发生回溯的次数和回溯的复杂度。

也许有些人还不太清楚回溯是什么。没关系,让我们从正则表达式的原理开始。

正则表达式引擎

正则表达式是一组便于匹配的符号。为了实现如此复杂且强大的匹配语法,我们必须有一组算法,算法的实现称为正则表达式引擎。简而言之,正则表达式的实现引擎有两种:一种是 DFA (有穷确定自动机 Deterministic Final Automata),另一种是 NFA (有穷非确定自动机 Non deterministic Finite Automaton).

这是两种不同的自动机。在这里,我们不会深入讨论它们的原理。简单地说,DFA 的时间复杂度是线性的。它更稳定,但功能有限。NFA 的时间复杂度相对不稳定。 根据正则表达式的不同,时间有时长,有时短。NFA 的优点是它的功能更强大,所以被 Java、.NET、Perl、Python、Ruby 和 PHP 用来处理正则表达式。

NFA 是怎样进行匹配的呢?我们用下面的字符串和表达式作为例子。

text="Today is a nice day."
regex="day"

记住,NFA 匹配是基于正则表达式的。也就是说,NFA 将依次读取正则表达式的匹配符,并将其与目标字符串进行匹配。如果匹配成功,它将转到正则表达式的下一个匹配符。否则,它将继续与目标字符串的下一个字符进行比较。

让我们一步一步地来看一下上面的例子。

  • 首先,提取正则表达式的第一个匹配符:d。然后,将它与字符串的第一个字符 T 进行比较。不匹配,所以转到下一个。第二个字符是 o,也不匹配。继续转到下一个,也就是 d。匹配成功。于是,读取正则表达式的第二个字符: a。
  • 正则表达式的第二个匹配符是:a。将它与字符串的第四个字符 a 进行比较。又匹配了。于是继续读取正则表达式的第三个字符 y。
  • 正则表达式的第三个匹配符是 y。让我们继续与字符串的第五个字符比较。匹配成功。接着,尝试读取正则表达式的下一个字符,发现没有字符了,因此匹配结束。

以上是 NFA 的匹配过程。实际的匹配过程要复杂得多。不过,匹配的原理都是一样的。

NFA 回溯法

现在,你已经了解了 NFA 是如何进行字符串匹配的。下面,让我们来看一下本文的重点:回溯法。我们将使用下面的例子,以便更好的解释回朔法。

text="abbc"
regex="ab{1,3}c"

这是一个比较简单的例子。正则表达式以 a 开始,以 c 结束。它们之间有以 1-3 个 b 组成的字符串。NFA 的匹配过程如下:

  • 首先,读取正则表达式的第一个匹配符 a,并将其与字符串的第一个字符 a 进行比较。两者匹配,所以,移动到正则表达式的第二个字符。
  • 读取正则表达式的第二个匹配符 b{1,3},将它与字符串的第二个字符 b 进行比较。它们又匹配了。b{1,3} 代表 1-3 个 b,基于 NFA 的贪婪特性(即,尽可能地进行匹配),此时它不会读取正则表达式的下一个匹配符,而是仍然使用b{1,3} 与字符串的第三个字符 b 进行比较。它们匹配了。于是继续用 b{1,3} 与字符串的第四个字符 c 进行比较。它们不匹配。 回溯 就出现在这里
  • 回溯是如何进行的?回溯后,字符串中已被读取的第四个字符 c 将被放弃。指针将返回到字符串的第三个字符。接着,正则表达式的下一个匹配符 c 会被用来与待匹配字符串当前指针的下一个字符 c 进行对比。两者是匹配的。这时,字符串最后一个字符已经被读取。匹配结束。

让我们回过头来看看用于验证 URL 的正则表达式。

^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\/])+$

出现问题的 URL 如下:

//www.fapiao.com/dzfp-web/pdf/download?request=6e7JGm38jfjghVrv4ILd-kEn64HcUX4qL4a4qJ4-CHLmqVnenXC692m74H5oxkjgdsYazxcUmfcOH2fAfY1Vw__%5EDadIfJgiEf

我们将正则表达式分为三个部分:

  • 第1部分:验证协议。 ^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)。
  • 第2部分:验证域。(([A-Za-z0-9-~]+).)+。
  • 第3部分:验证参数。([A-Za-z0-9-~\\/])+$。

可以发现,验证 // 协议这部分的正则表达式没有什么问题。但是,当用 xxxx. 验证 www.fabiao.com 时,匹配过程如下:

  • 匹配 www。
  • 匹配 fapiao。
  • 匹配 com/dzfp-web/pdf/download?request=6e7JGm38jf.....。由于“贪婪”的性质,程序会一直试图读取下一个字符进行匹配,直至上述一长串字符串读取完毕,发现找不到点号。此时,程序开始一个字符一个字符进行回溯。

这是正则表达式中的第一个问题。

另一个问题出现在正则表达式的第三部分??梢钥吹?,有问题的 URL 具有下划线(_)和百分号(),但是与第三部分对应的正则表达式中则没有。因此,只有在匹配完一长串字符之后,程序才发现两者不匹配,然后进行回溯。

这是这个正则表达式中的第二个问题。

解决方案

你已经知道回溯是导致问题的原因。所以,解决问题的方法就是减少回溯。事实上,你会发现,如果把下划线和百分比符号添加到第三部分,程序就会变得正常。

public static void main(String[] args) {
    String badRegex = "^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~_%\\\\/])+$";
    String bugUrl = "//www.fapiao.com/dddp-web/pdf/download?request=6e7JGxxxxx4ILd-kExxxxxxxqJ4-CHLmqVnenXC692m74H38sdfdsazxcUmfcOH2fAfY1Vw__%5EDadIfJgiEf";
    if (bugUrl.matches(badRegex)) {
        System.out.println("match!!");
    } else {
        System.out.println("no match!!");
    }
}

运行上面的程序,它会打印出“ match!! ”。

如果未来其他的 URL 中含有别的混乱字符怎么办? 再次修正代码? 当然不现实!

事实上,正则表达式有三种模式:贪婪模式 ,勉强模式独占模式。

如果你在正则表达式中添加一个 ? 标志,贪婪模式将变成勉强模式。此时,它将尽可能少地匹配。然而,勉强模式下回溯仍可能出现。例如:

text="abbc"
regex="ab{1,3}?c"

正则表达式的第一个字符 a 与字符串的第一个字符 a 相匹配。正则表达式的第二个运算符 b{1,3}? 匹配了字符串的第二个字符 b 。由于最小匹配的原则,正则表达式将读取第三个运算符 c,并与字符串第三个字符 b 进行比较。两者不匹配。因此,程序进行回溯并将正则表达式的第二个运算符 b{1,3}? 与字符串的第三个字符 b 进行比较。现在匹配成功了。之后,正则表达式的第三个匹配符 c 与字符串的第四个字符 c 正相匹配。匹配结束。

如果添加 +标志,则原来的贪婪模式将变成独占模式。也就是说,它将匹配尽可能多的字符,但不会回溯。

因此,如果你想将这个问题完全解决。你必须保证表达式能正确的行使它的功能,同时确保没有回溯发生。我在上述验证 URL 的正则表达式的第二部分增添了一个加号:

 

^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)
(([A-Za-z0-9-~]+).)++    --->>> (added + here)(“+”添加在这里)
([A-Za-z0-9-~_%\\\/])+$

现在,程序运行没有问题了。

最后,我推荐一个网站。它可以检查你写的正则表达式以及相应的匹配字符串是否存在问题。

例如,本文中存在问题的 URL 在使用上述网站检测后,会弹出如下提示:灾难性的回溯。

当你单击左下角的 “regex debugger” 时,它将告诉你已经进行了多少步匹配,列出所有的匹配步骤,并指出发生回溯的地方。

本文中的正则表达式在 110,000 次尝试之后自动停止。这表明,正则表达式存在一定的问题并需要改进。

`但是,当我用如下修改后的正则表达式测试时:

^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+).)++([A-Za-z0-9-~\\\/])+$

网站提示,仅用了 58 步就完成了匹配。

一个字符的差异导致了巨大的性能差距。

一些补充

一个小小的正则表达式也能神奇的让 CPU 卡死。这给我们提了一个醒。当遇到正则表达式的时候,一定要注意“贪婪模式”以及回溯问题。

正则表达式的隐藏陷阱,你都了解么?,首发于山西十一选五手机版。

]]>
//www.brhi.net/114536/feed/ 3
在 Linux 上自定义 bash 命令提示符 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114528/ //www.brhi.net/114528/#respond Tue, 27 Nov 2018 13:16:30 +0000 //www.brhi.net/?p=114528 尽管很多插件或工具都可以很轻易地满足这一需求,但我们也可以不使用插件和工具,自己手动自定义一些基本的显示方式,例如添加或者修改某些元素、更改前景色、更改背景色等等。

在 Linux 上自定义 bash 命令提示符,首发于山西十一选五手机版。

]]>

众所周知,bash(the Bourne-Again Shell)是目前绝大多数 Linux 发行版使用的默认 shell。本文将会介绍如何通过添加颜色和样式来自定义 bash 命令提示符的显示。尽管很多插件或工具都可以很轻易地满足这一需求,但我们也可以不使用插件和工具,自己手动自定义一些基本的显示方式,例如添加或者修改某些元素、更改前景色、更改背景色等等。

在 Linux 中自定义 bash 命令提示符

在 bash 中,我们可以通过更改 $PS1 环境变量的值来自定义 bash 命令提示符。

一般情况下,bash 命令提示符会是以下这样的形式:

在上图这种默认显示形式当中,“sk” 是我的用户名,而 “ubuntuserver” 是我的主机名。

只要插入一些以反斜杠开头的特殊转义字符串,就可以按照你的喜好修改命令提示符了。下面我来举几个例子。

在开始之前,我强烈建议你预先备份 ~/.bashrc 文件。

$ cp ~/.bashrc ~/.bashrc.bak

更改 bash 命令提示符中的 username@hostname 部分

如上所示,bash 命令提示符一般都带有 “username@hostname” 部分,这个部分是可以修改的。

只需要编辑 ~/.bashrc 文件:

$ vi ~/.bashrc

在文件的最后添加一行:

PS1="ostechnix> "

将上面的 “ostechnix” 替换为任意一个你想使用的单词,然后按 ESC 并输入 :wq 保存、退出文件。

执行以下命令使刚才的修改生效:

$ source ~/.bashrc

你就可以看见 bash 命令提示符中出现刚才添加的 “ostechnix” 了。

再来看看另一个例子,比如将 “username@hostname” 替换为 “Hello@welcome>”。

同样是像刚才那样修改 ~/.bashrc 文件。

export PS1="Hello@welcome> "

然后执行 source ~/.bashrc 让修改结果立即生效。

以下是我在 Ubuntu 18.04 LTS 上修改后的效果。

仅显示用户名

如果需要仅显示用户名,只需要在 ~/.bashrc 文件中加入以下这一行。

export PS1="\u "

这里的 \u 就是一个转义字符串。

下面提供了一些可以添加到 $PS1 环境变量中的用以改变 bash 命令提示符样式的转义字符串。每次修改之后,都需要执行 source ~/.bashrc 命令才能立即生效。

显示用户名和主机名

export PS1="\u\h "

命令提示符会这样显示:

skubuntuserver

显示用户名和完全限定域名

export PS1="\u\H "

在用户名和主机名之间显示其它字符

如果你还需要在用户名和主机名之间显示其它字符(例如 @),可以使用以下格式:

export PS1="\u@\h "

命令提示符会这样显示:

sk@ubuntuserver

显示用户名、主机名,并在末尾添加 $ 符号

export PS1="\u@\h\\$ "

综合以上两种显示方式

export PS1="\u@\h> "

命令提示符最终会这样显示:

sk@ubuntuserver>

相似地,还可以添加其它特殊字符,例如冒号、分号、星号、下划线、空格等等。

显示用户名、主机名、shell 名称

export PS1="\u@\h>\s "

显示用户名、主机名、shell 名称以及 shell 版本

export PS1="\u@\h>\s\v "

bash 命令提示符显示样式:

显示用户名、主机名、当前目录

export PS1="\u@\h\w "

如果当前目录是 $HOME ,会以一个波浪线(~)显示。

在 bash 命令提示符中显示日期

除了用户名和主机名,如果还想在 bash 命令提示符中显示日期,可以在 ~/.bashrc 文件中添加以下内容:

export PS1="\u@\h>\d "

在 bash 命令提示符中显示日期及 12 小时制时间

export PS1="\u@\h>\d\@ "

显示日期及 hh:mm:ss 格式时间

export PS1="\u@\h>\d\T "

显示日期及 24 小时制时间

export PS1="\u@\h>\d\A "

显示日期及 24 小时制 hh:mm:ss 格式时间

export PS1="\u@\h>\d\t "

以上是一些常见的可以改变 bash 命令提示符的转义字符串。除此以外的其它转义字符串,可以在 bash 的 man 手册 PROMPTING 章节中查阅。

你也可以随时执行以下命令查看当前的命令提示符样式。

$ echo $PS1

在 bash 命令提示符中去掉 username@hostname 部分

如果我不想做任何调整,直接把 username@hostname 部分整个去掉可以吗?答案是肯定的。

如果你是一个技术方面的博主,你有可能会需要在网站或者博客中上传自己的 Linux 终端截图?;蛐砟愕挠没椭骰?、太另类,不想让别人看到,在这种情况下,你就需要隐藏命令提示符中的 “username@hostname” 部分。

如果你不想暴露自己的用户名和主机名,只需要按照以下步骤操作。

编辑 ~/.bashrc 文件:

$ vi ~/.bashrc

在文件末尾添加这一行:

PS1="\W> "

输入 :wq 保存并关闭文件。

执行以下命令让修改立即生效。

$ source ~/.bashrc

现在看一下你的终端,“username@hostname” 部分已经消失了,只保留了一个 ~> 标记。

如果你想要尽可能简单的操作,又不想弄乱你的 ~/.bashrc 文件,最好的办法就是在系统中创建另一个用户(例如 “user@example”、“admin@demo”)。用带有这样的命令提示符的用户去截图或者录屏,就不需要顾虑自己的用户名或主机名被别人看见了。

警告:在某些情况下,这种做法并不推荐。例如像 zsh 这种 shell 会继承当前 shell 的设置,这个时候可能会出现一些意想不到的问题。这个技巧只用于隐藏命令提示符中的 “username@hostname” 部分,仅此而已,如果把这个技巧挪作他用,也可能会出现异常。

为 bash 命令提示符着色

目前我们也只是变更了 bash 命令提示符中的内容,下面介绍一下如何对命令提示符进行着色。

通过向 ~/.bashrc 文件写入一些配置,可以修改 bash 命令提示符的前景色(也就是文本的颜色)和背景色。

例如,下面这一行配置可以令某些文本的颜色变成红色:

export PS1="\u@

\[\e[31m\]

\h

\[\e[m\]

"

添加配置后,执行 source ~/.bashrc 立即生效。

你的 bash 命令提示符就会变成这样:

类似地,可以用这样的配置来改变背景色:

export PS1="\u@

\[\e[31;46m\]

\h

\[\e[m\]

"

添加 emoji

大家都喜欢 emoji?;箍梢园凑找韵屡渲冒?emoji 插入到命令提示符中。

PS1="\W ? >"

需要注意的是,emoji 的显示取决于使用的字体,因此某些终端可能会无法正常显示 emoji,取而代之的是一些乱码或者单色表情符号。

自定义 bash 命令提示符有点难,有更简单的方法吗?

如果你是一个新手,编辑 $PS1 环境变量的过程可能会有些困难,因为命令提示符中的大量转义字符串可能会让你有点晕头转向。但不要担心,有一个在线的 bash $PS1 生成器可以帮助你轻松生成各种 $PS1 环境变量值。

就是这个网站

EzPrompt

只需要直接选择你想要的 bash 命令提示符样式,添加颜色、设计排序,然后就完成了。你可以预览输出,并将配置代码复制粘贴到 ~/.bashrc 文件中。就这么简单。顺便一提,本文中大部分的示例都是通过这个网站制作的。

我把我的 ~/.bashrc 文件弄乱了,该如何恢复?

正如我在上面提到的,强烈建议在更改 ~/.bashrc 文件前做好备份(在更改其它重要的配置文件之前也一定要记得备份)。这样一旦出现任何问题,你都可以很方便地恢复到更改之前的配置状态。当然,如果你忘记了备份,还可以按照下面这篇文章中介绍的方法恢复为默认配置。

这篇文章是基于 ubuntu 的,但也适用于其它的 Linux 发行版。不过事先声明,这篇文章的方法会将 ~/.bashrc 文件恢复到系统最初时的状态,你对这个文件做过的任何修改都将丢失。

感谢阅读!

 

在 Linux 上自定义 bash 命令提示符,首发于山西十一选五手机版。

]]>
//www.brhi.net/114528/feed/ 0
网络应用优化——时延与带宽 - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114523/ //www.brhi.net/114523/#comments Thu, 22 Nov 2018 10:04:51 +0000 //www.brhi.net/?p=114523 本文网络应用优化中最重要的两个目标:时延与带宽。通过定义并区分两者的关系,并引申出网络服务优化的几种基本方法。

网络应用优化——时延与带宽,首发于山西十一选五手机版。

]]>
1. 用户感知的“速度”
用户体验能给网站带来更多的收益,因此人们也投入了更多精力去研究它。用户体验中,除了好的交互,精美的界面,用户感知的“速度”也是重要的一环。从网络角度来说,时延(latency)和带宽(bindwidth)是决定“速度”的重要环节。
不同的应用对时延和带宽需求的侧重点往往不同:
  • 网络游戏需要更低的时延。在一些对抗激烈的FPS、MOBA类的游戏中,单次数据传输的量并不大,因此带宽要求不高。但是若你顶着延迟和别人进行对抗,那么这局比赛可能已经输了一半;
  • 流媒体需要更高的带宽。高速带宽能让你观看高清电影,而延时就显得不那么重要,带来问题无非是在加载前等待一段时间罢了;
  • 视频聊天需要更低的时延。更低的时延意味着你能看到更流畅的实时画面,而不会掉帧。也许只有当你想要切换更高清晰度的时候才需要选择更高的带宽。
  • 浏览网页需要更低的时延。因为没人愿意在一个空白页面上花上几秒钟。更高的带宽常常无关紧要,除非你需要流量高分辨率的图片或者高清的视频。

2. 时延与带宽

2.1.糖果包装问题

某厂某天生产了N颗糖果,需要进行包装和验收。流水线一端的工人A负责包装,包装速度为N1颗/小时,另一端B的验收速度为N2颗/小时,两者通过协调达成某一相同的速度MIN(N1,N2)颗/小时。通过传送带传送到目的地。传送带长L米,速度为V 米/小时。从A开始计时到B验收完成,所需时间T为多少?
答:T = L / V + N / MIN(N1,N2) + 1 / MIN(N1,N2)
时间T反映了完成糖果包装并验收完成的总时间。如果糖果想象成可以需要传输的文件,那么就可以把糖果包装问题转换为一个简化的网络传输问题。
假设服务器A向用户B发送一个大小为100KB的图片(假设HTTP连接已经建立),服务器上行带宽为1Mbps,用户所在下行带宽为100Mbps。已知端对端物理距离为2000 km,光信号在光纤中的传播速度是200000 km/s,求图片从A发出到B完整接收的时间T。代入公式可得: T = 2000/200 + 100 * 8 / 1 = 810 ms(最后一项太小可以被忽略)
这个时间就是时延,具体的说是单向时延,即一个数据文件从传输到完整接收所花费的时间。

2.2.时延是什么

2.1中图片传输的时间叫做时延。时延并没有一个确切的定义。多数情况下是指单向时延,就是在数据通信过程中从A发送数据的第一个比特开始到B接受到数据的最后一个比特为结束产生的时间消耗,在某些场景下也指双向时延,即从网络请求发出到收到完整响应为结束经历的时间。时延常以毫秒为单位来衡量。数据包的大小、链路上传下行速率、通信距离、通信介质的种类、路由器的处理能力都会影响时延。常说的时延是下列这些不同时延的总和:
  • 传播时延。信号在信道中传输的时间=通信距离/传播速度。
  • 处理时延。路由器路由、差错控制以及数据包头信息处理的时间。
  • 队列时延。数据包在队列中等待路由器处理的时间。
  • 发送时延。将数据包发送到信道中的时间=数据包大小/信道带宽。
减少时延往往比增加带宽需要更多的成本。2015年9月,Hibernia网络公司为了最大程度上确保纽约和伦敦的通信延时,部署了一条名为“Hibernia Express”的海底光缆,总计耗费达3亿美元。采用新光缆之后,纽约伦敦两地的延时为58.95ms,比现存的所有大西洋光缆少了5ms。这意味着节约的每1毫秒,价值近6千万美元。

2.3.带宽是什么

带宽是指数据通信最大的吞吐量,根据传输方向的不同可以分为上行带宽和下行带宽,常用Mbps来进行衡量。对于互联网上的用户,运营商(ISP)提供的带宽就是数据通信的最大吞吐量,并且上下行带宽往往不对称。如中国电信百兆宽带最大下行速度为100Mbps,而最大上行速度只有20Mbps。
一般来说,核心网络(如海底光缆)的带宽往往可以达到几百Tbps。而终端用户实际可用的带宽,往往是网络服务所在服务器的上行带宽与用户下行带宽的最小值。
若某一网站部署在上行带宽为1Mbps服务器上,那么即使访问者拥有100Mbps的下行带宽,用户仍然只能以1Mbps的速度下载网页上的内容。

2.4.联系与区别

对终端用户而言,延时可以理解为某一网络服务的响应速度,而带宽可以理解为上传下载文件的最大速度,而实际可用的带宽,往往又是由网络服务所在服务器的上行带宽与用户下行带宽的最小值所决定。
以浏览网页为例子,若响应速度快,用户实际可用的带宽(见2.3节的定义)小,就可能导致页面上的图片以肉眼可见的速度一点点显示出来;若响应速度慢,用户实际可用的带宽大,就可能导致页面上的内容需要等待很久才能有显示,在此之前都是空白。但是当响应完成,会立即显示网页内容。
有人说带宽和时延没有关系,这句话是有问题的。因为在2.2节中介绍了发送延时,它通常由服务器的上行带宽与用户下行带宽的最小值所决定。准确的说是,目前现实场景中大部分的时延不是由带宽决定,而往往是由传播距离、网络状况等所决定。

3.性能优化

了解了带宽和时延,那么就可以更好地理解网站性能优化背后的本质——减少延时,增加带宽。常见的性能优化的方式有合并请求和建立内容分发网络(CDN):
合并请求。从优化角度来说,合并请求就是在减少总时延。一个100KB的文件和 10个10KB大小的文件大小相同。若D为传播时延,T为发送10KB文件的发送时延,那么一次发送100KB文件的时延为 D + 10T,而发送10次单个10KB文件的延时为 10D+10T。相同情况下,请求次数越少,总时延就越少。
建立内容分发网络。内容分发网络通过将网站内容服务器分布在靠近用户的位置,从而使用户就近获取所需内容,减少传播延时,进而显著提升网站的响应速度。
举例来说,高质量的视频网站必须租用高速的上行带宽,确保能够承担大规模的视频流量,因为没人愿意等待几分钟缓冲一个流媒体视频。同时它也要在各地建立大规模的内容分发网络(CDN)来降低视频内容的传播延迟,这样才不会让用户等待很久才能获得网站的响应。

4.总结

本文网络应用优化中最重要的两个目标:时延与带宽。通过定义并区分两者的关系,并引申出网络服务优化的几种基本方法。和所有的教程一样,本文不可能涵盖到网络优化的所有细节,但是若能对你有所启发,那就是再好不过了。

5.参考链接

网络应用优化——时延与带宽,首发于山西十一选五手机版。

]]>
//www.brhi.net/114523/feed/ 1
程序员神器 StackOverflow 10 岁了,它长大后想成为什么? - 山西十一选五手机版▁山西11选五前三组遗漏▁山西十一选五任七遗漏▁山西11选五遗漏top10▁山西体彩十一选5一定牛 //www.brhi.net/114499/ //www.brhi.net/114499/#comments Tue, 20 Nov 2018 03:20:53 +0000 //www.brhi.net/?p=114499 今年 9 月,程序员必备神器之一的 Stack Overflow 正式成立 10 周年了。截至目前为止,SO 用户量高达 930 万,也许你经常在 SO 上找解决方案。但你可能还不真正了解 SO。来看看 SO 创始人 Jeff Atwood 是怎么说的。

程序员神器 StackOverflow 10 岁了,它长大后想成为什么?,首发于山西十一选五手机版。

]]>
【伯乐在线导读】:今年 9 月,程序员必备神器之一的 Stack Overflow 正式成立 10 周年了。截至目前为止,SO 用户量高达 930 万,也许你经常在 SO 上找解决方案。但你可能还不真正了解 SO。来看看 SO 创始人 Jeff Atwood 是怎么说的。


 

现实生活中常常有人问我,我的工作是什么,对此我有一个 15 秒的回答:

我们创建了一个类似维基百科的网站,程序员们可以在上面发表或者解答问题。网站的名字叫?Stack Overflow。

截至 2018 年 9 月,Joel Spolsky 与我共同创建的 Stack Overflow?已经走过了?10 个年头。从 2012 年开始我就在做其他的工作了,但是能让人们在我过世之后还能想起我的东西,那肯定还是我的老伙伴 Stack Overflow。

这里我好像应该滔滔不绝地说?Stack Overflow 有多么优秀,而我作为创始人是有多么伟大。

但I这些我都不在乎。

我真正在乎的是,Stack Overflow 对程序员们是不是有帮助。对此,让我们看看如今最牛叉的开发者之一,我的偶像?John Carmack 是怎么评价的。

Stack Overflow为提升开发者的效率事业差不多贡献了好几亿美元 在为提升开发者的效率方面,Stack Overflow 可能贡献了好几十亿美元

说实话,2013 年 9 月 17 日是很美好的一天。我读到这条推的时候吓了一跳,不光是因为我经常用 Carl Sagan 的方式读 Billions 这个词。我在 Twitter 每隔几天就会读到一些残酷无尽的人间疾苦,以及人们在网络上的互相叫骂。与此相反,那一天是我感觉到的只有喜悦。这也提醒了我,我该查查 Twitter,看看如今谁还对网络抱有不同的理解。

Stack Overflow 有着如此多用户,也帮助了一个时代的开发者,对此我感到既荣幸又谦卑。但是,实现这一成就的并不是我。

  • 是你们,对 Stack Overflow 贡献了经过深入研究后想到的提问;
  • 是你们,对 Stack Overflow 贡献出了简洁而清晰的答案;
  • 是你们,编辑了 Stack Overflow 的提问或答案,并使其变得更好;

世界各地开发者们所贡献的那些大大小小的提问与回答,把 Stack Overflow 变成了一个在开发领域能与维基百科抗衡的创意共享知识库。这实在是…非常的不可思议。

不过成功的故事都很无聊。这个世界上有很多人,本身运气好,但还时不时的告诉别人是自己的努力以及喝活力汽水换来了成功。我觉得失败的故事更有教育意义,在建立业务与规划未来时,我把自己想象成深渊专家,并开始一场比赛。这是我自己做事的习惯。

abyss-oc

当你在凝视深渊的时候,深渊也正在凝视着你 – Friedrich Nietzsche

由此,我现在要与耀眼的深渊对视,预测一下Stack Overflow未来十年会遇到的挑战。这之前,我要先澄清以下事实。

1、从 2012 年 2 月开始,我就没有再为 Stack Overflow 做事了,也没有对其运营有过任何建议。你问我对如何运作Stack Overflow 竟然能没有建议?额,那你可能不认识我。你问我难道我不会时不时给员工发邮件告诉他们我的想法?我也许会吧,但是我为数不多的归档邮件可以证明,这个事情很少发生。

2、Stack 有着优秀的员工,他们中的大多数(包括我离开之前的 Stack Overflow 社区成员)都能对我们的使命给出更好的,不像我那样胡思乱想的阐述。我会用生命信任他们吗?不会。但是我会用 Joel 的生命信任他们!

3、Stack Overflow并不属于我或者 Joel,或者其他一些优秀的开发者。Stack Overflow 的运作靠的是世界各地日复一日做开发的人们,就像你或我一样。我觉得 Stack Overflow 就像个家长,它的目标是让孩子们最终能离开家长身边,成为可以独当一面的大人。

4、作为 Stack Overflow 的创始人,我在社区成立的最初四年里,花了非常多的时间参与制定规则与规范。你现在阅读的是我所强观点,弱坚持。这只是我的一些想法,我也希望自己的预测是准确的,但是这并不意味着我可以预测未来,或者我有资格去预测未来。不过我并不会以自己是否具有资格而不去做一些事情。

Stack Overflow首先是一个 wiki

Stack Overflow不仅是个论坛,它跟维基百科有很多相似之处。我们衡量问题和答案是否有意义的方式,不是看那些问题和答案对特定几个人的帮助,而是看随着时间的推移,这些问题和答案能不能帮助到越来越多的人。我从?2008 年 Stack Overflow 上线后就在强调这个关系。来看看下面谁的地位最高。

为了强调这一核心价值,Stack Overflow添加了一个简洁的功能。那就是在用户资料里会显示,你所贡献的问题与回答帮助到了多少人。

这些问答内容到底服务于谁?回答问题为何有如此严格的审核过程?对于 Stack Overflow 最常见的抱怨通常来自于对前面这两个问题的误解。

我希望更多的人能明白,Stack Overflow并不是一个“回答我的问题”的地方,它是“让我们合作建立一个对未来的开发者们有益的地方”。也许Stack Overflow应该更加努力去帮助用户理解这件事。 我希望更多的人能明白,Stack Overflow并不是一个“回答我的问题”的地方,它是“让我们合作建立一个对未来的开发者们有益的地方”。也许 Stack Overflow 应该更加努力去帮助用户理解这件事。

如今很多用户,甚至泡在 Hacker News 上的技术圈网友,都不知道 Stack Overflow 上有个功能,那就是每一个问题都是可以修改的,即使是没有登录的匿名用户也可以修改。对此我深表惊讶。这个功能不奇怪,对吧,因为 Stack Overflow 就是一种维基百科,这也是维基百科的运行模式,任何人都可以修改任何内容。不信的话,现在就去试试吧,找一个你认为可以提高的问题或者回答,点击“改善这个回答(improve this answer)”或者“改善这个问题(improve this question)”,然后写下你的改良版。

Stack Overflow 有很多功能(甚至也包括我自己在 2012 年之前的一些所作所为)都容易导致用户误解其核心价值。理论上,“如今每一个开发者都听过,用过以及了解 Stack Overflow”,但我觉得这个假设不准确。毕竟每时每刻都有新的开发者诞生。说得更复杂一点,Stack Overflow 的使用模式有三种,从大到小,以倒金字塔的形式排列如下:

1、我在需要的时候去搜索答案

用户直接上网搜索,搜索引擎会直接显示出 Stack Overflow 中的高票答案。出现在搜索引擎第一页,这也是Stack Overflow的主要目标。如Stack Overflow正常运行,98%的开发者在他们的整个职业生涯中,不需要主动提出或者回答问题。只要通过网络搜索就可以找Stack Overflow上到他们需要的结果。这是个好事,非常好的事。

2、我遇到很困难的问题时会参与Stack Overflow的讨论,因为单纯的搜索找不到我想要的答案

只在遇到难以解决的困难时,参与Stack Overflow的讨论,这很合理。然而,我觉得这个阶层的用户最容易感觉到Stack Overflow不是那么容易使用,因为这类用户可能对Stack Overflow很熟悉,但是并不清楚发布问题的流程。并且在他们急切想寻找答案的时候,他们没有时间或心思去应对Stack Overflow对于问题背景、格式、描述以及引用要求。

3、为了自己的职业发展,我主动参与Stack Overflow的问题讨论

这个阶层的用户很有经验,他们贡献了很多答案,也了解什么样的问题是好问题,是他们感兴趣、愿意回答的问题。他们不经常提问,因为他们知道如何去全面搜索他们想要的答案。但是他们一旦提问,那一定是个示范性的好问题。

(理论上这里还有个第四阶层用户,他们无私的贡献了很多提问与回答,目的只是为了推动软件开发行业的发展,造福于新一代的开发者们。但是我们没空提这些大神,你们只会让我们显得更加平凡,所以我们就此打住吧)

第一阶层的用户在社区里开心地逛了好几年,却在变为第二阶层用户时,一下子有了不开心的用户体验。对此我一点儿也不惊讶。我认为解决这个问题最主要的方式,就是改变并提高提问页面的用户体验。另外值得注意的一点是,用户在提出了某个问题后,可能收到关于问题信息不足的负面反馈,但是他们也许并不知道,你的问题应该是“有益于其他用户而并不只是你自己”。

Stack Overflow采用了维基百科的模式,也使其自身受到了很多限制。即使用户在提问前就知道这些,很多时候到底什么是“有用的信息”也很难判断。同理,很多时候我们也不确定到底什么样的话题,人群或者地点需要一份维基百科。Henrietta Lacks?有自己的维基百科页面,这毫无争议,但是他住在奥哈马市的表兄 Dave,那个提出了一个关于 PHP 5.6 的奇怪问题的人,是不是该被写入维基百科呢?

随着时间的推移,重复内容像地雷一样遍地都是

这事我很早就预料到了。老实说,我有点庆幸自己在 2012 年离开了 Stack Overflow,这样我就不用去处理这个难以置信的技术性难题:重复性内容。在我听到的关于 Stack Overflow 的所有抱怨里,重复内容是我觉得最有共鸣的。

如果你接受Stack Overflow是个类似于维基百科系统这一前提,那同理你显然不能接受,在维基百科中,对于意大利有五个不同的词条。Stack Overflow不允许对于同一个技术问题有重复的提问。我们确实有很多避免重复问题的功能,比如输入问题时的同步搜索,以及提交问题前,你会看到一个很明显的,鼓励用户先去搜索相关问题的搜索框。

… 如何查找并判断重复内容是个非常有难度的问题,即使是Google这样的公司,有着名副其实世界最聪明的工程师团队,专攻了20年也没有解决这个问题。

当你在一个不允许重复问题的网站中提问时,系统去重的难度取决于总问题数量,处理一百万的问题总量的去重与一千万甚至一亿相比,是非常不同的。系统处理问题去重的难度,会从不太难处理变为最终的完全无法处理。比如你提出了一个与艺术类相关的问题,那么系统需要根据你的提问内容,在不胜枚举的已有问题中进行筛选,以确保没有看起来相似的提问。

等会儿,还有个更难的问题!

  • 相似问题中有一点内容变化也是可以的,因为十个不同的人在提出同一个问题时,完全可能使用毫不相关的词语来形容这个问题。我知道这听起来很疯狂,但是相信我:人类极其擅长做这样的事。我们希望保留这些重复的问题,并且让他们都指向同一个主问题,以便于用户更好的搜索他们需要的内容,即使这些用户使用了那些平常不太会被用到的词语去描述问题。
  • 如何判断你提出的问题是不是重复,这是个不小的挑战。多少词语的重叠才能决定一个问题是不是与另一个重复?谁来决定?不同人有不同理论。这是个以人类语言为标准的解析,然后人类吧……不可预知。这个系统无法做到让所有人满意,去重的缺陷会一直存在于系统之中。

我对于越来越严重的重复问题并没有一个好的解决方案。但是我想指出,早期在?Stack Exchange?有很多先例,它们把网站分为“初级”和“高级”区域,不同区域的规则不同。我们在别的地方也能找到类似的例子,比如 Math 和 MathOverflow,English 和 English Learners, Unix 和 Ubuntu,也许是时候搞一个以初级用户为主的 Stack Overflow了,在那里我们可以允许多一些重复,少一些规则。

Stack Overflow是个可以同行评审的竞争性系统

Stack Overflow确实是个相当明确的竞争性系统,它的一大标志就是“总会有更好的解决办法”。根据我的多年观察,激励开发者最有效的方式就是…巧妙地暗示出别人的解决方案也许比你的更好。

- 你好Randall。医生说你能听到我说话,虽然你看起来像植物人。我是来告诉你,别着急慢慢康复。因为Ross接替了你的工作,并且做的非常好。他甚至找到了你代码里的瓶颈,还说他改过的代码变快了两倍。 - 这不可能?。。。?!我现在就回办公室! – 你好Randall。医生说你能听到我说话,虽然你看起来像植物人。我是来告诉你,别着急慢慢康复。因为Ross接替了你的工作,并且做的非常好。他甚至找到了你代码里的瓶颈,还说他改过的代码变快了两倍。

– 这不可能?。。。?!我现在就回办公室!

Stack Overflow的竞争性质体现在了它的公开声望系统上,就是用户名旁边那个拥有神奇力量的数字。所有的声望值都来源于其他用户,而不是所谓的系统。

每当你提出问题或者提交回答时,你的问题或回答都可以被其他用户指指点点,他们可以编辑、标记、关闭、打开、顶、踩或者收起。这样做的目的是让 Stack Overflow 成为一个同行评审和友好竞争的系统,就像在公司里,你的代码被你从没见过的另一个部门的人来评审。有人以友好的方式去质疑你所提问题的提论,也是完全合理的,比如,你真的想用这个正则表达式去匹配 HTML 吗?

我完全清楚这种竞争性质的同行评审系统,并不适合每一个人。Stack Overflow 采用维基百科的模式,导致它存在不能接受重复内容这样的限制。那么根据你的情况与背景,同行评审时,你收到的评价可能会让你觉得不舒服。

我听部分用户反应,在 Stack Overflow 提问的过程中会感觉到焦虑。对我来说,在 Stack Overflow上提问,应该感受到一种 ”我要展示出我最好的一面“ 的正常焦虑:

  • 在你的同事面前演讲的焦虑
  • 考试要取得好成绩的焦虑
  • 开始新工作,与你尊敬的优秀同事们一起工作的焦虑
  • 第一天去学校报到,即将见到新同学的焦虑

至于那种完全不会感到焦虑的地方,我唯一能想到的就是,从事了很久的工作,已经不再关注与工作本身,因此也没有那种担心有一天就会丢了工作的焦虑。这样怎么会好呢?所以说我不喜欢零焦虑的系统。

也许你不喜欢竞争。那么能不能有个少量竞争模式的问答系统呢?一个没有投支持或者反对票功能的系统,这样无论发表什么内容都不会感觉焦虑。这就像是一个全是你的支持者的网络,大家都相信你,希望你成功。这当然也是可以的。我认为应该有类似这样的网站,用户可以根据自己的需求与目标来选择适合自己的体验。那么 Stack 应该建立一个这样模式的社区吗?这样的社区已经有了吗?这是个开放题。也请随意在留言区发表你的看法。

Stack Overflow是为了日??⒄叨杓频?/h2>

Stack Overflow的目标用户到底是谁,这也是经常容易被混淆的一点。这个回答很直观,而且从从未改变过:

一个为专业和热情的程序员而存在的问答平台。这是指:

当前正在从事程序开发职业的人,或者如果愿意就能立即胜任程序开发工作的人。

如果你觉得好奇,这个定义的一部分是公开的商业决策。为了盈利,你的用户群体必须要有一部分拿着开发者薪水的人,或者在找开发者的工作的人。整个 Stack Overflow 社区也许有着知识共享的标签,但是它并不是个非营利组织。我们的出发点是可持续经营,这也是为什么我们在 Stack Overflow 上线一年之后,就成立?Stack Overflow Careers 招聘平台的原因,回顾一下,成立的确实有点过早了。为了实现比 2009 好很多的集成化用户体验,招聘平台被归入了 Stack Overflow,放在了?stackoverflow.com/jobs下面。

用户的选择定位并不是说要排斥非开发者,但是 Stack Overflow 确实是一个有着严格同行评审,对已经在从事相关行业的人来说非常优秀的功能,但同时也是对于学生或者初学者来说很不友好的功能。这也是为什么,我每次在推特上,看到有人推荐学生去 Stack Overflow 找答案时,我会小心翼翼的建议不要这样。对于开发领域的新手或者学生来说,他们需要的,与 Stack Overflow 所提供的是完全相反的。他们需要的是:

  • 一对一的指导
  • 实时屏幕共享协作
  • 实时语音
  • 理论背景知识课程
  • 初学者练习
  • 一个练习与实验的场所

这些都是对初学者来说,很好很合理的事情,但是 Stack Overflow 一个也不做。你可以通过 Stack Overflow 来从头学习如何编程吗?理论上你可以通过任何软件做任何事情,你甚至可以通过 Reddit 与人进行日常交流,如果你是受虐狂的话。但是答案还是肯定的,理论上你可以通过 Stack Overflow 学习如何编程,如果你是喜欢竞争模式(声望、被关闭、被踩)的神童,也完全能接受要去帮助别人而不只是自己学习知识这一观点。但是我强烈不推荐这样做。对初学者来说,除了 Stack Overflow 外还有很多更好更合适的平台。那么 Stack Overflow 能不能成为一个适合新手和学生的平台呢?我不清楚,我也不能决定。

这些就是我要说的。我们可以不再与深渊对视。

我希望我的观点对 Stack Overflow 不会有什么负面影响。总的来说,我认为目前的 Stack Overflow 很强大。但是,无论是?2008 年还是2018 年,我怎么想有关系吗?

Stack Overflow 是你们的。 Stack Overflow 将信念赌在了这一点:信任你的同行。Stack Overflow 的成长离不开那些积极参与社区讨论的开发者们。是你们让我相信开发者社区是最好的学习与成长的地方。是你们让我收获了如此多的对于 Stack Overflow 的赞誉。这不是我的功劳,而是你们的。 很久之前我在 Code Horror 上就知道了合作的力量是多么强大。目前我们的社区已经达到我今生难以企及的高度。我唯一能要求的,或者是我们能要求的,就是大家互相帮助互相成长。 如果有人认可了你的付出,那么你值得为此感到骄傲。

开发者社区的力量能够创造以及终结 Stack Overflow。Stack Overflow 长大了会成为什么?它的未来将由我们共同创造。

PS:Stack Overflow 十周年快乐!

山西十一选五手机版,首发于山西十一选五手机版。

]]> //www.brhi.net/114499/feed/ 1