树莓派安装koa2/flask+react+nginx获取内网内路由器WAN口ip并发布在服务器上

获取内网IP

  • 前言
  • 依赖
  • 源代码
  • 树莓派上部署
  • 成果
    • 体会
          • javascript版的getip
          • python版getip

前言

学校的上网是通过dr.com客户端(v6.0pppoe)版拨号上网,所以可以通过路由器pppoe的方式拨号上网,但是经常会重连,而且分配的ip是变化的,所以在图书馆或者实验室不好操作宿舍的电脑,所以通过这样的办法实时获取路由器wan口ip,顺便尝试一下koa2+react前后端分离的东西,同时顺便以后在树莓派上扩展aria2等工具。

依赖

  • nodejs
  • python
  • nginx
  • create-react-app koa2
  • ssh2-utils或paramiko
    ssh2-utils是js的一个ssh库,可以连接路由器的ssh获取wanip地址

源代码

  1. 文件夹和文件结构如图所示
  • koa2
    • controllers
      • index.js
    • app.js
    • controller.js
    • package.json
  • rasp
    • public
    • src
    • package.json
  1. 进入koa2文件夹
    npm install koa2 koa2-bodyparser koa2-cors koa-router ssh-utils
  • koa2/App.js
const Koa = require('koa');//导入koa
const router = require('koa-router')();
const bodyParser = require('koa-bodyparser');
//创建一个Koa对象表示webapp
const app = new Koa();
const controller = require('./controller');
var cors = require('koa2-cors');
app.use(cors());
app.use(controller());
//监听3000端口
app.listen(5000);
console.log('app started at port 5000...');
  • koa2/controller.js
const fs = require('fs');
function addMapping(router, mapping) {
    for (var url in mapping) {
        if (url.startsWith('GET ')) {
            var path = url.substring(4);
            router.get(path, mapping[url]);
            console.log(`register URL mapping: GET ${path}`);
        } else if (url.startsWith('POST ')) {
            var path = url.substring(5);
            router.post(path, mapping[url]);
            console.log(`register URL mapping: POST ${path}`);
        } else {
            console.log(`invalid URL: ${url}`);
        }
    }
}

function addControllers(router) {
    var files = fs.readdirSync(__dirname + '/controllers');
    var js_files = files.filter((f) => {
        return f.endsWith('.js');
    });

    for (var f of js_files) {
        console.log(`process controller: ${f}...`);
        let mapping = require(__dirname + '/controllers/' + f);
        addMapping(router, mapping);
    }
}
module.exports = function (dir) {
    let
        controllers_dir = dir || 'controllers', // 如果不传参数,扫描目录默认为'controllers'
        router = require('koa-router')();
    addControllers(router, controllers_dir);
    return router.routes();
};
  • koa2/controller/index.js
var getip = function(){
    return new Promise(resolve => {var ssh2 = require('ssh2-utils');//异步获取ip,其实同步会很快,但是ssh.exec()方法调用回调,我javascript比较菜,拿到返回值但是赋给下面ctx.respose.body值还没有到。koa2学的皮毛都不到。先这样写着能拿到就Ok
    var ssh = new ssh2();
    var server = {host: "192.168.6.1", username:"admin", password:"admin" };//路由器网关地址,ssh账号密码
    ssh.exec(server, 'ip addr', function(err,stdout,stderr){
        if(err) console.log(err);
        var res = stdout.match(/(10\.69\.\d{1,3}\.\d{1,3})\speer\s10.69.0.1/)//通过ip addr 命令查到网址,再用正则表达式获取ip
        ip =res[1];
        console.log(ip);
        resolve(ip);
    });
    }
    )}
module.exports={
    'GET /ip':async(ctx,next)=>{
        ctx.response.type='application/json';
        ctx.set('Access-Control-Allow-Origin', 'http://localhost:80');
        let ip = await getip();
        console.log(ip);
        ctx.response.body={ip};
    },//导出路由(ES6写法)访问localhost:5000/ip会返回当前Ip
}

3.在与Koa2同级目录下执行

1. npm install create-react-app react react-bootstrap
2. create-react-app rasp
  • rasp/App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import {Button} from 'react-bootstrap'
class App extends Component {
  render() {
    return (
      
logo

K2P路由WAN口IP

); } } class Refresh extends React.Component { constructor(props) { super(props); this.state = { ip:[], }; this.handleClick = this.handleClick.bind(this); }; handleClick(event){ this.setState({ip:[]}); this.getData(); } /*获取ip,因为采用前后端分离,所以访问后端时会被同源策略限制,所以要在后端设置跨域访问,使用koa2-cors即可。但是我在这里 填127.0.0.1:5000/ip,前端fetch会被后端拒绝。但是curl http://127.0.0.1:5000/ip会返回ip,查了好久也没明白原因,希望大神解答*/ getData(){ fetch('http://192.168.6.80:5000/ip').then(response => response.json()) .then(data =>{ console.log(data); this.setState({ ip: data }); }); } componentDidMount() { this.getData(); } render() { return (
); } } export default App; export {Refresh}
  • index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App, {Refresh}  from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(, document.getElementById('root'));
ReactDOM.render(, document.getElementById('example'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

树莓派上部署

  1. 我安装的是官方ubuntu-mate armv8版的ubuntu-mate-pi,也可以安装github上这个,简洁好用ubuntu64-pi
  2. sudo apt install nginx-light supervisor 安装nginx 和supervirsor
  3. 进去/etc/supervirsor的conf.d下,创建自己的子进程脚本.(参考supervisor使用详解 进程管理supervisor的简单说明)
    这是我的配置文件
[program:serve]
directory=/home/cmq/js/koa2
command=/usr/bin/node /home/cmq/js/koa2/app.js
autostart=true
autorestart=false
startsecs=1
stderr_logfile=/home/cmq/serve_err_log
stdout_logfile=/home/cmq/serve_out_log
redirect_stderr=true

4.最后执行

service nginx restart
supervisorctl reload
supervisorctl  shutdown
supervisord -c /etc/supervisor/supervisord.conf
supervisorctl start all

成果

示例
树莓派安装koa2/flask+react+nginx获取内网内路由器WAN口ip并发布在服务器上_第1张图片

体会

javascript版的getip
var getip = function(){
    return new Promise(resolve => {var ssh2 = require('ssh2-utils');
    var ssh = new ssh2();
    var server = {host: "192.168.6.1", username:"admin", password:"admin" };//路由器网关地址,ssh账号密码
    ssh.exec(server, 'ip addr', function(err,stdout,stderr){
        if(err) console.log(err);
        var res = stdout.match(/(10\.69\.\d{1,3}\.\d{1,3})\speer\s10.69.0.1/)//通过ip addr 命令查到网址,再用正则表达式获取ip
        ip =res[1];
        console.log(ip);
        resolve(ip);
    });
python版getip
import paramiko
def getip():
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(hostname='192.168.6.1', port=22, username='admin', password='admin')
    cmd = 'ip addr'
    stdin, stdout, stderr = ssh.exec_command(cmd)
    result = stdout.read()
    ip = re.search(r'(10\.69\.\d{1,3}\.\d{1,3})\speer\s10.69.0.1', result.decode()).group(1)
    return ip
    ssh.close()

一开始用的python的flask做后端restful接口,然后碰到一个问题,就是树莓派上nodejs访问python的服务器127.0.0.1:5000/ip的时候被拒绝,然后换了nodejs的服务器,还是这样最后发现原来不是flask的问题,只需要把ip地址改为树莓派的路由器的ip就好了。(我还因为这个重新装了树莓派的系统。。。。)。这次接触到了很多新的东西,像linux的开启自启脚本,

  1. rc.local(要注意查看/lib/systemd/system/rc.local.service中最下面有没有
[Install]
WantedBy=multi-user.target
Alias=rc-local.service

没有的话,加上这句,这样/etc/rc.local开机脚本就会自动运行了.
2. 还有通过服务的方式,同样的在/lib/systemd/system/目录下新建自己的service注意格式

[Unit]
Description=ngrok //你的服务描述
After=network.target //在网络服务后启动
[Service]
Type=simple
ExecStart=/usr/bin/nodejs app.js //你要运行的脚本
[Install]
WantedBy=multi-user.target

然后运行systemctl enable [新建的service名称]
3.通过supervisor,(参考supervisor使用详解 进程管理supervisor的简单说明)
先整理这么多吧。以后的慢慢积累

你可能感兴趣的:(树莓派,Linux)