Linux下解决同一硬盘因为连接设备不一样导致扇区大小不一致的问题

我有块硬盘放进了我家云盒子里面,前段时间想把这个硬盘拿出来插到电脑上面拷贝数据,结果发现分区表完全是乱的,分区变小了很多,在电脑上调整了分区表以后大小对了,放回我家云盒子,分区表又变得不合法了。

仔细研究了一下,发现硬盘直接接在电脑上面时候,扇区大小是 512 字节的,但是接在我家云盒子上面,扇区的大小是 4096 字节。之前有人说有些 USB 硬盘线也会造成这样的效果,大概也是相同的情况。分区表里面的单位都是按照扇区大小来计算的,所以分区大小自然也就不一样了

知道了这个原因就是想解决方式了。Linux 下面解决起来倒是简单,loop 设备设置的时候可以用 –sector-size 来设置大小,因此我们只要先不着急 mount 硬盘,用 losetup 设置一个扇区大小是 512 字节的 loop 设备。之后在 loop 设备上面再分区和格式化,就可以让这个硬盘在电脑上也可以正常读取了。

需要注意的是,不同的设备有可能导致最终看到的扇区数也是不一样的,我实测电脑比我家云盒子多看到几KB的大小,因此在 losetup 时候通常需要手动加上 –sizelimit 的值。

例如

losetup -P –sector-size 4096 –sizelimit 3000591892480 -f /dev/sda

之后直接对 loop 设备分区啥的就都很正常了

RHEL/CentOS/OracleLinux 8 yum 能看到,安装却没有的情况

最近发现 CentOS 强制升级到 OracleLinux 8 以后有些包用 yum search 可以看到,但是 yum install 却说没有。比如 golang 就是这样的。

简单研究了一下,是因为 RHEL8 里面引入了 module 的概念,可以把一些软件包给做成 module , 可以自己选择用哪个分叉,比如 gcc8 和 9 会依赖完全不同的两套软件包,这就可以做成两个不同版本的 module 。 yum search 能看到,但是安装不了就是因为 module 信息乱了,选了一个不存在的版本。

解决方案是 yum module reset , 有哪些 module 可以 yum module list 看,比如 golang 的就是 go-toolset,执行 yum module reset go-toolset 以后, yum install golang 就成功了。

让服务器响应整个网段中的请求

最近有个需求是让某个服务器能够响应一整个网段的请求,研究了一下,发现比想象的容易。

假设需要的网段是 172.16.0.0/16 (好多IP!) 我们需要让用户能用这个段里面任何一个 IP 访问我的服务器,服务器IP实际是 192.168.1.4 ,那么分这样两步走就行。

1: 在路由上将 172.16.0.0/16 设置一条静态路由,网关是 192.168.1.4
在别的机器上 ping 172.16 段里面任何一个 IP,肯定现在还 ping 不通,但是在 192.168.1.4 上抓包,保证报文已经被路由到了这台服务器
2: 给本机的 lo 上增加一条 local 表里面的路由
ip route add local 172.16.0.0/16 dev lo

然后就一切正常了。

PS: 这个办法 IPV6 一样可以用,例如
ip route add local fc::/64 dev lo
就可以让 Linux 响应 fc::/64 里面所有的 IP

PS1: 除了路由器上设置服务器为网关,其实还有其他办法让请求报文能到达服务器,V4 可以用 tarpd,V6 可以用 ndppd,但是这些方法都会给网关和服务器的 ARP 表和邻居表里面增加非常多的记录,对性能有很大影响,因此不建议使用,还是用静态路由的方式比较好。

PS2: 不要设置在 eth0 上,可能会造成一些其他问题,lo 就挺好的

不要买技嘉 X570 Gaming X 主板

装了这么多年电脑,头一次遇到被电脑主板散味熏的头疼了好几天的情况。。。

之前台式机是 3700X + MSI Mortar B450m, 用的没啥问题就是槽不够用,因为有加设备的需求,打算借机就换个 X570 飞一下,于是选择了一线品牌里面最便宜的这个 GIGABYTE X570 Gaming X,1099 大元入手。

拿到以后一看 PCB 觉得比较一般,看上去不像一线品牌应该有的样子,也没多想就直接上机了。结果开始烤机以后电脑机箱里面温度上升,主板就开始发出比较浓的化学品味道,熏得人坐立不安,大冬天的不得不开窗放气。开始想着这可能是临时现象,没想到过了几天依然如此,而且不开电脑时候依然有味,整个书房里面都充满了化学品的味道,简直要疯掉。

最后忍无可忍,简单做了一下功课以后,直接狗东下单微星 B550 暗黑,虽然是 B550 但是供电比 570 GAMING X 好太多,看在算是相对高端定位的份上,应该不会太差把。拿到以后上机果然没味。

以后买东西还是坚决不能买丐版,钱包不够好的话,还是稍微差一点的品牌的旗舰级别产品会更好一些。宁为鸡首不为牛后。

Golang socket 里面奇怪的 pipe 使用

有个 golang 写的 proxy server, 大概日常 tcp 连接数两万多左右,结果某次在 /proc/pid/fd 下面一看,竟然有五到六万多文件,ls -l 一看,居然 socket 只有两万多,pipe 反而有三万多小四万,这就奇了怪了,哪儿来的这么多 pipe?

读了一阵子源码搞清楚了,golang 在 Linux 下面,对于 fd 对拷这种操作【具体是 net.Conn.readFrom(net.Conn)】,有个用 splice 系统调用的优化,会先试着用 splice 调用在内核里面完成两个 fd 之间的拷贝,这个可以省去将大量数据从 kernel 里面拷贝到 user space 的操作。如果失败才正常拷贝。

然而 splice 这个调用可能是为了内部实现方便,目标一方必须是 pipe 类型的 fd。所以 golang 里面的实现其实比较龌龊,先创建一对 pipe fd,然后从源 fd splice 进 pipe 入端,接下来从 pipe 出端 splice 到目标 fd。 这样下来一个 readFrom 操作,里面要一次 pipe2 调用,2 次 splice 调用,还有 2 次 close 操作关掉 pipe。有趣的是,即使这么龌龊的实现,在数据量大的应用,比如 proxy 上面,依然可以达到比直接拷贝更好的性能,可以参考下面的第一个链接。

唯一感觉比较不爽的也就是每次 readFrom 都要创建 pipe 再销毁了,这个为了不影响 golang 的架构设计,可能也只能这么做。不过一般 proxy 里面最后大多是 io.Copy ,而这个调用一旦调用就直到 tcp 连接断开了,生命周期不会太短,所以完全没有必要再做任何优化了。

参考传送门

https://github.com/golang/go/issues/10948
https://github.com/golang/go/blob/0e85fd7561de869add933801c531bf25dee9561c/src/net/tcpsock_posix.go#L47
https://man7.org/linux/man-pages/man2/splice.2.html

最近评论

时光机

其他