记录学习的过程,优秀的文章转载

1 修改跳转页面对应的模板文件配置

// 文件位置 application/config.php (不想直接thinkphp框架中的源文件,因为在git clone之后composer install只会安装框架源文件)
'dispatch_success_tmpl'  => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
'dispatch_error_tmpl'    => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
// 修改(路径可看个人习惯)
'dispatch_success_tmpl'  => ROOT_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
'dispatch_error_tmpl'    => ROOT_PATH . 'tpl' . DS . 'dispatch_jump.tpl',

2 创建跳转页面并添加内容

{__NOLAYOUT__}<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
    <title>跳转提示</title>
    <script src="__STATIC__/lib/jquery.min.js"></script>  <!-- 必须先引入jQuery1.8或以上版本 -->
    <script src="__STATIC__/layui/layui.js"></script>  <!-- 根据自己的环境自行引入layui.js -->
</head>
<body>
<div class="system-message">
    <input type="hidden" id="msg" value="<?php echo(strip_tags($msg));?>" />
    <input type="hidden" id="url" value="<?php echo(strip_tags($url));?>" />
    <input type="hidden" id="wait" value="<?php echo(strip_tags($wait));?>" />
</div>
<script type="text/javascript">
    (function(){
        var msg=$('#msg').val();
        var url1=$('#url').val();
        var wait=$('#wait').val();

        layui.use('layer', function(){
            var layer = layui.layer;
            layer.open({
                content:msg,//提示信息
                success:function(layero,index){
                    var interval = setInterval(function(){
                        var time = --wait;
                        if(time <= 0) {
                            location.href = url1;
                            clearInterval(interval);
                        };
                    }, 1000);
                }
            })
        });
    })();
</script>
</body>
</html>

3 通过以上两步就可测试 $this->error(); 和 $this->success(); 方法了

背景

因当前开发功能需要用微信绑定第三方网站的用户表,然而微信订阅号没有 网页授权获取用户基本信息 的权限,于是就想到利用微信自动回复功能实现,点击自动回复的超链接跳转到第三方网站,这种方式有可能不当或者有其他更好的方式实现此功能,欢迎留言或者加QQ指出,具体实现如下:

步骤

// 在这里就不提微信接入及其他问题,只记录如何利用自动回复打开笫三方网站获取用户信息
// 因为在用户关注或者在给公众号文字消息的时候可以获取到用户的openid
// 于是就可以利用自动回复的功能
define("TOKEN", "token");
$echoStr = $_GET["echostr"];
//如果有$echoStr说明是对接
if (!empty($echoStr)) {
    //对接规则
    $signature = $_GET["signature"];
    $timestamp = $_GET["timestamp"];
    $nonce = $_GET["nonce"];
    $token = TOKEN;
    $tmpArr = array($token, $timestamp, $nonce);
    sort($tmpArr, SORT_STRING);
    $tmpStr = implode( $tmpArr );
    $tmpStr = sha1( $tmpStr );
    if( $tmpStr == $signature ){
        echo $echoStr;
    }else{
        echo "";
        exit;
    }
}else{
    responseMsg();
}

//用于回复用户消息
function responseMsg(){
    $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
    if (!empty($postStr)){
        $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
        $fromUsername = $postObj->FromUserName;
        $toUsername = $postObj->ToUserName;
        $MsgT = $postObj->MsgType;
        $time = time();
        //如果用户发的text类型
        if($MsgT=="text"){
            $key = trim($postObj->Content);
            $fromUsername = $postObj->FromUserName;
            $textTpl = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[%s]]></MsgType>
                        <Content><![CDATA[%s]]></Content>
                        </xml>"; 
            $msgType = "text";
            $answer = "<a href='http://www.baidu.com?openid=%s'>点击跳转</a>";
            // 如果有占位符就替换成openid
            $contentStr = strpos($answer, '%s') ? sprintf($answer,$fromUsername) : $answer;
            $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
            echo $resultStr;
            exit;
        }

        //如果用户发的event(事件)类型
        if($MsgT=="event"){
            $Event = $postObj->Event;
            if ($Event==subscribe) {
               $contentStr = "欢迎关注";
            }else{
                $contentStr = "希望您下次关注,但您收不到此条消息了";
            }

            $textTpl = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[%s]]></MsgType>
                        <Content><![CDATA[%s]]></Content>
                        </xml>"; 
            $Title = $postObj->Title;
            $Description = $postObj->Description;
            $Url = $postObj->Url;
            $msgType = 'text';
            $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
            echo $resultStr;
            exit;
        }
    }else{
        echo "";
        exit;
    }
}

结果

点击自动回复超链接就可以把openid带到第三方网站,然后就可以利用openid查到用户的信息

linux内置的cron进程能帮我们实现这些需求,cron搭配shell脚本,非常复杂的指令也没有问题。

cron介绍
我们经常使用的是crontab命令是cron table的简写,它是cron的配置文件,也可以叫它作业列表,我们可以在以下文件夹内找到相关配置文件。

- 阅读全部 -

zip

// 1、把/home目录下面的mydata目录压缩为mydata.zip
zip -r mydata.zip mydata #压缩mydata目录

// 2、把/home目录下面的mydata.zip解压到mydatabak目录里面
unzip mydata.zip -d mydatabak

// 3、把/home目录下面的abc文件夹和123.txt压缩成为abc123.zip
zip -r abc123.zip abc 123.txt

// 4、把/home目录下面的wwwroot.zip直接解压到/home目录里面
unzip wwwroot.zip

// 5、把/home目录下面的abc12.zip、abc23.zip、abc34.zip同时解压到/home目录里面
unzip abc\*.zip

// 6、查看把/home目录下面的wwwroot.zip里面的内容
unzip -v wwwroot.zip

// 7、验证/home目录下面的wwwroot.zip是否完整
unzip -t wwwroot.zip

// 8、把/home目录下面wwwroot.zip里面的所有文件解压到第一级目录
unzip -j wwwroot.zip

// 常用参数
-c:将解压缩的结果
-l:显示压缩文件内所包含的文件
-p:与-c参数类似,会将解压缩的结果显示到屏幕上,但不会执行任何的转换
-t:检查压缩文件是否正确
-u:与-f参数类似,但是除了更新现有的文件外,也会将压缩文件中的其它文件解压缩到目录中
-v:执行是时显示详细的信息
-z:仅显示压缩文件的备注文字
-a:对文本文件进行必要的字符转换
-b:不要对文本文件进行字符转换
-C:压缩文件中的文件名称区分大小写
-j:不处理压缩文件中原有的目录路径
-L:将压缩文件中的全部文件名改为小写
-M:将输出结果送到more程序处理
-n:解压缩时不要覆盖原有的文件
-o:不必先询问用户,unzip执行后覆盖原有文件
-P:使用zip的密码选项
-q:执行时不显示任何信息
-s:将文件名中的空白字符转换为底线字符
-V:保留VMS的文件版本信息
-X:解压缩时同时回存文件原来的UID/GID

unzip

// 1、把文件解压到当前目录下
unzip test.zip

// 2、如果要把文件解压到指定的目录下,需要用到-d参数。
unzip -d /temp test.zip

// 3、解压的时候,有时候不想覆盖已经存在的文件,那么可以加上-n参数
unzip -n test.zip
unzip -n -d /temp test.zip

// 4、只看一下zip压缩包中包含哪些文件,不进行解压缩
unzip -l test.zip

// 5、查看显示的文件列表还包含压缩比率
unzip -v test.zip

// 6、检查zip文件是否损坏
unzip -t test.zip

// 7、将压缩文件test.zip在指定目录tmp下解压缩,如果已有相同的文件存在,要求unzip命令覆盖原先的文件
unzip -o test.zip -d /tmp/

PHP开发很多时候都要读取大文件,比如csv文件、text文件,或者一些日志文件。这些文件如果很大,比如几个G。这时,直接一次性把所有的内容读取到内存中计算不太现实。
使用生成器读取文件,可以第一次读取了第一行,第二次读取了第二行,以此类推,每次被加载到内存中的文字只有一行,可以大大的减小了内存的使用。

header("content-type:text/html;charset=utf-8");
function getLines($file) {
    $f = fopen($file, 'r');
    try {
        while ($line = fgets($f)) {
            yield $line;
        }
    } finally {
        fclose($f);
    }
}

foreach (getLines("sgland.log") as $n => $line) {
    //逐行内容
    echo $line . "</br>";
    //行数
    // var_dump($n);
}

microtime();  //返回当前 Unix 时间戳的微秒数:
$start = microtime(true);
$data = range(0, 1000000, 1);
foreach ($data as $val){
    echo $val;
}
$end = microtime(true);
echo  '耗时' . round($end - $start, 3) . '秒' . "\n";

memory_get_usage();  //返回当前分配给PHP脚本的内存量,单位是字节(byte)
echo '开始内存:'.memory_get_usage(), ''; 
$tmp = str_repeat('hello', 1000);   
echo '运行后内存:'.memory_get_usage(), '';  
unset($tmp);   
echo '回到正常内存:'.memory_get_usage(); 

<?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;
    }


    function posturl($url,$data){
            $data  = json_encode($data);    
            $headerArray =array("Content-type:application/json;charset='utf-8'","Accept:application/json");
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE);
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            $output = curl_exec($curl);
            curl_close($curl);
            return json_decode($output,true);
    }


    function puturl($url,$data){
        $data = json_encode($data);
        $ch = curl_init(); //初始化CURL句柄 
        curl_setopt($ch, CURLOPT_URL, $url); //设置请求的URL
        curl_setopt ($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); //设为TRUE把curl_exec()结果转化为字串,而不是直接输出 
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"PUT"); //设置请求方式
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//设置提交的字符串
        $output = curl_exec($ch);
        curl_close($ch);
        return json_decode($output,true);
    }


    function delurl($url,$data){
        $data  = json_encode($data);
        $ch = curl_init();
        curl_setopt ($ch,CURLOPT_URL,$put_url);
        curl_setopt ($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "DELETE");   
        curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
        $output = curl_exec($ch);
        curl_close($ch);
        $output = json_decode($output,true);
    }


    function patchurl($url,$data){
        $data  = json_encode($data);
        $ch = curl_init();
        curl_setopt ($ch,CURLOPT_URL,$url);
        curl_setopt ($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "PATCH");  
        curl_setopt($ch, CURLOPT_POSTFIELDS,$data);     //20170611修改接口,用/id的方式传递,直接写在url中了
        $output = curl_exec($ch);
        curl_close($ch);
        $output = json_decode($output);
        return $output;
    }
?>

前提:目前需要删除大部分的数据,保留最近一段时间的数据

1、delete删除数据
我们知道delete语句的删除速度与索引量成正比,此表中的索引量已经很大了,而且数据量非常之巨大,若采用常规delete语句删除,必定会话费很长的时间。并且Delete语句删除不会释放出磁盘空间,所以肯定还是会出现报警,所以此种方式不可取。
2、drop删除表
流程简述:新建结构相同的表,命名“table_new”,’将需要保存的数据插入到此表中,然后drop掉老表"table_old",然后修改“table_new”的表名。

# Sql语句如下:
# 基于老表新建新表
CREATE TABLE table_new LIKE table_old;
# 插入数据到新表(以保存2019-10-01到现在的数据为例,如果数据过大可分批插入)
INSERT INTO table_new SELECT * FROM table_old WHERE date > '2019-10-01 00:00:00';
# 然后drop老表“table_old”
DROP TABLE table_old;
# 重命名新表“table_new”
ALTER TABLE table_new RENAME TO table_old;

CentOS安装GeoIP

yum -y install nginx-module-geoip

yum 安装好后找到安装的模块文件
如果nginx是用yun安装的一般是安装到 /etc/nginx/modules/目录下

手动加入模块

在nginx.conf配置文件的头部载入模块和http是同一个级别的

load_module "modules/ngx_http_geoip_module.so";
load_module "modules/ngx_stream_geoip_module.so";
ps: load_module 不能放在events{} 的后面,放在后面重启nginx会报错

因为GeoIP是基于MaxMind 提供了数据库文件来读取地域信息的所以需要下载ip的地域文件。
这个数据库是二进制的,不能用文本编辑器打开,需要上面的 GeoIP 库来读取,下面提供下载地址。
country.dat.gz
city.dat.gz
解压之后到nginx目录的geoip文件夹中,然后在项目的http中配置

geoip_country /etc/nginx/geoip/GeoIP.dat;  #加载国家IP
geoip_city /etc/nginx/geoip/GeoLiteCity.dat; #加载城市IP

server中添加配置

#判断如果不是中国的就返回403;
if ($geoip_country_code != CN) {
    return 403;
}

这样就可以实现除中国以外的ip访问返回403.

背景

因老服务器负载较高 故新增一台服务器 需要调整时间到加拿大温哥华时区

步骤

首先真正常调整时区时间

// 首先备份
mv /etc/localtime /etc/localtimeBak
// 再调整
ln -sf /usr/share/zoneinfo/America/Vancouver /etc/localtime

调整之后发现执行的java程序不管怎么样都跟北京时间一样,然后各种百度,

hwclock --set --date="08/30/19 07:26:50"
.
hwclock --hctosys
.
.
.
然并卵...

结果

最后发现问题出在 /etc/timezone 上面,在 /etc/timezone 中设置的是 Asia/Shanghai ,把它修改成 America/Vancouver ,问题解决 ...