STF STF 开发环境搭建与制作 docker 镜像过程

blueshark · 2016年06月19日 · 最后由 张三 回复于 2021年02月28日 · 5664 次阅读
本帖已被设为精华帖!

一、前言

看到很多同学在研究 STF,大部分人只是讲了怎么安装,然后运行一个 stf local 命令可以开始使用了,但是在实际使用中,比如大公司中肯定不能使用 stf local 方式给大家演示一下吧,哈哈~~~

另外也不能使用 mock 方式让任何人都能随意的登录。如果你想自己定制一些东西,需要自己对源码进行一些修改,说实话,想随意修改 stf 源码还真不是一件特别简单的事。下面根据我自己的一些经验介绍一个生产环境中 stf 平台的搭建及一些开发注意事项,希望想了解的同学不要踩这些坑。
参考前辈的一些文章,特别是 monkey 的 “STF 改造之 first blood”,给了我很大帮助,多谢他们!

(1)STF 改造之 first blood

(2)MAC 下 STF 的环境搭建和运行

(3)WEB 端批量移动设备管理控制工具 STF 的环境搭建和运行

二、生产环境中 STF 平台的搭建

这里是官方的搭建文档:
Deployment

官方推荐使用 docker 容器来搭建,根据我的使用经验,docker 容器确实更方便一些,关于 docker 的知识就不作介绍了,详情可以自行搜索,或者参考 docker 官方网站。

使用 docker 搭建 STF 平台需要 pull 下来五个镜像,这里假设你已经安装过了 docker 容器,为了加快 pull 速度,可以参考下面的文章,换成国内的 docker 镜像

Docker 学习笔记 — 配置国内免费 registry mirror

确定安装好 docker 以后,pull 下面几个镜像:

docker pull openstf/stf:latest
docker pull sorccu/adb:latest
docker pull rethinkdb:latest
docker pull openstf/ambassador:latest
docker pull nginx:latest

拉下来这几个镜像以后,stf 就可以直接在容器中运行了,也就是说你宿主机上完全不用再装 stf 的相关工具,甚至 adb 也不用。

很多文章介绍的装 stf 要先装一堆工具,然后使用 npm install -g stf 安装到系统中,大部分人会发现,由于网络或者其他原因,npm install -g stf 方式也不太容易成功,其实在 docker 里也可以直接运行 stf local,并且更加简单,使用以下三条命令即可:

#先启动一个数据库
docker run -d --name rethinkdb -v /srv/rethinkdb:/data --net host rethinkdb rethinkdb --bind all --cache-size 8192 --http-port 8090
#再启动adb service
docker run -d --name adbd --privileged -v /dev/bus/usb:/dev/bus/usb --net host sorccu/adb:latest
#再启动stf
docker run -d --name stf --net host openstf/stf stf local --public-ip your-ip

这样就可以直接从 7100 端口也访问了,下面介绍正宗的安装方式,先介绍下几个组件:

  • openstf/stf 就是 stf 主镜像了。

  • sorccu/adb 是 adb 工具,adb 工具是和 provider 模块在一台机器上的,这个后面会再说。

  • rethinkdb 就是数据库了,不知道开发者为什么想用这个数据库,而不用常用的 mysql 之类的,反正感觉这个数据库挺另类的,和 mysql 的查询语法完全不一样。 这里注意,官方文档上要 pull rethinkdb:2.1.1,但是现在版本的 stf 好像不支持 rethinkdb:2.1.1,经测试,最新版本的 rethinkdb 也是没问题的,所以就用最新的了。

  • openstf/ambassador 这个网络代理工具,是连接 docker 内部网络的一个工具,估计作者是基于 ambassador 官方镜像进行修改的,ambassador 可以让不同 dokcer 之前以私有网络的方式进行连接,可以理解为虚拟网络,如果你把所有的端口暴露在外面,这个东西也可以不要。

  • nginx,这是一个 web 服务器反向代理工具,详细的就不介绍了,反正 stf 依赖它将不同的 url 转发到不同模块上,反正没有 nginx,生产环境中的 stf 是肯定不能正常工作的。

好了,docker 镜像讲完了,下面就是搭建过程了,为了简单,所有的模块搭建在一台机器上,如果要搭建在不同机器,修改 nginx 里的反向代理 server 就行了。其实搭建就是启动几个 docker 容器,设置一些端口的事情。stf 作者希望用 systemd 来启动这些容器,在官方部署文档上可以看到类似下面的代码

[Unit]
Description=ADB daemon
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
Restart=always
ExecStartPre=/usr/bin/docker pull sorccu/adb:latest
ExecStartPre=-/usr/bin/docker kill %p
ExecStartPre=-/usr/bin/docker rm %p
ExecStart=/usr/bin/docker run --rm \
  --name %p \
  --privileged \
  -v /dev/bus/usb:/dev/bus/usb \
  --net host \
  sorccu/adb:latest
ExecStop=-/usr/bin/docker stop -t 2 %p

刚开始我纠结了几天,不知道这是个什么东西,其实它就是一个启动工具,跟手动执行 shell 命令是一样样的,只不过可以开机启动,或者在失败以后可以自动重启。在使用 sysyted 启动的系统中,systemd 所有可用的单元文件存放在 /usr/lib/systemd/system/ 和 /etc/systemd/system/ 目录(后者优先级更高),可以去这两个目录看看已经有脚本。

ubuntu 15.04 和 centos7 以后的版本都是使用 systemd 进行启动的,如果你用的这些系统,可以考虑使用 systemd 来启动 stf 容器,确实更方便一些,如果你不要使用 systemd,使用 shell 脚本也是可以的,为了更好理解,下面介绍时会 shell 脚本来启动。

为了搭建更加顺利,先介绍几个 docker 命令:

#运行docker镜像,不再多说
docker run 一大堆参数
#查看所有的docker镜像
docker images
#查看所有的docker运行实例
docker ps -a
#停止/杀死/删除/重启 docker实例
docker stop/kill/rm/restart
#查看docker的log
docker logs 实例名或ID

其中 docker logs 比较重要,docker 实例出了什么问题可以查看 log。

启动过程:

1、启动 nginx

一般来说,nginx 肯定要第一个启动的,因为它要转发不同 url 到不同的模块,启动 nginx 需要一个 nginx.conf 配置文件,官方给的配置文件比较复杂,而且启用了 ssl,我想大部分公司都不会在内网用 ssl 吧,所以就修改了一个简单的版本如下,这里的配置需要你根据情况来修改:

daemon off;
worker_processes 4;

events {
  worker_connections 1024;
}

http {
  upstream stf_app {
    server 192.168.3.16:3100 max_fails=0;
  }

  upstream stf_auth {
    server 192.168.3.16:3200 max_fails=0;
  }

  upstream stf_storage_apk {
    server 192.168.3.16:3300 max_fails=0;
  }

  upstream stf_storage_image {
    server 192.168.3.16:3400 max_fails=0;
  }

  upstream stf_storage {
    server 192.168.3.16:3500 max_fails=0;
  }

  upstream stf_websocket {
    server 192.168.3.16:3600 max_fails=0;
  }

  types {
    application/javascript  js;
    image/gif               gif;
    image/jpeg              jpg;
    text/css                css;
    text/html               html;
  }

  map $http_upgrade $connection_upgrade {
    default  upgrade;
    ''       close;
  }

  server {
    listen 80;
    server_name stf.test;
    keepalive_timeout 70;
    root /dev/null;

    resolver 127.0.0.1 valid=300s;
    resolver_timeout 10s;

    # Handle stf-provider@floor4.service
    location ~ "^/d/floor4/([^/]+)/(?<port>[0-9]{5})/$" {
      proxy_pass http://192.168.3.16:$port/;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_set_header X-Forwarded-For $remote_addr;
      proxy_set_header X-Real-IP $remote_addr;
    }

    location /auth/ {
      proxy_pass http://stf_auth/auth/;
    }

    location /s/image/ {
      proxy_pass http://stf_storage_image;
    }

    location /s/apk/ {
      proxy_pass http://stf_storage_apk;
    }

    location /s/ {
      client_max_body_size 1024m;
      client_body_buffer_size 128k;
      proxy_pass http://stf_storage;
    }

    location /socket.io/ {
      proxy_pass http://stf_websocket;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $http_x_real_ip;
    }

    location / {
      proxy_pass http://stf_app;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $http_x_real_ip;
    }
  }
}

nginx 启动命令

docker run -d -v /home/blueshark/stf/nginx/nginx.conf:/etc/nginx/nginx.conf:ro --name nginx --net host nginx nginx

启动 nginx 以后就可以访问你的网站,看看有没起来,正常起来的现象是报一个 nginx 的错误,没错,是报一个错误,因为其他服务还没起。

好了,nginx 起来了,下面就是 db 了。

2、启动 rethinkdb

数据库当然要比其他模块要早一点儿启动,否则影响连接嘛,rethinkdb 启动命令

docker run -d --name rethinkdb -v /srv/rethinkdb:/data --net host rethinkdb rethinkdb --bind all --cache-size 8192 --http-port 8090

启动完去用浏览器访问一下 8090 端口看看,如果能看到 rethinkdb 的管理界面就是 OK 的。

3、给数据库建表

rethinkdb 启动以后,要给 stf 建立相关的表,openstf/stf 镜像提供了这个功能,执行下面这条命令即可

docker run -d --name stf-migrate --net host  openstf/stf stf migrate

可以使用 docker logs 来查看命令的执行状态

docker logs stf-migrate

4、下面要启动一堆 storage 等,这些模块在 stf 截图和安装 app 时会用到


docker run -d --name storage-plugin-apk-3300 -p 3300:3000 --dns 192.168.1.5 openstf/stf stf storage-plugin-apk --port 3000   --storage-url http://stf.test/
docker run -d --name storage-plugin-image-3400  -p 3400:3000 --dns 192.168.1.5 openstf/stf stf storage-plugin-image --port 3000 --storage-url http://stf.test/
docker run -d  --name storage-temp-3500 -v /mnt/storage:/data -p 3500:3000 --dns 192.168.1.5 openstf/stf  stf storage-temp --port 3000  --save-dir /data

这里要注意几点,stf 官方 docker 镜像使用的 google dns,但是大部分公司都有自己的内网域名,因此必须换成自己的 dns,否则内网域名没法访问。如果你有需要持久保存的数据,最好用-v 对 docker 中的目录进行映射。这里使用-p 参数把 docker 内的端口绑定到主机端口,否则都是 3000 会冲突。

5、三方代理

说实话,这个东西我也是很懂,感觉是跟总线一样的东西,这个模块的启动顺序不一定放到这里,反正我是按照这个顺序来的,能工作

docker run -d  --name triproxy-app  --net host  openstf/stf  stf triproxy app   --bind-pub "tcp://*:7150"   --bind-dealer "tcp://*:7160"  --bind-pull "tcp://*:7170"
docker run -d --name triproxy-dev  --net host  openstf/stf  stf triproxy dev  --bind-pub "tcp://*:7250"  --bind-dealer "tcp://*:7260" --bind-pull "tcp://*:7270"

6、登录授权

登录授权的重要性不言自明,没人希望自己的手机被别人随意使用,最后也不知道谁用了。

docker run -d --name stf-auth3200 -e "SECRET=YOUR_SESSION_SECRET_HERE" -p 3200:3000 --dns 192.168.1.5 openstf/stf stf auth-mock --port 3000  --app-url http://stf.test/

默认情况下的 mock 登录随便输入 name 和 email 登录,当然可以自己接入自己的授权系统。

7、stf-app

这个就是主 web 界面了。

docker run -d --name stf-app3100 --net host -e "SECRET=YOUR_SESSION_SECRET_HERE" -p 3100:3000 openstf/stf stf app --port 3100 --auth-url http://stf.test/auth/mock/ --websocket-url http://stf.test/

启动到这里,访问 stf.test 网站,应该有点儿模样了。

8、stf-processor、websocket、reaper

processor 和 websocket 不知道具体是干什么的,这和消息队列好像有点儿关系,但是 reaper 是用来不断监控手机的在线状态的。

#stf-processor
docker run -d --name stf-processor --net host openstf/stf  stf processor stf-processor.service --connect-app-dealer tcp://192.168.3.16:7160 --connect-dev-dealer tcp://192.168.3.16:7260

#websocket 3600
docker run -d --name websocket -e "SECRET=YOUR_SESSION_SECRET_HERE" --net host openstf/stf stf websocket --port 3600  --storage-url http://stf.test/ --connect-sub tcp://192.168.3.16:7150 --connect-push tcp://192.168.3.16:7170

#reaper
docker run -d --name reaper --net host openstf/stf stf reaper dev --connect-push tcp://192.168.3.16:7270  --connect-sub tcp://192.168.3.16:7150 --heartbeat-timeout 30000

至此为至,stf 主框架已经搭起来了,就等 provider 给提供手机了。

9、provider

provider 的作为就是给主框架提供手机,注意,provider 可以运行在同一台机器,也可以运行在其他机器,但是,这台机器一定要可直接访问的,因为手机屏幕其实就是从这里出来的。

在 provider 机器上一定要先运行 adb 的 docker,毕竟安卓手机要依赖 adb 调试

#adb services
docker run -d --name adbd --privileged -v /dev/bus/usb:/dev/bus/usb --net host sorccu/adb:latest

下面就可以运行 provider 了

sudo docker run -d --name provider1 --net host openstf/stf stf provider --name "provider-test" --connect-sub tcp://192.168.3.16:7250  --connect-push tcp://192.168.3.16:7270  --storage-url http://192.168.3.16  --public-ip 192.168.3.16  --min-port=15000  --max-port=25000  --heartbeat-interval 20000 --screen-ws-url-pattern "ws://stf.test/d/floor4/<%= serial %>/<%= publicPort %>/"

到这里,整个基于 docker 的 stf 生产环境就搭建好了,只要加上域名和授权控制,就可以邀请别人使用了!

三、STF 开发

如果你和我一样,觉得限制使用别人做好的东西很不爽,你肯定想要自己对 STF 框架进行开发,加入一些特色功能。但是,要想通过源码来把 STF 跑通,还真没有那么容易,其中大大小小的坑令人防不胜防。

1、 安装 nodejs。

stf 是用 nodejs 来编写的,当然要 nodejs 来运行,如果你用的是 ubuntu 系统执行下面两条命令就可以安装好了

curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
sudo apt-get install -y nodejs

也可以安装 6.x 版本的

curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs

最好再安装一些编译的工具

sudo apt-get install -y build-essential

如果你用的是其他系统就恕不奉告了,上面都是从 nodejs 官网上抄的,可以自己去上面瞅瞅。

2、既然从源码来搞它,先拉源码吧,地址 https://github.com/openstf/stf.git
养成好习惯,拉下代码先看看分支,很多项目的 master 分支不能正常运行。stf 仓库有多个分支,其中最重的就是 master 和 2.0.0 分支,看了下 github,似乎 2.0.0 已经发布了,1.1.1 才发布,不知道怎么回事,不过看到 master 分支经常更新,就用 master 分支来搞吧。

3、根据 monkey 前两天的介绍,先安装所需要的 module 吧,在 stf 项目根目录执行

npm install

等待完成,很慢吧?可以换成淘宝的 npm 镜像,地址 http://npm.taobao.org/ ,首先执行

npm install -g cnpm --registry=https://registry.npm.taobao.org

以后就可以用 cnpm 代替 npm 命令了,cnpm 用的是淘宝镜像。注意 cnpm 要求 nodejs 版本在 4.x 以上。
下面执行

cnpm install

速度很快,然后就遇到了下面的问题

[stf@1.1.1] scripts.prepublish: "bower install && not-in-install && gulp build || in-install"
bower ESUDO         Cannot be run with sudo

Additional error details:
Since bower is a user command, there is no need to execute it with superuser permissions.
If you're having permission errors when using bower without sudo, please spend a few minutes learning more about how your system should work and make any necessary repairs.

http://www.joyent.com/blog/installing-node-and-npm
https://gist.github.com/isaacs/579814

You can however run a command with sudo using --allow-root option
Error: Run "sh -c bower install && not-in-install && gulp build || in-install" error, exit code 1
Error: Run "sh -c bower install && not-in-install && gulp build || in-install" error, exit code 1
    at ChildProcess.proc.on.code (/usr/lib/node_modules/cnpm/node_modules/runscript/index.js:67:21)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at maybeClose (internal/child_process.js:852:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:215:5)

这里提示 bower 不能用 root 安装,其实我也不知道 bower 到底是什么鬼,我喜欢用 root 账户来搞,这也不是一个好习惯,主要是非 root 账户问题提醒没有写入权限,百度一下,发现只要加一个 --allow-root 就行了,打开项目根目录下 package.json 文件,在 bower 那一行加上--allow-root 就行了,然后再次运行 cnpm install
然后 bower balabala 安装一大堆东西,duang! 又报了一个错!

bower ng-context-menu#~1.0.5    ECMDERR Failed to execute "git ls-remote --tags --heads git://github.com/AdiDahan/ng-context-menu.git", exit code of #128 fatal: unable to connect to github.com: github.com[0: 192.30.252.131]: errno=Connection timed out

Additional error details:
fatal: unable to connect to github.com:
github.com[0: 192.30.252.131]: errno=Connection timed out
Error: Run "sh -c bower install --allow-root && not-in-install && gulp build || in-install" error, exit code 1
Error: Run "sh -c bower install --allow-root && not-in-install && gulp build || in-install" error, exit code 1
    at ChildProcess.proc.on.code (/usr/lib/node_modules/cnpm/node_modules/runscript/index.js:67:21)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at maybeClose (internal/child_process.js:852:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:215:5)

遇到这种 time out 问题我一般是多试几次就行了,可是这次怎么试都不奏效了,哎,还是多分析一下错误的原因吧,提示这个命令 fail

git ls-remote --tags --heads git://github.com/AdiDahan/ng-context-menu.git

手动执行一下看看,果然是 fail,突然灵光一闪,我们都是用https://github.com/https 试试?,改成

git ls-remote --tags --heads https://github.com/AdiDahan/ng-context-menu.git

果然可以了,那么在哪里改呢,找了半天没找到,google 一下,有人提到 git 自带把 git://替换成 https://的功能,简直是雪中送炭啊!

执行一下下面的命令就行了

git config --global url."https://".insteadOf git://

如果你不放心,可以去 git 的 config 文件中看一下有没配置成功。再执行一下前面 git ls-remote 命令,这下子不报错了。

下面继续进行 cnpm install 命令,又遇到下面的问题

[stf@1.1.1] scripts.prepublish: "bower install --allow-root && not-in-install && gulp build || in-install"
(node:1305) fs: re-evaluating native module sources is not supported. If you are using the graceful-fs module, please update it to a more recent version.
module.js:442
    throw err;
    ^

Error: Cannot find module 'strip-json-comments'
    at Function.Module._resolveFilename (module.js:440:15)
    at Function.Module._load (module.js:388:25)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/root/stf-master/node_modules/.npminstall/eslint/2.13.0/eslint/lib/config/config-file.js:23:21)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
Error: Run "sh -c bower install --allow-root && not-in-install && gulp build || in-install" error, exit code 1
Error: Run "sh -c bower install --allow-root && not-in-install && gulp build || in-install" error, exit code 1
    at ChildProcess.proc.on.code (/usr/lib/node_modules/cnpm/node_modules/runscript/index.js:67:21)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at maybeClose (internal/child_process.js:852:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:215:5)

还是先升级 graceful-fs 吧,然后再安装 strip-json-comments,执行

cnpm install graceful-fs
cnpm install strip-json-comments

继续 cnpm install,终于执行完了,见到了结尾

chunk    {6} entry/commons.entry.js (entry/commons.entry.js) 0 bytes [rendered]

ERROR in ENOENT: no such file or directory, scandir '/root/stf-master/node_modules/.npminstall/node-sass/3.8.0/node-sass/vendor'
 @ ./res/web_modules/nine-bootstrap/nine-bootstrap.scss 4:14-197
[13:35:01] Finished 'webpack:build' after 16 s
INF/webpack:config 1645 [*] Build progress 100% (complete)
All packages installed (use 25s, speed 0B/s, json 0(0B), tarball 0B)

等等,还是有点错误,删除 node_modules/.npminstall/node-sasss 目录,重新执行 cnpm install

这样就好了,如重复执行 cnpm install 命令,就不会有错误了。

这时执行 stf 命令是找不到的,最后来一个 cnpm link 就行了,然后就可以 stf local 了

stf local 的时候还是有错误:

INF/util:procutil 15 [*] Forking "/app/lib/cli.js poorxy --port 7100 --app-url http://localhost:7105/ --auth-url http://localhost:7120/ --api-url http://localhost:7106/ --websocket-url http://localhost:7110/ --storage-url http://localhost:7102/ --storage-plugin-image-url http://localhost:7103/ --storage-plugin-apk-url http://localhost:7104/"
/app/node_modules/zmq/node_modules/bindings/bindings.js:83
        throw e
        ^

Error: libzmq.so.3: cannot open shared object file: No such file or directory
    at Error (native)
    at Object.Module._extensions..node (module.js:568:18)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
    at bindings (/app/node_modules/zmq/node_modules/bindings/bindings.js:76:44)
    at Object.<anonymous> (/app/node_modules/zmq/lib/index.js:6:30)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
FTL/cli:local 15 [*] Child process had an error ExitError: Exit code "1"
    at ChildProcess.<anonymous> (/app/lib/util/procutil.js:49:23)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:204:12)
INF/cli:local 15 [*] Shutting down all child processes
/app/node_modules/zmq/node_modules/bindings/bindings.js:83
        throw e
        ^

Error: libzmq.so.3: cannot open shared object file: No such file or directory
    at Error (native)
    at Object.Module._extensions..node (module.js:568:18)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
    at bindings (/app/node_modules/zmq/node_modules/bindings/bindings.js:76:44)
    at Object.<anonymous> (/app/node_modules/zmq/lib/index.js:6:30)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)

这里提示缺少 zmp 的一个库文件,如果你有兴趣,可以把 zmq 装一遍,就没问题,但是我有更简单的方法,去 openstf/stf 的 docker 镜像中把 libzmq.* 这类文件拷到你的系统中就行了,库目录是/usr/lib/x86_64-linux-gnu,下面还有一个类似的错误,同样拷一下库文件就行了,什么?你不知道怎么从 docker 镜像中很外拷东西?我只能说一句,查查 docker -v 命令,其他真的不能多说了。

localhost:7106/ --websocket-url http://localhost:7110/ --storage-url http://localhost:7102/ --storage-plugin-image-url http://localhost:7103/ --storage-plugin-apk-url http://localhost:7104/"
/app/node_modules/zmq/node_modules/bindings/bindings.js:83
        throw e
        ^

Error: libpgm-5.1.so.0: cannot open shared object file: No such file or directory
    at Error (native)
    at Object.Module._extensions..node (module.js:568:18)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
    at bindings (/app/node_modules/zmq/node_modules/bindings/bindings.js:76:44)
    at Object.<anonymous> (/app/node_modules/zmq/lib/index.js:6:30)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
FTL/cli:local 112 [*] Child process had an error ExitError: Exit code "1"
    at ChildProcess.<anonymous> (/app/lib/util/procutil.js:49:23)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:204:12)
INF/cli:local 112 [*] Shutting down all child processes

下面这个错误不一定每个人都会遇到,如果遇到了还真不好解决

INF/util:procutil 209 [*] Forking "/app/lib/cli.js poorxy --port 7100 --app-url http://localhost:7105/ --auth-url http://localhost:7120/ --api-url http://loc                                                   alhost:7106/ --websocket-url http://localhost:7110/ --storage-url http://localhost:7102/ --storage-plugin-image-url http://localhost:7103/ --storage-plugin-a                                                   pk-url http://localhost:7104/"
/app/node_modules/zmq/node_modules/bindings/bindings.js:83
        throw e
        ^

Error: Module version mismatch. Expected 48, got 46.
    at Error (native)
    at Object.Module._extensions..node (module.js:568:18)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
    at bindings (/app/node_modules/zmq/node_modules/bindings/bindings.js:76:44)
    at Object.<anonymous> (/app/node_modules/zmq/lib/index.js:6:30)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
FTL/cli:local 209 [*] Child process had an error ExitError: Exit code "1"
    at ChildProcess.<anonymous> (/app/lib/util/procutil.js:49:23)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:204:12)
INF/cli:local 209 [*] Shutting down all child processes

这里提示 zmq 的 version 有问题,我尝试把 zmq 重装了几次,还是不行,最终 google 了一把,原来不是 zmq 的问题,是 nodejs 版本太高了,我是个喜新厌旧(除了人)的人,所有的东西都要用最新的,系统用 ubuntu 16.04,nodejs 要用 6.x 版本,这次就栽在这里了,其实只要把 nodejs 版本换成 node-v4.4.5 就 ok 了,具体怎么换就不说了,可以了解一下 cnpm install -g n,这里吐槽一下 nodejs 的版本问题,感觉 nodejs 在 0.12 徘徊了几年,不知道什么时候突然就到 4.x 和 6.x 了,看来大跃进是国际惯例啊。

到这里 stf 已经完全可以正常运行了,终于见到了久违的登录界面!

cnpm link 会把 stf 全集安装到系统中,cnpm link 的时候还报了一个警告

root@ubuntu-mtc:~/git/stf-dev/stf-github# cnpm link
npm WARN skippingAction Module is inside a symlinked module: not running remove pinkie-promise@2.0.1 node_modules/node-sass/node_modules/meow/node_modules/read-pkg-up/node_modules/find-up/node_modules/path-exists/node_modules/pinkie-promise
npm WARN lifecycle stf@1.1.1~prepublish: cannot run in wd %s %s (wd=%s) stf@1.1.1 bower install --allow-root&& not-in-install && gulp build || in-install /root/git/stf-dev/stf-github
npm WARN optional Skipping failed optional dependency /karma/chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.12
npm WARN optional Skipping failed optional dependency /webpack/watchpack/chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.12
/usr/bin/stf -> /usr/lib/node_modules/stf/bin/stf
/usr/lib/node_modules/stf -> /root/git/stf-dev/stf-github

fsevents 是 mac 系统上的东西,linux 上不能安装,所以报 warning,但是其他 warning 我也没搞懂是怎么回事,但是不影响运行。

以后每次修改 stf 源码,都要执行一下 cnpm install,最好再 cnpm link 一下,这样修改的代码就生效了。

四、自己制作 docker 镜像

前面说过,生产环境中的 stf 是部署在 docker 当中的,我们修改完 stf 源码以后肯定要更新到镜像里才可以。制作 docker 镜像有两种方式:

  • 自己修改完代码以后,替换掉原 openstf/stf 镜像中的/app 目录即可,这样是最简单的方法,原系统有很多链接库也不用管了,但是有个缺点,就是依赖于原 docker 镜像的操作系统,stf 作者说是 coreos 系统,据说是专门为 docker 而生,但是这个系统我连自己安装软件都不会。

  • 完全自己从零开始制作镜像。这个工作的挑战性比较大,可以会遇到很多问题,特别是一些依赖的库,还有什么安装软件时 unmet 问题,太坑了!其实在 stf 项目中有一个作者的 Dockerfile,但是我基于这个 Dockerfile 制作镜像始终都没有成功。

下面分别介绍两种制作镜像的方法:

1、替换原镜像/app 文件夹。准备好你自己修改好的 stf 目录,假设为 stf-github,用下面的 Dockerfile 生成新镜像即可

FROM openstf/stf

USER root
RUN rm -rf /app
ADD ./stf-github /app

USER root 是因为原镜像不用 root 账户不能删除/app 目录。

2、从零开始构建自己的镜像。

这里我使用的是 ubuntu 系统,所以首先要 docker pull 一个 ubuntu 系统镜像

docker pull ubuntu

准备好修改过的 stf-github 文件夹,和 Dockerfile 放在同一目录下,另外准备原 openstf/stf 镜像中的两种 lib 文件,在/usr/lib/x86_64-linux-gnu 目录下,还有最好换成国内的 ubuntu 源,使用下面的 Dockerfile 创建镜像

FROM ubuntu

ADD ./stf-github /app

EXPOSE 3000

#replace source
ADD ./sources.list /etc/apt/sources.list
RUN apt-get update
RUN apt-get install -y vim curl git sudo

ADD /x86_64-linux-gnu/libzmq.* /usr/lib/x86_64-linux-gnu/
ADD /x86_64-linux-gnu/libpgm* /usr/lib/x86_64-linux-gnu/

#install npm
curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
sudo apt-get install -y nodejs

RUN npm install -g cnpm --registry=https://registry.npm.taobao.org

WORKDIR /app

RUN cnpm install -g graceful-fs
RUN cnpm install
RUN cnpm link

如果构建镜像过程中提示缺少某个模块,自己加上就行了,这个不是绝对的,上面的 graceful-fs 是因为有警告说 graceful-fs 的版本太低,就顺便更新一下了。其实也可以在宿主机上把 stf 全部弄好以后再整个放到 docker 中,都一样的。

至此,自己的镜像也构造完了,至于源码怎么修改,等我研究透了再说了

后续更新:

文章中说的复制 libzmq 的东西有点儿麻烦,事实上每个系统都有安装 zmq 的命令比,如说 ubuntu 上用 apt-cache search zmq 可以找到 zmq 的库 (PS:说实话我没搞清楚到底是哪个,反正装了几个以后就可以了,试试 libzmq-dev),mac 上可以用 brew install zmq 来安装。

共收到 76 条回复 时间 点赞

#28 楼 @zangtian2 手机掉线说明 web 或者 provider 出了错误,可以看下 log 是什么错误,不过看你前面的描述是请求不到接口的问题,很奇怪你那里为什么会去 3100 端口请求接口,官方文档是 3700,mock 的时候是 7100,如果你用了 nginx,建议你检查一下 nginx 的映射是否正确,从其他机器上 provide 机器一定要 nginx 吧。我这篇文章是针对 stf1.2 的,从 2.0 开始已经有独立的 api 模块了,需要用 nginx 做控制,上文中没有写。

大概用 Mac 部署了一下,有两个地方有点问题:

  • 第一是--net host参数好像在 Mac OS 并不支持,所以导致无法访问 nginx 等(估计 windows 也会有同样的问题?)
  • 第二个是文中的 DNS 部分描述,如果完全按照描述的配置,最后也无法使用 url 来访问啊,是否需要申请个域名,并且 dns 有对应记录才可以使用呢?
雨夜狂奔 回复

1、--net host 是指定使用宿主机的网络,如果不方便使用宿主机网络,可以想其他办法进行返向代理,这个其实和 STF 本身无关了。
2、和域名无关,ip 也是可以的。

我用的 centos7 node 版本是 9.0.0,执行 npm install 的时候一直报 fsevents,难道需要改回 Ubuntu 么

请问下我使用 docker 部署的 STF,现在我想在容器里面改动 stf 代码,然后重新编译,但是总是报错,有人知道怎么回事么?

docker stf 真得安装好快哇!!
stf 开发环境,装得好累,cnpm install 可以了,cnpm link 不行,最后搞不定,
还是用另外一大神的安装方式https://testerhome.com/topics/6112,在这基础上准备进行二次开发

楼主问下,我这边在 docker 里边拉了几个镜像,容器三个都跑起来了,vm 内部可以通过 IP 访问,宿主机和局域网其他物理机都访问不了是什么原因?ip 都是可以 ping 的通的

space 回复

我也想知道为什么?请问你的问题解决了么?

我 stf local 启动后 localhost:7100 页面无法打开请问这个怎么解决

tcp://127.0.0.1:7111 --bind-dealer tcp://127.0.0.1:7112 --bind-pull tcp://127.0.0.1:7113"

2021-02-28T12:38:30.404Z INF/util:procutil 1 [*] Forking "/app/lib/cli triproxy dev001 --bind-pub tcp://127.0.0.1:7114 --bind-dealer tcp://127.0.0.1:7115 --bind-pull tcp://127.0.0.1:7116"

2021-02-28T12:38:30.405Z INF/util:procutil 1 [*] Forking "/app/lib/cli processor proc001 --connect-app-dealer tcp://127.0.0.1:7112 --connect-dev-dealer tcp://127.0.0.1:7115"

2021-02-28T12:38:30.407Z INF/util:procutil 1 [*] Forking "/app/lib/cli processor proc002 --connect-app-dealer tcp://127.0.0.1:7112 --connect-dev-dealer tcp://127.0.0.1:7115"

2021-02-28T12:38:30.408Z INF/util:procutil 1 [*] Forking "/app/lib/cli reaper reaper001 --connect-push tcp://127.0.0.1:7116 --connect-sub tcp://127.0.0.1:7111"

2021-02-28T12:38:30.410Z INF/util:procutil 1 [*] Forking "/app/lib/cli provider --name docker-desktop --min-port 7400 --max-port 7700 --connect-sub tcp://127.0.0.1:7114 --connect-push tcp://127.0.0.1:7116 --group-timeout 900 --public-ip 192.168.1.4 --storage-url http://localhost:7100/ --adb-host 127.0.0.1 --adb-port 5037 --vnc-initial-size 600x800 --mute-master never --allow-remote"

2021-02-28T12:38:30.417Z INF/util:procutil 1 [*] Forking "/app/lib/cli auth-mock --port 7120 --secret kute kittykat --app-url http://192.168.1.4:7100/"

2021-02-28T12:38:30.432Z INF/util:procutil 1 [*] Forking "/app/lib/cli app --port 7105 --secret kute kittykat --auth-url http://192.168.1.4:7100/auth/mock/ --websocket-url http://192.168.1.4:7110/"

2021-02-28T12:38:30.441Z INF/util:procutil 1 [*] Forking "/app/lib/cli api --port 7106 --secret kute kittykat --connect-push tcp://127.0.0.1:7113 --connect-sub tcp://127.0.0.1:7111 --connect-push-dev tcp://127.0.0.1:7116 --connect-sub-dev tcp://127.0.0.1:7114"

2021-02-28T12:38:30.450Z INF/util:procutil 1 [*] Forking "/app/lib/cli groups-engine --connect-push tcp://127.0.0.1:7113 --connect-sub tcp://127.0.0.1:7111 --connect-push-dev tcp://127.0.0.1:7116 --connect-sub-dev tcp://127.0.0.1:7114"

2021-02-28T12:38:30.472Z INF/util:procutil 1 [*] Forking "/app/lib/cli websocket --port 7110 --secret kute kittykat --storage-url http://localhost:7100/ --connect-sub tcp://127.0.0.1:7111 --connect-push tcp://127.0.0.1:7113"

2021-02-28T12:38:30.495Z INF/util:procutil 1 [*] Forking "/app/lib/cli storage-temp --port 7102"

2021-02-28T12:38:30.503Z INF/util:procutil 1 [*] Forking "/app/lib/cli storage-plugin-image --port 7103 --storage-url http://localhost:7100/"

2021-02-28T12:38:30.518Z INF/util:procutil 1 [*] Forking "/app/lib/cli storage-plugin-apk --port 7104 --storage-url http://localhost:7100/"

2021-02-28T12:38:30.531Z INF/util:procutil 1 [*] Forking "/app/lib/cli poorxy --port 7100 --app-url http://localhost:7105/ --auth-url http://localhost:7120/ --api-url http://localhost:7106/ --websocket-url http://localhost:7110/ --storage-url http://localhost:7102/ --storage-plugin-image-url http://localhost:7103/ --storage-plugin-apk-url http://localhost:7104/"

2021-02-28T12:38:30.633Z INF/triproxy 19 [dev001] PUB socket bound on tcp://127.0.0.1:7114

2021-02-28T12:38:30.635Z INF/triproxy 19 [dev001] DEALER socket bound on tcp://127.0.0.1:7115

2021-02-28T12:38:30.638Z INF/triproxy 19 [dev001] PULL socket bound on tcp://127.0.0.1:7116

2021-02-28T12:38:30.839Z INF/triproxy 18 [app001] PUB socket bound on tcp://127.0.0.1:7111

2021-02-28T12:38:30.849Z INF/db 29 [*] Connecting to 127.0.0.1:28015

2021-02-28T12:38:30.854Z INF/triproxy 18 [app001] DEALER socket bound on tcp://127.0.0.1:7112

2021-02-28T12:38:30.854Z INF/triproxy 18 [app001] PULL socket bound on tcp://127.0.0.1:7113

2021-02-28T12:38:30.873Z INF/reaper 34 [reaper001] Subscribing to permanent channel "*ALL"

2021-02-28T12:38:30.876Z INF/reaper 34 [reaper001] Reaping devices with no heartbeat

2021-02-28T12:38:30.876Z INF/processor 29 [proc002] App dealer connected to "tcp://127.0.0.1:7112"

2021-02-28T12:38:30.876Z INF/processor 29 [proc002] Device dealer connected to "tcp://127.0.0.1:7115"

2021-02-28T12:38:30.877Z INF/db 34 [reaper001] Connecting to 127.0.0.1:28015

2021-02-28T12:38:30.890Z INF/reaper 34 [reaper001] Receiving input from "tcp://127.0.0.1:7111"

2021-02-28T12:38:30.891Z INF/reaper 34 [reaper001] Sending output to "tcp://127.0.0.1:7116"

2021-02-28T12:38:30.945Z INF/db 24 [*] Connecting to 127.0.0.1:28015

2021-02-28T12:38:30.985Z INF/processor 24 [proc001] App dealer connected to "tcp://127.0.0.1:7112"

2021-02-28T12:38:30.986Z INF/processor 24 [proc001] Device dealer connected to "tcp://127.0.0.1:7115"

2021-02-28T12:38:31.175Z INF/groups-engine 67 [*] Subscribing to permanent channel "*ALL"

2021-02-28T12:38:31.173Z INF/poorxy 97 [*] Listening on port 7100

2021-02-28T12:38:31.194Z INF/groups-engine 67 [*] Groups engine started

2021-02-28T12:38:31.196Z INF/db 67 [*] Connecting to 127.0.0.1:28015

2021-02-28T12:38:31.214Z INF/groups-engine 67 [*] Sending output to "tcp://127.0.0.1:7113"

2021-02-28T12:38:31.214Z INF/groups-engine 67 [*] Receiving input from "tcp://127.0.0.1:7111"

2021-02-28T12:38:31.215Z INF/groups-engine 67 [*] Sending output to "tcp://127.0.0.1:7116"

2021-02-28T12:38:31.215Z INF/groups-engine 67 [*] Receiving input from "tcp://127.0.0.1:7114"

2021-02-28T12:38:31.228Z INF/provider 36 [*] Subscribing to permanent channel "b8dffek2TyWjhplVh+Qf+g=="

2021-02-28T12:38:31.245Z INF/app 55 [*] Using pre-built resources

2021-02-28T12:38:31.256Z INF/app 55 [*] Listening on port 7105

2021-02-28T12:38:31.263Z INF/provider 36 [*] Sending output to "tcp://127.0.0.1:7116"

2021-02-28T12:38:31.268Z INF/db 55 [*] Connecting to 127.0.0.1:28015

2021-02-28T12:38:31.271Z INF/auth-mock 49 [*] Listening on port 7120

2021-02-28T12:38:31.273Z INF/provider 36 [*] Receiving input from "tcp://127.0.0.1:7114"

2021-02-28T12:38:31.277Z INF/provider 36 [*] Tracking devices

2021-02-28T12:38:31.284Z INF/db 49 [*] Connecting to 127.0.0.1:28015

2021-02-28T12:38:31.298Z INF/storage:plugins:image 85 [*] Listening on port 7103

2021-02-28T12:38:31.322Z INF/storage:temp 79 [*] Listening on port 7102

2021-02-28T12:38:31.331Z INF/storage:plugins:apk 91 [*] Listening on port 7104

2021-02-28T12:38:31.410Z INF/websocket 73 [*] Subscribing to permanent channel "*ALL"

2021-02-28T12:38:31.415Z INF/websocket 73 [*] Listening on port 7110

2021-02-28T12:38:31.425Z INF/db 73 [*] Connecting to 127.0.0.1:28015

2021-02-28T12:38:31.428Z INF/websocket 73 [*] Sending output to "tcp://127.0.0.1:7113"

2021-02-28T12:38:31.429Z INF/websocket 73 [*] Receiving input from "tcp://127.0.0.1:7111"

2021-02-28T12:38:31.700Z INF/api 60 [*] Subscribing to permanent channel "*ALL"

2021-02-28T12:38:31.731Z INF/api 60 [*] Listening on port 7106

2021-02-28T12:38:31.760Z INF/api 60 [*] Sending output to "tcp://127.0.0.1:7113"

2021-02-28T12:38:31.760Z INF/api 60 [*] Receiving input from "tcp://127.0.0.1:7111"

2021-02-28T12:38:31.761Z INF/api 60 [*] Sending output to "tcp://127.0.0.1:7116"

2021-02-28T12:38:31.761Z INF/api 60 [*] Receiving input from "tcp://127.0.0.1:7114"

2021-02-28T12:38:32.114Z INF/db 60 [*] Connecting to 127.0.0.1:28015

stf 2.0.0 还没发布,只是有个叫 Banthia 在上面加入 appium 等测试工具的集成。建议还是使用 master 版本。

为啥感觉好复杂。。= =。。这个和源码中给的是一样的镜像么?

#1 楼 @monkey 主要是要安装很多依赖,再解决一些报错,镜像中代码和源码是一样的,只是经过编译,然后放到了 docker 中

#2 楼 @blueshark 看着就好累。。辛苦。。。

匿名 #4 · 2016年06月20日

看得我当时就吓尿了。。。
我有两个疑问,望解答:)
1、“provider 可以运行在同一台机器,也可以运行在其他机器”
——可以实现多个 provider 向同一个 stf 主框架提供手机的方式吗?
2、把 stf 放在 docker 中,对 USB 连接数上是否会造成限制?
——因为我试过把 stf 放在 vm 虚拟机中会有 USB 连接数限制的问题。
3、stf+docker 楼主在落地过程中还有遇到些什么坑?
——环境限制或者其它。
😁 😁 😁

#4 楼 @link1220
1、当然可以用多个 provider 向一个 stf 主框架提供手机,而且 stf 本来就是这样设计的,希望这样来用
2、目前我没发现限制,连个十几台是没问题的,docker 和 vm 原理不一样,所以不用太担心数量限制问题
3、遇到的坑基本上在文章中都说过了

#5 楼 @0x88 多谢提醒

#6 楼 @blueshark 你有试过多少台手机连续工作多少天么?之前我试过十台手机连续工作后就会出异常,系统报 usb 相关的错误。

#9 楼 @0x88 我用最新的代码跑过大概一星期是没问题的,时间再长就没试过了,因为经常重新部署,我这边也报过一些 USB 的错误,但是感觉是手机是问题,而不是平台的问题,总体感觉还是挺稳定的

匿名 #11 · 2016年06月20日

#6 楼 @blueshark 多谢回复。下一步我也要学习下 docker!

—— 来自 TesterHome 官方 安卓客户端

就冲你写那么多,我也要顶一下,看完了,部署起来确实各种大小坑。

#12 楼 @simple 多谢,共同交流

看着就好累,楼主一生平安

我的镜像和你的为什么不一样? 确实看着好累

非常感谢楼主如此详细的文档。今天试着在 docker 里搭建 STF 环境,我已经 PULL 了上面提到的镜像,然后分别运行了上面提到的三个在 docker 的命令,然后用 docker ps 看到三个容器,说明它们都是正常启动的。但在浏览器上访问 localhost:7100 是失败的,我想问这是什么原因呀?还是我漏掉了什么操作?多谢帮助

#14 楼 @mads 共同交流

#15 楼 @liuxiaoyao0602 哪里不一样?

#16 楼 @xutester 其实在 docker 里运行和外面运行是一样的,只不过不用搭建复杂的环境,你可以看看 docker 的 log 哪里出问题了

看着就好累,楼主平安

@blueshark 请问,在另外的主机上运行 provider 时,参数怎么指定 stf 运行的机器?

#21 楼 @xiaodian provider 启动的时候会指定 --connect-sub、 --screen-ws-url-pattern 等参数

#20 楼 @ivymobi 谢谢关注

#24 楼 @lilili 我没见过也没尝试过在 windows 上直接安装,不过可以通过 windows 的 docker 安装,其实就是 linux 虚拟机了

文中有几个 IP,不知道是本机的,还是 docker 的,我 QQ349111840,坐等大神指导😹 👏

#26 楼 @tql 可以说是本机的,也可以说是 docker 的,这取决于你的 docker 有没有一个独立的 ip,如果有,就是 docker 的,没有就是本机的,注意端口不同

@blueshark 楼主我在一台机子上,通过 docker 启动了 stf 可以登录,在另一台电脑 provider 设备,同时在网页中可以看到 provider 的设备,但是当我点击设备,想进入 control 界面的时候,页面只是进到 control 页面什么都没有然后就刷新回来,并且手机断连了,但是我从 adb devices 去查看,设备是正常的。只能拔线重插后网页才显示正常。但是还是无法进入 control 界面。
https://github.com/openstf/stf/issues/455,具体描述在这。

分步启动的时候 /api/v1/devices 访问一直是 404,无法访问到.我根据 deployment 启动了 api 后,仍然无法访问到。

@blueshark ,谢谢楼主,已解决。是浏览器的问题。firefox 导致,其他浏览器正常。

@blueshark 又麻烦下楼主。我通过 php 或 python 在 post STF 时,由于 crsf 原因无法跨源请求(403),请问源码中如何干掉这部分,主要是为了解决直接跳过登陆界面。/auth/mock 这个页面

#31 楼 @zangtian2 你是想做 SSO 吧,SSO 确实存在这个问题,我是模仿 mock.js 做了一个接口,然后把这段代码干掉了
app.use(function(req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken())
next()
})
还有 app.use(csrf())
或者看看 oauth2 有没什么好办法实现

#32 楼 @blueshark 嗯好的,我也是把这两段干掉的,还是没通。我再研究下。多谢了

请教下,我不是用 DOCKER 建立的,是本地的,最多连接手机是 37 台,是 STF 限制,还是 ADB 限制,有什么解决方案吗

#40 楼 @onlinesen123 这怎么可能,必须安装 stf 环境和 adb,所以最好用 docker,否则就要自己搭环境了

#6 楼 @blueshark
#28 楼 @zangtian2
请问下,provider 提供设备的启动命令式什么啊?我也想从别的电脑 A,向 stf 服务器 B 提供设备,但不知 B 的启动命令式什么?

#39 楼 @blueshark
哦,晕死,那就是只要 provider 设备的,都要安装 STF 环境。。这个晕菜了,老板竟然提出随便找个设备裸体就能接入 stf,这要求怎么做啊。。。

@zangtian2 确实是本地 ADB 问题,我改成 DOCKER 限制台数取消了。现在我想问一下,我想把 STF 允许外网访问进来,是用 NGINX 反代吗?

@blueshark 我外网 IP:7100 访问,然后网页直接转向到 192.168.10.10:7100 。这个是不是要在 STF 什么参数上设置,才能允许外网访问

#38 楼 @onlinesen123 在连接手机的电脑上启 provider 和 adb,在服务器上启其他模块,比如 app,websocket 等等,provider 启动的命令可以参考官方:

stf provider \
   --name "%H/%i" \
   --connect-sub tcp://devside.stf.example.org:7250 \
   --connect-push tcp://devside.stf.example.org:7270 \
   --storage-url https://stf.example.org/ \
   --public-ip ${COREOS_PRIVATE_IPV4} \
   --min-port=15000 \
   --max-port=25000 \
   --heartbeat-interval 10000 \
   --screen-ws-url-pattern "wss://stf.example.org/d/%i/<%= serial %>/<%= publicPort %>/"

#37 楼 @blueshark 感谢留言,我就想知道你 A 的启动 provider 带的参数是啥啊?难道 A 也要装 STF 环境?我意思是 B 是装了 STF,A 是一台 XP 电脑连了 1 台设备,B 想操控 A 电脑的设备。。
我以为是在 B 上面的 stf 启动 provider 的命令呢,不是这样吗?

#34 楼 @hongxang 本地的可能和 adb 有关,我这里超过 37 台是没问题的,而且有的电脑很怪,只能识别 9 台,我遇到过。

#35 楼 @onlinesen123 A 上启动 provider,B 上搭建正常的环境就行,B 上有手机就在 B 上也启一个 provider,没有就不用启。

#43 楼 @hongxang nginx 反向代理可以的,但是需要注意一些事情,provider 与 web 有很多交互,其实用户与 provider 也有交互,web 与用户的交互要保证所有的交互都通过 nginx 进行代理。

#45 楼 @hongxang 如果是 7100 好像不用设置什么了,我也没试过,不过 7100 只是个 demo,最好自己分开搭建

@blueshark 请教下:
1.如果用 WIFI 连接,是不是必须手机安装无线 ADB(我通过此方法用 7100 的架好了),但不知道 STF 本身可以不用无线 ADB 吗?
2.按上面的教程,DEMO 的没问题,但分开架的,查看日志都没错误了,但是连接设备会马上断开,然后设备就断开了,不知道哪里设置错误,我是将你的域名改成我的外网域名,然后路由做端口印射,IP 改成我的 IP,其它都没有变动。
3.STF 的 PLUGAPK,要怎么使用,应该能支持批量下发 APK 吧?

#47 楼 @hongxang 1、我不太清楚你说的无线 adb 是什么意思,我们一般把手机插在台式电脑上。电脑上安装 provider,如果你想用远程 adb,要把 provider 的--allow-remote 参数加上,否则 stf 不允许类似于 ip:端口号的 serial 上线的。2、分开架的时候 nginx 转发比较复杂,单凭你说的现象我也没办法判断问题所在,你可以看一下 stf 的 log,看看报什么错。3、PLUGAPK 是什么功能?我好像没见到这个

楼主,你好!本文中未提及 rethinkdb-proxy-28015.service 这个服务。这个是可以不采用的么?

rethinkdb-proxy-28015.service 这个其实只是连接 rethinkdb 的一个代理模块,如果直接写死了 rethinkdb 的地址,可以不用


你好,这是我写的一个 Dockerfile 文件,想替换掉镜像中的,tables.js,想请教下,RUN rm -rf /app 这个路劲是写我要替换掉的 tables.js 源码中的位置吗????

刘扬 回复

当然要,否则把整个 app 文件夹都删除了

生产环境,一台服务器最多可连多少设备?

Bob 回复

这个我还没发现上限,100 台是没问题的,不够的话可以扩展的

6、登录授权
请教登录授权有更具体的介绍么?

Kun 回复

登录授权不同的公司不一样,所以没有详细介绍,不过可以参考 stf mock 模块

blueshark 回复

@zangtian2 @blueshark 的确需要部署单独的 api server,还需要在 nginx 配置文件里添加二段描述。参考了这篇文章,我弄了一个一键部署 stf 的脚本 https://github.com/thinkhy/STF-Assistor/blob/master/deploy_stf.sh.template

方叶 回复

脚本写的很棒,赞一个!我用 nginx 做负载均衡的时候遇到的两个问题,希望对你有用
1、torage-plugin-apk、storage-plugin-image、storage-temp 这三个最好不要做均衡,因为 nginx 会把文件上传一个 server,而去另外一个 server 拉下来安装,结果拉不到文件,造成安装失败。
2、provider 中的这一段--screen-ws-url-pattern "ws://IP_ADDRESS/d/floor4/<%= serial %>/<%= publicPort %>/",如果用户和 provider 在同一网络,在IP_ADDRESS这里可以直接换成 PROVIDRE_IP_ADDRESS__:<%= publicPort %>,就是直接换成 provder 的 ip 加端口号,这样就不经 nginx 转发了,减少 nginx 的压力。

方叶 回复

请问这个脚本文件下载下来之后直接就在 win7 下面点击相应的.sh 文件就可以了吗

blueshark 回复

@blueshark Thanks! nginx 的负载均衡这块我还没弄, Provider 的 websocket 直连已经注意到了,provider 的部署也做成了一键脚本:https://github.com/thinkhy/STF-Assistor/blob/master/deploy_stf_provider.sh.template 另外还把 systemd 的配置也自动化了,这样以服务方式启动 stf,可用性提高不少,比如 adb server 和 provider 断了能自动重启。

wanxiaoqiang 回复

自动部署脚本只支持 ubuntu。本想用 chef 和 ansible 实现自动批量部署,考虑到实现简单和使用方便,直接用 Bash shell 写了。

方叶 回复

能不能加下我的联系方式,共同建个群交流一下,可以看我的个人介绍,我后面又写了一些文档,感觉对 STF 的理解还不够清楚,所以没发出来。

blueshark 回复

OK. 晚点我联系你

Awesome 回复

brew install zmq
brew install yasm # 安装 jpegturbo 会用到

windows 按照楼主的方式,通过 docker 启动,不能访问

Yat_Ho 回复

麻烦你把具体的操作和遇到的错误描述一下,或者看我的资料联系我共同交流

方便加下 QQ1076947473 进行交流

windows 下怎么安装?可以指导下不@blueshark

陈恒捷 treafik 试用记录 中提及了此贴 01月09日 14:43

你好,想请教一个问题
在 Mac 机器上安装开源的 stf,安装完成后执行 stf local 命令后,提示如下错误:Error:Could not locate the bindings file.,请大神们帮忙指点迷津

bogon:pkgconfig baidu$ stf -V
2.3.0
bogon:pkgconfig baidu$
bogon:pkgconfig baidu$ stf local
/usr/local/lib/node_modules/stf/node_modules/bindings/bindings.js:91
throw err
^
Error: Could not locate the bindings file. Tried:
→ /usr/local/lib/node_modules/stf/node_modules/zmq/build/zmq.node
→ /usr/local/lib/node_modules/stf/node_modules/zmq/build/Debug/zmq.node
→ /usr/local/lib/node_modules/stf/node_modules/zmq/build/Release/zmq.node
→ /usr/local/lib/node_modules/stf/node_modules/zmq/out/Debug/zmq.node
→ /usr/local/lib/node_modules/stf/node_modules/zmq/Debug/zmq.node
→ /usr/local/lib/node_modules/stf/node_modules/zmq/out/Release/zmq.node
→ /usr/local/lib/node_modules/stf/node_modules/zmq/Release/zmq.node
→ /usr/local/lib/node_modules/stf/node_modules/zmq/build/default/zmq.node

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册