<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Linux | Easton Man's Blog</title>
	<atom:link href="https://blog.eastonman.com/blog/category/linux/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.eastonman.com</link>
	<description>临渊羡鱼，不如退而结网</description>
	<lastBuildDate>Mon, 06 Dec 2021 03:32:53 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.5</generator>

<image>
	<url>https://blog.eastonman.com/wp-content/uploads/2021/02/cropped-Logo-e1613298891313-32x32.png</url>
	<title>Linux | Easton Man's Blog</title>
	<link>https://blog.eastonman.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>全球大内网与Zerotier</title>
		<link>https://blog.eastonman.com/blog/2021/12/zerotier/</link>
					<comments>https://blog.eastonman.com/blog/2021/12/zerotier/#comments</comments>
		
		<dc:creator><![CDATA[Easton Man]]></dc:creator>
		<pubDate>Mon, 06 Dec 2021 03:32:53 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[网络]]></category>
		<category><![CDATA[Zerotier]]></category>
		<guid isPermaLink="false">https://blog.eastonman.com/?p=910</guid>

					<description><![CDATA[<p>预计阅读时间： 6 分钟前段时间把笔记本换成了MacBook Pro（真香），为了数据安全，自然是需要把Tim [&#8230;]</p>
The post <a href="https://blog.eastonman.com/blog/2021/12/zerotier/">全球大内网与Zerotier</a> first appeared on <a href="https://blog.eastonman.com">Easton Man's Blog</a>.]]></description>
										<content:encoded><![CDATA[<p class="wpwc-reading-time">预计阅读时间： 6 分钟</p>
<p>前段时间把笔记本换成了MacBook Pro（<s>真香</s>），为了数据安全，自然是需要把Time Machine利用起来。而Time Machine只能备份到本地的硬盘或者AFP或者SMB或者Time Capsule。显然我没有多余的硬盘，也没有rich到来一个Time Capsule，但是我手头上恰好有一个2T HDD的大盘鸡（<s>远在天边</s>），所以想把Time Machine的备份放到这个大盘鸡里。</p>



<p>那么现在问题来了，SMB这个玩意儿的安全问题相信大家也都有所耳闻，我实在是不想把它暴露在公网上，这就需要一个VPN。正好我前几天黑五搞了一些BGP Player友好的鸡，甚至还有公网的ASN号，因此就想干脆组一个全球大内网吧。</p>



<h2 class="wp-block-heading">为什么选择Zerotier</h2>



<p>其实我一开始的想法是Wireguard，因为这玩意儿大家都在吹，也在内核主线里，可以说相当的轻量，也很flexible。但是Wireguard的问题在于它是点对点的，也就是如果没有一个管理的途径的话，每条边都需要手动操作一次，非常麻烦。有的大佬用ansible解决，<s>然而我并不会这么复杂的ansible</s>。</p>



<p>我总结了一下我对于全球大内网最主要的需求：</p>



<ul class="wp-block-list"><li><strong>无中心节点</strong>，或者说流量不能由中心节点转发</li><li><strong>轻量高效</strong>（OpenVPN什么的就免了），因为有的节点之间可以跑到千兆，如果不够轻量的话会有CPU瓶颈。</li><li><strong>配置简易</strong>，超过Wireguard的就免了</li><li><strong>确保安全</strong>，必须加密传输，稍弱一些如aes128的也可以，但是不能接受明文传输，所以VXLAN和GRE等也不满足了。</li></ul>



<p>除此之外还有一些加分项：</p>



<ul class="wp-block-list"><li>multipath，我们的VPS服务商提供的网络接入质量不尽相同，如果有一种方式可以让两个线路较差的VPS通过一个线路较好的VPS进行转发其实可以得到更好的质量。不过目前除了iBGP+自定义cost似乎没有别的方式可以达到这样的效果。</li><li>中心化的路由配置，这一项Zerotier恰好可以满足，如果我们需要桥接别的“真正的”内网，这个功能还是很实用的。</li><li>跨平台客户端，虽然目前的方案并不需要这个功能，但是如果我们以后希望将大内网进一步扩大，可能会需要这个功能。</li></ul>



<h2 class="wp-block-heading">自建VS官方</h2>



<p><s>有这么多鸡不自建也是浪费</s></p>



<p>zerotier有network controller，planet，moon等很多概念/角色，我也没搞懂，有懂的可以指点一下。自建network controller的好处在于可以避免官方的同一个网络50个客户端限制。自建moon的好处在于对称nat的情况下可以有较好的转发质量。</p>



<p>由于我们不需要考虑nat，所以就只自建network controller。</p>



<h2 class="wp-block-heading">自建方案选型</h2>



<p>由于<s>好看是第一生产力</s>手动添加网络和批准加入十分繁琐，所以需要一个GUI在网络控制器上，而不是按照官方的API使用curl来管理网络。</p>



<p>ztncui（<a href="https://github.com/key-networks/ztncui" target="_blank" rel="noreferrer noopener" title="https://github.com/key-networks/ztncui">Github</a>和<a href="https://key-networks.com/ztncui/" target="_blank" rel="noreferrer noopener" title="https://key-networks.com/ztncui/">官网</a>）是一个基于zerotier-one API的前端，提供类似于官方my.zerotier.com的管理操作，可以添加网络，管理网络和路由等。</p>



<p>其他服务器自然是使用正常的zerotier-one作为节点加入。zerotier还提供有各个嵌入式平台和路由器平台的支持，可以说十分的跨平台了。</p>



<p>还有一点，这次我希望安装的服务器是一台buyvm/frantech的512MB内存的服务器，计划之后还要在上面跑<s>鸟</s>bird，如果要收全表的话，512MB的内存可谓是捉襟见肘，所以首先排除使用docker的安装方式，尽量使用overhead比较小的安装。</p>



<h2 class="wp-block-heading">安装过程</h2>



<h3 class="wp-block-heading">Zerotier</h3>



<p>zerotier在我使用的Debian系发行版上只需要一行命令，注意需要gpg已安装，未安装的话会提示需要安装。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">curl -s https://install.zerotier.com | sudo bash</pre>



<p>如果你是安全nerd，也可以使用gpg验证脚本以后再执行，仍然是一行。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">curl -s 'https://raw.githubusercontent.com/zerotier/ZeroTierOne/master/doc/contact%40zerotier.com.gpg' | gpg --import &amp;&amp; \
if z=$(curl -s 'https://install.zerotier.com/' | gpg); then echo "$z" | sudo bash; fi</pre>



<p>安装完成以后zerotier的源就会被加入apt中，以后只需要使用apt来管理和升级即可。</p>



<h3 class="wp-block-heading">Ztncui</h3>



<p>根据其<meta charset="utf-8"><a href="https://key-networks.com/ztncui/" target="_blank" rel="noreferrer noopener" title="https://key-networks.com/ztncui/">官网</a>的说明，是采用deb打包的方式安装，需要首先下载deb的安装包，然后再安装。</p>



<p>注意！此处具有实效性，建议按照官网安装最新的包！</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">curl -O https://s3-us-west-1.amazonaws.com/key-networks/deb/ztncui/1/x86_64/ztncui_0.7.1_amd64.deb
sudo apt-get install ./ztncui_0.7.1_amd64.deb</pre>



<p>由于ztncui是使用nodejs开发的，因此还需设置一下production mode</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">sudo sh -c "echo 'NODE_ENV=production' >> /opt/key-networks/ztncui/.env"</pre>



<p>ztncui默认监听127.0.0.1:3000，可以使用以下命令转发到本地访问</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">ssh -f user@network.controller.machine -L 3333:localhost:3000 -N</pre>



<p>也可以使用以下命令打开一个https端口，没有配置的话使用的是self-signed证书，如果需要配置证书的话可以参考<a href="https://key-networks.com/ztncui/#installation" target="_blank" rel="noreferrer noopener" title="https://key-networks.com/ztncui/#installation">官方教程</a>。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">sudo sh -c "echo 'HTTPS_PORT=3443' > /opt/key-networks/ztncui/.env"</pre>



<p>最后重启ztncui是配置生效。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">sudo systemctl restart ztncui</pre>



<h2 class="wp-block-heading">网络配置</h2>



<p>这部分的配置其实比较简单，按照提示来就可以了，此处放一些截图供调研方案和选型的读者参考。</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img fetchpriority="high" decoding="async" width="529" height="255" src="https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-11.21.12-AM.png" alt="" class="wp-image-926" srcset="https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-11.21.12-AM.png 529w, https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-11.21.12-AM-300x145.png 300w" sizes="(max-width: 529px) 100vw, 529px" /><figcaption>创建网络</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img decoding="async" width="763" height="311" src="https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-11.21.29-AM.png" alt="" class="wp-image-927" srcset="https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-11.21.29-AM.png 763w, https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-11.21.29-AM-300x122.png 300w" sizes="(max-width: 763px) 100vw, 763px" /><figcaption>创建后结果</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-full"><img decoding="async" width="428" height="500" src="https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-11.21.45-AM.png" alt="" class="wp-image-928" srcset="https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-11.21.45-AM.png 428w, https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-11.21.45-AM-257x300.png 257w" sizes="(max-width: 428px) 100vw, 428px" /><figcaption>Easy setup中添加cidr</figcaption></figure></div>



<h2 class="wp-block-heading">最终效果</h2>



<p><s>辣鸡nodejs果然占内存</s> 安装完成以后大概内存占用是111MB，ztncui自己占了60MB，相对来说还可以接受。</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="940" height="139" src="https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-10.35.04-AM.png" alt="" class="wp-image-917" srcset="https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-10.35.04-AM.png 940w, https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-10.35.04-AM-300x44.png 300w, https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-10.35.04-AM-768x114.png 768w" sizes="(max-width: 940px) 100vw, 940px" /><figcaption>mtr</figcaption></figure></div>



<p>可以看到，一天的丢包率只有0.1%，我认为是可以接受的。</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="653" height="263" src="https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-10.36.31-AM.png" alt="" class="wp-image-918" srcset="https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-10.36.31-AM.png 653w, https://blog.eastonman.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-06-at-10.36.31-AM-300x121.png 300w" sizes="(max-width: 653px) 100vw, 653px" /><figcaption>iperf3</figcaption></figure></div>



<p>我的两台vps之间也能跑到比较高的速率。</p>The post <a href="https://blog.eastonman.com/blog/2021/12/zerotier/">全球大内网与Zerotier</a> first appeared on <a href="https://blog.eastonman.com">Easton Man's Blog</a>.]]></content:encoded>
					
					<wfw:commentRss>https://blog.eastonman.com/blog/2021/12/zerotier/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Bash History的使用技巧</title>
		<link>https://blog.eastonman.com/blog/2021/06/bash-history-tricks/</link>
					<comments>https://blog.eastonman.com/blog/2021/06/bash-history-tricks/#comments</comments>
		
		<dc:creator><![CDATA[Easton Man]]></dc:creator>
		<pubDate>Thu, 10 Jun 2021 14:51:35 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[Bash]]></category>
		<guid isPermaLink="false">https://blog.eastonman.com/?p=792</guid>

					<description><![CDATA[<p>Bash是常见的shell环境，大多数Linux发行版也都带有Bash，因此高效地利用history可以节省手动输入重复命令的时间。本文分享一下几个我自己使用的技巧和配置。</p>
The post <a href="https://blog.eastonman.com/blog/2021/06/bash-history-tricks/">Bash History的使用技巧</a> first appeared on <a href="https://blog.eastonman.com">Easton Man's Blog</a>.]]></description>
										<content:encoded><![CDATA[<p class="wpwc-reading-time">预计阅读时间： 3 分钟</p>
<p>Bash是常见的shell环境，大多数Linux发行版也都带有Bash，因此高效地利用history可以节省手动输入重复命令的时间。本文分享一下几个我自己使用的技巧和配置。</p>



<h3 class="wp-block-heading">搜索</h3>



<p>这个技巧大家应该多少都知道，就是在输入界面按<code>Ctrl-R</code>就可以进行搜索了，返回的结果是最近一个匹配的命令，然后按回车就可以执行。</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="526" height="220" src="https://blog.eastonman.com/wp-content/uploads/2021/06/image.png" alt="" class="wp-image-794" srcset="https://blog.eastonman.com/wp-content/uploads/2021/06/image.png 526w, https://blog.eastonman.com/wp-content/uploads/2021/06/image-300x125.png 300w" sizes="(max-width: 526px) 100vw, 526px" /><figcaption>Ctrl-R</figcaption></figure></div>



<p>但是有的时候搜索结果只是与我想要的很相近，但又不完全一样，我希望能够在执行之前对命令做小的修改，那怎么办?其实此时按Esc就可以退出并且编辑。</p>



<p>还有一个方式是利用<code>:p</code>，<code>:p</code>在Bash中表示打印但不执行，因此如果我们想要查看某个前缀的命令，就可以使用<code>!prefix:p</code>来打印。</p>



<h3 class="wp-block-heading">HISTIGNORE</h3>



<p>HISTIGNORE是一个环境变量，它指示Bash什么样的命令不要加入history中，例如这样的一个变量。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">export HISTIGNORE='pwd:exit:fg:bg:top:clear:history:ls:uptime:df'</pre>



<p>就可以把无意义的交互命令从history中去除了。如果你经常使用<code>ll</code>或者<code>la</code>这样的简写，那么把他们加入HISTIGNORE中或许是一个不错的选择。</p>



<h3 class="wp-block-heading">HISTCONTROL</h3>



<p>HISTCONTROL也是一个环境变量，它有几个选择</p>



<ul class="wp-block-list"><li>ignorespace：以空格开头的所有命令都不会加入history中</li><li>ignoredups：重复的命令不会加入history中</li><li>ignoreboth：打开以上的两个特性</li></ul>



<p>通常一些发行版已经带有ignoredups的选项，如果你想要避免某些特定的命令计入history中，那么可以打开ignorespace选项。</p>



<h3 class="wp-block-heading">并行的窗口之间的history问题</h3>



<p>这个问题相信很多同学也会有，在远程管理服务器的时候，通常为了某些监视任务或者耗时长的任务不阻塞人的操作，会使用各种窗口复用工具，比如<code>tmux</code>或者<code>screen</code>，那么由于Bash在关闭的时候才会将history写入<code>.bash_history</code>文件，那么大多数时候当我们关闭这些窗口以后就只有最后一个关闭的窗口的History被记录了下来。</p>



<p>我们可以使用</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">shopt -s histappend</pre>



<p>来指示Bash讲history附加到原本的history上而不是覆盖。</p>



<h3 class="wp-block-heading">使用!来执行history中的命令</h3>



<p>!可以用来执行命令，比如!10就是执行history中的第10条命令。当然也可以执行最近的第几条命令，比如!-3就是倒数第三条命令。</p>



<p>这里还可以结合<code>:p</code>使用，以避免直接执行带来的风险。</p>



<p>如果你一定要避免所有的风险，每次都希望检查命令再执行，而又不想输入<code>:p</code>，那么Bash还有一个选项可以做到这一点：<code>shopt -s histverify</code>。这个选项会使得所有用!执行的命令都需要按Enter键确认才会执行。</p>



<h3 class="wp-block-heading">使用上一个命令的参数</h3>



<p>!$和!*分别会将上一个命令的最后一个参数和所有参数填补到这个位置，例如</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">$ mv list.txt items.txt
$ vim !$
vim items.txt
$ cp !$ shopping.txt
cp items.txt shopping.txt</pre>



<p></p>The post <a href="https://blog.eastonman.com/blog/2021/06/bash-history-tricks/">Bash History的使用技巧</a> first appeared on <a href="https://blog.eastonman.com">Easton Man's Blog</a>.]]></content:encoded>
					
					<wfw:commentRss>https://blog.eastonman.com/blog/2021/06/bash-history-tricks/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Git: Failed sending HTTP2 data解决办法</title>
		<link>https://blog.eastonman.com/blog/2021/04/git-failed-sending-http2-data/</link>
					<comments>https://blog.eastonman.com/blog/2021/04/git-failed-sending-http2-data/#comments</comments>
		
		<dc:creator><![CDATA[Easton Man]]></dc:creator>
		<pubDate>Sun, 25 Apr 2021 12:47:30 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[Git]]></category>
		<guid isPermaLink="false">https://blog.eastonman.com/?p=556</guid>

					<description><![CDATA[<p>预计阅读时间： 5 分钟 最近一段时间发现手中的Debian机器在Git Clone的时候出现奇怪的错误，经过 [&#8230;]</p>
The post <a href="https://blog.eastonman.com/blog/2021/04/git-failed-sending-http2-data/">Git: Failed sending HTTP2 data解决办法</a> first appeared on <a href="https://blog.eastonman.com">Easton Man's Blog</a>.]]></description>
										<content:encoded><![CDATA[<p class="wpwc-reading-time">预计阅读时间： 5 分钟</p>
<p>最近一段时间发现手中的Debian机器在Git Clone的时候出现奇怪的错误，经过一番Google，最终发现是libcurl3-gnutls这个库的bug。</p>



<p></p>



<p>2021-10-01 Update: Buster-backports仍未修复此问题，但是Bullseye已经合入了新的版本，修复了此问题。</p>



<p>2021-06-19 Update: 修复补丁仍未合入backports中，问题的原因似乎是libcurl-guntls的TLSv1.3实现有问题。</p>



<p>2021-08-03 Update: Curl 7.76.1修复了此问题，但尚未合并进入Buster backports, Bullseye也未更新。</p>



<h2 class="wp-block-heading">现象</h2>



<p>在使用https协议进行git clone的时候，出现HTTP2报错</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">xxxxx$> git clone https://github.com/TechMinerApps/portier
Cloning into 'portier'...
fatal: unable to access 'https://github.com/TechMinerApps/portier/': Failed sending HTTP2 data</pre>



<p>起初我以为和GitHub即将禁止Basic Auth的https操作有关，但是使用<code>GIT_TRACE2=2 GIT_CURL_VERBOSE=1</code>进行调试的时候，发现是curl中的问题。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">20:35:22.968833 http.c:756              == Info: Couldn't find host github.com in the .netrc file; using defaults
20:35:22.973819 http.c:756              == Info:   Trying 192.30.255.113:443...
20:35:23.144791 http.c:756              == Info: Connected to github.com (192.30.255.113) port 443 (#0)
20:35:23.168789 http.c:756              == Info: found 411 certificates in /etc/ssl/certs
20:35:23.169022 http.c:756              == Info: ALPN, offering h2
20:35:23.169092 http.c:756              == Info: ALPN, offering http/1.1
20:35:23.341023 http.c:756              == Info: SSL connection using TLS1.3 / ECDHE_RSA_AES_128_GCM_SHA256
20:35:23.341674 http.c:756              == Info:         server certificate verification OK
20:35:23.341682 http.c:756              == Info:         server certificate status verification SKIPPED
20:35:23.341750 http.c:756              == Info:         common name: github.com (matched)
20:35:23.341754 http.c:756              == Info:         server certificate expiration date OK
20:35:23.341757 http.c:756              == Info:         server certificate activation date OK
20:35:23.341763 http.c:756              == Info:         certificate public key: EC/ECDSA
20:35:23.341766 http.c:756              == Info:         certificate version: #3
20:35:23.341786 http.c:756              == Info:         subject: C=US,ST=California,L=San Francisco,O=GitHub\, Inc.,CN=github.com
20:35:23.341791 http.c:756              == Info:         start date: Thu, 25 Mar 2021 00:00:00 GMT
20:35:23.341795 http.c:756              == Info:         expire date: Wed, 30 Mar 2022 23:59:59 GMT
20:35:23.341807 http.c:756              == Info:         issuer: C=US,O=DigiCert\, Inc.,CN=DigiCert High Assurance TLS Hybrid ECC SHA256 2020 CA1
20:35:23.341818 http.c:756              == Info: ALPN, server accepted to use h2
20:35:23.341851 http.c:756              == Info: Using HTTP2, server supports multi-use
20:35:23.341853 http.c:756              == Info: Connection state changed (HTTP/2 confirmed)
20:35:23.341858 http.c:756              == Info: Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
20:35:23.341866 http.c:756              == Info: Failed sending HTTP2 data
20:35:23.341873 http.c:756              == Info: Connection #0 to host github.com left intact</pre>



<p>随即Google了一番后找到了Debian Bug Tracker中的一个提交 <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=987187" target="_blank" rel="noreferrer noopener" title="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=987187">libcurl3-gnutls from debian backports breaks git http operations</a></p>



<p>原文如下，完全一模一样。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Package: libcurl3-gnutls
Version: 7.74.0-1.2~bpo10+1
Severity: important
|X-Debbugs-CC: |debian-backports@lists.debian.org

After upgrading the Debian system from "backports" any git http operations (clone/fetch ...) has stopped working, bringing libcurl3-gnutls to the previous version (7.74.0-1.2~bpo10+1) fix the problem:

Output of git command
> git clone https://github.com/git/git
Cloning into 'git'...
fatal: unable to access 'https://github.com/git/git/': Failed sending HTTP2 data
>

-- apt-cache policy libcurl3-gnutls
libcurl3-gnutls:
  Installato: 7.74.0-1.2~bpo10+1
  Candidato:  7.74.0-1.2~bpo10+1
  Tabella versione:
 *** 7.74.0-1.2~bpo10+1 100
        100 https://deb.debian.org/debian buster-backports/main amd64 Packages
        100 /var/lib/dpkg/status
     7.64.0-4+deb10u2 500
        500 https://deb.debian.org/debian-security buster/updates/main amd64 Packages
     7.64.0-4+deb10u1 500
        500 https://deb.debian.org/debian buster/main amd64 Packages

-- Extra detailed informations:
- Output of GIT_CURL_VERBOSE=1 GIT_TRACE2=1 git clone https://github.com/git/git
13:03:36.251941 common-main.c:48                  version 2.29.2
13:03:36.251960 common-main.c:49                  start git clone https://github.com/git/git
13:03:36.251981 git.c:445                         cmd_name clone (clone)
13:03:36.252185 repository.c:130                  worktree /tmp/gh/git
Clone in 'git' in corso...
13:03:36.253276 run-command.c:735                 child_start[0] git remote-https origin https://github.com/git/git
13:03:36.254468 common-main.c:48                  version 2.29.2
13:03:36.254485 common-main.c:49                  start /usr/lib/git-core/git remote-https origin https://github.com/git/git
13:03:36.254572 git.c:723                         cmd_name _run_dashed_ (clone/_run_dashed_)
13:03:36.254586 run-command.c:735                 child_start[0] git-remote-https origin https://github.com/git/git
13:03:36.259050 common-main.c:48                  version 2.29.2
13:03:36.259065 common-main.c:49                  start /usr/lib/git-core/git-remote-https origin https://github.com/git/git
13:03:36.259138 repository.c:130                  worktree /tmp/gh
13:03:36.259176 remote-curl.c:1482                cmd_name remote-curl (clone/_run_dashed_/remote-curl)
13:03:36.259581 http.c:756              == Info: Couldn't find host github.com in the .netrc file; using defaults
13:03:36.469244 http.c:756              == Info:   Trying 140.82.121.3:443...
13:03:36.520476 http.c:756              == Info: Connected to github.com (140.82.121.3) port 443 (#0)
13:03:36.544248 http.c:756              == Info: found 381 certificates in /etc/ssl/certs
13:03:36.544365 http.c:756              == Info: ALPN, offering h2
13:03:36.544371 http.c:756              == Info: ALPN, offering http/1.1
13:03:36.595957 http.c:756              == Info: SSL connection using TLS1.3 / ECDHE_RSA_AES_128_GCM_SHA256
13:03:36.596671 http.c:756              == Info: 	 server certificate verification OK
13:03:36.596680 http.c:756              == Info: 	 server certificate status verification SKIPPED
13:03:36.596778 http.c:756              == Info: 	 common name: github.com (matched)
13:03:36.596786 http.c:756              == Info: 	 server certificate expiration date OK
13:03:36.596790 http.c:756              == Info: 	 server certificate activation date OK
13:03:36.596799 http.c:756              == Info: 	 certificate public key: EC/ECDSA
13:03:36.596804 http.c:756              == Info: 	 certificate version: #3
13:03:36.596838 http.c:756              == Info: 	 subject: C=US,ST=California,L=San Francisco,O=GitHub\, Inc.,CN=github.com
13:03:36.596854 http.c:756              == Info: 	 start date: Thu, 25 Mar 2021 00:00:00 GMT
13:03:36.596868 http.c:756              == Info: 	 expire date: Wed, 30 Mar 2022 23:59:59 GMT
13:03:36.596884 http.c:756              == Info: 	 issuer: C=US,O=DigiCert\, Inc.,CN=DigiCert High Assurance TLS Hybrid ECC SHA256 2020 CA1
13:03:36.596914 http.c:756              == Info: ALPN, server accepted to use h2
13:03:36.596955 http.c:756              == Info: Using HTTP2, server supports multi-use
13:03:36.596960 http.c:756              == Info: Connection state changed (HTTP/2 confirmed)
13:03:36.596974 http.c:756              == Info: Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
13:03:36.596984 http.c:756              == Info: Failed sending HTTP2 data
13:03:36.596993 http.c:756              == Info: Connection #0 to host github.com left intact
13:03:36.597168 usage.c:64                        error impossibile accedere a 'https://github.com/git/git/': Failed sending HTTP2 data
fatal: impossibile accedere a 'https://github.com/git/git/': Failed sending HTTP2 data
13:03:36.597194 usage.c:68                        exit elapsed:0.338490 code:128
13:03:36.597203 trace2/tr2_tgt_normal.c:123       atexit elapsed:0.338501 code:128
13:03:36.598095 run-command.c:990                 child_exit[0] pid:179509 code:128 elapsed:0.343497
13:03:36.598114 git.c:745                         exit elapsed:0.343919 code:128
13:03:36.598155 trace2/tr2_tgt_normal.c:123       atexit elapsed:0.343959 code:128
13:03:36.598389 transport-helper.c:581            exit elapsed:0.346748 code:128
13:03:36.598639 trace2/tr2_tgt_normal.c:123       atexit elapsed:0.347003 code:128</pre>



<h2 class="wp-block-heading">解决方法</h2>



<p>既然是Debian官方源中的问题，那除了等官方解决以外，就只能降级这个库了。</p>



<p>降级到stable，也就是buster的命令如下。APT会自动降级有依赖关系的库，如libcurl4</p>



<p>2021-10-01 Update：Debian 11发布后Buster不再是Stable，因此在Debian 10遇到此问题需要降级到buster或者oldstable，推荐升级至Debian 11解决此问题。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Downgrade command
sudo apt reinstall libcurl3-gnutls/buster
</pre>



<p></p>The post <a href="https://blog.eastonman.com/blog/2021/04/git-failed-sending-http2-data/">Git: Failed sending HTTP2 data解决办法</a> first appeared on <a href="https://blog.eastonman.com">Easton Man's Blog</a>.]]></content:encoded>
					
					<wfw:commentRss>https://blog.eastonman.com/blog/2021/04/git-failed-sending-http2-data/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Linux内核CFS调度器的实现</title>
		<link>https://blog.eastonman.com/blog/2021/02/cfs/</link>
					<comments>https://blog.eastonman.com/blog/2021/02/cfs/#respond</comments>
		
		<dc:creator><![CDATA[Easton Man]]></dc:creator>
		<pubDate>Fri, 26 Feb 2021 14:24:47 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[CFS]]></category>
		<category><![CDATA[Kernel]]></category>
		<category><![CDATA[Scheduler]]></category>
		<guid isPermaLink="false">https://blog.eastonman.com/?p=477</guid>

					<description><![CDATA[<p>预计阅读时间： 5 分钟 本文简易而快速地介绍了Linux内核中完全公平类调度类CFS调度器的原理和实现。 原 [&#8230;]</p>
The post <a href="https://blog.eastonman.com/blog/2021/02/cfs/">Linux内核CFS调度器的实现</a> first appeared on <a href="https://blog.eastonman.com">Easton Man's Blog</a>.]]></description>
										<content:encoded><![CDATA[<p class="wpwc-reading-time">预计阅读时间： 5 分钟</p>
<p>本文简易而快速地介绍了Linux内核中完全公平类调度类CFS调度器的原理和实现。</p>



<h2 class="wp-block-heading">原理</h2>



<p>其实CFS（Completely Fair Scheduler）的核心原理很简单，就是使得每个进程都尽可能“公平”地获得运行时间。因此每次都选择过去运行得最少得进程运行。当然，作为一个调度器，它要满足的需求远不止于此。Linux的抢占式进程和在完全公平类<code>fair_sched_class</code>中支持优先级等一系列特性，使得CFS的设计变得比简单的选出运行时间最少要复杂得多。但是不要着急，我们一步一步来理解CFS的原理。</p>



<h2 class="wp-block-heading">最小运行时间</h2>



<p>为了避免过度频繁的抢占发生，Linux内核设置了每个Task（进程）的最小运行时间（或称运行时间粒度），在这个时间内，这个进程的CPU资源是不可被抢占的。除非进程主动让出CPU或者执行了阻塞的系统调用，一般而言进程都可以执行最少执行完这个时间。最小运行时间可以通过内核参数<code>sched_min_granularity_ns</code>来查看。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cat /proc/sys/kernel/sched_min_granularity_ns
3000000</pre>



<h2 class="wp-block-heading">时间片</h2>



<p>CFS通过引入权重来保证高优先级的进程能够获得更多的CPU时间，进程间按照权重比例分配时间片。调度周期内分配给进程的运行时间按照这个公式计算：</p>



<p class="has-text-align-center"><strong>运行时间tn=调度周期T * 进程权重w / 运行队列中全部进程的权重之和S</strong></p>



<p>权重是一个和nice值有关的量，现在在Linux内核中的定义位于<a href="https://github.com/torvalds/linux/blob/2c87f7a38f930ef6f6a7bdd04aeb82ce3971b54b/kernel/sched/core.c#L9516" target="_blank" rel="noreferrer noopener" title="https://github.com/torvalds/linux/blob/2c87f7a38f930ef6f6a7bdd04aeb82ce3971b54b/kernel/sched/core.c#L9516">kernel/sched/core.c#L9516</a>（文章发布时），数值如下：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const int sched_prio_to_weight[40] = {
 /* -20 */     88761,     71755,     56483,     46273,     36291,
 /* -15 */     29154,     23254,     18705,     14949,     11916,
 /* -10 */      9548,      7620,      6100,      4904,      3906,
 /*  -5 */      3121,      2501,      1991,      1586,      1277,
 /*   0 */      1024,       820,       655,       526,       423,
 /*   5 */       335,       272,       215,       172,       137,
 /*  10 */       110,        87,        70,        56,        45,
 /*  15 */        36,        29,        23,        18,        15,
};</pre>



<p>其中nice值为0的权重NICE_0_LOAD=1024，nice值每差1，权重大约差1.25倍。这里的1.25计算依据来源于nice值差1，运行时间相差10%这样的设计。</p>



<h2 class="wp-block-heading">虚拟运行时间</h2>



<p>解决完每次分配多少时间的问题后，还有一个问题需要解决，就是下一个运行的进程是谁？CFS实现的原则是“完全的公平”，那么高优先级的进程如何保证多一点的运行时间？这就要引入一个概念，叫“虚拟运行时间”了。假设我们希望有如下的情况出现：</p>



<p class="has-text-align-center"><strong>高优先级进程运行15ms=低优先级运行5ms</strong></p>



<p>那么我们就将这个相等的量设置为一个“虚拟运行时间”，这样就可以保证高优先级进程运行的时间几乎总是低优先级的3倍。在Linux中，这个虚拟运行时间与实际运行时间的关系就是刚刚提到的权重：</p>



<p class="has-text-align-center"><strong>虚拟运行时间=真实运行时间 * NICE_0_LOAD / 进程的权重</strong></p>



<p>Linux在调度元素中定义了vruntime变量（<a href="https://github.com/torvalds/linux/blob/66f73fb3facd42d0a7c899d7f4c712332b28499a/include/linux/sched.h#L453" target="_blank" rel="noreferrer noopener" title="https://github.com/torvalds/linux/blob/66f73fb3facd42d0a7c899d7f4c712332b28499a/include/linux/sched.h#L453">include/linux/sched.h#L453</a>），用于记录进程的累计虚拟运行时间，代码如下：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="c" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">struct sched_entity {
	/* For load-balancing: */
	struct load_weight		load;
	struct rb_node			run_node;
	struct list_head		group_node;
	unsigned int			on_rq;

	u64				exec_start;
	u64				sum_exec_runtime;
	u64				vruntime;
	u64				prev_sum_exec_runtime;

	u64				nr_migrations;

	struct sched_statistics		statistics;
        ...
}</pre>



<p>进程每次运行完毕后就会更新vruntime变量，至于如何挑选出vruntime最少的进程，这将由红黑树完成。</p>



<h2 class="wp-block-heading">红黑树</h2>



<p>红黑树是一种自平衡的二叉树，最左的叶子节点永远是key最小的节点。红黑树通过插入（更新）和删除时的操作保证这些原子操作之间红黑树永远是平衡的。</p>



<p>具体的操作参见<a href="https://www.jianshu.com/p/e136ec79235c" title="https://www.jianshu.com/p/e136ec79235c">https://www.jianshu.com/p/e136ec79235c</a></p>



<p>内核将调度队列上的进程按照vruntime排列成红黑树，这样选取最小vruntime的进程就变为了简单地选出最左边的叶子节点了。</p>



<h2 class="wp-block-heading">最小vruntime</h2>



<p>内核除了红黑树以外还维护一个min_vruntime变量，以记录此时最小的虚拟运行时间。</p>



<p>为什么需要这个min_vruntime？我们设想以下几种状况：</p>



<ul class="wp-block-list"><li>新的进程加入了红黑树，那么它的vruntime应当是多少？</li><li>休眠了10万年的进程等待到了它要求的事件，现在被唤醒了，它还保持原有的vruntime吗？</li><li>进程被负载均衡迁移到另一个CPU上（另一个调度队列），那么它的vruntime如何改变？</li></ul>



<p>由此可以看出，min_vruntime的作用就是帮助Linux内核解决这些情况。</p>



<h2 class="wp-block-heading">深入阅读</h2>



<ul class="wp-block-list"><li><a href="https://github.com/torvalds/linux/tree/master/kernel/sched" target="_blank" rel="noreferrer noopener" title="https://github.com/torvalds/linux/tree/master/kernel/sched">https://github.com/torvalds/linux/tree/master/kernel/sched</a></li><li><a href="https://www.kernel.org/doc/html/latest/scheduler/sched-design-CFS.html" target="_blank" rel="noreferrer noopener" title="https://www.kernel.org/doc/html/latest/scheduler/sched-design-CFS.html">https://www.kernel.org/doc/html/latest/scheduler/sched-design-CFS.html</a></li><li>有意思的BFS<a href="https://www.utappia.org/2012/02/bfs-vs-cfs-some-personal-observations.html" target="_blank" rel="noreferrer noopener" title="https://www.utappia.org/2012/02/bfs-vs-cfs-some-personal-observations.html">https://www.utappia.org/2012/02/bfs-vs-cfs-some-personal-observations.html</a></li></ul>



<p></p>The post <a href="https://blog.eastonman.com/blog/2021/02/cfs/">Linux内核CFS调度器的实现</a> first appeared on <a href="https://blog.eastonman.com">Easton Man's Blog</a>.]]></content:encoded>
					
					<wfw:commentRss>https://blog.eastonman.com/blog/2021/02/cfs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
