个人
2024-01-20
最新一期《开发者周刊》上有一个言论击中我了:
有一个名词叫做"报复性熬夜",指的是有些人明明在白天疲劳不堪,晚上却不愿意早睡,宁愿在床上玩手机。
这是因为他们控制不了自己的生活,通过在晚上推迟睡觉,获得一点自己掌控时间的自由感。
-- 《报复性熬夜》
我也一直持差不多的观点,白天太多事了,工作的、家庭的,这些时间并不属于我自己,直到晚上、半夜,一片寂静中,才有片刻时间真正可以自由支配。
坐在沙发上,坐在马桶上,抑或躺在床上,刷刷抖音,打打代码。
百度百科对熬夜是这样定义的:
熬夜,汉语词语,意为深夜还不睡。泛指因事通宵或至深夜忍困不眠。出自《清平山堂话本·快嘴李翠莲记》。
熬夜是一种现代生活经常听到或者做到的一种现象,是一种危害人的身体的不良习惯,可导致一些疾病,降低效率。熬夜是不良习惯的一种,容易缺乏内源氧。
报复性熬夜,原文中讲的都是一些老生常谈的内容,伤害身体之类,只有 “获得一点自己掌控时间的自由感” 这一句话表达得非常精彩,比我之前的表达更准确。
熬夜自然是伤身体的,这每个人都知道。
挤出来的这点时间感觉才是真正的休息,从各种角色中抽身出来,做做自己。
难以抵抗这片刻自由的诱惑啊!
开发者
2024-01-18
公众号 Python 集中营发了一篇文章《盘点即将消失的五种编程语言!》,介绍了 Ruby、VB、Perl、Delphi、Haskell 这 5 种语言。
消失不消失我不知道,这里对这几种语言做个简单了解。
服务器
2024-01-17
基础环境
- Debian 操作系统
- MariaDB 集群方案、数据同步、备份与恢复
- MongoDB 集群方案
- Redis 集群方案
- Redis Cluster
- Codis Cluster
- 如果考虑内存成本,又没有那么高的性能要求,可以改用基于磁盘的 Redis 兼容服务作为替代
- PocketMQ 集群方案
- HAProxy + Keepalived
Web 服务器
- Nginx
- 后端:Golang / Python / PHP / Java / Node.js
- CDN、云存储
其他
- 通用管理后台
- 分布式任务系统
- S3 存储
- 推送系统(邮件、短信等)
Golang
2024-01-12
后期优化:
- items 按照链表的方式组织起来,按过期时间排序,加快清理速度。
或者另外设计一个数据结构,存储缓存过期时间。
放弃每次 Get 的时候判断是否过期。
package main
import (
"fmt"
"sync"
"time"
)
type CacheItem struct {
key string
value interface{}
expiration time.Time
}
type Cache struct {
items map[string]CacheItem // 缓存项
mu sync.Mutex // 锁保护并发读写
cleanupInterval time.Duration // 清理缓存的时间间隔
}
// 创建一个新的缓存实例
func NewCache(cleanupInterval time.Duration) *Cache {
c := &Cache{
items: make(map[string]CacheItem),
cleanupInterval: cleanupInterval,
}
// 启动后台清理任务
go c.startCleanup()
return c
}
// 启动后台定期清理过期缓存的任务
func (c *Cache) startCleanup() {
ticker := time.NewTicker(c.cleanupInterval)
for {
<-ticker.C
c.cleanUpExpiredItems()
}
}
// 清理过期缓存项
func (c *Cache) cleanUpExpiredItems() {
c.mu.Lock()
defer c.mu.Unlock()
// 清理有过期时间的缓存项
for key, item := range c.items {
if time.Now().After(item.expiration) {
delete(c.items, key)
}
}
// 打印清理日志(可以根据需要调整)
fmt.Println("Expired cache items cleaned up")
}
// 添加缓存项,支持过期时间
func (c *Cache) Set(key string, value interface{}, expiration time.Time) {
c.mu.Lock()
defer c.mu.Unlock()
c.items[key] = CacheItem{key: key, value: value, expiration: expiration}
}
// 获取缓存项
func (c *Cache) Get(key string) (interface{}, bool) {
c.mu.Lock()
defer c.mu.Unlock()
// 再检查有过期时间的缓存项
if item, found := c.items[key]; found {
// if item.expiration.IsZero() || time.Now().Before(item.expiration) {
// return item.value, true
// }
// // 如果缓存项已过期,则删除并返回未找到
// delete(c.items, key)
return item.value, true
}
return nil, false
}
// 删除缓存项
func (c *Cache) Delete(key string) {
c.mu.Lock()
defer c.mu.Unlock()
delete(c.items, key)
}
func main() {
// 创建一个缓存实例,每 1 秒清理一次过期缓存
cache := NewCache(1 * time.Second)
// 设置缓存项(带过期时间)
cache.Set("key1", "value1", time.Now().Add(5*time.Second))
// 设置没有过期时间的缓存项
cache.Set("key2", "value2", time.Time{}) // 空时间表示永不过期
// 获取缓存项
if value, found := cache.Get("key1"); found {
fmt.Println("Found key1:", value)
} else {
fmt.Println("key1 not found")
}
if value, found := cache.Get("key2"); found {
fmt.Println("Found key2:", value)
} else {
fmt.Println("key2 not found")
}
// 等待 6 秒后,key1 会过期
time.Sleep(6 * time.Second)
// 再次获取缓存项
if value, found := cache.Get("key1"); found {
fmt.Println("Found key1:", value)
} else {
fmt.Println("key1 not found (after expiration)")
}
if value, found := cache.Get("key2"); found {
fmt.Println("Found key2:", value)
} else {
fmt.Println("key2 not found")
}
// 让清理任务继续运行
select {}
}
个人
2024-01-11
开发者
2023-12-28
Email
2023-12-25
- 退订
- FBL 举报
- 运营商反馈
- 收件人反馈(投诉)
- 地址不存在
- 邮箱容量已满
- 平台或客户手动指定的域名或地址
- 第三方提供的黑名单地址
有些是永久禁止,有些是临时禁止(比如一个月、三个月、半年)。
Windows
2023-12-23

触摸板
- 单指:点击,双击,双击拖动
- 双指:滚动,点击(鼠标右键),捏合(缩放场景)
- 三指:
- 上、下:多任务视图/显示桌面
- 左、右:切换应用
- 点击:搜索
- 四指:
- 上、下:多任务视图/显示桌面(调整为:最大化窗口/最小化窗口)
- 左、右:切换桌面
- 点击:通知中心
快捷键
TAB
按键 |
作用 |
Win + Tab |
多任务视图 |
Alt + Tab |
切换应用 |
Alt + Ctrl + Tab |
应用切换(应用选择) |
任务栏应用
按键 |
作用 |
Win + Num |
启动任务栏应用/窗口切换 |
Win + Ctrl + Num |
启动任务栏应用/窗口切换(有点不一样) |
Win + Shift + Num |
启动任务栏应用(新窗口) |
Win + Shift + Alt + Num |
启动任务栏应用(管理员权限) |
Win + Alt + Num |
任务栏应用菜单 |
浏览器
2023-12-12

OpenSSL HTTPS SMTP TLS
2023-12-10
HTTPS
echo | openssl s_client -connect sendcloud.net:443
echo | openssl s_client -showcerts -connect sendcloud.net:443
echo | openssl s_client -showcerts -debug -connect sendcloud.net:443 >/dev/null
echo | openssl s_client -showcerts -debug -connect sendcloud.net:443 2>/dev/null | openssl x509 -inform pem -noout -text
# 导出证书
openssl s_client -connect sendcloud.net:443 </dev/null | openssl x509 -outform pem > sendcloud.net.cer
# 导出所有证书
openssl s_client -showcerts -connect sendcloud.net:443 </dev/null | sed -n '/-----BEGIN/,/-----END/p' > sendcloud.net.cer
# 查看证书信息
openssl s_client -showcerts -connect sendcloud.net:443 </dev/null | sed -n '/-----BEGIN/,/-----END/p' | openssl x509 -noout -text
# 查看证书链上所有证书信息
OLDIFS=$IFS; IFS=':' certs=$(openssl s_client -showcerts -connect sendcloud.net:443 2>/dev/null </dev/null | sed -n '/-----BEGIN/,/-----END/{/-----BEGIN/ s/^/:/; p}'); for cert in ${certs#:}; do echo $cert | openssl x509 -noout -text; done; IFS=$OLDIFS
# # 查看证书链上所有证书 OCSP URI
OLDIFS=$IFS; IFS=':' certs=$(openssl s_client -showcerts -connect sendcloud.net:443 2>/dev/null </dev/null | sed -n '/-----BEGIN/,/-----END/{/-----BEGIN/ s/^/:/; p}'); for cert in ${certs#:}; do echo $cert | openssl x509 -noout -ocsp_uri; done; IFS=$OLDIFS
# -ocsp_uri
# -serial
# -fingerprint
# -subject
# 检查证书在 30 天之后有没有过期
openssl s_client -connect sendcloud.net:443 2>/dev/null </dev/null | openssl x509 -outform pem | openssl x509 -noout -checkend 2592000
# -checkend intmax Check whether the cert expires in the next arg seconds
# -checkhost val Check certificate matches host
# -checkemail val Check certificate matches email
# -checkip val Check certificate matches ipaddr
echo | openssl s_client -verify_hostname baidu.com -connect sendcloud.net:443 1>/dev/null
SMTP
一样的,只是加 -starttls smtp
。
echo | openssl s_client -connect smtp.sendcloud.net:25 -starttls smtp
echo | openssl s_client -connect smtp.sendcloud.net:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -text
其他
校验证书
# echo | openssl s_client -connect smtp.sendcloud.net:25 -starttls smtp 2>/dev/null | openssl verify
# echo | openssl s_client -showcerts -connect smtp.sendcloud.net:25 -starttls smtp 2>/dev/null | openssl verify
echo | openssl s_client -showcerts -connect smtp.sendcloud.net:25 -starttls smtp 2>/dev/null | sed -n '/-----BEGIN/,/-----END/p' > smtp.sendcloud.net.cer
openssl verify -CAfile smtp.sendcloud.net.cer smtp.sendcloud.net.cer
IMAP
echo | openssl s_client -connect imap.126.com:143 -starttls imap
测试 TLS 1.3 支持
echo | openssl s_client -connect smtp.sendcloud.net:25 -starttls smtp -tls1_3
OCSP 检测
用上面的 sendcloud.net.cer 举例,需要将文件中第一个证书和下面的其他证书拆开,分成 sendcloud.cer 和 chain.cer
openssl x509 -noout -ocsp_uri -in sendcloud.cer
# http://ocsp.sectigo.com
openssl ocsp -issuer chain.cer -cert sendcloud.cer -text -url http://ocsp.sectigo.com
# Error querying OCSP responder
# 140052849842064:error:27076072:OCSP routines:PARSE_HTTP_LINE1:server response error:ocsp_ht.c:314:Code=400,Reason=Bad Request
遇到上面报错是因为 OSCP 客户端使用 HTTP 1.0,但是服务器端现在都是 1.1,需要 Host 头。
$ openssl ocsp -issuer chain.cer -cert sendcloud.cer -text -url http://ocsp.sectigo.com -header "HOST" "ocsp.sectigo.com"
OCSP Request Data:
Version: 1 (0x0)
Requestor List:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 21F3459A10CAA6C84BDA1E3962B127D5338A7C48
Issuer Key Hash: 17D9D6252767F931C24943D93036448C6CA94FEB
Serial Number: DB5F1FFAFFB770CA38E8120A6121852E
Request Extensions:
OCSP Nonce:
0410F47624DDB17E9703BFCDCC96E983018B
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: 17D9D6252767F931C24943D93036448C6CA94FEB
Produced At: Dec 9 07:52:17 2023 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 21F3459A10CAA6C84BDA1E3962B127D5338A7C48
Issuer Key Hash: 17D9D6252767F931C24943D93036448C6CA94FEB
Serial Number: DB5F1FFAFFB770CA38E8120A6121852E
Cert Status: good
This Update: Dec 9 07:52:17 2023 GMT
Next Update: Dec 16 07:52:16 2023 GMT
Signature Algorithm: sha256WithRSAEncryption
5f:65:bf:3e:d1:8c:16:63:76:bc:83:82:b8:a3:67:54:1d:26:
78:e1:b9:7f:64:c7:61:bc:40:0d:4b:b0:7f:49:29:bc:38:48:
43:87:a5:dd:a1:e6:b4:74:ce:58:44:24:30:c3:0d:f5:ab:da:
8c:f9:25:0e:3e:e2:fe:5a:64:5f:32:d9:f5:15:6f:0c:0c:89:
97:30:f6:6c:07:56:6e:54:81:4f:d3:22:1f:16:94:a0:2b:99:
49:2f:2c:0f:c8:b7:b4:90:2f:60:01:54:9c:f9:34:c0:c6:e1:
09:3f:93:d4:dd:a7:0b:34:bb:cb:4b:06:c3:5a:8c:fc:dc:85:
4f:9d:a7:08:c3:22:98:06:b8:b9:d4:47:51:9c:36:43:f3:53:
db:f5:d1:2f:4c:a6:97:c7:5a:f5:15:04:c4:94:a4:9e:95:4c:
03:fd:5a:60:b8:4c:75:e8:02:74:e4:80:1c:8f:17:85:8a:a2:
9e:b9:5d:74:4a:2e:7d:9f:5e:d8:40:6b:60:63:74:3f:dc:11:
d4:f6:b4:86:6e:6b:83:8a:ff:57:cf:b4:41:1f:a3:66:b2:e2:
00:6a:3a:33:dc:c3:3d:13:1d:37:97:d9:9c:d9:b5:9b:24:74:
24:82:7a:f9:ca:51:b3:39:24:e3:90:f4:ff:4b:8e:be:f8:0f:
ec:7a:16:55
WARNING: no nonce in response
Response Verify Failure
139766041024400:error:27069076:OCSP routines:OCSP_basic_verify:signer certificate not found:ocsp_vfy.c:92:
sendcloud.cer: good
This Update: Dec 9 07:52:17 2023 GMT
Next Update: Dec 16 07:52:16 2023 GMT