NBD
NBD的全称是Network Block Device,网络块设备,简单理解就是通过网络访问的硬盘。
这里使用开源的jsnbd来实现NBD。通过jsnbd,Web浏览器成为了服务器端,存放着文件,而本地系统通过/dev/nbdx来访问Web浏览器文件。
下载
下载源码:
git clone https://github.com/openbmc/jsnbd.git
下载到目录:
$ ls
autom4te.cache configure.ac m4 nbd-proxy.c web
config.sample.json LICENCE Makefile.am README
编译
首先nbd-proxy.c依赖于JSON和udev,所以需要安装cjson库和udev库:
$ sudo apt install libjson-c-dev libudev-dev
之后需要生成makefile文件,具体过程如下(需要安装autoconf,pkgconf):
$ autoscan
configure.ac: warning: missing AC_CHECK_FUNCS([dup2]) wanted by: nbd-proxy.c:151
configure.ac: warning: missing AC_CHECK_FUNCS([memset]) wanted by: nbd-proxy.c:258
configure.ac: warning: missing AC_CHECK_FUNCS([socket]) wanted by: nbd-proxy.c:89
configure.ac: warning: missing AC_CHECK_FUNCS([strchr]) wanted by: nbd-proxy.c:398
configure.ac: warning: missing AC_CHECK_FUNCS([strdup]) wanted by: nbd-proxy.c:622
configure.ac: warning: missing AC_CHECK_HEADERS([fcntl.h]) wanted by: nbd-proxy.c:23
configure.ac: warning: missing AC_CHECK_HEADERS([limits.h]) wanted by: nbd-proxy.c:25
configure.ac: warning: missing AC_CHECK_HEADERS([stdint.h]) wanted by: nbd-proxy.c:28
configure.ac: warning: missing AC_CHECK_HEADERS([stdlib.h]) wanted by: nbd-proxy.c:30
configure.ac: warning: missing AC_CHECK_HEADERS([string.h]) wanted by: nbd-proxy.c:31
configure.ac: warning: missing AC_CHECK_HEADERS([sys/socket.h]) wanted by: nbd-proxy.c:35
configure.ac: warning: missing AC_CHECK_HEADERS([unistd.h]) wanted by: nbd-proxy.c:32
configure.ac: warning: missing AC_CHECK_HEADER_STDBOOL wanted by: nbd-proxy.c:48
configure.ac: warning: missing AC_CHECK_MEMBERS([struct stat.st_rdev]) wanted by: nbd-proxy.c:766
configure.ac: warning: missing AC_FUNC_FORK wanted by: nbd-proxy.c:133
configure.ac: warning: missing AC_FUNC_MALLOC wanted by: nbd-proxy.c:820
configure.ac: warning: missing AC_TYPE_PID_T wanted by: nbd-proxy.c:58
configure.ac: warning: missing AC_TYPE_SIZE_T wanted by: nbd-proxy.c:63
configure.ac: warning: missing AC_TYPE_SSIZE_T wanted by: nbd-proxy.c:196
configure.ac: warning: missing AC_TYPE_UINT8_T wanted by: nbd-proxy.c:62
$ aclocal
$ autoreconf --install
$ ./configure
$ make
完成之后得到nbd-proxy工具:
$ ls
aclocal.m4 config.log install-sh nbd-proxy
ar-lib config.sample.json LICENCE nbd-proxy.c
autom4te.cache config.status m4 nbd_proxy-nbd-proxy.o
autoscan.log configure Makefile README
compile configure.ac Makefile.am stamp-h1
config.h configure.scan Makefile.in web
config.h.in depcomp missing
使用
直接使用nbd-proxy工具会报错:
$ ./nbd-proxy
json_object_from_file: error opening file /usr/local/etc/nbd-proxy/config.json: No such file or directory
nbd-proxy: can't read configuration from /usr/local/etc/nbd-proxy/config.json
因为它需要配置文件,源代码中本来就有一个示例:
$ cat config.sample.json
{
"timeout": 30,
"configurations": {
"0": {
"nbd-device": "/dev/nbd0",
"metadata": {
"description": "Virtual media device"
}
},
"1": {
"nbd-device": "/dev/nbd1",
"metadata": {
"description": "Dump Offload"
}
}
}
}
将该文件拷贝到/usr/local/etc/nbd-proxy/目录并重命名为config.json,另外需要注意这里提到的/dev/nbdx,如果不安装会报错:
$ ./nbd-proxy
nbd-proxy: can't stat nbd device /dev/nbd0: No such file or directory
它们也需要额外安装:
$ sudo apt install nbd-client
$ sudo modprobe nbd
注意需要modprobe,之后可以看到在/dev下多出来了nbdx设备:
# ls /dev/nbd*
/dev/nbd0 /dev/nbd12 /dev/nbd2 /dev/nbd6
/dev/nbd1 /dev/nbd13 /dev/nbd3 /dev/nbd7
/dev/nbd10 /dev/nbd14 /dev/nbd4 /dev/nbd8
/dev/nbd11 /dev/nbd15 /dev/nbd5 /dev/nbd9
然后再运行nbd-proxy,报错如下:
nbd-proxy: no config specified, and no default
这里是代码本身还有问题,最简单的一个修改办法是去掉配置中的第二项,配置文件变成如下的样子:
$ cat /usr/local/etc/nbd-proxy/config.json
{
"timeout": 30,
"configurations": {
"0": {
"nbd-device": "/dev/nbd0",
"metadata": {
"description": "Virtual media device"
}
}
}
}
再次执行nbd-proxy还是会报错:
$ ./nbd-proxy
nbd-proxy: can't bind to path /usr/local/var/run/nbd.17370.sock: No such file or directory
/usr/local/var/run/nbd.17370.sock这个文件确实也不存在。
原因是下面的代码:
static const char *sockpath_tmpl = RUNSTATEDIR "/nbd.%d.sock";
这里的RUNSTATEDIR
就是/usr/local/var/run目录,但是这个目录在当前系统中无法创建,修改为如下的目录:
static const char *sockpath_tmpl = "/tmp/nbd.%d.sock";
程序就能够正常执行了。
当然光有这个程序还不够,因为jsnbd浏览器端依赖于websocket,所以需要额外的工具来支持。
这里使用websocketd工具,首先下载该工具:
sudo apt install websocketd
之后通过如下的命令启动websocketd和nbd-proxy:
$ sudo websocketd --port=8000 --staticdir=web --binary ./nbd-proxy
Wed, 18 Aug 2021 00:40:24 +0800 | INFO | server | | Serving using application : ./nbd-proxy
Wed, 18 Aug 2021 00:40:24 +0800 | INFO | server | | Serving static content from : web
Wed, 18 Aug 2021 00:40:24 +0800 | INFO | server | | Starting WebSocket server : ws://X1C:8000/
Wed, 18 Aug 2021 00:40:24 +0800 | INFO | server | | Serving CGI or static files : http://X1C:8000/
–staticdir指定了使用的web目录,jsnbd源码目录中存在web目录,其中包含index.html和nbd.js文件;–binary指定执行的二进制,就是nbd-proxy程序。
成功之后就可以打开浏览器,输入地址http://X1C:8000/,访问到的就是index.html文件:
点击“浏览”增加文件,然后点击“Serve Image”上传文件,结果如下:
可以看到上传的记录,也就是说文件被上传了。但是上传到哪里去了呢?这就要看前面提到的/dev/nbd0了:
$ sudo fdisk -l /dev/nbd0
Disk /dev/nbd0:25.5 MiB,26759168 字节,26132 个扇区
单元:扇区 / 1 * 1024 = 1024 字节
扇区大小(逻辑/物理):1024 字节 / 1024 字节
I/O 大小(最小/最佳):1024 字节 / 1024 字节
实际上这里看到的文件就是前面上传的sogoupinyin_2.3.1.0112_amd64.deb。不过大小有一些区别,这跟文件系统有关,问题不大。
点击“stop”再次查看,就会发现/dev/nbd0无法操作了:
$ sudo fdisk -l /dev/nbd0
fdisk: 打不开 /dev/nbd0: 对设备不适当的 ioctl 操作
这也证明了/dev/nbd0中确实包含了上传的文件。
总结
以上是nbd-proxy的一些基础内容,为了进一步了解nbd-proxy,对以下的内容还需要进一步了解:
- nbd-client
- websocket