搭建在线Selenium执行环境(二)
Keep Team Lv4

  在《搭建在线Selenium执行环境(一)》中描述了如何利用websocket和codemirror搭建一套Python远程执行环境,但是文章仅完成了前端与后端的数据通道,并没有让Python脚本真正的执行起来,那么今天就来实现后端实时执行这个关键需求。

  要完成远程执行Python这个目标,至少需要完成以下几点:

  1. 完整获取前端脚本文本内容(包括文本缩进格式)
  2. 将执行结果完整返回至前端
  3. 将错误信息完整返回至前端
  4. 主机安全保障

    完整获取前端内容

      Websocketd通过将接受到的数据转换为标准输入传递给处理脚本,之前我尝试用SHELL的read命令进行获取,发现这样的方案存在一个致命的缺陷,read会自动去掉读取字符串首位的空格。

The line is split into fields as with word splitting, and the first word is assigned to the first NAME, the second word to the second NAME, and so on, with any leftover words assigned to the last NAME. Only the characters found in $IFS are recognized as word delimiters.

  由于read会自动将读取到的字符串按词组进行分割,所以如果读取的该行数据带有缩进(一般为空格)就会被丢弃掉,进而导致接收到的Python脚本无法通过语法校验(Python格式需满足PEP8要求)。

  这种情况下显然不能依赖简单的SHELL命令了,我们需要一个能完整读取标准输入流中数据的脚本。我选择通过一个简单的Python脚本来完成这一工作。为什么选择Python呢?在后面会做解释。

  脚本很简单,只需要实现读取保存即可,代码如下:

pyfile = open('tmp.py', 'w')
size = sys.stdin.readline()
maxsize = int(size)
while(maxsize > 0):
    line = sys.stdin.readline().replace("\t","    ")
    pyfile.write(line)
    maxsize -= len(line)
pyfile.close()

脚本选取的考量

  脚本首先读取即将保存的文本大小(长度),然后循环读取这么多大小(长度)的数据即可。既然涉及文件长度的判断,那么不得不考虑中英文字符串长度的差别。前后端如果对长度判断存在误差,会导致后端接收数据不完整。我们前端肯定是通过JS来获取文本长度,那么后端应该选什么样的脚本来对接呢?实测发现Python的长度判断与JS一致,因此后端选择Python做接收脚本。回过头再来看看前端如何发送数据的。

function upload(editor, type){
    let content = editor.getValue();
    let blob = new Blob([content], {type: "text/plai
;charset=utf-8"});
    wss.send(content.length);
    wss.send(blob);
    wss.send("\n");
};

执行与返回

  既然后端已完整保存了前端输入的脚本内容,剩下的只需执行Python tmp.py就好了。可是执行时发现仅有成功执行的数据被送回前端,而错误信息均未送达。这又是为啥呢?原因在于Websocketd仅接收标准输出流,对于标准错误流是不处理的。既然如此,第一反应当然就是重定向标准错误流咯。下面是执行脚本:

env PYTHONIOENCODING=utf-8 python tmp.py 2>err.log
if [ -s "err.log" ]; then
   cat err.log
fi

  脚本将标准错误流重定向至err.log,并在该文件有内容的时候输出到标准输出流上,从而让所有信息都能通过Websocketd发送到前端。

效果

codeonline

  执行效果上看还不错,唯一有点麻烦的是每次执行完连接就会断开,再次执行前需要点一下连接。毕竟🤪

又不是不能用

主机安全

  目前我也没想好怎么做好相关的防护,虽然整个环境都运行在docker里。在《搭建Selenium执行环境》一文中曾提到要特别小心docker.sock的使用,其实除此之外还要小心Docker群组以及磁盘映射的配置。毕竟每个docker内部都是以root权限在运行,如果磁盘映射不合理,很容易给主机安全带来风险。

  等以后再系统性的总结相关的内容吧,毕竟我也需要多学习一下相关的知识和实战应用的经验呢。