WebShell中实现SFTP文件管理
WebShell终端给了用户网页形式操作终端的能力后,还需要提供可视化的文件管理,具体来说就是文件上下载,权限修改,在线编辑等。
这里总结下关于这块的实现。
ssh2+ssh2-sftp-client
使用ssh2模块进行解决终端连接后,继续使用ssh2-sftp-client
来实现文件的相关操作
- list方法实现文件列表获取
- 返回值中可以拿到文件类型,文件名称,文件所属用户id,文件所属用户组id,文件大小,访问时间,修改时间
- 需要说明,如果是软链接,返回的type是
l
,硬连接的话会是-
- get/put方法实现流方式的上下载
- rename方法实现文件重命名
- delete方法实现文件删除
- stat方法实现文件信息获取
- mkdir方法实现文件夹创建
- rename方法实现文件重命名
如上使用这些方法可以解决了文件管理的一些基本问题,但还有些问题需要处理
问题
- 判断当前用户是否有权限
首先需要知道当前用户的uid,gid,因此需要走ssh2的exec执行id命令从而获取这些信息,然后当list方法返回文件的uid,gid后,两者进行比较判断即可确定权限
- 用户列表
GUI上需要实现修改文件所有者,通过执行文件list或者stat命令可以知道文件归属的uid,gid,因此只需要再获取user list即可。这里使用执行命令
1 | 返回格式如下 |
文件列表-隐藏文件显示控制
如果需要隐藏文件不可见,如下配置正则表达式,即过滤掉.开头文件
1
conn.list(path, /^[^.]/);
这里有意思的是SFTP协议是没有针对文件列表过滤支持的,因此ssh2实际上还是拿了全量的文件列表,在客户端进行的过滤。
ssh2-sftp-client v9已经调整了list方法,filter从正则改为了回调函数,还是可以实现上述效果
以终端会话的当前工作路径作为缺省打开路径
这个文件严格来说是终端部分,并不是SFTP问题,但支持该功能,非常提升UE。这个feat的实现简单,主要是利用了终端钩子,用户每次执行命令后,执行PWD命令,并将解决返回客户端,客户端解析PWD了解当前的路径并存储起来。这样当用户操作到某个路径下时,打开SFTP,将该路径作为path参数传入即可
1
2
3
4source /usr/local/bash-precmd/bash-preexec.sh
preexec() { printf "\x1B]1337;PreExec;Timestamp=$(date +%s);\x7"; }
precmd() { printf "\x1B]1337;PostExec;Exit=$?;CurrentDir=$(pwd);Timestamp=$(date +%s);CurrentUser=$USER;\x7"; }
除了SFTP协议下支持文件管理,还有一些其它情况,比如kubectl
kubectl
如果是kubectl管理连接的容器,那么并不能使用sftp协议,因此需要走透传执行各种命令来解决。命令获取后则解析结果
ls等命令来实现文件列表。但问题在于不同容器系统下命令存在一定程度的兼容性,这里就需要区分处理了
1
ls -l --time-style=full-iso /
- 如果是不显示隐藏文件,则增加
A
选项 - full-iso用于控制时间的格式化,如果不加的话,时间参数的格式受系统locale影响
- 如果是不显示隐藏文件,则增加
文件属性的方法不建议采用stat命令做,因为命令结果存在国际化部分,比如其中的文件类型,下图显示是directory,但是如果目标机器locale不是en,则会不同。
因此,这里推荐仍然走ls命令解决,注意携带参数d,这样结果只有一个,即目标文件/文件夹。另外注意与ls -l相比,没有第一行的统计结果。
1
ls -ld --time-style=full-iso /
写在最后
以上即为文件管理的大致实现,当然实际会比上述复杂些,但关键点还是这些
在WebShell上线了文件管理相关功能后,通过长期的观察,文件功能属于现有所有功能的No1,可见该功能非常重要。