C语言编写 执行mysql脚本,禁止delete操作

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct sqlConfig
{
        char *db_name;//数据库名称
        char *db_sql;//sql语句
} Config;

int main(int argc,char *argv[])
{

        if(argc!=3)
        {
                printf("第一个参数为数据库名,第二个数据库名为sql语句。\n");
                printf("例如:./a.out mysql 'select * from user;'\n");
                return 0;
        }


        char *shell_cmd = "/xxx/xxx/bin/mysql -h127.0.0.1 -Pxxxx -u xxxx -pxxxx -S /xxx/xxxx/mysql.sock";

        //初始化 结构体
        Config config = {*(argv+1),*(argv+2)};


        /*****  判断是否为delete语句  ******/
        char del_char[6] = {100,101,108,101,116,101};//delete 这个单词的ascii 码
        int is_bool = 0;//如果全部 ascii相同赋值为1
        for(int i=0;i<6;i++)
        {
                if(config.db_sql[i]==del_char[i])
                {
                        is_bool=1;
                }else{
                        is_bool=0;
                        break;
                }
        }
        if(is_bool==1)
        {
                printf("%s\n","危险操作!");
                return 0;
        }

        //动态分配字符变量,用来拼接sql语句
        char *return_text = (char *) malloc(strlen(shell_cmd)+strlen(config.db_name)+strlen(config.db_sql)+10);
        sprintf(return_text,"%s%s%s%s%s%s%s",shell_cmd," -D ",config.db_name," -e ","\"",config.db_sql,"\"");
        printf("%s\n",return_text);
        //执行sql语句
        system(return_text);
        //释放动态变量
        free(return_text);
}

运行:gcc test.c -o my_mysql

接着运行delete操作

./my_mysql bilbil “delete from bilbil_user;”

危险操作

运行 其他操作

./my_mysql bilbil “select * from bilbil_user_info;”
+—-+———+———–+———–+———-+————+———–+———————+———————+
| id | user_id | user_icon | user_name | user_uid | user_birth | user_desc | update_time | create_time |
+—-+———+———–+———–+———-+————+———–+———————+———————+
| 17 | 35 | NULL | NULL | NULL | NULL | | 2019-06-06 14:54:45 | 2019-06-06 14:54:45 |
+—-+———+———–+———–+———-+————+———–+———————+———————+

appium 编写获取 虎扑社区信息脚本

首先我们打款appium桌面版

运行

接着下载
pip install Appium-Python-Client

先用aapt工具查看下虎扑包的 包名 和 首activity

aapt dump badging C:\Users\Administrator\Desktop\hupu.apk (你当前包名地址)

这个就是包名
这个就是首activity

接着我们连接 我们的安卓手机

我们用 adb devices 查看连接的手机名

然后我们要 adb kill-server 不然appium的adb就会被占用

好了 万事俱备只欠运行了

我们点一下搜索按钮
{
  "platformName": "Android", //系统 android or ios
  "platformVersion": "7.0", //系统 版本 7.0 5.1 4.0
  "deviceName": "BWN9X17615W02808", //手机名称
  "appPackage": "com.hupu.games", //打开的apk包名
  "appActivity": "com.hupu.games.activity.LaunchActivity" //apk首页
}

保存

然后 start session

如果成功的话会看到一些画面

我们在手机上点允许

点一下 appium的 刷新按钮

我们随便点击一个更多按钮 右边就是这个按钮的属性,有了这些属性我们就可以写python脚本了。

代码实现逻辑

  1. 首先 进来的时候 点击允许权限
  2. 进来后 点击 更多
  3. 再点击手机图标 然后进到登录页 点击 账号密码登录用send_key 来输入手机和密码 再点击登录
  4. 登录后 点击社区按钮 然后 循环 上拉加载 把显示在当前屏幕的 每一行的内容打印出来。

代码实现

from appium import webdriver

desired_caps = {}

desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '7.0'
desired_caps['deviceName'] = 'BWN9X17615W02808'
desired_caps['appPackage'] = 'com.hupu.games'
desired_caps['appActivity'] = 'com.hupu.games.activity.LaunchActivity'

driver = webdriver.Remote("http://localhost:4723/wd/hub",desired_caps)

首先引入appium 把设备信息和包名填上 接着运行 (端口就是appium的端口)

第二部

#电话权限 xpath
phone_quanxian = driver.find_element_by_xpath("/hierarchy/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.LinearLayout/android.widget.LinearLayout/android.widget.LinearLayout/android.widget.Button[2]")
phone_quanxian.click()

#存储权限
save_quanxian = driver.find_element_by_id("com.android.packageinstaller:id/permission_allow_button")
save_quanxian.click()

这两端代码就是点击 权限

第三步

#更多按钮
genduan_btn = driver.find_element_by_id("com.hupu.games:id/btn_mytab")
genduan_btn.click()

第四步

#登录手机按钮
denlv_phone_btn = driver.find_element_by_id("com.hupu.games:id/mobile_login_new")
denlv_phone_btn.click()

#使用密码登录
click_pass_login = driver.find_element_by_id("com.hupu.games:id/bt_accout_login").click()

#输入手机号
input_phone_number = driver.find_element_by_id("com.hupu.games:id/username_text").send_keys("**************")

#输入密码
input_pass_number = driver.find_element_by_id("com.hupu.games:id/password_text").send_keys("****************")

#登录
login = driver.find_element_by_id("com.hupu.games:id/btn_account_submit").click()

#社区按钮
sequ_btn = driver.find_element_by_id("com.hupu.games:id/btn_bbs").click()

第五步

#查看社区信息
for i in range(1000):
view_group = driver.find_element_by_class_name("android.support.v7.widget.RecyclerView")
#获取当前可见的所有列表
view_layouts = view_group.find_elements_by_class_name("android.widget.LinearLayout")
for view_layout in view_layouts:
#判断此列表是否是 主列表
if(view_layout.get_attribute("resourceId")=="com.hupu.games:id/hot_replies_main"):
#获取当前主列表,下的全部textView
text_views = view_layout.find_elements_by_class_name("android.widget.TextView")
for text_view in text_views:
#判断当前textView 文字是否是 内容
if(text_view.get_attribute("resourceId")=="com.hupu.games:id/tv_content"):
print(text_view.text)
#向上滚动
height = int(driver.get_window_size()['height'] - 200)
driver.swipe(0, height, 0,height/3)

好了我们运行整个程序

用koa来 编写一个简单的docker web管理工具

需要用到的库

npm install koa

npm install koa-router

npm install koa-static

npm install koa-views

npm install ejs

目录结构

server 里

sh 里面

产品描述

通过nodejs 里的 child_process 库里的 exec方法来 操作docker shell脚本

然后显示到前端页面上

看一下效果吧

首页

点击运行

容器页面

代码实现(只拿取一些代码)

首先server 里的 index.js 文件 (注释我已经写好了)

const koa = require('koa')
const routerRule = require('./router/router')
const views = require('koa-views')
const static = require('koa-static');
const path = require('path')
const app = new koa()

//加载html页面
const viewPath = './views'
app.use(views(path.join( __dirname,viewPath), {extension: 'ejs'}))

// 配置静态资源
const staticPath = './static'
app.use(static(
    path.join( __dirname, staticPath)
))

//配置路由
app.use(routerRule.routes())

//监听3322端口
app.listen(3322)

接着是 router/router.js 文件

const Router = require('koa-router')
const routerRule = new Router()
//加载dockerCmd 函数
const DockerCmd = require('../utils/dockerCmd')
const path = require('path')
const filePath = path.join(__dirname,"../../sh/")

//sh目录的全局变量
global.filePath = filePath
//DockerCmd函数的全局变量
global.DockerCmd = DockerCmd

//获取全部镜像
routerRule.get('/',require("../controller/index").all)

//删除某个镜像
routerRule.get('/delImage/:imageID',require("../controller/index").del)

//运行某个镜像
routerRule.get('/runImage/:image',require("../controller/index").run)

//获取全部容器
routerRule.get('/container',require("../controller/container").all)

//获取某个容器开启的镜像
routerRule.get('/container/:containerID',require("../controller/container").id)

//删除某个容器
routerRule.get('/delContainer/:containerID',require("../controller/container").del)

//停止某个容器
routerRule.get('/stopContainer/:containerID',require("../controller/container").stop)

//运行某个容器
routerRule.get('/startContainer/:containerID',require("../controller/container").run)

module.exports = routerRule

接着是 utils/dockerCmd.js 文件

const exec = require('child_process').exec
module.exports = class DockerCmd {
        static async execFile(cmdStr) {
                return new Promise((resolve, reject) => {
                        //执行传输过来的 shell命令
                        exec(cmdStr, (err, str, stderr) => {
                                if (err) {
                                        reject(err)
                                } else {
                                        resolve(str)
                                }
                        })
                })
        }
}

最后是controller 这个 文件里的 index.js文件

module.exports = class Index {
        static async all(ctx, next) {
                let str = `/bin/bash ${filePath}get_docker_images.sh`
                let res = await DockerCmd.execFile(str)
                let lists = []
                if (res) {
                        let arr = res.split(" ")
                        if (arr.length > 0) {
                                for (let i = 0; i < arr.length; i++) {
                                        if (arr[i] != "\n") {
                                                let list = arr[i].split("|")
                                        }
                                }
                        }
                }
                await ctx.render("index/index", { title: "docker镜像", lists: lists })
        }

module.exports = class Index {
        //获取全部镜像
        static async all(ctx, next) {
                let str = `/bin/bash ${filePath}get_docker_images.sh`
                let res = await DockerCmd.execFile(str)
                let lists = []
                if (res) {
                        let arr = res.split(" ")
                        if (arr.length > 0) {
                                for (let i = 0; i < arr.length; i++) {
                                        if (arr[i] != "\n") {
                                                let list = arr[i].split("|")
                                        }
                                }
                        }
                }
                await ctx.render("index/index", { title: "docker镜像", lists: lists })
        }

        //运行镜像
        static async run(ctx, next) {
                let str = `${ctx.params.image}`
                ctx.response.type = 'text/html'
                try {
                        let res = await DockerCmd.execFile(str)
                        ctx.response.body = res + " 运行成功!<a href='#' onclick='self.location=document.referrer;'>返回</a>"
                } catch (err) {
                        ctx.response.body = "运行失败!<a href='#' onclick='self.location=document.referrer;'>返回</a>"
                }
        }

        //删除镜像
        static async del(ctx,next)
        {
                let str = `docker rmi ${ctx.params.imageID}`
                ctx.response.type = 'text/html'
                try {
                        let res = await DockerCmd.execFile(str)
                        ctx.response.body = "删除成功!<a href='#' onclick='self.location=document.referrer;'>返回</a>"
                } catch (err) {
                        ctx.body = "删除失败!<a href='#' onclick='self.location=document.referrer;'>返回</a>"+err
                }
        }

}

container.js 文件

module.exports = class Container {
        //获取全部容器
        static async all(ctx, next) {
                let str = `/bin/bash ${filePath}get_docker_images_ps.sh`
                let res = await DockerCmd.execFile(str)
                let lists = []
                if (res) {
                        let arr = res.split(",")
                        if (arr.length > 0) {
                                for (let i = 0; i < arr.length; i++) {
                                        if (i != arr.length - 1) {
                                                let list = arr[i].split("|")
                                                let status_type = 0;//0为未运行或其他 1为运行中
                                                if (list[2].search("Up") != -1) {
                                                        status_type = 1
                                                }

                                        }
                                }
                        }
                }
                await ctx.render("container/index", { title: "docker容器", lists: lists })
        }
        //根据id获取容器
        static async id(ctx, next) {
                let str = `/bin/bash ${filePath}get_docker_images_ps.sh`
                let res = await DockerCmd.execFile(str)
                let lists = []
                let containerID = ctx.params.containerID
                if (res) {
                        let arr = res.split(",")
                        if (arr.length > 0) {
                                for (let i = 0; i < arr.length; i++) {
                                        if (i != arr.length - 1) {
                                                //是否是当前容器
                                                let add_list = false
                                                let list = arr[i].split("|")
                                                let containerName = containerID.split("&")
                                                if (containerName[0]) {
                                                        for (let j = 0; j < list[1].length; j++) {
                                                                if (containerName[0][j]) {
                                                                        if (containerName[0][j] != list[1][j]) {
                                                                                add_list = false
                                                                                break
                                                                        } else {
                                                                                add_list = true
                                                                        }
                                                                }
                                                        }
                                                if (containerName[1] && !add_list) {
                                                        if (containerName[1] == list[1]) {
                                                                add_list = true
                                                        } else {
                                                                add_list = false
                                                        }
                                                }

                                                if (containerName[2] && !add_list) {
                                                        if (containerName[2] == list[1]) {
                                                                add_list = true
                                                        } else {
                                                                add_list = false
                                                        }
                                                }


                                                if (add_list) {
                                                        let status_type = 0;//0为未运行或其他 1为运行中
                                                        if (list[2].search("Up") != -1) {
                                                                status_type = 1
                                                        }
                                                }
                                        }
                                }
                        }
                }
                await ctx.render("container/index", { title: "docker-" + containerID + "-容器", lists: lists })
        }

        //删除容器
        static async del(ctx, next) {
                let str = `docker rm ${ctx.params.containerID}`
                ctx.response.type = 'text/html'
                try {
                        let res = await DockerCmd.execFile(str)
                        ctx.response.body = "删除成功!<a href='#' onclick='self.location=document.referrer;'>返回</a>"
                } catch (err) {
                        ctx.body = "删除失败!<a href='#' onclick='self.location=document.referrer;'>返回</a> "+err
                }
        }

        //停止容器
        static async stop(ctx, next) {
                let str = `docker stop ${ctx.params.containerID}`
                ctx.response.type = 'text/html'
                try {
                        let res = await DockerCmd.execFile(str)
                        ctx.response.body = "停止成功!<a href='#' onclick='self.location=document.referrer;'>返回</a>"
                } catch (err) {
                        ctx.body = "停止失败!<a href='#' onclick='self.location=document.referrer;'>返回</a>"
                }
        }
        //运行容器
        static async run(ctx,next){
                let str = `docker start ${ctx.params.containerID}`
                ctx.response.type = 'text/html'
                try {
                        let res = await DockerCmd.execFile(str)
                        ctx.response.body = "运行成功!<a href='#' onclick='self.location=document.referrer;'>返回</a>"
                } catch (err) {
                        ctx.body = "运行失败!<a href='#' onclick='self.location=document.referrer;'>返回</a>"
                }
        }

}

最后就是 git地址 git@gitee.com:huxierong/dockerMsg.git

nodejs开发一个 网站百度关键字查询

我们首先 npm init

下载包

npm install koa

npm install request

npm install iconv-lite

npm install cheerio

然后目录如下

request.js文件是 进一步封装 request的get请求

var request = require('request');
var iconv = require('iconv-lite');
module.exports = class Request{
  static get(apiUrl)
  {
    return new Promise((resolve,reject)=>{
      request({
        url:apiUrl,
        method: "get",
        encoding: null,
        headers: {
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
        }
      }, function(err, res, body) {
        if (err) {
          reject(null)
        } else {
          body = iconv.decode(body, 'utf-8');
          resolve(body)
        }
      })
    })
  }
}

我们先看baiduSeo.js 文件

这个文件 是用来获取传递过来的url 把keyword解析成数组返回

const request = require('../utils/requests.js');
const cheerio = require('cheerio');
module.exports = class BaiduSeo{
  
  //获取url
  async getUrl(url)
  {
    try{
      const data = await request.get(this.isHttp(url))
      if(data)
      {
        return this.parseData(data)
      }else{
        return null
      }
    }catch(error)
    {
      return null
    }
  }

  //判断是否有http
  isHttp(url)
  {
    if(url.search("http")!=-1)
    {
      return url
    }else{
      return "http://"+url
    }
  }

  //解析数据
  parseData(data)
  {
    if(data!=null)
    {
      const get = cheerio.load(data)
      const keyword = get("meta[name=keywords]").attr('content')
      const keywords = keyword.split(',')
      let arr = []
      if(keywords.length>0)
      {
        for(let i=0;i<keywords.length;i++)
        {
          arr.push({name:keywords[i]})
        }
        return arr
      }else{
        return null
      }
    }else{
      return null
    }
  }
  
}

接着我们来看看 seoRank.js 文件 它是返回 某个网站的某个关键字 是否在百度前10页 如果是就返回当前页,否则返回0

const request = require('../utils/requests.js');
const cheerio = require('cheerio');
module.exports = class SeoRank{
  
  //获取数据
  async getData(data,searchName)
  {
    let rank = {name:data,rank:0}
    searchName = await this.delMaterial(searchName)
    for(let i=0;i<10;i++)
    {
      let page = i*10
      let urlStr = `https://www.baidu.com/s?ie=utf-8&wd=${data}&pn=${page}`
      let url = encodeURI(urlStr)
      let response = await request.get(url)
      if(response.search(searchName)!=-1)
      {
        rank = {name:data,rank:i+1}
        return rank
      }
    }
    return rank
  }

  //去掉https:// http:// 斜杠 保留
  async delMaterial(url)
  {
    return url.replace(/\//g,'').replace("https:","").replace("http:","")
  }

}

接着 我们创建一个中间件 searchKeyword.js 这个文件是根据get请求来 判断是获取 关键字 还是 当前关键字的排名

const BaiduSeo = require('../middleware/baiduSeo');
const SeoRank = require('../middleware/seoRank');
module.exports = async function searchKeyword(ctx,next)
{
  let query = ctx.request.query
  if(query['type'])
  {
    if(query['type'] && query['url'])
    {
      if(query['type']=="getKeyword")
      {
        let baiduSeo = new BaiduSeo()
        const keyword = await baiduSeo.getUrl(query['url'])
        if(keyword)
        {
          ctx.body = keyword
        }else{
          ctx.body = "null"
        }
      }else if(query['type']=="searchKeyword" && query['keyword'])
      {
        let rank = []
        let seoRank = await (new SeoRank()).getData(query['keyword'],query['url'])
        rank.push(seoRank)
        ctx.body = rank
      }else{
        ctx.body = "null"
      }
    }else{
      ctx.body = "null"
    }
  }
  else{
    ctx.body = "null"
  }
  await next()
}

好了到了我们的index.js 文件了 使用koa框架

const Koa = require("Koa")
const app = new Koa()
const SearchKeyword = require('./use/searchKeyword')
app.use(SearchKeyword)
app.listen(8776)
console.log("run")

现在我们可以运行下看看 首先是获取全部关键字

接着根据某个关键字来获取 排名

也就是说这个关键字 在百度第4页

当然这里面还有点bug

php 简单使用 C语言编写一个 根据域名获取ip的函数

php版本 php-7.3.2

我们首先进入php安装包里面

cd ext/ 进入此目录

这时你会看见一个 ext_skel.php的文件

然后 ./ext_skel.php –ext say_hello (say_hello 可以随便取)

我们首先写一个示例先 这个示例是 写一个函数 输出 hello

我们cd进入 say_hello 这个目录

vim say_hello.c 可以看到很多乱七八糟的鬼东西 我们先不要管

我们在 这个 函数下面 定义一个 set_hello函数

PHP_FUNCTION(set_hello)
 {
         char *res;
         res = strpprintf(0,"hello world!");
         RETURN_STR(res); //把hello world 返回出去!
 }

接着我们找到 zend_function_entry 这里

把生成的 say_hello_test1 和 say_hello_test2 注释掉或del掉

然后 写上 PHP_FE(set_hello,NULL)

保存退出

接着 运行

/php/bin/phpize (这是我的目录 请根据自己的目录)

./configure –with-php-config=php/bin/php-config
(这是我的目录 请根据自己的目录)

make && make install

接着我们修改 php.ini 文件 添加 extension=say_hello.so

保存 我们写一个 test.php 测试一下

<?php
echo set_hello();

/php/bin/php test.php 运行

ok 完成。

接着我们回到正题

一些繁琐的步骤我就不写了

首先

./ext_skel.php –ext hello

接着 vim hello.c

我们在头部引入

#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>

接着新建一个函数

PHP_FUNCTION(yeye)
{
        struct hostent *h;
        zend_string *return_str;
        char *host;
        char strIp[32];
   // zend_parse_parameters 是获取传递过来的 测试 s 是字符串类型 &host就是传递过来的参数
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!",&host) == FAILURE){
                RETURN_NULL();
        }

        char ch = '/';
        char *ret;

        ret = strrchr(host, ch);
        if(ret)
        {
                ret = ret+1;
        }else
        {
                ret = host;
        }
        //gethostbyname 返回hostent结构体类型指针 这里判断是否成功 里面的参数可以上网查询
        if((h=gethostbyname(ret))!=NULL){
                //inet_ntop 将网络传输的二进制数值转化为成点分十进制的ip地址 不懂上网查询
                inet_ntop(h->h_addrtype,h->h_addr,strIp,sizeof(strIp));
                return_str = strpprintf(0,strIp);
                RETURN_STR(return_str);
        }else
        {
                RETURN_FALSE;
        }
}

修改 zend_function_entry

static const zend_function_entry hello_functions[] = {
        PHP_FE(yeye,NULL)
        PHP_FE_END
};

保存 然后根据前面的步骤编译就可以了

最后要把 extension=hello.so 加进 php.ini文件

好了我们测试下吧

<?php
if(!isset($_GET['url'])){
        exit("url不能为空!");
};
var_dump(yeye($_GET['url']));

保存 重启php-fpm 运行

成功的失败

失败的时候

参考教程:
https://blog.csdn.net/u011957758/article/details/72513935

python 使用myqr 生成动态二维码

myqr 是一个可以生成动态二维码的 python模块

github:
https://github.com/sylnsfar/qrcode/blob/master/README-cn.md

下载 pip install myqr

简单使用

from MyQR import myqr

myqr.run(words=”https://www.huxierong.xyz”,colorized=True,picture=”nick.gif”,level=”L”)

生成如下图片

picture 就是要覆盖的图片

colorrized 是否填充色彩

level 生成图片的质量 L M Q H 从左到右 依次增加

下面我们来实战下吧

我们首先docker pull python 拉一个python镜像下来

docker run -it -d -p 5000:5000 -p 5001:5001 python 运行此命令

进入 容器里面

apt-get update

pip install flask

pip install myqr

apt-get install vim

运行命令 也可以 写一个 dockerFile来一次性完成

新建 web/

新建 uploads

目录

进入web目录

放入一张gif图

vim run.py

from flask import Flask,request
import hashlib
from MyQR import myqr
def md5(str):
    m = hashlib.md5()
    m.update(str.encode('utf-8'))
    return m.hexdigest()

def getUrl():
    return request.args.get('url')

app = Flask(__name__)

@app.route('/')
def hello_world():
    if getUrl():
        myqr.run(words=getUrl(),colorized=True,level="L",picture="test.gif",save_name="/uploads/static/images/"+md5(getUrl())+".gif")
        return "http://xxxxxxxx:8800/static/images/"+md5(getUrl())+".gif"
    return "Hello World"

if __name__ == '__main__':
    app.run(host='0.0.0.0')

进入uploads目录

新建static 进入static 新建images目录

进入uploads目录

vim run.py

from flask import Flask,request

app = Flask(__name__)

if __name__ == '__main__':
    app.run(host='0.0.0.0',port="5001")

进入宿主机

配置nginx 让它代理5001端口


upstream dockerserver {
    server 172.17.0.1:5001;
}
server {
        listen       8800;
        server_name localhost;
        location / {
                proxy_pass http://dockerserver;
        }
}

新建qr.php

<?php
function geturl($url){
        #$headerArray =array("Content-type:application/json;","Accept:application/json");
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        #curl_setopt($url,CURLOPT_HTTPHEADER,$headerArray);
        $output = curl_exec($ch);
        curl_close($ch);
        #$output = json_decode($output,true);
        return $output;
}

$path = geturl("http://172.17.0.1:5000?url=".htmlspecialchars($_GET['url']));
echo "<img src='{$path}' />";

运行

一个小项目完成了。当然还有好多细节要改哦。

ios plist 安装应用

我们知道如果要安装ios应用的话除了上架和用itunes 之外,好像没有什么其他好方法了。

其实还有一种比较便捷的方法。

如:

我们先打一个ipa包出来

接着

编写一个 app.plist (app随便写)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>items</key>
        <array>
                <dict>
                        <key>assets</key>
                        <array>
                                <dict>
                                        <key>kind</key>
                                        <string>software-package</string>
                                        <key>url</key>
                                        <string>https://www.huxierong.xyz/yg.ipa (ipa的路径)</string>
                                </dict>
                                <dict>
                                        <key>kind</key>
                                        <string>full-size-image</string>
                                        <key>needs-shine</key>
                                        <true/>
                                        <key>url</key>
                                        <string>https://www.huxierong.xyz/yg.png (图标)</string>
                                </dict>
                                <dict>
                                        <key>kind</key>
                                        <string>display-image</string>
                                        <key>needs-shine</key>
                                        <true/>
                                        <key>url</key>
                                        <string>https://www.huxierong.xyz/yg.png(图标)</string>
                                </dict>
                        </array>
                        <key>metadata</key>
                        <dict>
                                <key>bundle-identifier</key>
                                <string>xxx.xxx.xxx (填写bundle id 如 com.xxx.xxx)</string>
                                <key>bundle-version</key>
                                <string>127 (填写版本code 不是版本名称哦) </string>
                                <key>kind</key>
                                <string>software</string>
                                <key>title</key>
                                <string>测试(填写app名称)</string>
                        </dict>
                </dict>
        </array>
</dict>
</plist>

然后编写一个 down.html

<script>
window.location = "itms-services://?action=download-manifest&url=https://www.huxierong.xyz/x5.plist"; //填写.plist 文件的路径
</script>

用ios手机运行下 正常情况下会出现下面这种情况



注意:如果是个人开发者(¥99) 需要把当前手机的uuid 加入描述文件中,而

企业用户(¥299)就不用,企业用户可以安装在所有ios手机设备上。

个人用户不要用生产环境的证书,不然会出现,点不了的情况

lua脚本 实现灰度发布 线上测试

大概逻辑是,先用redis 把测试人员的ip存入到一个集合中,然后用lua脚本判断当前客户端ip是否在这个集合,如果在,就做测试通道,否则就是正式环境。

如图:

把测试人员的ip地址存入 redis集合中

代码如下

首先要安装 ngxin lua 模块 我博客里有,就不在这里写了

首先是lua脚本

local redis = require "resty.redis" --导入redis包
local red = redis:new() --实例化redis
local headers = ngx.req.get_headers()--获取头部文件
local ok,err = red:connect("127.0.0.1",6379) --连接redis
local ip = headers["X-REAL-IP"] or headers["X_FORWARDED_FOR"] or ngx.var.remote_addr or "0.0.0.0" --获取ip
if not ok then
ngx.say("fail to connect 127.0.0.1:6379")
return
end
--red:sadd("hxr",ip)
local str = red:smembers("hxr") --获取hxr这个集合里的 ip
for k,v in pairs(str) do --遍历
if(v==ip)
then
ngx.exec("@here") --存在就跳转到这个节点
return
end
end
ngx.exec("@noHere") --否则 就跳转到 noHere这个节点

然后是 test_lua.conf 配置文件

server{
        listen 9090;
        server_name localhost;
        location / {
                default_type 'text/plain';
                charset utf-8;
                content_by_lua_file /soft/nginx/conf/conf/test_lua.lua;
        }

        location @here {
                root /web/testLua/one;
        }

        location @noHere{
                root /web/testLua/two;
        }

}

运行下 9090端口

打印的是 @noHere 这里的代码

然后我们把ip加进集合中

再次运行

这时显示的是@here 这里的代码