This blog is rated 🔞, viewer discretion is advised

4句话自动换win10壁纸

  1. 获取当前用户 sid。cmd下设变量如此复杂。而且 | 的转义字符居然是 ^|
  2. 读取 LogonUI 的自动壁纸。reg query输出极其不友好。需要 tokens=3
  3. 设置为当前桌面。
  4. 刷新。这个属于按运气成功。真正刷新的需要调用 dll 。算了
for /f %%g in ('wmic useraccount where name^="%USERNAME%" get sid ^| findstr ^S\-d*') do set USERSID=%%g
For /f "tokens=3" %%k IN ('reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Creative\%USERSID%  /s /v  landscapeImage /t REG_SZ ^| findstr /ri "REG_SZ"') do set img_path=%%k
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v Wallpaper /t REG_SZ /d %img_path% /f
RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters 

之前的方法搞复杂了

Posted

stderr

FastAPI/Starlette支持静态文件支持SPA

FastAPI 官方支持 from fastapi.staticfiles import StaticFiles 充当一个静态文件服务器

其实实现是 starlette。这玩意可以在 directory 下放一个 404.html,恰好单页应用也需要用 index.html 充当所有 javascript 框架注册的 router

只是有一个毛病,这货返回的 HTTP status code 是 404。用起来没啥大毛病,但是就是浏览器不会记录网址,导致没法匹配浏览历史快速找到之前访问过的页面。

拿来改改继续用

  from starlette.staticfiles import StaticFiles, Scope, Headers, Response, FileResponse

  class StaticFilesWithout404(StaticFiles):
      async def get_response(self, path: str, scope: Scope) -> Response:
          r = await super().get_response(path, scope)
          h = Headers(scope=scope)
          full_path, stat_result = await self.lookup_path('404.html')
          if isinstance(r, FileResponse) and r.path == full_path:
              if 'text/html' in (h.get('accept') or ''):
                  r.status_code = 200
              else:
                  return Response('', status_code=404)
          return r

  app.mount("/frontend", StaticFilesWithout404(directory="frontend", html=True), name="static")

这段代码大概是起到了类似 nginx try_files 的作用。默认静态文件映射一个目录,但是如果找不到就按根目录的 index.html 输出。这里还判断了请求的 accept 头,如果是 xhr/Fetch 就会直接返回一个0字节长度无MIME的404。

由此我想到了一个学究式的 leaky abstraction。众所周知,如果一个URL不存在,那么服务器应该返回404

但是现在都是 SPA 单页应用,都是先 200 返回 index.html 的内容,再由 javascript 的 router 去决定是否正常显示还是404 。所以返回 200 但是显示 404 就破坏了这个语义。如果要精确匹配SPA里的router如果不存在由服务器返回404,第一是搞 SSR,把前端那一坨代码跑在服务器端,第二种办法是 npm build 的时候输出一个可路由URL列表,然后部署的时候导入静态文件服务器更新。这个具体实现就留作homework由读者自行解决了。

Posted

stdout

人工构造Flask session模拟cookie登陆

有没有好奇为什么 Flask 配置必须要求一个 SECRET_KEY,然后就可以在浏览器保存一个 session 状态读写数据。

这里记一下它的底层实现,其实需要依赖的包是 itsdangerous

  import hashlib
  from itsdangerous import URLSafeTimedSerializer
  URLSafeTimedSerializer(
          'YOUR_SECRET_KEY',  # flask SECRET_KEY
          'cookie-session',  # from flask.sessions.SecureCookieSessionInterface.salt
          # serializer=TaggedJSONSerializer(),
          signer_kwargs={'key_derivation': 'hmac', 'digest_method': hashlib.sha1}
  ).dumps({
      "your_key": "your_value"
  })

别人如果拿到你的 SECRET_KEY 就可以伪造任意 session cookie 了

Posted

stdout

苏35的UI汉化

原文禁止转载,那我就转载原文的原文

日前,俄罗斯《消息报》采访了俄罗斯无线电电子技术集团(俄罗斯技术集团下属企业)副总经理吉维∙占季加夫,该集团是苏-35几乎所有航电系统的研制生产单位。
占季加夫表示,“根据订购方的国情要求改装机载设备是重要的技术程序之一,一年多来我们都在致力于将驾驶舱内的信息翻译成汉语。但是,不像斯拉夫和拉丁字母,汉语的象形文字“很难”在LCD显示器上阅读。最终,中方要求维持原样,即显示器上保留西里尔字母。中国飞行员已有驾驶俄苏-27战机的飞行经验,该飞机的驾驶舱同样没有为中国进行改装,但飞行员们‘阅读’俄语的机上信息。”
该报称,苏-35显示器上译成汉语的仪表读数说明和指令太过微小和模糊,以致难以阅读。通过扩大显示器的尺寸可以解决该问题,但这样就要彻底改造驾驶舱,研制和试验需要额外的资金和时间,中方伙伴并不希望这样。
报道还指出,提供给中国的苏-35飞机唯一的特殊之处是在机载系统中加入了中国的“北斗”卫星导航系统。

中文字库还是很大的,渲染也麻烦。

Posted

stdin

Python 3.X ctypes 和 greenlet size changed 坑三则

安装 setup.py 的时候 No module named '_ctypes' 报错

  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/usr/local/python3/lib/python3.9/site-packages/setuptools/__init__.py", line 18, in <module>
      from setuptools.dist import Distribution
    File "/usr/local/python3/lib/python3.9/site-packages/setuptools/dist.py", line 34, in <module>
      from setuptools import windows_support
    File "/usr/local/python3/lib/python3.9/site-packages/setuptools/windows_support.py", line 2, in <module>
      import ctypes
    File "/usr/local/python3/lib/python3.9/ctypes/__init__.py", line 8, in <module>
      from _ctypes import Union, Structure, Array
  ModuleNotFoundError: No module named '_ctypes'

解决办法是不要用 3.9。

如果实在要用,则自己编译前需要加上 yum install libffi-devel 或者 sudo apt-get install libffi-dev

来自SO

greenlet.greenlet size changed 然后出错

/usr/local/lib/python3.7/importlib/_bootstrap.py:219: RuntimeWarning: greenlet.greenlet size changed, may indicate binary incompatibility. Expected 144 from C header, got 152 from PyObject
  return f(*args, **kwds)
/usr/local/lib/python3.7/importlib/_bootstrap.py:219: RuntimeWarning: greenlet.greenlet size changed, may indicate binary incompatibility. Expected 144 from C header, got 152 from PyObject
  return f(*args, **kwds)

Segmentation fault (core dumped)

这个摘自官方 iseue

On Python 3.7 and higher, gevent 20.9.0 is required to use (a standard build of) greenlet 0.4.17.

解决办法:pip install gevent==20.9.0 pip install greenlet==0.4.17

SQLAlchemy 1.4 大战 greenlet 0.4.17

sqlalchemy changelog

to accommodate for the handling of Python contextvars (introduced in Python 3.7) for greenlet versions greater than 0.4.17. Greenlet version 0.4.17 added automatic handling of contextvars in a backwards-incompatible way; we’ve coordinated with the greenlet authors to add a preferred API for this in versions subsequent to 0.4.17 which is now supported by SQLAlchemy’s greenlet integration. For greenlet versions prior to 0.4.17 no behavioral change is needed, version 0.4.17 itself is blocked from the dependencies.

然后就直接在 setup.cfg里greenlet != 0.4.17了。

神仙打架,不听不听,和尚念经,果断 sqlalchemy==1.3.24 降级。

Posted

stdout

Edge调教指南——如何设置本地PAC代理和首页天气

之前一直用的chrome v70,为什么呢?

第一是这个老版本允许 --proxy-pac-url="file:///Users/me/1.pac 这样设置,但是Chromium项目的大爷们觉得你本地的.pac不够安全,要网上的.pac才安全,所以一刀切给禁了。当然有热心人士觉得这没啥大不了的。不外乎装个插件就可以切PAC。但是chrome插件其实会有一个fingerprint。Extension一启用,隔壁老王都知道你开代理了。

第二,也是最重要的原因,这是最后一个chrome版本支持 about://net-internals 在本地查看浏览器底层网络请求。现在无论是 Edge 还是 Chrome 都必须把 .json 文件从 https://netlog-viewer.appspot.com/ 加载才能看了。很尼玛保护了隐私有没有啊。

但是坚持老版本,也付出了巨大的代价。很多新的 ES 语法不支持,比如说 Grafana 最新版 login 都进不去。这就尴尬了。只能被自愿升级了。

既然升级是必选项,那么就换 Edge 试试。

第一就是得解决这个本地 .pac 问题,其实从上面第二个工具里才能知道,PAC加载失败有个返回 ERR_DISALLOWED_URL_SCHEME。stackoverflow 上找到个奇技淫巧

open "/Applications/Microsoft Edge.app" --args --proxy-pac-url='data:application/x-javascript-config;base64,'$(base64 -i /Users/me/2.pac)

还能这样玩?双击666。

第二个把该禁用的禁用了,首页只留一个搜索框一个天气。但是这天气就特么定位到坡县了。而且下拉框点不出来啊。F12打开 devtool 一看,我尼玛好家伙 https://www.bing.com/api/v6/Places/AutoSuggest 被 Bing China 的网管给一把梭302到 https://cn.bing.com/api/v6/Places/AutoSuggest 了。然后就特么 CORS 给拦截,js读取不到列表。。。

最后怎么办?点那个天气图标,进入到 https://www.msn.com/en-sg/weather/today/weather-today/we-city

然后找那个地图,手动选择自己所在城市,设置为 Home 。等 cookie 写入生效了,打开edge新tab就ok了

这年头上个网真鸡儿累。

btw 设置M$账号同步的时候,发现账号所在国家可以选很多不是国家的地方,但是时区就不能随便选了。F12改了也没用。微软的后台开发做的过滤还挺细致的。

btw2 发现一个很干净的启动页: chrome-search://local-ntp/local-ntp.html 或者直接在 hosts 里把 ntp.msn.com 干掉,有奇效。

Posted

stdout

烧脑两题:蚂蚁和橡皮筋,30万公里的电路

今天遇到的两道题:

  1. 一只蚂蚁站在静止不动的一米长的橡皮筋的左边端点开始向右边爬,爬行速度是每秒一厘米。现在固定橡皮筋的左端点,拉伸橡皮筋使之以每秒一厘米的速度伸长,蚂蚁仍然是以之前的速度向右爬,试问蚂蚁能否爬到橡皮筋右端点?假设橡皮筋可以拉无限长,求蚂蚁是否能追上橡皮筋,追不上的话两者差多少?

解答没那么容易,见 zhihu 回答1, 2

  1. 如果长一光秒,宽1米的长方形电路,忽略导线的电阻,那么打开开关后灯泡要多久才通电?

答案来自视频,主要讲了一通 坡印廷矢量 的道理。。。囧

Posted

stdin

TiDB不支持JSON字段默认值

继前面的日期不兼容坑,又发现一个

The BLOB, TEXT, and JSON columns cannot be assigned a default value.

虽然 MySQL 5.7 也是这么说的:

A JSON column cannot have a non-NULL default value.

但是 MySQL 8.0.13 就支持指定默认值

Prior to MySQL 8.0.13, a JSON column cannot have a non-NULL default value.
The default value specified in a DEFAULT clause can be a literal constant or an expression. With one exception, enclose expression default values within parentheses to distinguish them from literal constant default values. Examples:

虽然语法很丑但是很实用啊。

所以这种语句

  ALTER TABLE mytable MODIFY COLUMN my_json JSON DEFAULT (json_object());

在 TiDB 里就没法支持。这也带来一个问题,就是要 upsert 这个 字段的时候,写起来就很拧巴,以 peewee 这个ORM为例:

  MyTable.update({
      'my_json' = fn.json_set(
          fn.COALESCE(MyTable.my_json, Cast('{}', 'JSON')),
          '%.some_key', 'some_value',
  )})

必须用 COALESCE 预防默认值为 NULL 的情况。太麻烦了。

btw 玩MySQL/TiDB的 JSON 有个坑的,那就是 json 的 null 是有值的,和 sql 的 NULL 是不同的。

也就是说

  select json_extract('{}', '$.hey') IS NULL;
  select json_extract('{"hey": null}', '$.hey') = Cast('null' as JSON);

要注意。

btw2 MySQL的JSON数据抽取 ->> 是返回真正的值,等价于TiDB里的 json_unquote(json_extract(t.json_field, '$.key1.key2'))

Posted

stdout

怕学生会看HTML源码里的答案,Chrome允许网管禁止查看特定网站源码

看到一个奇葩issue

With "view-source" in the URLBlacklist, the view-source:http://[URL] should not be available. With Schools using Google Forms as a testing platform, students are able to use this shortcut to search through the source of the page, and determine the correct answers.

然后 Google Chrome 就真的改了。。。

https://chromium-review.googlesource.com/c/chromium/src/+/3260807

Google 是开发人员太富余了。这种问提都要通过升级浏览器解决?

让人想起了前几天的密苏里州的查看HTML源码刑事诉讼

一名记者偶然发现,密苏里州官方教师资格证查询网站,存在严重的系统安全漏洞。仅仅通过查看网页HTML源代码,就能获取教师的身份证号码信息。于是,他向政府教育部门报告了这个问题。然而两天后,先于漏洞修复到来的,是州长即将对他发起刑事起诉。“政府不会掉以轻心,”州长Mike Parson在周四的新闻发布会上发言,“本届政府绝不姑息任何试图窃取个人信息并会造成威胁的作恶者。”

via

Posted

stdin

Chrome 指定域名解析,绕过 hosts

看到 V站有人问这个,随手一记

可以参考源码里的注释文档

--host-resolver-rules=rules

Like --host-rules but these rules only apply to the host resolver.
A comma-separated list of rules that control how hostnames are mapped.
For example:
- MAP * 127.0.0.1 Forces all hostnames to be mapped to 127.0.0.1
- MAP *.google.com proxy Forces all google.com subdomains to be resolved to proxy.
- MAP test.com [::1]:77 Forces test.com to resolve to IPv6 loopback. Will also force the port of the resulting socket address to be 77.
- MAP * baz, EXCLUDE www.google.com Remaps everything to baz, except for www.google.com.

These mappings apply to the endpoint host in a net request (the TCP connect and host resolver in a direct connection, and the CONNECT in an HTTP proxy connection, and the endpoint host in a SOCKS proxy connection).

官方文档有语焉不详的提到过

https://chromium.googlesource.com/chromium/src/+/refs/heads/main/net/dns/README.md

Starting Chrome with --host-resolver-rules="MAP the.hostname.com [dead::beef]" where the.hostname.com is the hostname to allow resolving and dead::beef is the IPv6 address to resolve it to. net::MappedHostResolver acts at a level before IPv6 connectivity checks, and if a hostname is remapped to an IP literal, connectivity checks do not apply.

还有很多 proxy的参数

curl 的参数

也顺便贴一下。调试的时候用得上

参数:

  • -4, --ipv4
  • -6, --ipv6
  • --dns-interface <interface>
  • --dns-ipv4-addr <ip-address> Tell curl to bind to <ip-address> when making IPv4 DNS requests
  • --dns-ipv6-addr <ip-address> Tell curl to bind to <ip-address> when making IPv6 DNS requests
  • --dns-servers <ip-address,ip-address> Set the list of DNS servers to be used instead of the system default. The list of IP addresses should be separated with commas. Port numbers may also optionally be given as :<port-number> after each IP address.
  • --resolve <host:port:address> Make the curl requests(s) use a specified address and prevent the otherwise normally resolved address to be used. Consider it a sort of /etc/hosts alternative provided on the command line. The port number should be the number used for the specific protocol the host will be used for. It means you need several entries if you want to provide address for the same host but different ports. This option can be used many times to add many host names to resolve. (Added in 7.21.3)

最后一个很有用 😹

Posted

stdout

reverse proxy FastCGI (fcgi) with uWSGI

People are still using FastCGI, and it's hard. I used uWSGI to convert FCGI traffic to regular http/1.0 so I can keep my existing http service running without apache mod_fcgi shit.

CGI environ variables

This is some ancient knowledge, better keep them noted

KEY description
AUTH_TYPE ignore this
REMOTE_IDENT The user making the request.
REMOTE_USER The authenticated name of the user making the query.
CONTENT_LENGTH byte length of body
CONTENT_TYPE MIME such as text/html, without the charset shit
DOCUMENT_ROOT NEW. The directory from which web documents are served.
REQUEST_URI NEW. confusing shit similar with PATH_INFO
HTTP_* HTTP headers
PATH_INFO like /a/b/c
PATH_TRANSLATED not really used
QUERY_STRING the part after ? in an URL
REMOTE_ADDR client IP
REMOTE_HOST client host name by lookup ip
REQUEST_METHOD GET/POST
SCRIPT_NAME The virtual path (e.g., /cgi-bin/program.pl) of the script being executed.
SCRIPT_FILENAME confusing shit similar with SCRIPT_NAME
SERVER_NAME The server's hostname or IP address.
SERVER_PORT The port number of the host on which the server is running.
SERVER_PROTOCOL The name and revision number of the server protocol.

reverse proxy FastCGI with uWSGI

slap this into my_conf.ini

  [uwsgi]
  my_port = 9000  # can be set otherwise
  route-run = addvar:SERVER_NAME=%h
  route-run = addvar:SERVER_PORT=%(my_port)
  route-if  = empty:${REQUEST_METHOD} addvar:REQUEST_METHOD=GET
  route-if  = empty:${HTTP_HOST} addvar:HTTP_HOST=%h:%(my_port)
  route-run = seturi:/fcgi-proxy${PATH_INFO}
  route-run = http:127.0.0.1:9527
  fastcgi-socket = 0.0.0.0:%(my_port)
  http-socket = 0.0.0.0:8000  # for testing purpose.

Install uWSGI, install the binary from pypi wheels instead of compiling uwsgi.c shit

  pip install pyuwsgi

Run it

  uwsgi --ini my_conf.ini

Now you can run your regular http service behind 127.0.0.1:9527, while serving fcgi on 127.0.0.1:9000

Requests like fcgi://127.0.0.1:9000/hello will be fowwarded to http://127.0.0.1:9527/fcgi-proxy/hello

You may ask why adding a /fcgi-proxy in path? Because there's a gotcha.

fuckedup FastCGI requests

Learned this from some php-fpm tutorial, first install the standard fcgi client tool because curl doesn't speak fcgi.

  apt-get install libfcgi0ldbl
  yum --enablerepo=epel install fcgi
  SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000

You can observe from uWSGI logs that cgi-fcgi command sends flawed requests, the PATH_INFO was unset.

After hours wasted, I came up with a clever hack to force uWSGI's internal router to force seturi with a path prefix

ToDo

There are further problems that can be improved, for example, my http service is running uvicorn, it can not guess the client ip:port infor from its stupid get_remote_addr

what's worse, the uWSGI addheader directive are for responses, so I can't add request headers like x-forwared-for.

Also the reverse proxy is HTTP/1.0 only. to make the Connection: Keep-alive happen needs some further investigation.

Q&A

Thanks for reading my shitpost. Questions?

Posted

stdout

20211102币圈的古诗词大会

第一个是 Elon Musk 的

https://twitter.com/elonmusk/status/1455327010302087173

Humankind 煮豆燃豆萁 豆在釜中泣 本是同根生 相煎何太急

Shiba 大战 Dogecoin,然后SpaceX 大战 Blue Origin,然后怼 WFP David Beasley。

我觉得 DeepL 翻译得真好!

当然也有长者的,微博上有个 大弟子Leo 找到了视频,看水印是 AP 的,我去搜了下发现真的有 https://youtu.be/oSG01RUdUUg?t=71

然后学习了一下,这首诗原来是六句,最早出现在南北朝刘宋的《世说新语》:

煮豆持作羹, 漉菽以為汁。 萁在釜下燃, 豆在釜中泣。 本自同根生, 相煎何太急。

然后是币圈的大佬们继续背诗

十年磨一剑 霜刃未曾试 今日把示君 谁有不平事

https://twitter.com/GMEdd/status/1455363193455452166

真是疯狂的一天啊。

via

Posted

stdin

淘宝同一手机最多绑定6个小号

总结一些没用的知识

  1. 淘宝/阿里账号,可以一个手机最多绑定6个账号。淘宝注册的时候点击「企业注册」然后用邮箱注册,最后用同一个手机验证即可

  2. 「支付宝」在淘宝/阿里系里app里是和「账号」一一绑定的,这就产生了很多冲突。比如你一个第三方外卖app,支付的时候可以选择 微信/支付宝,一般不会限制下单手机号和支付手机号是否一样,你甚至可以帮别人支付订单,但是淘宝/阿里的app不一样,只能自己账号支付自己账号的订单。如果你有两个手机号和两个支付宝账号,那么没法交叉支付。

还有一个想不起了,想起了再补充。2333

Posted

stdout

《兵车行》竖排实验

群里闲聊起究竟生男好还是生女好,就想起了这首诗

兵车行——杜甫 车辚辚,马萧萧,行人弓箭各在腰。 耶娘妻子走相送,尘埃不见咸阳桥。 牵衣顿足拦道哭,哭声直上干云霄。 道旁过者问行人,行人但云点行频。 或从十五北防河,便至四十西营田。 去时里正与裹头,归来头白还戍边。 边庭流血成海水,武皇开边意未已。 君不闻,汉家山东二百州,千村万落生荆杞。 纵有健妇把锄犁,禾生陇亩无东西。 况复秦兵耐苦战,被驱不异犬与鸡。 长者虽有问,役夫敢申恨? 且如今年冬,未休关西卒。 县官急索租,租税从何出? 信知生男恶,反是生女好。 生女犹得嫁比邻,生男埋没随百草。 君不见,青海头,古来白骨无人收。 新鬼烦冤旧鬼哭,天阴雨湿声啾啾!

测试下 css 的文字竖排。

字体来自 fonts.css

Posted

stdout

Re-index page on Google Search Console

Request indexing webpage with Google used to be fun and simple, now it's a tedious task especially when you have tons of old pages ready to be crawled yet Google is reluctant to move.

Here is a simple script to speed up the stacks of page you have click in order to submit multiple missing pages to Google.

Open your Google Search Console, click Coverage then open Discovered – currently not indexed

Now open your browser devtool, paste these into javascript console, hit them one by one.

  document.querySelector('div[data-disabled] table td span[title] span[title="Inspect URL"]').click()

  document.querySelector('span[data-event-action=request-indexing] span[jsslot] div span span').click()

  document.querySelector('span[data-event-action=pivot-to-report-main-view-indexing-section] a').click()

Until you met with the daily quota. Rinse and try this shit everyday.

Fuck Google.

Posted

stdout

人教版语文课程《一只奶酪》

起初是娃的一个作业,被打了叉,百思不得其解

于是翻开课文仔细读一下

一块奶酪 作者:辛勤

蚂蚁队长集合好队伍,向大家宣布:“今天搬运粮食,只许出力,不许偷嘴。谁偷了嘴,就要受到处罚。 一只小蚂蚁在队列里嘀咕:“要是偷嘴的是您呢?”蚂蚁队长说:“照要就受处罚。” 大家一听,都来劲了,争先恐后赶到运粮地点,抢着抬大的,搬重的,谁也不愿偷懒。
就在这时,蚂蚁队长发现了一块大奶酪。那块奶酪实在太大了,他左抬抬不起,右搬搬不动,只好叫来七八只小蚂蚁当助手。
奶酪多诱人啊!抬着它,不要说吃,单是闻闻,都要淌口水。小蚂蚁们嘴叼着它,要做到不趁机舔一下,那要多大的毅力,多强的纪律性啊!
蚂蚁队长叼着奶酪一角往前拽着,也许是用力过猛,一下就把那个角拽掉了。盯着那一点掉在地上的奶酪渣,蚂蚁队长想:丢掉,实在可惜;趁机吃掉它,又要犯不许偷嘴的禁令。怎么办呢?他的心七上八下,只好下令:“休息一会儿子!”
听到命令,大家放下命令,却不走开。 “大家分散开,哪里凉快就到哪里休息。” 大家依旧不动,眼睛望着别处,心却牵挂着那一点儿奶酪渣子。
蚂蚁队长生气了。他登上一块大石板,突然下令:“注意啦,全体都有。稍息!立正!向后——转!齐步——走!”等小蚂蚁们消失在草丛中,他才大叫:“立——定!原地休息!”
这时,奶酪旁边只有蚂蚁队长,他偷个嘴,谁也看不见。他低下头,嗅嗅那点儿奶酪,味道真香!可是,他犹豫了一会儿,终于一跺脚:“注意啦,全体都有。稍息!立正!向后——转!齐步——走!”
小蚂蚁们从四面八方的草丛里走拢来了。当他们重新聚到奶酪旁边时,蚂蚁队长命令年龄最小的一只蚂蚁:“这点儿奶酪渣是刚才弄掉的,丢了可惜,您吃掉它吧!”
大家又干起活来了,劲头比刚才更足,奶酪一会儿就被搬到洞里去了。

读完这篇课文,对其故事没多少印象了,但是小时候也是被这「总结中心思想」搞出 PTSD了,再回头看看孩子的答案,貌似没毛病啊。为啥没答对呢,这是什么鬼。

只能网上搜一下答案,搜完之后我他妈裂开了,比如

Q: 蚂蚁们为什么争先恐后的搬运粮食?
A: 蚂蚁们听到蚂蚁队长说要和大家一起遵守规则,不搞特权,他们的积极性被调动起来了。
Q: 蚂蚁队长为什么两次下了同样的命令?他想干什么?
A: 蚂蚁队长第一次下命令是想让蚂蚁们离开,自己吃了这点儿奶酪渣,因为他实在抵制不了美食的诱惑。可是经过激烈的思想斗争,他改变了自己的想法,决定把这点儿奶酪渣留给年龄最小的蚂蚁吃。从这里可以看出蚂蚁队长具有抵制诱惑的勇气,能够以身作则,也反映了蚂蚁队长关爱弱小的品质。

我心里一万个问号,孩子学习语文,应该是从简单到困难吧,对社会这种复杂组织,孩子懂个屁什么叫「特权」?

搜了下作者:

辛勤 (1939~) 笔名良驽、木兰。云南昆明人。1960年毕业于昆明师专文史系。历任县中学教员、县委宣传部干事、云南人民出版社编辑、晨光出版社编辑室主任、《蜜蜂报》主编,副编审。云南省家庭教育研究会副会长。1956年开始发表作品。1990年加入中国作家协会。著有短篇儿童小说集《装在葫芦里的故事》,中长篇儿童小说《绿孔雀与金角龙》、《替身演员》、《小哥俩猎虎》、《鬼谷》、《魔匣》等,散文集《智慧女孩》,儿歌集《心灯》等。中篇小说《火把歌》获上海儿童文学园丁奖。2005年获中国青少年社会教育银杏奖突出贡献奖。

所以这就很容易理解了。这篇课文就是当年文革时期小镇宣传部笔杆子,写的一篇时政讥讽文。无非就是共产党功勋集团讲特权,脱离群众,私分蛋糕那些破事。问题是这些东西真的适合给孩子当教材学么?孩子真的搞得懂斗争么?

仔细一想,这特么哪跟哪呢。首先现实世界的工蚁是没有特权一说的,都是给蚁后打工,组织形式和人类有很大差别。其次虽然这蚂蚁队长嘴上没吃到奶酪,但是一会儿立正散开,一会儿立正回来折腾其他蚂蚁何尝不是滥用特权?然后这就算队长抵制诱惑了?它把奶酪分给小蚂蚁只不过是慷他人之慨,随意去分配受损资产,何尝不是一种特权?最后,为啥最小的蚂蚁吃到奶酪渣,别的蚂蚁就不闹了?难道发放奶酪有一个从幼到长的机制作为前提?想到这一层,莫非是发动群众斗群众?

其实分蛋糕这个问题,要的不是队长的高觉悟和内心斗争,有一个非常行之有效古老的办法,那就是先分蛋糕的人最后拿。这种靠队长的主观能动性「摆平」事情的,我觉得还是有一种居高临下藐视小蚂蚁的阶级优越感思维存在。可能是灌输论的遗毒吧。

作为小学语文课本,没有语言艺术性,没有文学性,没有故事性,纯粹就是阴阳怪气谜语人,《读者》式的鸡汤味。

想到这里,我觉得,孩子们对中心思想拿捏不准真的不是孩子的问题。标准化答案真的害人。垃圾课文真的应该滚出课本。

Posted

stderr

软件开发流程高血压五步曲

有个说他们实习生按字面意思回答了一个题

正经的回答是什么呢?

  1. design
  2. develop
  3. test
  4. fix
  5. deploy

还是

1 ...Sales guy tells you he sold a product
2 ...That doesn't exist
3 ...Using tech your team has no previous expertise
4 ...On a timeline the client dictated.
5 ...and they already cashed the deposit.

还是

  1. Boss: “Hey can you do this thing real quick? Here’s an example of the input data.”
  2. Me: “This can’t me done with the current architecture and would require a full redesign of the current approach.”
  3. Boss: “Yes but I just need {seemingly simple task} done real quick. Also could you join this meeting that you’re not on and started 15 minutes ago?”
  4. Join the meeting. Other team: “Hey Achrus, you’re late could you please try to be here on time. Where are you at on {seemingly simple task}. Our timeline needs you to be done with this yesterday. You’ve had two weeks and we need this to proceed.”
  5. Panic code some hacky solution in a few days, other team celebrates “their” success.

看到最后这一种,血压都上来了。。。

Posted

stdin

Letsencrypt 在老版本macOS Ubuntu 上修复TLS证书错误

一觉醒来,打开浏览器,各种连不上,调试了一下发现说lets encrypt 的 acme https证书错误

仿佛记得V站讨论过这个事,以为和自己无关,结果也中招了。DST Root CA X3 根证书在国庆前过期了。

老版本 Ubuntu 修复:

  sudo apt update
  sudo apt install ca-certificates

老版本 macOS 修复:

需要手动导入并信任新的 ISRG Root X1 根证书。来自https://letsencrypt.org/certificates/

保存下列为 1.pem

  -----BEGIN CERTIFICATE-----
  MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
  MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
  DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
  TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
  cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB
  AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC
  ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL
  wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D
  LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK
  4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5
  bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y
  sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ
  Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4
  FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc
  SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql
  PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND
  TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
  SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1
  c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx
  +tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB
  ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu
  b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E
  U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu
  MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC
  5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW
  9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG
  WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
  he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
  Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
  -----END CERTIFICATE-----

打开 keychain access,把这个 1.pem 拖入 system,双击打开,在 Trust 这个下拉,选择 信任。

因为浏览器没法用,所以搜索资料也麻烦。真是差点锁死。

Posted

stdout