京加高铁
今天了解到这么一件事,白令海峡原来也就 82.5km 宽,水深55米,对于现代工程技术来说修桥和隧道都不是问题。
如果中间那个岛做个中转站,那么两侧都各自30km左右。所以理论上从北京修一条到西雅图/加州的高铁完全没有问题。。
Posted
stdout
This blog is rated 🔞, viewer discretion is advised
今天了解到这么一件事,白令海峡原来也就 82.5km 宽,水深55米,对于现代工程技术来说修桥和隧道都不是问题。
如果中间那个岛做个中转站,那么两侧都各自30km左右。所以理论上从北京修一条到西雅图/加州的高铁完全没有问题。。
Posted
stdout
git notes is an interesting feature, you can use it like
git notes add -m "hello test git notes"
git push origin 'refs/notes/*'
Github supported them back in 2010 then gave up LMAO.
If you need to retrive them with Github API, try GraphQL like this
{
repository(owner: "est", name: "snippets") {
refs(refPrefix:"refs/notes/",first:1) {
nodes{
... on Ref{
target {
oid
... on Commit{
changedFilesIfAvailable
message
tree{
oid
entries{
oid
path
size
lineCount
mode
object{
... on Blob{
byteSize
text
}
}
}
}
}
}
}
}
}
}
}
It will return something like:
{
"data": {
"repository": {
"refs": {
"nodes": [
{
"target": {
"oid": "bfdfda121f3d8a2d6aa399e3e8f0d58b3db0a543",
"changedFilesIfAvailable": 1,
"message": "Notes added by 'git notes add'",
"tree": {
"oid": "2ab3e6a8b0dff6596fa60ecfb3c61bf91e5b4e1f",
"entries": [
{
"oid": "404d353a254ffbc97b2e16d17b8c100461aef586",
"path": "4fb1272f1e235580f87e3ec071984658de050dc9",
"size": 21,
"lineCount": 1,
"mode": 33188,
"object": {
"byteSize": 21,
"text": "hello test git notes\n"
}
}
]
}
}
}
]
}
}
}
}
Here "path": "4fb1272f1e235580f87e3ec071984658de050dc9"
is the commit SHA.
If you add more filter parameters in refs()
you can fetch all the notes.
Posted
stdout
继续上次 Racknerd 之后发现这家还行。写了个爬虫扒了一下各色配置,独立服除外,有需要的自取
pid | spec | Disk | Bandwidth | Annual $ |
---|---|---|---|---|
1 | 1C512M | 5GB | 100Mbps | $27.00 |
7 | 6C8G | 100GB | 100Mbps | $270.00 |
77 | 1C1G | 10GB | 1Tbps | $21.00 |
78 | 2C1.5G | 20GB | 2Tbps | $36.00 |
79 | 2C2G | 25GB | 3Tbps | $45.00 |
80 | 2C2.5G | 30GB | 4Tbps | $54.00 |
81 | 3C3G | 40GB | 5Tbps | $63.00 |
83 | 3C5G | 50GB | 8Tbps | $90.00 |
84 | 6C10G | 120GB | 12Tbps | $180.00 |
85 | 10C12G | 150GB | 15Tbps | $270.00 |
86 | 14C20G | 200GB | 20Tbps | $450.00 |
87 | 20C30G | 300GB | 30Tbps | $675.00 |
110 | 1C1G | 15GB | 2Tbps | $21.00 |
111 | 2C2G | 20GB | 4Tbps | $39.99 |
112 | 3C3G | 30GB | 6Tbps | $49.50 |
113 | 4C4G | 40GB | 8Tbps | $59.99 |
119 | 1C512M | 10GB | 500Gbps | $24.00 |
120 | 1C1G | 15GB | 1Tbps | $36.00 |
121 | 2C2G | 30GB | 2Tbps | $72.00 |
122 | 2C3G | 50GB | 3Tbps | $108.00 |
123 | 2C4G | 70GB | 4Tbps | $144.00 |
124 | 4C5G | 90GB | 5Tbps | $180.00 |
126 | 6C6G | 100GB | 6Tbps | $216.00 |
127 | 6C7G | 120GB | 7Tbps | $252.00 |
128 | 8C8G | 140GB | 8Tbps | $288.00 |
129 | 8C9G | 150GB | 9Tbps | $324.00 |
130 | 10C10G | 170GB | 10Tbps | $360.00 |
131 | 10C11G | 180GB | 11Tbps | $396.00 |
132 | 12C12G | 200GB | 12Tbps | $432.00 |
154 | 1C1G | 20GB | 4Tbps | $33.00 |
155 | 2C2G | 30GB | 6Tbps | $40.00 |
156 | 3C3G | 40GB | 8Tbps | $60.00 |
157 | 4C4G | 50GB | 10Tbps | $84.00 |
158 | 5C5G | 60GB | 12Tbps | $105.00 |
159 | 6C6G | 70GB | 14Tbps | $130.00 |
160 | 7C7G | 80GB | 16Tbps | $145.00 |
161 | 8C8G | 90GB | 18Tbps | $170.00 |
162 | 9C9G | 100GB | 20Tbps | $190.00 |
163 | 10C10G | 110GB | 22Tbps | $210.00 |
164 | 11C11G | 120GB | 24Tbps | $240.00 |
165 | 12C12G | 130GB | 26Tbps | $260.00 |
166 | 8C8G | 50GB | 30Tbps | $98.99 |
167 | 4C4G | 25GB | 15Tbps | $56.99 |
168 | 4C4G | 25GB | 15Tbps | $79.00 |
169 | 8C8G | 50GB | 30Tbps | $158.00 |
170 | 12C12G | 75GB | 30Tbps | $235.00 |
171 | 16C16G | 100GB | 30Tbps | $318.00 |
172 | 20C20G | 125GB | 30Tbps | $399.00 |
173 | 24C24G | 150GB | 30Tbps | $480.00 |
174 | 28C28G | 175GB | 30Tbps | $575.00 |
175 | 32C32G | 200GB | 30Tbps | $660.00 |
176 | 36C36G | 225GB | 30Tbps | $730.00 |
177 | 40C40G | 250GB | 30Tbps | $810.00 |
178 | 1C1G | 20GB | 2Tbps | $21.00 |
179 | 32C32G | 1TB | 1Gbps | $540.00 |
180 | 64C64G | 1TB | 1Gbps | $725.00 |
181 | 128C128G | 2x | 1Gbps | $1850.00 |
Posted
stdout
发现Astronomical symbols,Planet symbols
及 Alchemical symbol
IAU | 七金 | 符号 | 名 | name | 星期 | 七曜 | 备注 |
---|---|---|---|---|---|---|---|
金 | ☉︎ | 太阳 | Sun | 星期天 | 日曜 | ||
银 | ☾ | 月球 | Moon | 星期一 | 月曜 | 也可以画成 ☽︎ 或者月相 🌑︎🌒︎🌓︎🌔︎🌕︎🌖︎🌗︎🌘︎,🌚︎🌛︎︎🌝︎︎🌜︎︎ |
|
H | 汞 | ☿ | 水星 | Mercury | 星期三 | 水曜 | 赫耳墨斯(Hermes),罗马人称 Mercury 现代人称「爱马仕」的双盘蛇带翼权杖 Caduceus ☤ |
V | 铜 | ♀ | 金星 | Venus | 星期五 | 金曜 | 维纳斯 |
E | 🜨 | 地球 | Earch | Bible 里说的四条河把地球分成四洲 另外的符号是 ♁ 表示十字架钉个球 globus cruciger |
|||
M | 铁 | ♂ | 火星 | Mars | 星期二 | 火曜 | 符号是战神盾牌和长矛 |
J | 锡 | ♃ | 木星 | Jupiter | 星期四 | 木曜 | 字母 Zeta(大写Ζ小写ζ)加一杠,代表宙斯/朱庇特 |
S | 铅 | ♄ | 土星 | Saturn | 星期六 | 土曜 | 字母 kappa-rho ,表示 Kronos 加一杠 泰坦 克罗诺斯,宙斯他爹 |
U | ⛢ | 天王星 | Uranus | ||||
N | ♅ | 海王星 | Neptune |
几点:
其它各种卫星,小行星的名字就懒得贴了。
有了这些符号,我们可以画一个比如托勒密的简化版太阳系模型:
本文源自《哥白尼、伽利略、开普勒都是脱离证据拍脑袋撕逼》一文。HN
Posted
stdout
I am planning to setup by blogging environment on my Windows PC.
pelican
on Miniconda3 with Python 3.11My objective today is get rid of the static/js/core.js
from aether-pelican
theme and replace it with a simple CSS, and it turns out quite challenging.
As it turns out, the installed Ubuntu root filesystem on WSL1 is located here:
%localappdata%\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs
I plan to move my home dir (at least) to another SSD on my PC, as the C:\
drive is an old SanDisk Plus240, which is unforgivablly slow these days. I tried to mv ~ /mnt/d/home
, ok but the permission gets weird.
So I tried to copy the folder on Windows to D:\home
, and mklink
back. I tried both mklink /D
and mklink /J
( the /D
switch works on a remote drive whereas the /J
junction works on local NTFS disks only) and they both failed be recognized by WSL1. The bash yields Broken stdout/stdin
upon launch
So OK, default home dir then. Bad luck for me.
I just found out my cat /etc/lsb-release
shows Ubuntu 18, which is the default distro installed on WSL1
I assume. I tried to install Ubuntu 22 from the Microsoft Store, after several wasted minutes (curse the slow Internet in Mainland!) it turns out for WSL2 only. Luckily the Windows Subsystem for Linux was successfully upgraded to latest version:
C:\> wsl --version
WSL version: 1.2.5.0
Kernel version: 5.15.90.1
WSLg version: 1.0.51
MSRDC version: 1.2.3770
Direct3D version: 1.608.2-61064218
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.19045.3570
the wsl --list --online
commands stuck for a total of 10 minutes and returns nothing (curse the AS4134 163NET!)
So linux distro setup was back to where started, I only have Python to mess with. Miniconda3 gets insalled easily, now that's a some progress. The static site generator I am using pip install pelican[markdown]
finishes ok, the pypi was not blocked? Keke.
Then I typed make
. It was not part of WSL1? Blaspheme!
Manually running python -m pelican.server
, and voila! The Windows asks for firewall listening permission, granted, open up browser, BAM! My blog setup process is done and now I can write and tweak it on Windows.
Oh, and there's git config core.fileMode false
needs to be checked!
Posted
stdout
看到个段子
突然让我想起个事,如果去火星打工,薪资该怎么计算?摘录 wikipedia
火星的恒星时长
24小时37分钟22.663秒
,而太阳日则长24小时39分钟35.24409
秒。而地球的恒星时和太阳日则分别是23小时56分钟4.0916秒
及24小时
。在比较之下,一火星太阳日等于1.027491地球太阳日,即比地球太阳日长2.7%。
怎么有两个天?继续搜
太阳日(英语:solar day)是依据太阳运动,所定义的时间,可以分为视觉太阳日和平均太阳日。一太阳日传统称为一“日”、一“天”或一“昼夜”。
英语里把火星的一天叫做一个 Sol
。一个火星年在英文的 wikipedia 有讲
sidereal year ... is about 686.98 Earth solar days (≈ 1.88 Earth years), or
668.5991
sols 。也就是说火星一年有 668.5991 火星天。。。
火星因为有25.19°
的自转倾角,跟地球相近,所以也可以划分四季。但问题是,火星的轨道长这样:
所以如果按照四个季节划分,最长的季节有 194 个 Martian Sols
,最短的 142 Martian sols
那么问题来了。在火星上怎么算工资呢?我觉得得安天结了。还有,假如亲爱的读者小伙伴将来到火星务工,应聘的时候一定确认好是按地球年结算还是火星年哦。谨防火星历诈骗!
Posted
stdout
今天趁着11·11买了个 GZ104 黄轴键盘,感觉之前随便买的青轴的好了很多,于是手痒想打字。哈哈
娃今天吃饭的时候突然问了我一个问题:「人活着的意义是什么呀」,很不凑巧我也闲来无事琢磨过这事,但是想要在孩子面前把这事说清楚可能没那么容易。
于是我换了个思路,我问他,如果你是一个动物,你觉得意义是什么?他没回答,我又问,如果你是一块石头,石头会考虑自己的意义嘛?
孩子也没回答。最后我说,人活着的意义呀,可能很多人也不知道,但是有一点可以确定,正因为你有一个聪明的小脑袋,才会去思考「什么是意义」这样的问题
他又问到,为什么世界上有那么多国家呢,为什么联合国不是一个国家。怎么样才能统一全世界成为一个国家。
我的回答又把刚才的套路重复了一遍。如果你是一只动物,你会觉得自己属于某个国家吗?娃想了下,可能不会吧。我看到碗里的饭说,如果你是一粒大米,你会觉得自己有国家吗,孩子也不说话。最后我说,国家有很多个定义,但是正是因为人有了大脑,有了想象力,才会产生国家这个概念。所谓国家,就是一个想象的共同体。
这可能是我会记录的最无聊的两件事。因为我真的想拿着键盘痛快的打一打字哈哈。
或许我的回答都不是最好的,现在想起来真的有很多改进之处。比如没能鼓励孩子进一步对这个问题进行探索。
蹲茅坑的时候想了一下,我们小时候哪里会思考这些问题呀。小时候都在为了作业发愁,心思都花在了怎么玩上面。现在的孩子能思考这些问题说明生活条件比较好了。人在穷的时候,物质匮乏的时候是不会去思考存在的意义的,都忙着奔波生活去了。生存都照顾不过来,如何去顾及意义呢。
生命或许最大的意义就是生存。仅仅丰衣足食之后,才有闲心来考虑一下奋斗折腾这么大半辈子,究竟是图了个啥。
本文完成于 2023-11-05 22:39:59。
Posted
stderr
假如你用 FastAPI/Starlette框架,写了一段 Server-sent Events
@app.get('/api/my_stream')
async def api_stream():
async def gen():
while 1:
yield "data: {}\n\n"
await asyncio.sleep(1.0)
return StreamingResponse(gen, media_type="text/event-stream", headers={
'X-Accel-Buffering': 'no',
'Cache-Control': "no-cache",
'Connection': "keep-alive",
})
然后你重启了服务器,比如 gunicorn+uvicorn,你会发现这个连接不会断开,一直输出结果。直到 worker 进程超过配置里的 timeout
参数(默认60秒),被 master 强行杀死然后重启。
一开始尝试了 FastAPI 官方的 shutdown
事件,再在代码的 while 1
加一个 if
判断。发现不管用
@app.on_event('shutdown')
def on_server_shutdown():
app.state.running = False
发现这段代码执行是执行了,但是是在杀死worker的时候生效的。得更加提前。用ASGI推荐的lifespan
和 http.disconnect
太复杂,放弃。
尝试暴力监听 worker signal
import signal
signal.signal(signal.SIGINT, on_server_shutdown) # ctrl+c
signal.signal(signal.SIGUSR2, on_server_shutdown)
signal.signal(signal.SIGTERM, on_server_shutdown)
signal.signal(signal.SIGWINCH, on_server_shutdown)
signal.signal(signal.SIGHUP, on_server_shutdown)
signal.signal(signal.SIGQUIT, on_server_shutdown)
发现也不管用。研究了半天,似乎是 UvicornWorker.init_signals
的时候给signal.SIG_DFL
了。无语ing
看gunicorn日志:
[2023-11-02 09:50:38 +0800] [25918] [INFO] Shutting down
[2023-11-02 09:50:38 +0800] [25918] [INFO] Waiting for application shutdown.
[2023-11-02 09:50:38 +0800] [25918] [INFO] Waiting for connections to close. (CTRL+C to force quit)
....
[2023-11-02 09:51:18 +0800] [25918] [INFO] Application shutdown complete.
[2023-11-02 09:51:18 +0800] [25918] [INFO] Finished server process [25918]
[2023-11-02 09:51:18 +0800] [25918] [INFO] Worker exiting (pid: 25918)
观察到 Waiting for connections to close 之后卡住。
属于 uvicorn 的 Server.shutdown()
方法
这个方法调用链:
Server.install_signal_handlers
里注册 signal Server.handle_exit
里设置 Server.should_exit = True
Server.on_tick
就会打断 Server.main_loop()
死循环Server.shutdown
如果能拿到 Server.should_exit
自行判断就好了,但是 ASGI 是容器无感的,只继续研究
上面日志有一个比较关键:
# Request shutdown on all existing connections.
for connection in list(self.server_state.connections):
connection.shutdown()
await asyncio.sleep(0.1)
其http连接关闭方法实现为:
def shutdown(self):
"""
Called by the server to commence a graceful shutdown.
"""
if self.cycle is None or self.cycle.response_complete:
self.transport.close()
else:
self.cycle.keep_alive = False
这里应该走的是 else
分支。所以解决方法就是去代码里拿到 cycle.keep_alive
这个属性。
跟了一会儿,发现ASGI 在 starlette 里如下流程:
Route()
初始化 self.app = request_response(endpoint)
Route().handle()
的时候会调用 self.app(scope, receive, send)
unicorn
的 run_asgi
会 result = await app(self.scope, self.receive, self.send)
。其中 app
就是 starlette 的 Route()
实例所以解决方案逐渐明朗了
通过 FastAPI/Starlette 请求的 .receive
属性的 __self__
拿到 unicorn 的 cycle
实例,然后定时判断上面 shutdown
赋值的 self.cycle.keep_alive = False
@app.get('/api/my_stream')
async def api_stream(req: Request):
async def gen():
while 1:
yield "data: {}\n\n"
await asyncio.sleep(1.0)
if getattr(req.receive.__self__, 'keep_alive', None) is False:
break
return StreamingResponse(...
这里用了个 getattr()
是保证这个 hack 在非 unicorn 下代码也能正常跑
git commit . -m "haha"
上机联调,发现坑了。。。我特么。。。。这个 cycle.keep_alive
默认就是 False
这玩意一直为 False
的原因是,unicorn 的 HttpToolsProtocol.on_headers_complete
赋值过程:
self.cycle = RequestResponseCycle(..., keep_alive=http_version != "1.0")
这里 http_version
可以通过 req.scope['http_version']
得到,打印了一下,你猜怎么着,还真tm是。。。原因就是厂里反代 nginx的proxy_http_version没配置。这里是个常见的坑,非常影响性能,因为每个请求会生成一个新的 http 连接。
但是也等不急SA去改配置了。于是直接在代码 async def gen():
前面写死:
req.receive.__self__.keep_alive = True
。提交,再试。。。咦,怎么 keep_alive
依然为 False
????明明刚刚赋值了?
继续读代码,发现第二个坑,发现 unicorn 的 RequestResponseCycle.send()
方法里,在构造返回的时候,有一句
for name, value in headers:
elif name == b"connection" and value.lower() == b"close":
self.keep_alive = False
好吧。。。那么解决方法就是,把 keep_alive = True
挪到返回内部。先完成返回构造,再强行改值。
@app.get('/api/my_stream')
async def api_stream(req: Request):
# req.receive.__self__.keep_alive = True # doesn't work here
async def gen():
req.receive.__self__.keep_alive = True # works here
while 1:
yield "data: {}\n\n"
await asyncio.sleep(1.0)
if req.receive.__self__.keep_alive is False:
break
return StreamingResponse(gen, media_type="text/event-stream", headers={
'X-Accel-Buffering': 'no',
'Cache-Control': "no-cache",
'Connection': "keep-alive",
})
测试重启 worker,该连接在1秒后断开,worker平稳重启。完美。
苦逼撸业务的一天又开始了。
Posted
stdout
又是 corporate software engineering 吃屎的一天。用户在内部系统走流程,厂里用的是钉钉自带的OA工单审批。已经接入了API创建、完成工单
问题在于发起工单之后,用户并没有感知,不知道工单去哪里了,流程就断了,向钉钉官方售后发起咨询,对方丢了一句:不支持。无语
只能自己鼓捣。已知工单链接,在钉钉聊天窗口内部的最短的网址为:
https://aflow.dingtalk.com/dingtalk/mobile/homepage.htm?corpid=...&procInstId=...#approval
对方丢了一个 dingtalk:// 跳转协议
反复尝试,发现一个很有用:
桌面端打开URL
dingtalk://dingtalkclient/page/link
侧边栏:pc_slide=true
大容器(类似工作台容器)ddtab=true
于是构造一个试试:
dingtalk://dingtalkclient/page/link?url=https%3A%2F%2Faflow.dingtalk.com%2Fdingtalk%2Fpc%2Fquery%2Fpchomepage.htm%3Fcorpid%3D...%26procInstId%3D...%23%2Fapproval
然后果然ok了。
钉钉给人的感觉就是各个部门 hack 强行揉合起来一个怪物。各种不完善、不一致的问题。有空写一下吐槽。
Posted
stdout
最近想在 markdown 里搞图文混排,遇到一个大图把版面占完了,想缩小一些,由于 .md 渲染器安全限制,没法直接指定宽高
只能从图片本身想办法,首先最直接的手段就是服务器再缩放一次,但是蛋痛的问题是缩放之后文件怎么存,怎么给静态文件路由,怎么保障图片可用性,怎么兼容各种尺寸,想想都头大。
想到一个 hack,要不直接放一个 .svg 进去,因为 svg 支持加载位图资源,所以把 svg 位图缩小一点,让浏览器渲染 svg 不就行了。
没想到就被这个 hack 坑了。原因是 svg 如果被 <img>
标签渲染,那么禁止加载任何外部资源,脚本也禁止执行。
为了证明这个限制,我写了个 demo 放在 https://lab.est.im/shit_svg/
这个问题太隐蔽了。stackoverflow 上只有 Robert Longson、ThangLeQuoc、TheHippo
的答案提到隐约线索:
后来搜了到 skychx 把这个问题研究透了。罪魁祸首 SVG Security
If an SVG file is fetched as image, then certain requirements apply to this document:
- The SVG document is not allowed to fetch any resources. This also applies to scripts, stylesheets or images.
- Fonts shouldn't be loaded as well. The situation in UAs seems to still be unclear though.
Scripts must not be executed.- Event listeners must be disabled at all times.
浪费我好多时间。SVG2里把这个说得很明白了 https://www.w3.org/TR/SVG2/conform.html#processing-modes
When external references are disabled in an SVG document, any attempt to fetch a document through an external reference must instead be treated as if a network error occurred and no data was received.
不过查阅资料的时候发现个好玩的,SVG 1.1 支持 URL fragments
比如:
Posted
stdout
今天才知道,中国一共333个市一级行政单位。数据来源是 民政部首页 ➡ 民政数据
import re
def short_name(name):
m = re.search(r'''
(\S+?)
(?:
壮族|回族|维吾尔|省|自治区|特别| # 省
(?:侗|傈僳|傣|哈尼|回|土家|壮|布依|彝|景颇|朝鲜|白|羌|苗|藏)族|
蒙古|柯尔克孜|哈萨克|
地区|市|盟|自治州|自治县
).*$
''', name, re.VERBOSE)
if m:
return m.group(1)
return name
这段代码的作用是把比如 "黔南布依族苗族自治州"
这样的名字,缩短成 "黔南"
。
有一个小坑是,市一级行政区包含 蒙古|柯尔克孜|哈萨克
这三个名字后面没有 族
字。
有一些 XX林区
XX矿区
什么的,我觉得保留比较好。
Python的 re.VERBOSE
真是好东西!
Posted
stdout
bilibili.com 是国内热门长视频网站,俗称B站,百大UP是头部百万粉丝的视频上传者,前段时间无聊看了下《征集两万份问卷!全站最受欢迎的UP主居然是..?》,这部视频作者 -LKs-
抛出了一个惊世骇俗(对我而言)的理论:
频道和频道之间,天生就有占领心智和认知上的高低之分
记忆点排名:人设≥情绪≈观点>颜值>知识/新闻`
一般来说输出情绪和观点的频道,它一定会比那些输出知识和资讯的频道,要更容易被人记住和喜欢。因为前者的拟态更接近人,后者的拟态更接近「书」
注意它这句话有前提:
想起来,这也是为啥youtube/bilibili上很多视频封面都是各种大头照,以 LinusTechTips为例:
让人们记住一个鲜明的大活人,人设最重要啊。
无独有偶,今天又看到一则奇闻《不得不出“国区特供版”的波兰球,是怎么火进小学生圈子里的?》,简单的说 Steam 上出了一款波兰球游戏「Bang On Balls Chronicles」结果波兰球这个亚文化早就在国内流传开并在小学生里成功的「娘」化了
得出一个道理:自己对世界的理解,要去人化,祛魅脱敏;对品牌和迷因的传播,要拟人化萌娘化。
Posted
stderr
最近看到个巨扯谈的视频《个人主义盛行的美国是怎么建立国家认同的》
实际上,美国这一血腥的国家认同,正是在上个世纪30年代纳粹主义的渊源之一(wapo有讲)。简单的说,发现美洲之后,敢离开老欧洲漂洋过海的人都是胆大包天的亡命之徒。它们信奉的昭昭天命就是「应许之地」,加上新教核心理念就是「sola fide」,我强我有理,有理我就强,所以我就是比其他物种优越。最后发展成种族主义,实施对其他 race 的压迫。
这个视频的 up 主是「思维实验室」,他们家的视频有一些说不清道不明的诡异但的地方但是题材比较有趣。这个视频很方便的忽略了一个更有趣 whataboutism 的问题:太平洋对岸的国家认同是怎么建立的?
有理由相信,华夏的国家认同建立正是武装殖民。
白寿彝版《中国通史》在论述周初分封制直接说这就是武装殖民。
周初的分封是一种武装驻防事业,其目的主要在于作为王室的助手,以监视被征服的各族人民,实际上它具有武装部落殖民的性质。我们知道,周王当时所能直接统治的只有王巍之地。王畿是以镐京和洛邑为两个焦点,其范围现在不能确考,但可知其北不过黄河,南不到汉水,东不达淮水,西则镐京已接近边陲。王畿之外,周室先后封立了很多诸侯国,诸侯对王室的义务不过按期纳贡朝觐,出兵助王征伐,以及救济畿内的灾患而已。诸侯国的内政几乎完全自主,而王室开国初年的武王成王过去以后,诸侯对王室的义务也就成了具文。
另一方面,所有新建的封国大都是以少数周族奴隶主贵族统治多数被征服族人,其土既非周人所有,其民也与周人不类,这些新来者的统治地位,如果没有坚强的武力作其后盾是支持不住的。姜太公封到东方的营邱,史书说太公就东国,“夜衣而行,犁(黎)明至国。莱侯来伐,与之争营丘。”“营丘边莱,莱人,夷也”(均见《史记·齐太公世家》),新来的统治者占有其土地,拥有其人民,因而起来反抗。《礼记·檀弓上》云:“太公封于营丘,比及五世,皆反葬于周”,可见当时武装殖民之不易。当时被封的周族奴隶主贵族及其所率领的周族公社农民进入广大占领区后,首先建立一个军事据点,这在古代文献中名之曰“城”,只有如此,才能进行武力镇压。《诗经·小雅·黍苗》中召穆公营谢,诗人描述军族集镇之况云:“我任我辇,我车我牛,我行既集,盖云归哉!我徒我御,我师我旅,我行既集,盖云归处!”周人及其姻戚联盟,造邦筑城,镇戍征服地区,也见于周金铭文,例如《中甗》虽然铭文残泐,颇难卒读,但其大意,尚可通晓。意谓:王派中巡省南国,筑城殖民,并派兵镇戍。《班毁》记毛公伐东国■戎,■令班“■(以)乃族从父(毛父)征,■(出)■(城)卫。”毛公东征“三年静东国”。这里的■(城)就是征服筑城之证。
这个段子说,姜子牙去山东「上任」,实际上也就给了一点亲兵和战车,地盘要自己去抢,城要自己去建,太公当年差点被山东当地一个叫「莱」的土著部落给搞死……
为什么少数民族总是「能歌善舞」,并且大多住在偏远的山区?是不是换个译法就是 …… tribal reservation?
这让我想起另一个段子:《封神》导演乌尔善说【汉族称谓】形成于元代。
下面有个评论就很应景:「汉族是不是起源自元代,我不知道,但是我知道,“我是汉人”的意识是这些其它民族一遍一遍给我加强的」
这里有个感觉,无论是「通天纹大妈」,还是玩梗的「正米字旗」老不列颠,还是「红旗下长大」的大院子弟,对阶级的认同度远远大于普通国民。因为天下是他们或者他们的祖辈打下来的,有一种「股东感」。如果是普通人,和平年代的国籍无非是身份证件上的可以花代价更改的一行字罢了。
如果你读到这里,一定要暂停一下。如果你觉得这个太宏观,那么假想一下你去了个新公司。你跟普通同事交谈的是,今天做了哪些工作,明天又有哪些该死的任务下来;但是公司里总有那么一戳人,他们跟你讲公司的视角完全不同。他们会告诉你 A 这个市场是当年谁谁大干30天拿下的,B 这个股份是谁谁奋斗了几年才成为合伙人得到的,C 这个部门之前没有,是谁谁带资进组专门成立的。D 这个烂摊子之所以一直没解决是因为负责人跑路到友商,等等。那么把同等的视角换到国家,统治者或者他们的家属后代会明确告诉你,某某领土的由来就是谁谁当年打下来的,而且他们在这样的一种「传承」体系中,非常自豪。
这就是为啥平时很多 XX盟 XX旗 XX喇嘛教 会看不起汉人的根本原因。别人对某一篇山川有「ownership」的感觉。汉文化一个比较短视缺陷就是把天下看成一种零和博弈,「百姓」需要把自己一部分权力让渡给「君主」,人权需要迁就主权,但从唯物的角度来说,国家总是由一小部分人打下来的,大多数被土地绑定的人,并没有太多选择,作为 X国人 或 X朝人 的资格,只能是来自统治者的「施舍」。所以鱼肉百姓也是理所当然顺理其章的事了。因为人口就脱离了人的属性,只是附属和资产。
又联系起最近看马督工的 睡前消息652期《只靠民间热情,“山河大学”建不起来》,里面谈到高中 - 职校分流问题,现实中全世界成功的职业教育有且只有德国一家。职校前身实际上是行业 (学术概念:基尔特) 里师徒制的正规化(1969 Berufsausbildungsgesetz)。我有一个偏激的观点,职校早期雏形是条顿军官团拿来生产军需屯田和筹款的产物。容克军户在和平年代转型生产制造和银行业,大量的德意志职校几乎都是围绕汽车产业进行布局,归根结底就是一堆战备产业。
所以谁才是国家的主人?血与火铸成的核心利益阶级(class)
Class 是一个神奇的词汇,OOP的「类」和社会的「阶级」有异曲同工之妙。如果按照本篇思路推演下去,可以拿历朝历代作为例子总结一下朝代的消亡的实质,就是核心class的消解:
除了核心阶级所形成的可以继承的利益集团,其他人要么是归顺的食邑劳动力,要么是“穷凶极恶”的印第安人。
Posted
stderr
最近看渤海小吏讲汉文帝、汉景帝的《秦汉帝国完全体99%》很有收获,特别是 23:00 这段:
总体而言,汉代初期的官僚人数少,制度简单,政府没有整体干预经济的想法,所以超级省钱。养活当时的整个官僚,每年所需的粮食不过几十万石。哪怕按一百万石算,只用全国大约八百分之一的土地就可以养活这个官僚系统。这是整个中国历史上政府运营成本自成一档的优秀存在。
这套体制虽然简约,但却并不简单。中央对于局势的控制力度一点也没有弱化。这段时间,反而是整个有汉一朝,刑事案件与社会矛盾最少的年代。
《道德经》曾经讲过这么一句话:“太上,下知有之。其次,亲而誉之。其次,畏之。其次,侮之。”
- 最牛的水平,是下面的人仅仅知道有这么个领导。
- 水平差点的,是下面的人赞美夸奖这个领导。
- 再差点的,是所有人害怕这个领导。
- 最次的,是所有人都在骂这个货。
总觉得这段话在骂谁呢?没想到汉景帝的七国之乱也是折腾出来的。看完这视频我又在琢磨,皇权、王权、相权三权分立是什么?
看这一系列的视频总给人一种强烈 黄老之术讲究的一个「无为」,也不是很懂;
周末又昏昏沉沉看了了《长安三千里》,给我感动得,然后重新认识 李白 那种商人之子想通过刷干谒文当官,我心里一直在嘀咕,李白家里有钱,为啥非得要去当官?可能是,在那个时代,你有钱也没有安全感。权力一张纸就可以让你的财富化为灰烬。但是李白明明修道,却一辈子没能实现自己的政治抱负,最终取了功名的反而是 高适。
然后又看到一篇《gpt4开发人员拿柯尔莫哥洛夫复杂度数学上严格约束并解释gpt4的智力产生原因》。让我想起来前段时间看到的离谱故事:Gzip+ kNN文本分类竟然击败Transformers:无需预训练、14行代码实现
看起来风马牛不相及的三个生活经历,在今天产生了奇妙的化学反应。我突然想明白,无为的意思,就是承认因果律的局限性。
人的主观能动性——作为,有一个经常被忽略的大前提,你得抱着一定的「目的」才可能去作为,也就是拿着预设的最终结果去改变现状。准确的目的设定,需要对真实世界的反复推演和总结因果律。因果律的掌握程度就是智力水平,智力的高低就看你掌握的是有损压缩还是无损压缩,因为压缩的本质就是用更少的信息去模拟真实的全部信息。聪明就是用更小的成本去还原更多的事物,笨就是还原成本更高。这个成本,在学术上的定义就是 Kolmogorov复杂度。它有个上限但是不可及算,某些可计算的变体,比如conditional time-bounded Kolmogorov 复杂度是 NP 问题,不可知也。
以前一直不知道信息论学了有什么用,现在似乎摸到了一些门道。信息是中性的,但是因果就有得失和优劣之分。以前不会用,是因为不知道武器的哪一端是剑柄才能握住挥舞。
生活中许多东西是需要去「作为」的,但是需要区分哪些是自然事物,那些是人为的设置。人这个神奇的动物可以把不存在的实体看成实体。
胡思乱想一些心得,记录一下,或许将来可以整理得更清晰。
Posted
stderr
最近下载了一个Linux的病毒,把它解包了。
尝试用root身份运行,发现啥也没有。
Google了俩小时,发现这病毒没解包到 /usr/local/bin 而是解压到了 malware 用户没有写入权限的 /usr/bin,于是病毒创建不了进程文件。
从某个中文论坛里找到了修改过的 .configure 和 .make 文件,重新编译重新运行了一下。
病毒说它需要 cmalw-lib-2.0,结果发现这玩意是 CentOS 里的,Ubuntu 里没有。Google 了好几个小时找到了从源码构建 .deb 包的方法。
这病毒总算开始跑了,然后打出来几行日志,吐了个 core dump 就 crash 了。翻了一个小时日志发现这病毒假定自己跑在 ext4 文件系统上然后调用了 ext4 的加密 API。但是在 btrfs 里这个 API 已经弃用了,内核发现了这个问题然后把这个分区变成只读的了。
打开源文件,grep 搜索出病毒里的 BTC 钱包地址然后出于同情给它打了 $5。
哈哈虽然现在linux病毒也多,但是这个也太搞笑了 via
Posted
stdin
看了这篇文章之后,感受颇深。强烈推荐阅读
https://mp.weixin.qq.com/s/hqIMDADiPDVSWp8EKh5gbw
之前看到行业说法,北京便利店少的原因是“三个半”,即由于纬度高,天气寒冷,只能做“半年”生意,每日只能做“半天”生意,马路宽隔绝了人流,只能做“半条路”的生意。
当时不知道为啥北京有这么多栏杆,现在知道了,原来是模仿苏联的城市规划。
文章里提到
“窄马路、密路网、路口多”这种在风水上叫做“雍聚”,是上上之选,有利于聚财、聚气、增加流动性、繁荣商业、降低拥堵。那种“宽马路、大广场、路口少”叫做“散迭”,会造成西北风煞冲散街区的热气,导致地气不旺、商业冷落萧条。城市变成睡城、死城,民众精气散迭,日渐贫穷衰落。
搜了下,居然这个说法是公众号里早就有之的洗稿文。不过从另一个角度想,你分析blah那么一大堆,给没耐心或者没文化的小学生讲这个道理,不如就简化成:雍聚是上上之选。有的时候「道理」被过度复杂化了。不如直接给出上 - 中 - 下这种线性结论杀伤力更大。
想到现在政策层面反复炒作的「烟火气」,又想起2016年那个「不再建设封闭式小区」,当时被好多人骂来着。
最后感觉这篇文章讲的故事,如果放在网络社区上,也是同样的结论。把流量都往「主干道」「主旋律」上赶,必然会有大量的舆论翻车事故,最后得到的一定是商业上的萧条。
Posted
stdin
在这个下落和迷茫的时代,有的时候一段不经意的话真的很打动人:
张雪峰,男生本来就一无所有,你怕什么?放手干就行了 视频备份
男生,咋是爷们。咋男生咋没什么所谓好失去的,为什么?你本就一无所有啊!你怕什么。
你有什么好失去的呢?大不了从头再来,对吧?
但行好事,莫问前程,皇天不负有心人。
之前有个感悟,人的理性其实是一个很狭窄的波普,下限是死亡,上限是吃多了撑的。如果死亡都不怕,其实没啥好怕的;人吃撑了,才会有心思去发展琴棋书画,探讨抱负和情感。在死不了和吃不饱之间其实是完全没必要,干就完了。
Posted
stdin
感慨并记录一下,打交道的一些油腻的门门道道。房屋出租给某知名绿色logo中介,由于怕麻烦,参与了他们某个打包N年固定收益的出租方案,好处是所有问题该中介包干,确定收益,就算没租出去也是公司补贴收益;坏处是租金比理想市场价低一些。我自己判断,如果仅由中介帮你打广告,或者自己独自去招揽散客,很可能空档期导致还不如全打包。
这个条约有个很扯的费用,每年扣800维修基金。恰好今天租客很气愤的找到中介,说空调损坏。评估维修成本700左右。中介又找到我,说这属于维修基金不能覆盖的「大额支出」。
我当时听到菊花一紧,这疫情结束以来才起租,钱没挣多少,花费又多一截了。于是采取一边了解细节,一边不正面答应的策略。
想到,这空调不可能无缘无故损坏,维修那么贵可能是一口价宰人。于是我决定我的底线是「分摊」这笔费用,据理力争,几个回合下来,成功的把这个费用。。。。。全免了
事后回顾了一下。恰好看到网上一个类似的例子:
大概意思是一场交通事故,保险理赔一个大灯,发现大灯非原厂而是后期改装过,于是提出让车主自费。
后面大家的讨论是:
12378,一个(举报)电话就搞定。很多时候定损员希望你走这步,他也不用上下为难了,又不是从他包包头掏钱出来
这个道理让我的思路豁然开朗。用在我这个case上,可能是中介惯用的一个套路。首先这个合同不是跟中介签的,是跟中介所在的公司一个整包出租的项目签的。所以这里中介其实和房租收益没有「利益相关」,他只是从公司这个项目里拿到固定比例分成或者工资。至于这个出租项目整体亏了还是赚了,与中介自身无关。他只需要找到合适的客源,以合适的价格出租出去,把出租过程中所有的事摆平。剩下的问题都是公司开发这个项目的精算师的责任了。
一个中介办事员吃饭的本钱是什么?跟所在片区客户融洽的关系。所以得罪客户,让客户为难是下下策。公司就算这个项目亏本,跟办事员自己有一毛钱关系?就算公司明天倒闭,销售型员工换哪一家公司不是干?
那个车险的例子也一样。定损员吃饱了才会去找车主的茬,就算节约下来理赔的钱,也跟定损员自己没有一分钱「利益关系」。但之所以定损员会挑这样一个让客户难堪的毛病,无非是完成制度规定的一套动作。所以这个时候车主大可不必跟理赔员发火和吵架,只需要让理赔员有一个台阶站在自己这一边,整个问题的天平就会倾斜。
这是一个发生在我身边,如何同成年人争取自己利益的故事。油腻指数 ★★★★☆
Posted
stderr
比如开发需求是请求一个 http API,得到数据,解析一下返回,那么一般的做法是封装一个方法,比如
import httpx
def get_sth(p1, default=MY_VAL):
# network
r = httpx.get(API_URL, params={'t1': p1})
# parsing
res = r.json().get('my_key') or MY_VAL
但是如果想在 async/await 里用这段代码,就得改成
import httpx
async def get_sth(p1, default=MY_VAL):
# network
with http.AsyncClient() as client:
r = await client.get(API_URL, params={'t1': p1})
# parsing
res = r.json().get('my_key') or MY_VAL
注意其中 def get_sth()
也必须改成 async def get_sth
。这就是所谓 async/await 传染性
这个时候,如果你想把这块代码抽象出来,让同步/异步的库都能调用,我在最近重构里找到一个最佳实践:
import httpx
def get_sth(p1, default=MY_VAL):
r = httpx.Request('GET', API_URL, params={'t1': p1})
r.parse = lambda x: (x.get('my_key') or MY_VAL)
# 同步调用:
with httpx.Client() as client:
r = client.send(get_sth())
r.request.parse(r.json())
# 异步调用:
async with httpx.AsyncClient() as client:
r = await client.send(get_sth())
r.request.parse(r.json())
思路是 逻辑和 transport解耦,也是某种意义上的 Sans-IO 了吧?
Posted
stdout
如果你有多个 github、bitbucket、gitlab 账号需要来回切换,那么这个方法或许对你有用。
使用git你需要配置一个 ~/.ssh/id_rsa
,如果你有多个身份就麻烦了。传统网上搜到的办法是编辑 ~/.ssh/config
然后加入个类似这样的配置:
Host estgit
HostName github.com
Port 22
User git
IdentityFile ~/.ssh/est_github
IdentitiesOnly yes
这样做也不是不行,就是你输入命令的时候得把主机名改了。比如
git clone git@github.com:est/aether-pelican.git
你需要改成
git@estgit:est/aether-pelican.git
当然这还不是最蛋痛的。最蛋痛的是如果你用了 git submodules
那么你切换马甲变得非常麻烦。因为别人用你的项目没法解析 git@estgit
这样的玩意。
我研究出来了一个hack,直接改repo的 .git/config
可以达到同样的效果。比如
[core]
sshCommand = /usr/bin/ssh -o IdentitiesOnly=yes -i ~/.ssh/est_github -a
[user]
name = est
email = ...@...
这样你可以随意在不同的repo切换n个 ssh identity 身份。
Posted
stdout