GitHub
2022-11-17
https://github.com/topics/static-site-generator
GitHub 搜索了一下,知名的静态网站生成器,大部分是 JS/TS 写的。
社区上经常见到的一些项目有 JS 的 Hexo
,Ruby 的 Jekyll
,Go 的 Hugo
。
JavaScript
- gatsbyjs/gatsby
The fastest frontend for the headless web. Build modern websites with React.
- hexojs/hexo
A fast, simple & powerful blog framework, powered by Node.js.
- vuejs/vuepress
📝 Minimalistic Vue-powered static site generator
- netlify/netlify-cms
A Git-based CMS for Static Site Generators
- 11ty/eleventy
A simpler static site generator. An alternative to Jekyll. Transforms a directory of templates (of varying types) into HTML.
- react-static/react-static
⚛️ 🚀 A progressive static site generator for React.
- gridsome/gridsome
⚡️ The Jamstack framework for Vue.js
- metalsmith/metalsmith
An extremely simple, pluggable static site generator.
- getgridea/gridea
✍️ A static blog writing client (一个静态博客写作客户端)
- GetPublii/Publii
Publii is a desktop-based CMS for Windows, Mac and Linux that makes creating static websites fast and hassle-free, even for beginners.
Python
- mkdocs/mkdocs
Project documentation with Markdown.
- getpelican/pelican
Static site generator that supports Markdown and reST syntax. Powered by Python.
Ruby
- jekyll/jekyll
:globe_with_meridians: Jekyll is a blog-aware static site generator in Ruby
Rust
- getzola/zola
A fast static site generator in a single binary with everything built-in. https://www.getzola.org
Go
- gohugoio/hugo
The world’s fastest framework for building websites.
Pipenv
2022-11-13
~/.local/lib/python3.10/site-packages/pkg_resources/__init__.py:123: PkgResourcesDeprecationWarning: 1.1build1 is an invalid version and will not be supported in a future release
warnings.warn(
~/.local/lib/python3.10/site-packages/pkg_resources/__init__.py:123: PkgResourcesDeprecationWarning: 0.1.43ubuntu1 is an invalid version and will not be supported in a future release
warnings.warn(
~/.local/lib/python3.10/site-packages/pkg_resources/__init__.py:123: PkgResourcesDeprecationWarning: 2.9.0.Odd.Olm is an invalid version and will not be supported in a future release
warnings.warn(
Pipenv 最近执行命令的时候会有这些提示,看这个意思是检测了一些 Python 包的版本不被支持。
用 traceback 排查之后,确认是在 Python PATH 下检查所有包的版本。
出问题的三个包是:
- distro-info
<LegacyVersion('1.1build1')> /usr/lib/python3/dist-packages
- python-debian
<LegacyVersion('0.1.43ubuntu1')> /usr/lib/python3/dist-packages
- Shredder
<LegacyVersion('2.9.0.Odd.Olm')> /usr/lib/python3/dist-packages
查找路径:
~/.local/lib/python3.10/site-packages/pipenv/patched
~/.local/lib/python3.10/site-packages/pipenv/vendor
~/Projects/Mine/staticize
/usr/lib/python310.zip
/usr/lib/python3.10
/usr/lib/python3.10/lib-dynload
~/.local/lib/python3.10/site-packages
~/.local/lib/python3.10/site-packages/mackup-0.8.33-py3.10.egg
/usr/local/lib/python3.10/dist-packages
/usr/lib/python3/dist-packages
相关代码:
File "~/.local/lib/python3.10/site-packages/pkg_resources/__init__.py", line 997, in __init__
self.scan(search_path)
File "~/.local/lib/python3.10/site-packages/pkg_resources/__init__.py", line 1030, in scan
self.add(dist)
File "~/.local/lib/python3.10/site-packages/pkg_resources/__init__.py", line 1050, in add
dists.sort(key=operator.attrgetter('hashcmp'), reverse=True)
File "~/.local/lib/python3.10/site-packages/pkg_resources/__init__.py", line 2623, in hashcmp
self.parsed_version,
File "~/.local/lib/python3.10/site-packages/pkg_resources/__init__.py", line 2671, in parsed_version
self._parsed_version = parse_version(self.version)
File "~/.local/lib/python3.10/site-packages/pkg_resources/__init__.py", line 122, in parse_version
print(''.join(traceback.format_stack()))
HTTPS TLS 信息安全
2022-11-11
HTTPS = HTTP + TLS
原来是 TCP -> HTTP
现在是 TCP -> TLS -> HTTP
提升了安全性的同时,降低了一些性能。
更重要的是,互联网基础设施层面开始淘汰 HTTP:
- 包括谷歌在内的浏览器厂商将使用 HTTP 访问的网站标记为不安全网站,Google 还会降低 HTTP 网站的排名。
- 其他平台,比如苹果 App Store,微信小程序等,都要求使用 HTTPS 协议。
1、怎么提升安全性
- 加密数据传输: TLS 数据加密,难以被窃听和解密。即使攻击者能够截获传输的数据包,他们也不能轻易读取其中的内容。
- 身份验证: 受信任的第三方机构颁发的 TLS 证书,可以用来验证服务器身份。
- 完整性验证: 使用消息摘要算法(如 SHA-256)来验证数据的完整性,防止数据被篡改(中间人攻击)。
2、降低了多少性能
相关通信过程在 2021/01/08,了解 HTTPS 背后的原理 有描述。
损耗主要在哪些环节呢?
- 握手
- 加密、解密
- 数据传输(加密之后数据增大)
- 证书验证 - 优化:浏览器缓存证书
3、如何优化
参考 HTTPS 的资源消耗,针对消耗点进行优化。
4、工具
5、清单
在 2012 年的 RFC 6797 中,HTTP 严格传输安全被定义为网络安全标准。 创建这个标准的主要目的,是为了。
个人
2022-11-11
公司曾经强调过在内外交流中区分客户和用户,不要混用。今天突然想到这个问题,特意来仔细琢磨一下。
公司的定义
我记得大概是说:
- 客户:购买我们产品的人
- 用户:客户使用我们产品服务的对象,也就是客户的客户
我们提供的是消息触达服务(邮件和短信),落到产品中,基础功能可以免费使用(定量),增值功能需要收费。这是背景。
在这个过程中,客户是付费的部分,用户是客户发送消息的接收方。
作为内部规范,怎么定义都行,上面怎么说就怎么来。
但我私下越细琢磨越觉得不太对味,不严谨:
- 免费使用的这些人,是我们的什么?
- 消息接收方一定向客户付费么?
我认为
-
客户和用户
-
客户,这描述的是商务关系,认为是购买产品的人,没毛病。
- 用户,应该是使用我们产品的人,也就是我们的服务对象。
我在网上找了一遍,大概都是这个意思。和我对这个两个词语义上的理解是吻合的。
-
客户内部的角色
-
决策人(KP)
- 购买人/付款人
- 使用人
他们应该整体作为一个客户,不能区分开来,认为是决策人,或者购买人是客户,使用人是用户。
比如爸爸为孩子挑选了一款平板电脑,妈妈付钱,孩子使用。在平板电脑公司来看,应该认为他们是一个整体,然后找到 KP 做营销,告知这款平板多么利于学习,价格多么合适,还有最后一天的节日优惠。然后为了企业的品牌形象与二次营销,应该提升产品的质量和使用体验(持续更新的学习资料 + 游戏性能)。
- 客户使用我们的产品去通知也好,去营销也好,这些消息的接收方,应该叫做我们服务的影响人(我找不到更好的词)。
通过上面的定义,我们应该很容易理解下面几个观点:
- 仅根据是不是有商务关系(付钱)判断是不是客户。
- 用户分成免费用户、付费用户。免费用户一定不是客户,付费用户也不一定是客户。
- 免费用户:仅在免费额度范围内使用基础服务、部分产品提供的免费试用。
- 因为可能是客户购买之后提供给他使用的。
- 我以前做过的一款产品就是客户购买之后,客户的客户使用。
- 又比如,周黑鸭、良品铺子,每年有不少公司买他们的产品用来送人。那么他们的客户是这些购买的公司,接受这些礼品的就是用户了。
因为日常生活中,很多时候,客户(购买者)往往就是用户(使用者),我们才容易搞混。
在一些业务场景下,我们客户假定购买者就是使用者,那么付费用户也可以说成是付费客户。
免费用户不能说免费客户。
产品和服务
在写这篇文章的时候,我又想起另一个概念来了,我们是提供产品,还是提供服务?
如果没记错,在内部会议上讨论过,老板阐述了自己的观点。
当时的讨论内容我忘了,我这里就说说我现在的想法。
还是上面的例子,我买周黑鸭送给了客户,客户转手把周黑鸭送给朋友吃了。
周黑鸭的客户是我,没有问题。周黑鸭的用户是谁?
如果按照提供产品的观点,最后产品被老板的朋友吃了,那么老板的朋友是用户。
周黑鸭应该为我提供体面又具有性价比的产品,同时为最后吃到鸭脖子的人提供美味(产品体验)。
如果按照提供服务的理念,周黑鸭公司提供的是礼品服务,那么是我在使用这个服务,所以我既是客户,又是用户。
周黑鸭应该为我提供体面又具有性价比的礼品服务,同时为我提供最好的送礼效果(产品体验),就是让我的客户收到礼物之后觉得满意,然后我和客户的友好度 +1。
这个例子可能不太恰当,但是我想表达的意思都说清楚了。
Linux
2022-11-10
我们编写程序 write 数据到文件中时,其实数据不会立马写入磁盘,而是会经过层层缓存。每层缓存都有自己的刷新时机,每层缓存都刷新后才会写入磁盘。这些缓存的存在是为了加速读写操作,因为如果每次读写都对应真实磁盘操作,那么读写的效率会大大降低。带来的坏处是如果期间发生掉电或者别的故障,还未写入磁盘的数据就丢失了。对于数据安全敏感的应用,比如数据库,比如交易程序,这是无法忍受的。所以操作系统提供了保证文件落盘的机制。我们来看下这些机制的原理和使用。
编程语言 Clang
2022-10-31
英文原文:https://levelup.gitconnected.com/why-modern-alternative-languages-never-replace-c-c-cbf0afc5f1dc
中文翻译:https://mp.weixin.qq.com/s/tr69w96gOO7ia81ttilgVA
总结一下:
- C/C 是优秀的系统级编程语言,无数基础设施是用 C/C 开发的
- C/C++ 可以完全控制机器,开发者拥有最大的灵活性
- C/C++ 性能非常好
- C/C++ 学术友好,简单,高效,直接(没有封装得很抽象)
- 所有操作系统提供 C API,其他语言也都提供了和 C 交互的方式
开发者
2022-10-31
发现一个问题,暂时没有任何思路:
一个线上执行了 66 天的服务,突然在前天凌晨 1:30 没有日志输出了,从外网连接不上,内网可以连上。
等后续有了进展再更新。
Golang DNS
2022-10-30
A 记录
package main
import (
"fmt"
"net"
)
func main() {
// 方法 1
// func ResolveIPAddr(network, address string) (*IPAddr, error)
ipAddr, err := net.ResolveIPAddr("ip", "www.google.com")
if err != nil {
fmt.Println("解析IP地址失败:", err)
} else {
fmt.Println("IP地址是:", ipAddr.IP)
}
// 方法 2
// func LookupMX(name string) ([]*MX, error)
// func LookupTXT(name string) ([]string, error)
// func LookupIP(host string) ([]IP, error)
// func LookupHost(host string) ([]string, error) // only IPv4
ips, err := net.LookupHost("www.google.com")
if err != nil {
fmt.Println("解析主机名失败:", err)
} else {
for _, ip := range ips {
fmt.Println("IP地址是:", ip)
}
}
}
MX 记录
package main
import (
"fmt"
"net"
)
func main() {
records, err := net.LookupMX("qq.com")
if err != nil {
fmt.Println("解析MX记录失败:", err)
} else {
fmt.Printf("%#v", records)
}
}
指定 DNS 服务器
func queryMX(dns string, domain string) ([]*net.MX, error) {
resolver := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
dialer := &net.Dialer{}
return dialer.DialContext(ctx, "udp", dns)
},
}
return resolver.LookupMX(context.Background(), domain)
}
完整版本
package main
import (
"context"
"fmt"
"net"
"strings"
"time"
)
var dnsServers = []string{
"223.5.5.5:53",
"114.114.114.114:53",
"8.8.8.8:53",
}
type IPType int
const (
NotIP IPType = iota
IPv4
IPv6
)
const (
DNSLookupTimeout = 500 * time.Millisecond // time.Duration
)
func GetIPType(host string) IPType {
ip := net.ParseIP(host)
if ip == nil {
return NotIP
}
if ip.To4() != nil {
return IPv4
}
if ip.To16() != nil {
return IPv6
}
return NotIP
}
type Resolver struct {
DNS string
Resolver *net.Resolver
}
func NewResolver(dns string) Resolver {
resolver := Resolver{}
resolver.DNS = dns
resolver.Resolver = &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
dialer := &net.Dialer{}
return dialer.DialContext(ctx, "udp", dns)
},
}
return resolver
}
func (r Resolver) QueryA(domain string) ([]string, error) {
return r.Resolver.LookupHost(context.Background(), domain)
}
func (r Resolver) QueryMX(domain string) ([]*net.MX, error) {
ctx, cancel := context.WithTimeout(context.Background(), DNSLookupTimeout)
defer cancel()
return r.Resolver.LookupMX(ctx, domain)
}
func (r Resolver) Query(domain string) ([]*net.MX, error) {
addrs, err := r.QueryMX(domain)
if err != nil {
return nil, err
}
var result []*net.MX
for _, addr := range addrs {
// hostname := strings.TrimRight(addr.Host, ".")
ipType := GetIPType(addr.Host)
fmt.Printf("%s: %#v\n", addr.Host, ipType)
if ipType == NotIP {
ips, err := r.QueryA(addr.Host)
if err != nil {
continue
}
for _, ip := range ips {
result = append(result, &net.MX{Host: ip, Pref: addr.Pref})
}
}
}
return result, nil
}
var resolvers map[string]Resolver
func Query(domain string) ([]*net.MX, error) {
var addrs []*net.MX
var err error
for _, dns := range dnsServers {
var r Resolver
if r, ok := resolvers[dns]; !ok {
r = NewResolver(dns)
resolvers[dns] = r
}
addrs, err = r.Query(domain)
if err == nil {
break
}
fmt.Printf("Error: %s: %s: %#v\n", dns, domain, err)
}
return addrs, err
}
func QueryAsync(domain string, ch chan<- []*net.MX, errCh chan<- error) {
addrs, err := Query(domain)
if err != nil {
errCh <- err
return
}
ch <- addrs
}
func init() {
resolvers = make(map[string]Resolver)
}
func main() {
{
domains := []string{"qq.com", "gmail.com", "google.com"}
for _, domain := range domains {
fmt.Println(strings.Repeat("=", 100))
addrs, err := Query(domain)
if err != nil {
fmt.Printf("Error: %#v\n", err)
} else {
for _, addr := range addrs {
fmt.Printf("%#v\n", addr)
}
}
}
}
{
fmt.Println(strings.Repeat("=", 100))
ch := make(chan []*net.MX)
errCh := make(chan error)
go QueryAsync("google.com", ch, errCh)
select {
case addrs := <-ch:
fmt.Println("MX Records:")
for _, addr := range addrs {
fmt.Printf("%#v\n", addr)
}
case err := <-errCh:
fmt.Println("Error:", err)
}
}
}
个人
2022-10-27
CSDN 会拦截复制,提示需要登录。
近日在网上学到一招,在控制台输入一行代码就好了:
document.designMode = "on";
计算机网络
2022-10-27
git clone git@github.com:tornado/tornado
Cloning into 'tornado'...
ssh: connect to host github.com port 22: Connection refused
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
ping github.com
正在 Ping github.com [::1] 具有 32 字节的数据:
来自 ::1 的回复: 时间<1ms
来自 ::1 的回复: 时间<1ms
来自 ::1 的回复: 时间<1ms
::1 的 Ping 统计信息:
数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 0ms,最长 = 0ms,平均 = 0ms
Control-C
ping -4 github.com
正在 Ping github.com [127.0.0.1] 具有 32 字节的数据:
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=64
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=64
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=64
127.0.0.1 的 Ping 统计信息:
数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 0ms,最长 = 0ms,平均 = 0ms
Control-C
nslookup github.com
Server: 192.168.31.1
Address: 192.168.31.1#53
Non-authoritative answer:
Name: github.com
Address: 127.0.0.1
Name: github.com
Address: ::1
配置 DNS 为 AliDNS 223.5.5.5
,233.6.6.6
:
nslookup github.com
Server: 223.5.5.5
Address: 223.5.5.5#53
Non-authoritative answer:
Name: github.com
Address: 20.205.243.166
问题依旧。
ping 20.205.243.166
正在 Ping 20.205.243.166 具有 32 字节的数据:
请求超时。
请求超时。
请求超时。
20.205.243.166 的 Ping 统计信息:
数据包: 已发送 = 3,已接收 = 0,丢失 = 3 (100% 丢失),
Control-C
ping baidu.com
正在 Ping baidu.com [39.156.66.10] 具有 32 字节的数据:
来自 39.156.66.10 的回复: 字节=32 时间=23ms TTL=52
来自 39.156.66.10 的回复: 字节=32 时间=24ms TTL=52
来自 39.156.66.10 的回复: 字节=32 时间=23ms TTL=52
39.156.66.10 的 Ping 统计信息:
数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 23ms,最长 = 24ms,平均 = 23ms
Control-C
总结:
- hosts 没有特殊配置
- 改成可用 DNS,问题没有修复
ipconfig /flushdns
也不管用
- 重启也没有好
那就奇怪了,这个 ping 里面的本地回环地址是哪里来的呢?
最后,
ipconfig /displaydns
可以看到,还是用的回环地址
ipconfig /all
发现还有一个 DNSv6 配置。。。
DNSv6 设置成 AliDNS 的 IPv6 地址:2400:3200::1
,2400:3200:baba::1
再试,
ping github.com
正在 Ping github.com [20.205.243.166] 具有 32 字节的数据:
请求超时。
请求超时。
请求超时。
请求超时。
20.205.243.166 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 0,丢失 = 4 (100% 丢失),
终于好了。😂
事情的起源是 git clone 失败,最后 git clone 可以了。
ping 不通,可能是网络问题,也可能是 github 网络配置。
这就不管了。