【水】拿百度网盘备份大镜像的一种姿势与mkfifo命令、描述符和OpenSSL用于文件加密

Better pay for something instead of cry for losing everything!

【水】拿百度网盘备份大镜像的一种姿势与mkfifo命令、描述符和OpenSSL用于文件加密
Photo by Growtika / Unsplash
Better pay for something instead of cry for losing everything!

家里面新硬盘里存上一块盘的备份文件有470多个G大小。(为什么?因为这是一块全盘镜像)因此,我决定把它上传到百度网盘,毕竟一时半会估计用不着了,但说不准哪天还用得着。但是眼前立马出现了几个问题:

  1. 470多个G太大,baidupcs没法一次传完。#339
  2. 家里带宽太小,30Mbps小水管估计一时半会也没法直接传这么大的文件。
  3. 百度网盘是百度网盘,万一抽风删文件那还了得?

对于第一个问题,我的解决方法是拆分成一堆2GB大小的文件,一个一个传总传得完,稍小一点的文件重传成本也能接受。

对于剩下两个问题,我叫Copilot给写了个脚本。原本我想自己写的,奈何Copilot还是太热情了。☹️

百度网盘加密上传工具(Copilot写的)
百度网盘加密上传工具(Copilot写的). GitHub Gist: instantly share code, notes, and snippets.

脚本内容大概就是先压缩单个文件,然后加密、上传。但是如果单单这样未免有点太简单而且效率低下:压缩一个文件的时间跟上传一个文件的时间差不多长,要是压缩率没到50%那不久亏麻了!

Copilot给出了一套解决方案:首先,建立一个FIFO(mkfifo命令);然后,建立一个子进程,让它从这个FIFO里面读文件名。另外,Copilot还建了一个文件,用于计数目前存在在队列里面的文件数,这样只要计数文件归零了,子线程就能优雅地退出。计数文件不能被同时读写,所以还需要使用flock命令来建立一个锁文件锁住对计数文件的多重访问。


mkfifo是什么?

mkfifo(3) - Linux manual page

简单来说,FIFO是一个在文件系统里存在的特殊文件,跟pipe差不多。可以用这样来测试:

$ mkfifo test
$ echo "This is a test" > test # 此时会被阻塞
# 新建另一个终端
$ cat test # 此时上面的echo会被解除阻塞
This is a test

flock是什么?

flock(2) - Linux manual page

锁。


一切看起来都很好,甚至还考虑到了共享资源的加锁,不得不说还是AI牛逼。不过AI还是AI,它犯了个小错误。如果压缩+加密太慢,队列空了,那么还没传几个文件子进程就先人一步飘飘然而去矣。😃

可惜跟它说了一声之后它就明白了自己的错误。原本的列表是直接打开的,它将列表修改成文件描述符202打开。因为FIFO具有阻塞性质,所以它就不会因为暂时没有新输入而褒姒,而是知道接收到EOF后才断开。