最近在阿里云上买了台香港服务器,将相关博客系统迁移到次,为了方便管理,决定采用docker来部署新的博客系统。
本博客系统使用 Typecho 开源系统,并根据自身喜好进行了相关调整,如需了解更多,请前往 Github。

拉取LNMP镜像

docker pull php:7.1.0-fpm
 docker pull nginx
 docker pull mysql

创建容器

1. mysql

docker run --name blog-mysql -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=xxx mysql:5.6

2. fpm

docker run --name blog-fpm -d -v ~/code/blog:/code/blog --link blog-mysql:blog-mysql php:7.1.0-fpm

3. nginx

docker run --name blog-nginx -d -p 80:80 --link blog-fpm:blog-fpm --volumes-from blog-fpm nginx

--link 容器内部通讯
--volumes-from 挂在容器中数据卷

修改相关配置

1. fpm

使用数据库时,host仅需指定 `blog-mysql` 即可,根据需求使用 `docker-php-ext-install` 命令下载相关扩展。

2. nginx

`nginx.conf` 中 `fastcgi_pass` 指定为 `blog-fpm:9000` 即可。

相关指令

1. 启动、重启、停止容器

docker start blog-nginx
docker stop blog-nginx
docker restart blog-nginx

2. 查看所有容器

docker ps -a

当前博客系统为例,结果如下:

CONTAINER ID     IMAGE          COMMAND  CREATED      STATUS       PORTS                   NAMES
06b2657e8910     nginx          "..."    3 days ago    Up 3 days   0.0.0.0:80->80/tcp      blog-nginx
2902bf501c50     php:7.1.0-fpm  "..."    3 days ago    Up 3 hours  9000/tcp                blog-fpm
8e0cf6297380     mysql:5.6      "..."    3 days ago    Up 3 days   0.0.0.0:3306->3306/tcp  blog-mysql 

3. 进入容器

docker exec -ti blog-nginx bash

4. 删除容器

需先停掉容器

docker rm blog-nginx

4. nginx容器

修改nginx配置后需重启才能生效

nginx -s reload

todo

后续将调整使用dockerfile快速部署各个系统。

提问

str1=小***,**是我,我是**
str2=小宝宝,枪支是我,我是弹药
要把字符串2根据字符串1进行标红处理,这个咋搞呢?
有可能多个*对应一个汉子~

思考

刚开始想到使用数组,用 , 分隔,然后根据位置 (毕竟字符串也是字符序列 ^=^) 进行替换,但是总感觉太low了,应该有更加优雅的解决方案。

方案

自认为较优雅的解决方案是采用正则匹配分隔

具体demo如下:

<?php
    $str1 = '小***,**是我,我是**';
    $str2 = '小宝宝,枪支是我,我是弹药';

    $keywords = preg_split("/[小\s,\s是我,我是\s]/u", $str2);

    /下面三种情况均可,等待探究  (*囧*)
    / $keywords = preg_split("/[小\s,\s是我,我是\s]+/u", $str2);  
    / $keywords = preg_split("/[小\s,\s是我]/u", $str2);
    / $keywords = preg_split("/[小\s,\s是我]+/u", $str2);

    $keywords = array_values(array_filter($keywords));
    $params = explode(',', $str1);

    foreach ($params as $key => &$value) {
        $value = preg_replace('/\*{2,}/u', '<span style="color:red;">' . $keywords[$key] . '</span>', $value);
    }

    echo implode(',', $params);

总结

实际需要根据具体的业务(需求)场景编写合适的逻辑代码。

最近帮别人开发纽曼来电小秘书,小踩了几个坑,在此与大家分享,给大家排排雷

坑1. 文档不够详细,函数不全,更没有介入流程介绍,总之就是一个大坑。

    EnableCard()
    CheckLine(Line:Word)
    ...

坑2. 没有注明dll使用方式,是直接引用还是DllImport?

1.直接引用的话,vs会直接报错,说明此方法错误
2.DllImport申明方法,使用正常

附P/Invoke代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace Secretary
{
    class Secretary
    {
        [DllImport("usbms.dll", EntryPoint = "LoadDRV")]
        public static extern int LoadDRV();  

        [DllImport("usbms.dll", EntryPoint = "IsRing")]
        public static extern bool IsRing(int Line);

        [DllImport("usbms.dll", EntryPoint = "ReadUsbState")]
        public static extern bool ReadUsbState(int line);  

        [DllImport("usbms.dll", EntryPoint = "IsOffHook")]
        public static extern bool IsOffHook(UInt16 Line);

        [DllImport("usbms.dll", EntryPoint = "GetDtmfCode")]
        public static extern int GetDtmfCode(UInt16 Line);

        [DllImport("usbms.dll", EntryPoint = "GetCallerIDStr")]
        public static extern UInt16 GetCallerIDStr(UInt16 Line, StringBuilder IDStr);

        [DllImport("usbms.dll", EntryPoint = "ReadSerialNo")]
        public static extern int ReadSerialNo(UInt16 line, StringBuilder serialNo);

        [DllImport("usbms.dll", EntryPoint = "GetRingNum")]
        public static extern int GetRingNum(int line);

        [DllImport("usbms.dll", EntryPoint = "SetPCMode")]
        public static extern bool SetPCMode();

        [DllImport("usbms.dll", EntryPoint = "CheckLine")]
        public static extern bool CheckLine(UInt16 line);

        [DllImport("usbms.dll", EntryPoint = "InitRingNum")]
        public static extern void InitRingNum(int line);

        [DllImport("usbms.dll", EntryPoint = "EnableCard")]
        public static extern int EnableCard();
    }
}

坑三. 没有C#版本DEMO,只有Delphi版本DEMO

于是苦逼的我,一遍显示器开着Delphi版本的DEMO,一遍手写C#程序,强调各位一定要把Delphi的demo逻辑理清楚,也可以按照完全模仿。

附我整理的Delphi流程(c#基本实现此流程基本的功能均能ok)
1.Init


/record对应c#中的class
type TLines = record
Status:integer;
Timer:integer;
OldRingCounter:integer;
IsLine:Boolean;
IsKeyUpOld:Boolean;
end;
/对象数组
Lines:array[0..2] of Tlines;
/对应c#中stringbuilder
Serial:array[0..10] of char;
const STATUS_FREE     = 0 ;
const STATUS_RING     = 1 ;
const STATUS_WAIT_FSK = 2 ;
const STATUS_WAIT_RING_END = 3 ;

const STATUS_HANGUP            = 4 ;
const STATUS_WAIT_HANGUP_END   = 5 ;
const STATUS_RECORD   = 6 ;
const STATUS_PLAY   = 7 ;
const STATUS_SEND   = 8 ;

Lines[0].Status :=   STATUS_FREE ;
Lines[1].Status :=   STATUS_FREE ;
Lines[2].Status :=   STATUS_FREE ;

usbcount := LoadDRV;
if usbcount > 0 then
begin
    str:='加载USB驱动设备成功!';
    if EnableCard =1 then
    begin
       str:='启动USB设备成功!';
       
       ReadSerialNo(0,Serial);
       str := '序列号=';
       for i:=0 to 4 do begin
         str:= str+','+inttostr(ord(Serial[i]));
       end;
       /注意定时器启动了
       Timer1.Enabled := true;
       DeviceState := false;
    end;
    SetPCMode();
end else
begin
    str:='加载USB驱动设备失败!';
end;

2.Timer
2.1 GetTrunkState(0)


/line = 0
/<> -> !=   =->==   =:->=
if Lines[line].IsLine <> CheckLine(line) then
  begin
      if Lines[line].IsLine then
      begin
          str := '外线断开'
      end else
      begin
          str := '外线接通'
      end;
      Memo1.Lines.Add(str);
      Lines[line].IsLine := CheckLine(line);
  end;

/对应c# switch .. case
case Lines[line].Status of
     STATUS_FREE:begin
          if IsRing(line) then
          begin
              Lines[line].OldRingCounter := GetRingNum(line);
              Memo1.Lines.Add('外线振铃'+inttostr(Lines[line].OldRingCounter));
              Lines[line].Status :=  STATUS_RING  ;
          end;
          if IsOffHook(line) then
          begin
              Memo1.Lines.Add('外线摘机');
              Lines[line].Status :=  STATUS_HANGUP  ;
          end;
     end;
     STATUS_RING:begin
          if IsRing(line) then
          begin

          end else
          begin
             Lines[line].Status :=  STATUS_WAIT_FSK;
             Lines[line].Timer := 0;
          end;
     end;
     STATUS_WAIT_FSK:begin
          setlength(str,200);
          if (GetCallerIDStr(line,pchar(str))=3) then
          begin
              str :='外线来电='+ string((str));
              Memo1.Lines.Add(str);
          end;
          inc(Lines[line].Timer);
          if ( GetRingNum(line) > 1) or ( Lines[line].Timer > 50 ) then
          begin
              Lines[line].Status :=  STATUS_WAIT_RING_END  ;
              Lines[line].Timer := 0;
          end;
          if Lines[line].OldRingCounter <> GetRingNum(line) then
          begin
              Lines[line].OldRingCounter := GetRingNum(line);
              Memo1.Lines.Add('外线振铃'+inttostr(Lines[line].OldRingCounter));
           end;
     end;
     STATUS_WAIT_RING_END:begin
         if IsRing(line) then
         begin
            if Lines[line].OldRingCounter <> GetRingNum(line) then
            begin
               Lines[line].OldRingCounter := GetRingNum(line);
               Memo1.Lines.Add('外线振铃'+inttostr(Lines[line].OldRingCounter));
            end;
            Lines[line].Timer := 0;
         end else if Lines[line].Timer > 50 then
         begin
            Memo1.Lines.Add('外线空闲');
            Lines[line].Status :=  STATUS_FREE;
            Lines[line].Timer := 0;
            InitRingNum(line);
         end;
         inc(Lines[line].Timer);
     end;
     STATUS_HANGUP:begin
          if not IsOffHook(line) then
          begin
              Memo1.Lines.Add('外线挂机');
              Lines[line].Status :=  STATUS_FREE  ;
          end;
     end;
     STATUS_RECORD:begin
         if CheckRecordEnd(line) then begin
            Memo1.Lines.Add(datetimetostr(now)+'录音结束');
            Lines[line].Status :=  STATUS_FREE  ;
         end;
     end;
     STATUS_PLAY:begin
         if CheckPlayEnd(line) then begin
            Memo1.Lines.Add(datetimetostr(now)+'放音结束'+inttostr(line));
            Lines[line].Status :=  STATUS_FREE  ;
         end;
     end;
     STATUS_SEND:begin
         if CheckSendEnd(line) then begin
            Memo1.Lines.Add(datetimetostr(now)+'拨号结束'+inttostr(line));
            Lines[line].Status :=  STATUS_FREE  ;  
         end;
     end;
 end;

2.2 GetUserState(1)


/line = 1
if  DeviceState  <> ReadUsbState(line) then
  begin
     if DeviceState then
        str := datetimetostr(now)+':设备移除'
     else
       str := datetimetostr(now)+':设备接入';
     DeviceState := ReadUsbState(line);
     Memo1.Lines.Add(str);
  end;    

实现效果图

QQ20160804-2@2x.png

附:Delphi与c#类型转换对照表

附:使用C#开发纽曼USB来电小秘书客户端小结

原创声明,版权所有。

本文供大家交流,转载须注明地址

一套全文检索解决方案,涉及到的技术有elasticsearch、mongodb、php、monolog等。
具体流程:

  1. PHP程序添加文章写入Mongodb中。
  2. 通过mongodb-connector同步Mongodb数据到elasticsearch中。
  3. PHP程序(8134655617)全文检索elasticsearch。

Elasticsearch准备

1. 安装新版 java环境<br/>

2. 下载 6393960739<br/>

3. 解压压缩包

$ unzip elasticsearch-{version}.zip

4. 运行elasticsearch

$ ./elasticsearch-{version}/bin/elasticsearch

5. 测试运行情况 守护进程模式,加-d

$ curl 127.0.0.1:9200/?pretty

Notice - 正常可以看到以下返回信息:

{
  "name" : "Martinex",
  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "2.2.0",
    "build_hash" : "8ff36d139e16f8720f2947ef62c8167a888992fe",
    "build_timestamp" : "2016-01-27T13:32:39Z",
    "build_snapshot" : false,
    "lucene_version" : "5.4.1"
  },
  "tagline" : "You Know, for Search"
}

MongoDB准备

1. 下载7249004264,也可以采用以下方式进行安装(linux下)

$ brew install mongodb 

2. 解压压缩包到某个自定义目录下

3. 进入解压目录,新建data目录,然后在data目录下新建db目录,用来存放mongodb数据

4. 进入bin目录下,启动mongod,切记命令为

$ ./mongod 

首次需配置MongoDB数据存放位置

$ sudo ./mongod --dbpath /Users/wlei24/es/mongodb-osx-x86_64-3.0.0/data/db/

后面运行时可能出现

ERROR:dbpath (/data/db) does not exist.

这是由于mongod启动时没有找到mongodb.conf导致的,因此我们的启动mongodb的时候手动添加 --dbpath即可

5. 测试MongoDB运行情况

进入bin目录,运行 ./mongo 进入mongodb控制台,输入

$ show dbs

显示结果:

article  0.078GB
local    0.328GB

同样你可以通过 127.0.0.1:27017 访问,页面显示:


It looks like you are trying to access MongoDB over HTTP on the native driver port.

Mongo-Connector准备

1. 下载mongo-connector

首先需要确保你已经安装pip,否则执行以下命令

$ easy_install pip

若已安装,执行以下命令

pip install mongo-connector

同样你也可以这样安装 - 下载完成后执行sudo python setup.py install

git clone /github.com/10gen-labs/mongo-connector.git
cd mongo-connector
python setup.py install

2. 确保开启MongoDB复制集

mongod --replSet myDevReplSet

接着在mongodb控制台执行 rs.initiate()

3. 运行 mongodb-connector

mongo-connector -m 127.0.0.1:27017 -t 127.0.0.1:9200 -d elastic_doc_manager

发现报了一大堆的错误

No handlers could be found for logger "mongo_connector.util"
Traceback (most recent call last):
  File "/usr/local/bin/mongo-connector", line 9, in <module>
   load_entry_point('mongo-connector==2.3', 'console_scripts', 'mongo-connector')()
  File "/Library/Python/2.7/site-packages/mongo_connector-2.3-py2.7.egg/mongo_connector/util.py", line 85, in wrapped
    func(*args, **kwargs)
  File "/Library/Python/2.7/site-packages/mongo_connector-2.3-py2.7.egg/mongo_connector/connector.py", line 1041, in main
    conf.parse_args()
  File "/Library/Python/2.7/site-packages/mongo_connector-2.3-py2.7.egg/mongo_connector/config.py", line 118, in parse_args
    option, dict((k, values.get(k)) for k in option.cli_names))
  File "/Library/Python/2.7/site-packages/mongo_connector-2.3-py2.7.egg/mongo_connector/connector.py", line 824, in apply_doc_managers
    module = import_dm_by_name(dm['docManager'])
 File "/Library/Python/2.7/site-packages/mongo_connector-2.3-py2.7.egg/mongo_connector/connector.py", line 814, in import_dm_by_name
    "vailable doc managers." % full_name)
mongo_connector.errors.InvalidConfiguration: Could not import              mongo_connector.doc_managers.elastic_doc_manager. It could be that this doc manager has been moved out of     this project and is maintained elsewhere. Make sure that you have the doc manager installed alongside     mongo-connector. Check the README for a list of available doc managers.

错误提示-没有找到elastic_doc_manager不过感觉mongodb-connector也有点坑,默认doc_managers里面只有solr_doc_manageir
这时就需要你去6175815826
将elastic2-doc-manager.py拷贝到本地doc_manaers目录
执行之前命令,发现继续报错~

IOError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/mongo_connector-2.3-         py2.7.egg/mongo_connector/doc_managers/mongo-connector.log'

这个错误只需要根据报错信息,新建此文件,并赋予读写权限即可。
继续执行之前命令,惊奇发现已经显示正常迹象,不过随即退出。
解决此问题只需采用在命令前面加上sudo即可

Logging to mongo-connector.log.

实际效果

706-713-8911、
819-270-0023、
Elasticsearch存储文章形式、
搜索文章标题效果、
搜索文章内容效果

8885482126

参考资料:902-368-8948、(450) 366-5602、MongoDB数据自动同步到Elasticsearch