防空警报和防灾警报

防空警报

每年9月的第三个星期六是(中华人民共和国)全民国防教育日,这一天部分城市会试鸣防空警报。今年(2022年)是9月17日。

防空警报通常分为:“预先警报、空袭警报、解除警报”三种形式。预先警报是在敌方对我方空袭有预兆时鸣响;空袭警报是在敌方对我方空袭即将或者已经开始时鸣响;解除警报是在敌方空袭结束时鸣响。

预先警报:鸣36秒,停24秒,反复三遍为一个周期。

空袭警报:急促短音鸣6秒,停6秒,反复十五遍为一个周期。

解除警报:连续鸣三分钟为一个周期。

国内不同城市和地区试鸣防空警报的日期并不一样,具体可以参考维基百科或者当地政府网站。

 

防灾警报

不同城市和地区的防灾警报形式并不相同,比如参考3和4对应(山东省)日照市的和浙江省的防灾警报形式就不一样。所以具体到各省市请查询当地政府网站。

 

References:

  1. https://zh.wikipedia.org/zh-cn/防空警报
  2. https://video.sina.cn/news/2022-09-17/detail-imqmmtha7647263.d.html
  3. http://www.rizhao.gov.cn/art/2022/9/14/art_207870_10435896.html
  4. https://www.zj.gov.cn/art/2022/5/12/art_1554467_59699356.html

在Mac中的根目录下创建文件(比如创建/data目录)

从El Capitan (OS X 10.11)引入System Integrity Protection (SIP)开始,mac就已经开始逐步加强对系统文件的写限制,到Catalina(macOS 10.15)时完全限制了在根目录下进行写操作。从Catalina开始,官方提供了synthetic.conf文件以支持在根目录下创建软链。

可以通过man synthetic.conf查看文档。

操作步骤:

  1. sudo vi /etc/synthetic.conf

进行文件映射 or 软连接,如:

data Users/username/log
data1 Users/username/log1

注意:
1)  每行的两项配置不是以/开头。(可以理解系统会帮我们加入前缀/)
2)  data 与 Users/username/log 之间是使用tab进行分隔,否则重启后无效。如果指定目录不存在记得mkdir目录。

  1. 重启Mac,然后ls -l 就会发现/data, /data1就会存在了。

如果发现/data目录没有被创建,那么检查下你的/etc/synthetic.conf文件里的Tab分隔符是否被正确配置了。有的机器的vim配置了set expandtab,导致Tab被自动转换成了多个空格。这个时候可以在编辑模式下,先按ctrl+v再按tab键,就可以输入Tab了。可以用xxd查看,Tab是ASCII码是09,而空格的是20。

xxd  /etc/synthetic.conf

空格的情况(错误的情况)
00000000: 6461 7461 2020 2020 5573 6572 732f …  data    Users/…

Tab的情况(正确的情况)
00000000: 6461 7461 0955 7365 7273 2f…  data.Users/…

 

References:

https://javabase.cn/p/114

https://developer.apple.com/forums/thread/670391

 

聊聊WebSocket

  • WebSocket介绍

WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信,位于OSI模型的应用层。WebSocket协议在2011年由IETF标准化为RFC 6455,后由RFC 7936补充规范。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。

  • HTTP和WebSocket之间的异同点。

WebSocket是一种与HTTP不同的协议。两者都位于OSI模型的应用层,并且都依赖于传输层的TCP协议。 虽然它们不同,但是RFC 6455中规定:it is designed to work over HTTP ports 80 and 443 as well as to support HTTP proxies and intermediaries(WebSocket通过HTTP端口80和443进行工作,并支持HTTP代理和中介)。 为了实现兼容性,WebSocket握手使用HTTP Upgrade头从HTTP协议更改为WebSocket协议。
与HTTP不同,WebSocket提供全双工通信。
WebSockets URI的格式如下:

ws-URI = “ws:” “//” host [ “:” port ] path [ “?” query ]
wss-URI = “wss:” “//” host [ “:” port ] path [ “?” query ]

ws和wss分别对应明文和加密连接(对比HTTP和HTTPS)。

  • WebSocket实战

因为WebSocket被设计为和HTTP/HTTPS一起工作在80/443端口并且支持HTTP代理和网关,所以一个服务端程序同时接收HTTP和WebSocket请求。对,没错,一个Server端程序可以同时接收HTTP请求和WebSocket请求。

Demo如下:

//处理普通的HTTP请求
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello, world!"))
})
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, "index.html") 
})
http.HandleFunc("/ws/chat", func(w http.ResponseWriter, r *http.Request) {
    //这里写一个读取cookie的实例是告诉大家,在处理WebSocket的handshake请求时,服务端是可以读到该域名下的cookie的,具体细节和HTTP协议规范一致。 
    cookie, err := r.Cookie("key")
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("cookie:" + cookie.String())
    }
    //使用github.com/gorilla/websocket 
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
        return
    }
    //... 
    //此处conn就是一个websocket连接了,服务端可以通过conn来发送消息给客户端 
})

仔细一想,你就会明白。客户端发起ws请求,第一次握手(handshake)的请求和正常的HTTP请求体的格式是遵循的同一个规范——RFC2616。所以WebSocket的第一次握手请求正好被设计为要求和正常的HTTP请求体一样,这样就解答了为什么在一个普通的HTTP Server程序只监听一个端口的情况下可以同时处理HTTP请求和WebSocket请求了。同时也请注意对客户端而言,是建立了两个连接:一个HTTP连接,一个WebSocket连接。

如果你还是不明白,那么我换另外一种说法:

客户端发起了一个请求,可能是HTTP请求也可能是WebSocket,但是他们的请求体格式是一样的。服务端可以事先和客户端约定,根据path路径区分来源,进而决定哪一个是当HTTP请求处理:返回正常HTTP Response,哪一个当WebSocket请求处理:返回Upgrade,继而持有连接实现双向通信。

摘抄部分RFC内容如下:

The handshake MUST be a valid HTTP request as specified by [RFC2616].
The method of the request MUST be GET, and the HTTP version MUST be at least 1.1.
For example, if the WebSocket URI is “ws://example.com/chat”, the first line sent should be “GET /chat HTTP/1.1”.

 

References:

https://datatracker.ietf.org/doc/rfc6455

https://zh.wikipedia.org/wiki/WebSocket

https://developer.mozilla.org/zh-CN/docs/Web/API/WebSockets_API/Writing_WebSocket_servers

 

记录使用unredacter的流水账

unredacter是一个实验性的还原图片中打马赛克的文字的小工具。具体介绍请见github(https://github.com/BishopFox/unredacter)。 README中使用说明部分描述的使用步骤很简单,但是如果你照着尝试,会发现程序跑不起来,各种报错(node的三方库版本依赖的天坑😭),我就将我淌坑的经历记录下来吧。

工作环境:windows 11(因为windows 11才支持wslg),启用wsl2,使用Ubuntu 22.04镜像

步骤:

1. (wsl2的Ubuntu里)安装node v12版本。(直接去官网下载v12版本的二进制文件 https://nodejs.org/download/release/v12.22.12 ,将bin目录加到path路径即可)
2. (wsl2的Ubuntu里)下载源码到本地https://github.com/BishopFox/unredacter
3. (wsl2的Ubuntu里)进入项目根目录,执行 npm --registry https://registry.npmmirror.com install (注意:不要再使用https://registry.npm.taobao.org这个镜像地址了,该地址已经停用了)
4. (wsl2的Ubuntu里)进入项目根目录执行npm --registry https://registry.npmmirror.com install electron@10 (注意一定要安装electron v10版本, v11版本就不行)
5. (wsl2的Ubuntu里)进入项目根目录执行npm start

最终效果图:

问题1: 如果在执行 npm start时遇到如下错误:[5095:0621/232535.423408:FATAL:gpu_data_manager_impl_private.cc(442)] GPU process isn’t usable. Goodbye.
/home/{username}/unredacter /node_modules/electron/dist/electron exited with signal SIGTRAP

解决办法:在windows 11下需要按照官方说明安装对应显卡厂商的显卡驱动(https://github.com/microsoft/wslg ),这样wsl2就支持使用GPU了。

问题2: unredacter已经能正常工作了,但是隔了几天突然又不能工作了,有如下报错:
../../third_party/tcmalloc/chromium/src/tcmalloc.cc:337] Attempt to free invalid pointer 0x55dd1f867dc0
/home/{username}/unredacter-main/node_modules/electron/dist/electron exited with signal SIGSEGV
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! unredacter@1.0.0 start: `npm run build && electron ./dist/main.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the unredacter@1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

解决办法:检查你的显卡驱动是不是被操作系统升级,导致和wslg不兼容了。对于AMD:

 

 

References:

https://mp.weixin.qq.com/s/W20dZpX6nJrNFMrXB4P4Mg

 

查看Linux内核和发行版本的方法

查看Linux发行版本的方法

  • cat /etc/issue,适用于所有的发行版本
  • lsb_release -a,也适用于所有的发行版本,但是有些发行版本(尤其是一些精简版的镜像)可能没有预置lsb_release,需要手动安装。
  • cat /etc/redhat-release,这种方法只适合Redhat系的发行版本,包括CentOS
  • cat /etc/centos-release,只适用于CentOS

 

查看Linux内核版本命令

  • cat /proc/version
  • uname -a

记PHP比较运算符的一个用例

最近被问到如下的一道题:

$x = false;
$i = 9;
for ($i = 9; $i > $x; $i -= 2) {
    echo $i . "\n";
}
//请说出代码执行后的输出结果。

一般想到int类型$i和bool类型的$x比较,bool类型的false会被转换成int类型的0,所以代码块会有5次输出后停止结束。

那么实际执行结果是怎样的呢?

实际执行一次,就会发现,结果是无限循环输出:9,7,5,3,1,-1,-3,-5,……。

为什么呢?

仔细查看PHP文档:https://www.php.net/manual/en/language.operators.comparison.php

会发现有这样的描述:

Type of Operand 1 Type of Operand 2 Result
null or string string Convert null to “”, numerical or lexical comparison
bool or null anything Convert both sides to boolfalse < true
object object Built-in classes can define its own comparison, different classes are uncomparable, same class see Object Comparison
stringresourceint or float stringresourceint or float Translate strings and resources to numbers, usual math
array array Array with fewer members is smaller, if key from operand 1 is not found in operand 2 then arrays are uncomparable, otherwise – compare value by value (see following example)
object anything object is always greater
array anything array is always greater

其中第二行就有关于bool类型和其他类型的比较,有明确说明,会把其他类型转换成bool类型。那么上文中的这道题,$i总是不等于0,即意味着$i总是会被转换成bool类型的true,true永远大于false,所以会有无限循环的输出。

 

无法比较的两个概念:JWT和Session

这两个概念单独解释其实很简单,但是混在一起可能会说不清。正好看到网上有人聊起了这个,我就做个整理,也当知识回顾。

问题:为什么要用 jwt token 来做身份认证,而不是使用session+cookie方式?

那么我们先看概念本身的解释:

JWT ——JSON Web Token

JWE——JSON Web Encryption

JWS——JSON Web Signature

Session,此处可以翻译为会话,指客户端和服务端维持有状态的一种通信机制。根据Session Data的存储位置,可以分为Server Side Session和 Client Side Session。一般说的session & cookie机制是指使用的Server Side Session。

所以JWT和Session不是同一个概念的东西,没法拿来比较。回头再看这个问题就发现有点意思了。我们使用jwt token来做身份认证,我们可以把jwt token(会含有一些用户信息)通过cookie、HTTP头,url参数等多种方式下发给客户端(Client Side Session)从而实现session机制;而传统的服务端session-data + session-id(by cookie)方式,session-id只是一串随机字符串,不用解析,在和服务端交互时直接原样传输就行了。所以原作者问题可能是Server Side Session和Client Side Session的区别!

References:

https://en.wikipedia.org/wiki/JSON_Web_Token

https://blog.by24.cn/archives/about-session.html

https://www.v2ex.com/t/774127

1MB=1024KB? 1000KB?

如题,这个问题第一感觉是1MB肯定等于1024KB,只有在硬盘生产厂商那里才会使用1000进制。事实是如此吗?最近被人补了一课,了解单位换算中的两种标准。

按照国际单位制的标准: 1MB=1000KB (1Megabyte = 1000Kilobyte)
按照IEC 60027-2标准: 1MiB=1024KiB (1Mebibyte = 1024 Kibibyte)

字节的次方单位
十进制前缀
(SI)
名字 缩写 次方
Kilobyte KB 103
Megabyte MB 106
Gigabyte GB 109
Terabyte TB 1012
Petabyte PB 1015
Exabyte EB 1018
Zettabyte ZB 1021
Yottabyte YB 1024
二进制前缀
(IEC 60027-2)
名字 缩写 次方
Kibibyte KiB 210
Mebibyte MiB 220
Gibibyte GiB 230
Tebibyte TiB 240
Pebibyte PiB 250
Exbibyte EiB 260
Zebibyte ZiB 270
Yobibyte YiB 280

所以严格来说如果显示为1MB,则说明使用的是国际单位制标准,等于1000KB。1MiB说明是使用的IEC 60027-2标准,等于1024KiB。

  • 但是注意,Microsoft Windows系统中仍在大量使用公制前缀的二进制写法(比如显示为1MB的文件,按理说应该是使用的SI标准,等于1000KB,但是实际windows却按IEC 60027-2标准来处理的,实际文件大小是1024KB)。
  • Mac OS X自Snow Leopard(v10.6)发行以来,文件大小均是以十进制前缀记录的(比如显示为14KB,87.1MB)。(但是在shell环境里,部分软件使用的M,K等标识符表示1024进制,比如ls;但是df命令使用的是Gi,Mi等SI单位制的符号)

 

References:

https://zh.wikipedia.org/wiki/国际单位制

https://zh.wikipedia.org/wiki/千字节

聊聊固态硬盘(SSD)的接口和协议

固态硬盘固态驱动器(英语:Solid-state drive或Solid-state disk,简称SSD)是一种以集成电路制作的电脑存储设备。

最近如果你要买SSD,可能会频繁接触到M.2,NVMe,PCIe这几个名词。我上一次单独买SSD时,虽然已经是M.2接口了,但是当时没见NVMe协议,最近正好关心了SSD,就正好接机学习了解下。

  1. 接口:M.2是一种接口规范,与之类似的有U.2SATA接口mSATA接口,SATA Express接口,PCIe接口等。
    注意:SATA同时也是一种系统总线的名称,所以要区别SATA接口和SATA总线。SATA Express协议使用的接口是由两个传统的SATA样式的接口和一个小接口组成,因此也能当作两个SATA来用。
  2. 逻辑设备接口规范NVMe(NVM Express,或者Non-Volatile Memory Host Controller Interface Specification (NVMHCIS),AHCI(Advanced Host Controller Interface)
  3. 总线: SATA,SATA Express,PCI,PCI Express(PCIe)

 

下面这个短视频有很生动的介绍:

https://www.youtube.com/watch?v=alb6-zp52mA&t=505s

NVM Express(缩写NVMe),或称非易失性内存主机控制器接口规范(英语:Non-Volatile Memory Host Controller Interface Specification,缩写:NVMHCIS),是一个逻辑设备接口规范。它是基于设备逻辑接口的总线传输协议规范(相当于通讯协议中的应用层),用于访问通过PCI Express(PCIe)总线附加的非易失性存储器介质(例如采用闪存固态硬盘驱动器),虽然理论上不一定要求PCIe总线协议。NVMe是一种协议,是一组允许SSD使用PCIe总线的软硬件标准;而PCIe是实际的物理连接通道。

所以当下性能最佳的SSD的技术方案组合应该是:M.2接口+NVMe+PCIe。早些年在NVMe普及之前,有M.2接口+AHCI+SATA的SSD。SATA接口+AHCI+SATA总线的SSD也有,估计都是没有M.2接口的老电脑升级用吧,现在京东上都还有卖的。

 

References:

https://zh.wikipedia.org/wiki/PCI_Express

https://zh.wikipedia.org/wiki/SATA

https://zh.wikipedia.org/wiki/SATA_Express

       (SFFWG Renames PCIe SSD SFF-8639 Connector To U.2)

https://zh.wikipedia.org/wiki/NVM_Express

https://zh.wikipedia.org/wiki/M.2