2018年3月 - 炫Q香蕉派

2018年3月

重玩香蕉之一:玩M2U

今天是迷窟鞋盒运行第750天,除了期间因为整理接线或者误操作重启过两次,至今一直稳定运行,现在用uptime能查到的是连续536天了,过段时间可能会对鞋盒进行调整,难免会断电重启。
好吧,言归正传,下边是这次准备的清单

吃灰的bpi-m2u
二创专用电源线
川宇 8G TF卡
川宇读卡器
其它网线、USB插线板等

然后就是找一个比较新的镜像,百度云以慢著称,谷歌盘又在墙外,大球给了一个地址,https://dev.banana-pi.org.cn/Image/BPI-M2U/,下载了两个镜像

https://dev.banana-pi.org.cn/Image/BPI-M2U/2017-06-06-ubuntu-16.04-server-preview-bpi-m2u-sd-emmc.img.zip
https://dev.banana-pi.org.cn/Image/BPI-M2U/2017-11-13-ubuntu-16.04-mate-desktop-beta2-bpi-m2u-sd-emmc.img.zip

从命名看一个是desktop版,一个是server版吧,让人迷惑的是上百个镜像,除了preview版就是beta版,也不知道哪个是官方版,只能靠碰运气,以前比较喜欢用树莓系统控制一些外设,现在比较懒基本就是装软件玩,所以趋向于比较小巧的server版,如果能在emmc中运行还能省一块存储卡。
以前烧录镜像的工具SD Formatter & Win32DiskImager,还记得大球用来烧硬盘,听说有个新工具叫Etcher顺便也尝试一下吧,419M的镜像解压后7.28G,也服了做镜像的了,会是谁呢?烧录工具显示卡容量7.99G,镜像7.82G,应该是计量标准不同吧,怪不得很多程序员谈工资时说我要2k,不说我要两千,在他们的潜意识里1k=1024吧。
01.png

不光写完,还给校验了一遍,然后自动弹出了,怀着忐忑的心情把卡插入吃灰已久的M2U,插网线,接电源,红绿蓝三灯齐亮,如果一直这样就是死机了,还好,一会儿就闪动起来了,红灯常亮,绿灯闪烁,蓝灯熄灭了。登录路由,发现了一个叫bpi-iot-ros-ai的设备,附近bpi很多,暂时还不能确认是不是这个,ssh看一下吧,是它,应该就是它了

pi@bpi-iot-ros-ai:~$ uname -a
Linux bpi-iot-ros-ai 3.10.65-BPI-M2U-Kernel #1 SMP Thu May 25 11:46:04 CST 2017 armv7l armv7l armv7l GNU/Linux
pi@bpi-iot-ros-ai:~$

11点半了,困了,待续吧。

关于mysql的主从复制和文件位置

首先是文件位置,以前放到了docker里,结果docker容器崩溃了,数据也就找不回来了,
想到放共享文件夹,球猫说专业名词叫volume,好吧,其实就是个v的参数,下边开始从ubuntu开始,

mkdir mydata
docker run -ti -h mysql_1 --name mysql_1 -v /home/user/mydata:/mysqldata -p 10001:3306 ubuntu
apt-get update
apt-get install mysql-server
apt-get install vim
vi /etc/mysql/mysql.conf.d/mysqld.cnf
#修改datadir为/mysqldata,注释掉bind-address=127.0.0.1
cp /var/lib/mysql/. /mysqldata -r -a
service mysql restart
mysql -u root -p

CREATE USER 'test' IDENTIFIED BY '****';
create database testDB DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
grant all privileges on testDB.* to test@"%" identified by '****' with grant option;
flush privileges;
exit

应该就搞定了,可以通过客户端访问了,结果发现mydata文件夹是空的,后来通过find找到在这里,看来要写绝对路径/var/lib/docker/volumes/mydata/_data/

下面就是主从复制了,再建一个mysql容器

mkdir mydata2
docker run -ti -h mysql_2 --name mysql_2 -v /home/user/mydata2:/mysqldata -p 10002:3306 ubuntu
...

似乎很多重复过程,可以中间exit后保存一份镜像再继续run
docker commit -m "mysql ok" mysql_1 ubuntu:mysql

如果主库有了数据,就需要先备份一下

mysqldump -uroot -p'****' -S /run/mysqld/mysqld.sock --all-databases > /mysqldata/mysql_bak.$(date +%F).sql
cp /var/lib/docker/volumes/mydata/_data/mysql_bak.2018-03-2x.sql mydata2
mysql -uroot -p'****' -S /run/mysqld/mysqld.sock < /mysqldata/mysql_bak.2018-03-2x.sql

获取所有容器的ip

docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' $(docker ps -aq)

主机

vi /etc/mysql/mysql.conf.d/mysqld.cnf
#去掉Server-id和log-bin的注释
service mysql restart
mysql -u root -p
GRANT REPLICATION SLAVE ON *.* TO 'test'@'172.17.0.*' IDENTIFIED BY '****';
SHOW MASTER STATUS;
#记下日志的名字mysql-bin.000001和位置446

从机

vi /etc/mysql/mysql.conf.d/mysqld.cnf
#去掉Server-id的注释改为2
vi /mysqldata/auto.cnf
#修改uuid
service mysql restart
mysql -u root -p
CHANGE MASTER TO MASTER_HOST='172.17.0.x', MASTER_USER='test', MASTER_PASSWORD='****', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=446;
start slave;
SHOW SLAVE STATUS\G

这样就好了,一下是一些笔记

show binlog events;
show binlog events in 'mysql-bin.000001';
show variables like '%server_uuid%';
stop slave;set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;start slave;
find / -name mysqld.sock
cat /var/log/mysql/error.log
#!/bin/sh
service mysql start
/bin/bash

参考资料,排名不分先后
http://www.cnblogs.com/phpstudy2015-6/p/6485819.html
https://blog.csdn.net/seteor/article/details/17264633
https://www.cnblogs.com/phpstudy2015-6/p/6706465.html

android的tcp client

TcpClientConnector

package com.hadisi.socket;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * Created by hadisi on 2016/6/28.
 */

public class TcpClientConnector {
    private static TcpClientConnector mTcpClientConnector;
    private Socket mClient;
    private ConnectLinstener mListener;
    private Thread mConnectThread;

    public interface ConnectLinstener {
        void onReceiveData(String data);
    }

    public void setOnConnectLinstener(ConnectLinstener linstener) {
        this.mListener = linstener;
    }

    public static TcpClientConnector getInstance() {
        if (mTcpClientConnector == null)
            mTcpClientConnector = new TcpClientConnector();
        return mTcpClientConnector;
    }

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 100:
                    if (mListener != null) {
                        mListener.onReceiveData(msg.getData().getString("data"));
                    }
                    break;
            }
        }
    };

    public void creatConnect(final String mSerIP, final int mSerPort) {
        if (mConnectThread == null) {
            mConnectThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        connect(mSerIP, mSerPort);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
            mConnectThread.start();
        }
    }

    /**
     * 与服务端进行连接
     *
     * @throws IOException
     */
    private void connect(String mSerIP, int mSerPort) throws IOException {
        if (mClient == null) {
            mClient = new Socket(mSerIP, mSerPort);
        }
        InputStream inputStream = mClient.getInputStream();
        byte[] buffer = new byte[1024];
        int len = -1;
        while ((len = inputStream.read(buffer)) != -1) {
            String data = new String(buffer, 0, len);
            Message message = new Message();
            message.what = 100;
            Bundle bundle = new Bundle();
            bundle.putString("data", data);
            message.setData(bundle);
            mHandler.sendMessage(message);
        }
    }

    /**
     * 发送数据
     *
     * @param data 需要发送的内容
     */
    public void send(String data) throws IOException {
        OutputStream outputStream = mClient.getOutputStream();
        outputStream.write(data.getBytes());
    }

    /**
     * 断开连接
     *
     * @throws IOException
     */
    public void disconnect() throws IOException {
        if (mClient != null) {
            mClient.close();
            mClient = null;
        }
    }
}

用法

connector = TcpClientConnector.getInstance();
connector.creatConnect("服务端IP地址","服务端端口号");
connector.setOnConnectLinstener(new TcpClientConnector.ConnectLinstener() {
    @Override
    public void onReceiveData(String data) {
        //do somethings.
    }
});
connector.send("要发送的内容");
@Override
protected void onDestroy() {
    super.onDestroy();
    try {
        connector.disconnect();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

确实帮了忙,第一次网络打赏
参考地址:
https://www.jianshu.com/p/338a61ee5b42

nodejs & tcp socket

服务端

var net = require('net');
//模块引入
var listenPort = 8080;//监听端口
var server = net.createServer(function(socket){
  // 创建socket服务端
  console.log('connect: ' +
    socket.remoteAddress + ':' + socket.remotePort);
  socket.setEncoding('binary');
  //接收到数据
  socket.on('data',function(data){
    console.log('client send:' + data);
  });
socket.write('Hello client!\r\n');
 // socket.pipe(socket);
  //数据错误事件
  socket.on('error',function(exception){
    console.log('socket error:' + exception);
    socket.end();
  });
  //客户端关闭事件
  socket.on('close',function(data){
    console.log('client closed!');
     // socket.remoteAddress + ' ' + socket.remotePort);
  });
}).listen(listenPort);
//服务器监听事件
server.on('listening',function(){
  console.log("server listening:" + server.address().port);
});
//服务器错误事件
server.on("error",function(exception){
  console.log("server error:" + exception);
});

客户端

var net = require('net');
var port = 8080;
var host = '127.0.0.1';
var client= new net.Socket();
//创建socket客户端
client.setEncoding('binary');
//连接到服务端
client.connect(port,host,function(){
  client.write('hello server');
  //向端口写入数据到达服务端
});
client.on('data',function(data){
  console.log('from server:'+ data);
  //得到服务端返回来的数据
});
client.on('error',function(error){
//错误出现之后关闭连接
  console.log('error:'+error);
  client.destory();
});
client.on('close',function(){
//正常关闭连接
  console.log('Connection closed');
});

参考地址:
https://blog.csdn.net/lockey23/article/details/76408891

node.js & express

MEAN是啥东西?查询版本

node -v

结果

v8.9.3

建立文件hello.js

console.log('1+1='+(1+1));

运行

node hello.js

创建一个package.json文件

{
  "name": "Hello",
  "description": "hello mikuq.com",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "express": "4.x"
  }
}

然后

npm install

node_modules中会下在40多个包,可以用npm list查看,建立index.js,有中文记得uft8保存,否则会有乱码

var express = require('express');
var app = express();
app.get('/', function (req, res) {
  res.send('<h1>MikuQ的站点</h1>');
});
app.listen(80);

运行node index.js然后浏览器访问http://localhost就可以了

路线2

npm init

全部回车就可以了,自动生成package.json

npm install express --save

或者

npm install express-generator -g
express myapp
cd myapp & npm install
SET DEBUG=myapp:* & npm start

有点儿乱了,http和express有啥区别呢,有没有压力测试,生产环境如何部署?

参考:
http://www.expressjs.com.cn/
http://blog.csdn.net/u012468376/article/details/53245002
https://www.cnblogs.com/stoneniqiu/p/5538109.html