东东东 陈煜东的博客

WordPress super cache 出现 cURL Problem with the SSL CA cert

为了让博客加快访问速度,使用了 WP Super Cache 插件。不得不说,这个插件还是比较好用的,对网页的打开速度体验提升很大。平时打开需要 700ms 的网页,现在只要 100ms 左右就可以啦。

按照网上的教程,一步一步的操作,将这些配置好了,但是很奇怪的是,缓存页面的过期效果一直不是自己预期的那样的。

缓存在后台设置了 1800s 的过期时间,那么正常情况下,如果上次的缓存时间超过了这个时间,应该会更新新的缓存网页,但是这个家伙一直都不更新。

点击了 缓存测试,测试一下,发现有失败。

cURL: Problem with the SSL CA cert (path? access rights?)

从字面翻译一下,说是SSL的 CA 证书有问题。考虑目前的机器版本比较老,这个情况是存在的,因此需要更新一下 CA 的证书文件。

通过从互联网上下载最新的文件,来更新一下证书。

curl https://curl.haxx.se/ca/cacert.pem -o /etc/pki/tls/certs/ca-bundle.crt

更新后,在点击测试缓存,可以显示成功了。

wp-super-cache-test-cache

现在缓存的策略能够正常工作了,网页上需要展示的一些数据也被刷新了。

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: WordPress super cache 出现 cURL Problem with the SSL CA cert – https://www.chenyudong.com/archives/wordpress-super-cache-curl-problem-with-the-ssl-ca-cert.html

分类: WordPress

【偏方】 Python 寻找子列表是否存在与其他列表中

有一个 Python 技术优化,是判断一个列表是否属于另外一个列表,注意列表是有顺序的,不是集合。本来一直想找一个大方的简洁方法的,但没想到最后是通过偏门来解决的。

例如:

l = [(1, 2), (3, 4), (5, 6), (7, 8)]
find = [(3, 4), (5, 6)]

# 期望输出
find in l  -> True

字符串的启发

字符串有一些操作。

l = 'abcdefg'
>>> l.index('ef')
4

>>> l.index('h')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: substring not found

字符串有index方法,可以很方便的判断子字符串是否在给定的字符串中,但是列表类的操作,一直没有找到这类的方法。

在和同事的讨论中,同事给了一个启发,使用repr函数获取可以试试。

用字符串的index函数还有一个好处,就是如果子串不在父串中,直接抛出异常,Python 不像其他语言一样,返回-1

repr转成字符串来处理

l = [(1, 2), (3, 4), (5, 6), (7, 8)]
find = [(3, 4), (5, 6)]

>>> repr(l)
'[(1, 2), (3, 4), (5, 6), (7, 8)]'
>>> repr(find)
'[(3, 4), (5, 6)]'

>>> repr(l)[1:-1].index(repr(find)[1:-1])
8
>>> repr(l)[1:-1].index(repr([(5, 5)])[1:-1])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: substring not found

使用join操作的字符串来判断

http://stackoverflow.com/a/2250981 中获得启发,也是利用字符串的方来进行解决的。

>>> ''.join(map(repr, [(3, 4)])) in ''.join(map(repr, [(1, 2), (3, 4)]))
True

不得不说,对比两个方法,其实都是类似的原理,都是通过字符串的字串来进行比较。思路很新颖,直观给人不用for循环进行处理,代码看上去也很简洁。

但是这些方法也只能是说判断子列表是否存在于另外一个列中的,不能判断子列表在另外一个列表的索引值。

另外该方法也不能保证子串只出现一次的情况。

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: 【偏方】 Python 寻找子列表是否存在与其他列表中 – https://www.chenyudong.com/archives/python-find-lists-in-lists.html

分类: Python

Python 将两层列表展开平铺成一层的5种方法

这几天和同事在讨论,如何用 Python 写出优雅的让列表中的列表展开,变成扁平化的列表。

例如

# 期望输入
input = [[('A', 1), ('B', 2)], [('C', 3), ('D', 4)]]

# 期望输出
output = [('A', 1), ('B', 2), ('C', 3), ('D', 4)]

map 函数合并

>>> new = []; map(new.extend, input); new
[None, None]
[('A', 1), ('B', 2), ('C', 3), ('D', 4)]

这个方法看上去还可以,但是有个致命的缺点,就是map函数会返回值,并且这个返回值是没有用的。另外还需要提前声明一个变量,从代码的简洁性上,不够简洁优雅。

sum 函数合并

>>> sum(input, [])
[('A', 1), ('B', 2), ('C', 3), ('D', 4)]

这个看上去很简洁,不过有类似字符串累加的性能陷阱。后面有性能对比。

reduce 函数

>>> reduce(list.__add__, input)
[('A', 1), ('B', 2), ('C', 3), ('D', 4)]

做序列的累加操作。也是有累加的性能陷阱。

列表推导式

>>> [item for sublist in input for item in sublist]
[('A', 1), ('B', 2), ('C', 3), ('D', 4)]

列表推导式,看着有些长,而且还要for循环两次,变成一行理解需要费劲一些,没有那么直观。

itertools 类库

>>> list(itertools.chain(*input))
[('A', 1), ('B', 2), ('C', 3), ('D', 4)]

通过第三方类库类实现的,相比其他的几个实现,看着还算比较优雅。最后的性能发现居然还很高。

性能大对比

python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(list.__add__,l)'
1000 loops, best of 3: 547 usec per loop

python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 509 usec per loop

python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 52.8 usec per loop

python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99; import itertools;' 'list(itertools.chain(*l))'
10000 loops, best of 3: 35.9 usec per loop

python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'new = []; map(new.extend, l); new'
10000 loops, best of 3: 34.1 usec per loop

欢迎大家共同探讨优雅的的实现和性能的优化。

参考:http://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: Python 将两层列表展开平铺成一层的5种方法 – https://www.chenyudong.com/archives/python-make-flat-list-of-list.html

分类: Python

Python 优雅获取本机 IP 方法

见过很多获取服务器本地IP的代码,个人觉得都不是很好,例如以下这些

不推荐:靠猜测去获取本地IP方法

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import socket
import fcntl
import struct

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])

print "br1 = "+ get_ip_address('br1')
print "lo = " + get_ip_address('lo')
print "virbr0 = " + get_ip_address('virbr0')

这类代码带有猜测的行为。

如果机器上只有eth0 或者 只有bond0上有IP,那么此类代码都有可能失败,而且还不容易移植到其他平台上。

不推荐:通过hostname来获取本机IP

import socket
print(socket.gethostbyname(socket.gethostname()))

# 有可能出现这个情况
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
socket.gaierror: [Errno -2] Name or service not known

这个方法是通过获取hostname,然后再通过hostname反查处机器的IP。这个方法也是不推荐的。因为很多的机器没有规范这个hostname的设置。

另外就是有些服务器会在 /etc/hosts 中添加本机的hostname的地址,这个做法也不是不可以,但是如果设置成了 127.0.0.1,那么获取出来的IP就都是这个地址了。

通过 UDP 获取本机 IP,目前见过最优雅的方法

这个方法是目前见过最优雅获取本机服务器的IP方法了。没有任何的依赖,也没有去猜测机器上的网络设备信息。

而且是利用 UDP 协议来实现的,生成一个UDP包,把自己的 IP 放如到 UDP 协议头中,然后从UDP包中获取本机的IP。

这个方法并不会真实的向外部发包,所以用抓包工具是看不到的。但是会申请一个 UDP 的端口,所以如果经常调用也会比较耗时的,这里如果需要可以将查询到的IP给缓存起来,性能可以获得很大提升。

# 在 shell 中可以一行调用,获取到本机IP
python -c "import socket;print([(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])"
10.12.189.16
# 可以封装成函数,方便 Python 的程序调用
import socket

def get_host_ip():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        ip = s.getsockname()[0]
    finally:
        s.close()

    return ip

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: Python 优雅获取本机 IP 方法 – https://www.chenyudong.com/archives/python-get-local-ip-graceful.html

分类: Python

二八择时轮动模型 量化交易信号

二八择时模型量化交易信号是根据我喜欢的一个微信公众账号 seekingbeta_earl的一个量化模型制作出来的。

二八择时模型有好几个类似的名称,但都是一回事:二八轮动量化模型多空指数二八轮动策略什么的。主要就是大盘蓝筹股和小盘成长股的切换。

因此做了一个简单的网页信号,用来发送信号给判断。不用人肉打开软件计算。网址:二八择时轮动信号 – https://www.chenyudong.com/quant/

效果图

二八择时量化信号

二八择时量化信号

特点

  1. 如果是买入,那么背景颜色是  红色  ;如果是空仓,那么背景是  绿色 
  2. 每天 中午11点31分 计算一次。
  3. 每天临近收盘的 14:3014:4514:5014:55各计算一次。以作决策参考。
  4. 每天 下午15点01分 计算一次。
  5. 起始时间是四周前的收盘价,终止时间是本周的最近一个时刻,方便观察本周的信号。

二八轮动策略?

也叫大小盘轮动策略,“二” 代表数量占比 20% 左右的大盘权重股,“八” 代表数量占比 80% 左右的中小盘股票,二八轮动就是指在大盘股与小盘股中间不断切换,哪个涨的好,就持有哪一个。现在有很多优化策略,增加了一个择时指标,在市场不好的时候,股票空仓,转入债券、货币基金或者国债等稳定性的基金。这样不至于在下跌的过程中空仓浪费本金。

其中大盘权重股一般使用 沪深300指数(399300) 来表示,小盘股一般用 中证500指数(399905) 来表示。

二八轮动策略的原理

二八轮动策略实质是一种“动量效应”。动量效应(Momentum effect)又称“惯性效应”,由Jegadeesh和Titman(1993)提出的,是指股票的收益率有延续原来运动方向的趋势,即过去一段时间收益率较高的股票在未来收益率仍会高于过去收益率较低的股票。总得来说,二八轮动是根据动量效应设计的一种“追涨杀跌”的趋势投资方法,解决了投资者面临的“买什么,什么时候买”等一系列投资痛点。

摘自:https://www.gffunds.com.cn/jjkt/llzl/201611/t20161101_55713.shtml

很多的策略都是这样的追涨杀跌,常见的有 海龟模型趋势交易

二八轮动策略具体规则

操作时间:每周五(或者本周的最后一个交易日)临近收盘时。

买入条件:将沪深300指数和中证500指数切换到周线状态,分别查看两者过去四周的累计涨幅。如果过去四周涨幅大的那个指数在四周中能够获得正回报,那么就在收盘前买入对应的ETF持有一周,直至下一次的切换。

卖出条件:但是如果过去四周涨幅大的那个指数在四周中依然是亏损的,那么就选择空仓(或者购买稳定的债券、货币基金),直至下一次切换。

这个策略,算是一个完整的交易系统了。有买入卖出时机,不过仓位都是满仓。

收益情况

二八轮动 二八择时 收益率曲线

二八轮动 二八择时 收益率曲线

只有在大牛市的时候 2007年 和 2015年 收益快速增加,其他的时候收益率低,甚至还会有比较大的回测。如果这个图延伸到2017年,会再下降好多。

这样的收益率的曲线,我见过一个,就是一个 60日均线的策略。在 60日均线之上买入持有,在60日均线下卖出。基本都能把牛市的一个大收益给纳入囊中。

这类靠趋势吃饭的策略,收益都是靠大牛市来获取的,或者行业轮动什么的。靠分析成长股的策略收益的曲线比指数熊市要好。

60日均线上买入收益率曲线

60日均线上买入收益率曲线

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: 二八择时轮动模型 量化交易信号 – https://www.chenyudong.com/archives/blue-chip-growth-stocks-trading-signal.html

分类: 量化交易

分享一个不用验证码的阻止垃圾机器人提交留言表单算法

spam-evil

每个博客主或者网站都会受到各式各样的垃圾留言骚扰。如果网站不及时清理这些垃圾留言,那么整个网站的可读性将会变得越来越糟糕,最后完全被垃圾浏览给占领了。

现在博客使用的是 WordPress,使用的是一个官方的插件 Akismet,这个程序还不错,通过后台大数据分析来识别垃圾评论。

不过除了 Akismet,我还有安装另外一个插件,这个插件很小巧,并且我觉得思路很不错。通过这两个插件来可以过滤很多的垃圾评论。

作者的思路是这样的:

为什么人类应该通过填充验证码(CAPTCHA)证明他们是人类?应该是让机器人通过 JavaScript 来证明他们不是机器人!

下面说说这个插件 anti-spam 使用的算法。

这个算法是基于 2 个方法:不可见的 JS 验证码(invisible js-captcha)不可见的输入框陷阱(invisible input trap)

不可见的 JS 验证码 invisible js-captcha

不可见的 JS 验证码(invisible js-captcha)方法基于一个事实:机器人在他们的在程序中不会执行 JavaScript 代码。

所以默认在输出 HTML 评论框的时候,加入了一个隐藏的问题和输入框,问题是今年是公元 xxxx 年。

如果用户访问网站,这个输入框答案会被 JavaScript 自动回答,并且会被 JavaScript 和css 的手段隐藏起来,不让用户看到。

如果机器人去填写答案没有填写正确,那么就会被判定是垃圾信息。

作者实现很鸡贼,其实这里有两个输入框,一个输入框是正确的答案,一个输入框是错误的答案。

<p class="antispam-group antispam-group-q" style="clear: both;">
    <label>Current ye@r <span class="required">*</span></label>
    <input type="hidden" name="antspm-a" class="antispam-control antispam-control-a" value="'.date('Y').'" />
    <input type="text" name="antspm-q" class="antispam-control antispam-control-q" value="'.ANTISPAM_PLUGIN_VERSION.'" autocomplete="off" />
</p>

如果用户没有开启 JavaScirpt ,那么需要在这里情况内容,输入正确的答案。否者在后台就被判断是无效留言。

JS 自动回答答案

// 对表单答案添加答案,答案已经在 antispam-control-a 提供出来了。
elements = document.querySelectorAll('.antispam-control-q');
len = elements.length;
for (i = 0; i < len; i++) { // set answer into other input instead of user
    elements[i].value = answer;
}

...

// 这里利用 JavaScript 添加一个动态的表单
// 如果没有开启
dynamic_control = document.createElement('input');
dynamic_control.setAttribute('type', 'hidden');
dynamic_control.setAttribute('name', 'antspm-d');
dynamic_control.setAttribute('class', 'antispam-control antispam-control-d');
dynamic_control.setAttribute('value', current_year);
...
elements[i].appendChild(dynamic_control);

后台判断逻辑片段

if ( $antspm_q != date('Y') ) { // year-answer is wrong - it is spam
    if ( $antspm_d != date('Y') ) { // extra js-only check: there is no js added input - it is spam
        $spam_flag = true;
        if (empty($antspm_q)) { // empty answer - it is spam
            $antispam_error_message .= 'Error: empty answer. ['.esc_attr( $antspm_q ).']<br> '.$rn;
        } else {
            $antispam_error_message .= 'Error: answer is wrong. ['.esc_attr( $antspm_q ).']<br> '.$rn;
        }
    }
}

如果用户没有启用 JavaScript 会怎么样呢?

用户会在提交表单中看到今天是公元多少年的问题,然后需要将错误的答案修改成正确的答案。这样在上面的后台检测脚本中就会发现,这里填写是正确的。就不用再关心 JavaScript 动态的答案了。

不可见的输入框陷阱 invisible input trap

不可见的输入框陷阱(invisible input trap)是基于一个事实:大多数机器人遇到 email 或者 url 关键字表单会自动填充一些信息。

因此在评论框中增加一个隐藏字段,正常用户是看不到这个字段,所以也不会去填写它。

// 默认不展示给用户看。
<p class="antispam-group antispam-group-e" style="display: none;">
    <label>Leave this field empty</label>
    <input type="text" name="antspm-e-email-url-website" class="antispam-control antispam-control-e" value="" autocomplete="off" />
</p>

但是机器人是可以看到这个字段的,如果在这里填写了任何东西,那么就会被判定为机器人。

后台的判断逻辑片段

// 如果填写了这个表单,那么就被判定是垃圾信息了
if ( ! empty($antspm_e)) { // trap field is not empty - it is spam
    $spam_flag = true;
    $antispam_error_message .= 'Error: field should be empty. ['.esc_attr( $antspm_e ).']<br> '.$rn;
}

总结一下

目前从后台效果来看,这个插件的效果很好,很少遇到垃圾留言。

目前的一些垃圾机器人无法执行 JavaScript,所以很多利用这个特性就可以做一些排除了。很多的第三方评论都是利用 JS 展示出来了。

不过很优秀的 Disqus 在国内经常抽风,甚至不可用

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: 分享一个不用验证码的阻止垃圾机器人提交留言表单算法 – https://www.chenyudong.com/archives/anti-spam-comments-algorithm.html

分类: WordPress

docker 容器自定义 hosts 网络访问

在搭建 Drone CI 服务的时候,拉取git代码出现了网络不通。

+ git init
Initialized empty Git repository in /drone/src/testgit.com/root/demo1/.git/
+ git remote add origin http://testgit.com:10080/root/demo1.git
+ git fetch --no-tags origin +refs/heads/master:
fatal: unable to access 'http://testgit.com:10080/root/demo1.git/': Couldn't resolve host 'testgit.com'
exit status 128

也是到 Drone 的论坛问了 http://discourse.drone.io/t/help-git-clone-with-custom-extra-hosts/217。 看来需要自己设置网络问题,没有办法通过 docker-compose.yml 文件来进行设置。

普通的 Docker 容器解决方案

在 docker-compose.yml 中增加 extra_hosts 关键字就可以将数据写入到容器的 /etc/hosts

version: '2'

services:
  drone-server:
    image: drone/drone:latest
    ports:
      - 8100:8000
    extra_hosts:
      - "mygit.com:10.123.123.130"
    volumes:
      - ./drone:/var/lib/drone/
    restart: always
    environment:
      - DRONE_OPEN=true
      - DRONE_DEBUG=true

Drone CI 的情况

Drone CI这个情况比较麻烦。是在Drone agent容器里面又启动了一个容器,这个时候没有关于extra_hosts设置给子容器。于是子容器无法访问特定的域名。

修改 hosts 文件失败

本来想设置添加一个 hosts 文件到镜像中的。但是发现一只失败,无法写入成功。

FROM plugins/git

ADD ./hosts /etc/
RUN cat /etc/hosts

不过这条路走失败了。

hosts文件其实并不是存储在Docker镜像中的,/etc/hosts, /etc/resolv.conf/etc/hostname,是存在/var/lib/docker/containers/(docker_id)目录下,容器启动时是通过mount将这些文件挂载到容器内部的。因此如果在容器中修改这些文件,修改部分不会存在于容器的top layer,而是直接写入这3个文件中。容器重启后修改内容不存在的原因是每次Docker在启动容器的时候,Docker每次创建新容器时,会根据当前docker0下的所有节点的IP信息重新建立hosts文件。也就是说,你的修改会被Docker给自动覆盖掉。

摘录自:https://wongxingjun.github.io/2016/04/06/Docker%E4%BF%AE%E6%94%B9hosts/

问了同事,一般很多容器的做法是,通过将hosts 文件写入容器,然后在容器启动后, cat /data/hosts > /etc/hosts到,然后再执行命令。

我觉得这个方法不适合我,因此我重新寻找新的方法。后面找到了利用 DNS 服务来规避。

搭建 dnsmaq DNS 服务

将需要配置的 hosts 写入到 /etc/hosts 中。

在虚拟机或者特定服务安装 dnsmaq 服务。

yum install dnsmasq -y

touch /etc/dnsmasq.hosts

# 重启
service dnsmasq restart

# 测试一下是否可以查询到域名
dig @127.0.0.1 testdomain.com

使用 Docker 的 DNS 解决

vim /etc/docker/daemon.json

{
    "dns": ["10.123.12.14", "8.8.8.8"]
}

将刚刚的 DNS 服务器 IP 写入到配置中,追加一个字段 dns。如果还有其他的 DNS 服务器,那么就写入在数组中写入其他的 IP。

重启一下 Docker 服务。

service docker restart

Docker 容器测试网络

这个是我的容器
docker run --rm -e DRONE_REMOTE_URL=http://mydomain.com:10080/root/demo1.git plugins/git

或者
docker run busybox nslookup google.com

参考文章

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: docker 容器自定义 hosts 网络访问 – https://www.chenyudong.com/archives/docker-custom-hosts-network-via-dns.html

分类: DevOps

website impress 网站评分插件

抽空写了个 Google Chrome的插件。github地址 https://github.com/daoiqi/website-impress

Chrome 插件下载地址: https://chrome.google.com/webstore/detail/fjfddiiaeehjogpabflgicipdgdfljof/

在互联网上经常充斥着一些垃圾网站,网站缺少真实的内容或者带有欺骗性的内容,欺骗用户的感情,影响用户的使用。

** 这类网站应该被揪出来,并且不建议逗留。 **

目前无意做一个点评网站,本插件的数据是利用百度口碑的数据来展示的。

如果有什么好的点评数据,欢迎给我留言。

评分说明

从百度口碑获取好评率。好评率理论上从 0-100% 的。 由于百度口碑的打分最低是一星,所以好评率最低是 20%

数字太大不方便看,因此从0-100的分数映射为 0-10分。

  • 0-59 红色,好评率在0-59%之间,实际最低应该是20%。对应就是一星~三星之间。
  • 60-79 橙色,好评率在60%-79%之间。对应在三星~四星之间。
  • 80-100 绿色,好评率在80%-100%之间。对应在四星和五星。

demo

demo2

demo1

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: website impress 网站评分插件 – https://www.chenyudong.com/archives/website-impress.html

分类: Web 开发

rinetd – Linux tcp port forward

在寻找一个 Linux 的TCP 端口转发程序,大部分都是使用 iptables 来使用的,但我觉得 iptables 不是很好用,主要是不熟悉他的命令。

上网找了一个程序 rinetd,写个配置文件,可以后台运行,很简单。

下载地址:https://centos.pkgs.org/6/nux-misc-x86_64/rinetd-0.62-9.el6.nux.x86_64.rpm.html

教程 https://www.boutell.com/rinetd/

配置很简单vim /etc/rinetd.conf

# config rules


# 设置允许的请求来源
# allow 206.125.69.*

# 配置端口转发信息
# bindaddress bindport connectaddress connectport
0.0.0.0 23 206.125.69.81 23

service rinetd restart 重启一下服务。

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: rinetd – Linux tcp port forward – https://www.chenyudong.com/archives/rinetd-linux-tcp-port-forward.html

分类: Linux 软件

利用 Docker 镜像 gogs 搭建一个私有的 git 服务

本文是为了构建一个私有的持续集成服务而准备的。

利用 Docker 来方便构建,不怕环境错乱,同时也帮忙配置好了一些东西。

Docker 安装准备

需要有一个 Docker 环境, 简单的提及一下 Docker 的事项。

yum install docker
pip install doker-compose

更多参考 https://www.chenyudong.com/archives/docker-practice.html

gogs的搭建是参考https://zhuanlan.zhihu.com/p/24896056

说一下文中的

    links:
        - mysql:mysql

在配置 gogs 的时候,输入数据库地址,需要输入 mysql:3306,被这个给绕晕了。

同步 git 仓库

因为不是提供一个稳定的仓库给大家推送,因为网络的原因,我的CI服务器无法直接访问git仓库,因此单独搞一个git服务,那么需要将代码同步过来。

看到 这篇文章,觉得思路不错。

# 首先先下载过来
git clone --mirror git@github.com:git_user/project.git

# 先拉取一下代码
cd project.git
git fetch -q --all -p

# 推送代码到另外一个服务上
git remote add another_git http://git.com/git_user/project.git


# 周期任务
sudo vi /etc/cron.d/sync_git_repos
*/5 * * * * app cd /path/to/project.git && git fetch -q --all -p && git push another_git --all

接下来配合文档服务和CI服务,进行持续集成。

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: 利用 Docker 镜像 gogs 搭建一个私有的 git 服务 – https://www.chenyudong.com/archives/gogs-git-docker-service.html

分类: DevOps

« 较早的 文章

Copyright © 2017 东东东 陈煜东的博客 粤ICP备13059639号-1

SITEMAP回到顶部 ↑