Litao OK Blog

A little blog for my life.

在CentOS 6.8 X86 64bit上安装GitLab Community Edition 8.12.3

参考资料: https://bbs.gitlab.cc/topic/35/gitlab-ce-8-7-%E6%BA%90%E7%A0%81%E5%AE%89%E8%A3%85%E6%89%8B%E5%86%8C-centos6-rehl6

一、关闭SELinux

1. 修改/etc/selinux/config 文件

将SELINUX=enforcing改为SELINUX=disabled, 然后重启电脑

2. 查看selinux状态

1
sestatus -v

关闭后应该显示:

1
SELinux status:                 disabled

二、安装相关程序

1. 添加EPEL源

1) 下载EPEL的GPG KEY,导入到系统中

1
2
wget -O /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6 https://mirrors.tuna.tsinghua.edu.cn/epel/RPM-GPG-KEY-EPEL-6
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6

2) 安装epel-release-latest-6.noarch.rpm包,启用EPEL

1
rpm -Uvh http://mirrors.ustc.edu.cn/epel/epel-release-latest-6.noarch.rpm

2. 安装开发工具库

1
yum install automake bison cmake cpio curl curl-devel expat-devel gcc gcc-c++ gettext-devel perl-devel perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker libcurl-devel libffi-devel libicu-devel libtool libxml2-devel libxslt-devel libyaml-devel make mlocate nodejs  openssl-devel patch readline-devel ruby-devel unzip vim vixie-cron wget zlib-devel

3. 安装Git

  1. 检查git版本,需要高于2.7版本
1
git version
  1. 下载安装git
1
2
3
4
5
6
7
8
9
10
mkdir -p src/tar
cd src/tar/
wget https://github.com/git/git/archive/v2.10.0.tar.gz
cd ..
tar -zxf tar/v2.10.0.tar.gz
cd git-2.10.0/
make prefix=/usr/local all
make prefix=/usr/local install
# 查看版本号
git version

4. 添加用户

1
adduser -c 'Gitlab' -s /bin/bash git

5. 安装Ruby环境

  1. 如果系统有老版本ruby,先删除之
1
yum remove ruby
  1. 通过rvm安装
1
2
3
4
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
\curl -sSL https://get.rvm.io | bash -s stable
source /etc/profile.d/rvm.sh
rvm install 2.3.1
  1. 修改gem源为国内
1
gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
  1. 安装bundle工具
1
2
3
gem install bundler --no-ri --no-rdoc
su - git
bundle config mirror.https://rubygems.org https://gems.ruby-china.org/

6. 安装Go

1
2
3
4
5
cd ~/src/tar/
wget https://storage.googleapis.com/golang/go1.7.1.linux-amd64.tar.gz
cd ..
tar -zxf tar/go1.7.1.linux-amd64.tar.gz
mv go /usr/local/

修改环境变量 /etc/profile,在export PATH前面添加

1
2
3
export GOROOT=/usr/local/go
export GOBIN=$GOROOT/bin
PATH=$PATH:$GOBIN:$JAVA_HOME/bin

7. 安装数据库

虽然官方建议使用postgresql,但是我对其并不熟悉,所以还是继续选用MySQL,此处使用mysql-community 5.7.15

先去http://dev.mysql.com/downloads/repo/yum/ 下载源文件,选择mysql57-community-release-el6-9.noarch.rpm,下载完后安装

1
2
3
yum localinstallmysql57-community-release-el6-9.noarch.rpm
yum installmysql-community-servermysql-community-develmysql-community-commonmysql-community-libsmysql-community-client
mysql_secure_installation

由于新版本对密码复杂度和长度有要求,12个字符以上,包含中英文大小写、数字、符号等,设置完登录开始配置数据库:

1
2
3
4
5
6
7
mysql -u root -p
mysql> CREATE USER 'git'@'localhost' IDENTIFIED BY '$password';
mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES, REFERENCES ON `gitlabhq_production`.* TO 'git'@'localhost';
mysql> FLUSH PRIVELEGES;
mysql> \q
 

8.安装Redis

添加用户和组:

1
groupadd redis && useradd -g redis redis -s /sbin/nologin

下载安装:

1
2
3
4
5
6
7
8
9
cd ~/src/tar/
wget http://download.redis.io/releases/redis-3.2.4.tar.gz
cd ..
tar -zxf tar/redis-3.2.4.tar.gz
cd redis-3.2.4/
make
make install
mkdir -p /etc/redis
cp redis.conf /etc/redis

修改配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cp /etc/redis/redis.conf /etc/redis/redis.conf.orig
# 把'post'设置为0以禁止监听TCP端口
sed 's/^port .*/port 0/' /etc/redis/redis.conf.orig | sudo tee /etc/redis/redis.conf
# 让redis以socket方式启动
echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf
# 启动守护进程
sed -i 's/daemonize no/daemonize yes/g' /etc/redis/redis.conf
# 创建存放socket的目录
mkdir /var/run/redis
sudo chown redis:redis /var/run/redis
sudo chmod 755 /var/run/redis
# Persist the directory which contains the socket, if applicable
if [ -d /etc/tmpfiles.d ]; then
  echo 'd  /var/run/redis  0755  redis  redis  10d  -' | sudo tee -a /etc/tmpfiles.d/redis.conf
fi
# 把git用户加入redis组
sudo usermod -aG redis git
# 下载redis init 脚本
$ curl -L http://packages.gitlab.cc/install/init-script/redis/cenots6/redis-server -o /etc/init.d/redis-server
$ chmod +x /etc/init.d/redis-server

启动redis

1
2
3
4
# 启动redis服务
$ service redis-server start
# 将redis加入自启动
$ chkconfig redis-server on

三、安装Gitlabe-CE

1. 用git克隆代码

1
2
3
su - git
cd /home/git/
git clone https://github.com/gitlabhq/gitlabhq.git -b 8-12-stable gitlab

2. 配置Gitlab-CE

1
2
3
4
5
# 进入gitlab目录
cd /home/git/gitlab

# 复制gitlab.yml(Gitlab的主配置文件)
cp config/gitlab.yml.example config/gitlab.yml

3. 修改gitlab.yml

1
vim config/gitlab.yml
  • 修改第32行 host: localhost为 host: 你的域名或者ip
  • 修改第479行 bin_path: /usr/bin/git 为 bin_path: /usr/local/bin/git

4. 复制文件,创建文件夹,修改权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
cp config/secrets.yml.example config/secrets.yml
chmod 0600 config/secrets.yml
chown -R git log/
chown -R git tmp/
chmod -R u+rwX,go-w log/
chmod -R u+rwX tmp/
chmod -R u+rwX tmp/pids/
chmod -R u+rwX tmp/sockets/

mkdir public/uploads/
chmod 0700 public/uploads

chmod -R u+rwX builds/

chmod -R u+rwX shared/artifacts/

# 复制 Unicorn 配置文件
cp config/unicorn.rb.example config/unicorn.rb

# 查询CPU核心数
nproc

# 如果你想搭建一个高负载的Gitlab实例,可启用集群模式.
# 修改'worker_processes'参数,至少要跟cpu核心数一样.
# 举例:2G RAM的服务器修改workers数量为3
# vim config/unicorn.rb

# 复制Rack attack 配置文件
cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb

# Configure Git global settings for git user
# 'autocrlf' is needed for the web editor
git config --global core.autocrlf input

# Disable 'git gc --auto' because GitLab already runs 'git gc' when needed
git config --global gc.auto 0

# 复制 Redis 连接配置文件
cp config/resque.yml.example config/resque.yml

# 如果之前修改过redis socket的路径,在config/resque.yml文件里面修改为当前的路径.

检查unicorn启动端口,默认8080,如果已经被别的服务占用了,必须要修改config/unicorn.rb文件

5. 修改GitLab DB 设置

1
cp config/database.yml.mysql config/database.yml

修改文件config/database.yml中的用户名和密码

修改权限:

1
chmod o-rwx config/database.yml

6. 安装gems包

1
2
3
# su - git 使用git用户
cd /home/git/gitlab
bundle install --deployment --without development test postgres aws kerberos --withmysql

7. 安装Gitlab-shell

1
2
3
# su - git
cd /home/git/gitlab
bundle exec rake gitlab:shell:install REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production

8. 安装gitlab-workhorse

1
2
3
4
5
cd /home/git/
git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git
cd gitlab-workhorse
git checkout v0.7.1
make

9. 初始化数据库,激活高级特性

1
2
3
4
5
6
7
# su - git
cd /home/git/gitlab
bundle exec rake gitlab:setup RAILS_ENV=production

# 输入 'yes' 以创建数据库表

# 当看到 'Administrator account created:' 表示已经安装完成

10. 安全设置 secrets.yml

secrets.yml 文件为每个会话和安全变量存储密钥.把这个文件备份到别的地方,但是不要和数据库备份放在一块,否则你的数据库备份损坏会导致这个文件丢失.

11. 安装Gitlab启动脚本

1
2
3
4
5
6
7
8
9
10
# su - root
sudo cp /home/git/gitlab/lib/support/init.d/gitlab /etc/init.d/gitlab

sudo cp /home/git/gitlab/lib/support/init.d/gitlab.default.example /etc/default/gitlab

# 设置自动启动
chkconfig gitlab on

# 安装logrotate
sudo cp /home/git/gitlab/lib/support/logrotate/gitlab /etc/logrotate.d/gitlab

12. 检查环境配置

1
2
3
su - git
cd gitlab/
bundle exec rake gitlab:env:info RAILS_ENV=production

13. 生成GitLab前端资源

1
2
3
# su - git
cd /home/git/gitlab
bundle exec rake assets:precompile RAILS_ENV=production

14. 启动GitLab

1
2
3
sudo service gitlab start
# 或者
sudo /etc/init.d/gitlab start

15. 再检查一次Gitlab的所有组件

1
2
3
su - git
cd /home/git/gitlab
bundle exec rake gitlab:check RAILS_ENV=production

四、设置nginx代理

1.yum安装nginx

1
2
# 创建/etc/yum.repos.d/nginx.repo
touch /etc/yum.repos.d/nginx.repo

文件内容:

1
2
3
4
5
6
7
# 编辑nginx.repo,把下面的内容写入;
# 注意修改OS和OSRELEASE,如centos6则把OS改成centos, OSRELEASE改成6;
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/OS/OSRELEASE/$basearch/
gpgcheck=0
enabled=1

安装:

1
2
yum update
yum install -y nginx

2. 设置代理

1
2
# 复制gitlab的nginx配置文件到nginx的conf.d目录
sudo cp /home/git/gitlab/lib/support/nginx/gitlab /etc/nginx/conf.d/gitlab.conf

修改文件 /etc/nginx/conf.d/gitlab,将YOUR_SERVER_FQDN修改为你的域名

修改/home/git/目录的权限

1
sudo chmod 755 /home/git/

修改vim /home/git/gitlab/config/gitlab.yml中host,改为相同域名

3. 启动nginx

1
service nginx restart

Nginx Error Log : Too Many Open Files While Connecting to Upstream

当访问量增大时,nginx连接upstream后端时会大量报错,例如:

1
2016/03/29 01:49:47 [alert] 8675#0: *297501684 socket() failed (24: Too many open files) while connecting to upstream, client: 191.109.198.194, server: api.xxxx.com, request: "POST /myapps/native HTTP/1.1", upstream: "http://127.0.0.1:9001/myapps/native", host: "api.xxxx.com"

检查系统limit设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 63615
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1048576
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 63615
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

发现open files那项已经足够大,检查/etc/sysctl.conf,增加参数:

1
fs.file-max = 1048576

执行命令使之生效:

1
sudo sysctl -p

检查nginx配置文件,发现配置打开数量过少,修改之:

1
2
3
4
5
worker_processes  4;
worker_rlimit_nofile 40960;
events {
    # worker_connections  1024;
}

修改upstream配置,把fail_timeout设置为最小的1s:

1
2
3
4
5
6
upstream my_api {
    server 127.0.0.1:9000 fail_timeout=1;
    server 127.0.0.1:9001 fail_timeout=1;
    server 127.0.0.1:9002 fail_timeout=1;
    server 127.0.0.1:9003 fail_timeout=1;
}

重启nginx,注意这里是restart,不是reload:

1
sudo /etc/init.d/nginx restart

通过系统命令查看效果:

1
2
ss -s
top

发现连接数开始下降,nginx不再报错,打开系统监控,看到nginx请求响应时间由报错时的400ms下降到60ms,修改成功!

api

创建OS X EI Capitan启动U盘

首先下载安装文件

可以去App Store下,下载时会提示你的系统已经是OS X EI Capitan啦,点继续就会创建安装文件,由于文件比较大,下载可能需要一段时间。

执行命令,制作启动盘

打开Mac的终端Shell窗口,输入下面命令:

1
sudo 安装文件路径/Install\ OS\ X\ El\ Capitan.app/Contents/Resources/createinstallmedia --volume /Volumes/U盘名称 --applicationpath 安装文件路径/Install\ OS\ X\ El\ Capitan.app --nointeraction

执行该命令需要输入你的系统密码来授权,开始执行时会先擦除U盘,然后再写入数据,所以U盘不用提前格式化,等执行完,就可以拿U盘去安装系统啦。

安装系统

把做好的U盘插到待装机Mac电脑USB口,按住alt键重启系统,一直到出现启动磁盘选项,选择U盘,然后根据提示操作即可。

Python Tornado 启动参数解析

Tornado 4.3/Python3.4

Tornado典型server启动方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging as log
import socket
import sys

import os
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

PROJECT_ROOT = os.path.realpath(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(PROJECT_ROOT, os.pardir))

import config


# 初始化参数
def init_options():
    tornado.options.define('port', default=9000, type=int)
    tornado.options.define('worker', default=2, type=int)
    tornado.options.define('debug', default=config.is_debug, type=bool)
    tornado.options.define('doc', default=False, type=bool)
    tornado.options.define('timeout', default=2, type=int)
    tornado.options.parse_command_line()

    return tornado.options.options


# 处理其他请求
class BaseHandler(tornado.web.RequestHandler):
    def data_received(self, chunk):
        pass

    def get(self):
        self.write_error(404)

    def write_error(self, status_code, **kwargs):
        if status_code == 404:
            self.render('404.html')
        elif status_code == 500:
            self.render('500.html')
        else:
            self.write('error:' + str(status_code))


# 主程序
def main():
    try:
        _options = init_options()

        socket.setdefaulttimeout(_options.timeout)
        # static_path = os.path.join(os.path.dirname(__file__), settings.static_path)

        # 总路由列表
        url_list = [
            (r'/myuri', MyURIHandler),  
            (r'.*', BaseHandler),  # 这个放在最后,处理404和500
        ]

        application = tornado.web.Application(url_list,
                                              template_path=os.path.join(os.path.dirname(__file__), "public"),
                                              debug=_options.debug)

        _http_server = tornado.httpserver.HTTPServer(application, no_keep_alive=True)
        _http_server.bind(_options.port)
        _http_server.start(1 if _options.debug else _options.worker)

        echo_str = "HTTPServer 1 thread(s), {} worker(s), listen on http://{}:{}, debug={}, logging={}"
        log.info(echo_str.format(str(_options.worker),
                                 str(socket.gethostname()),
                                 str(_options.port),
                                 str(_options.debug),
                                 str(_options.logging)))
        tornado.ioloop.IOLoop.instance().start()
    except Exception as e:
        log.exception(e)


if __name__ == "__main__":
    main()

启动时,可以通过命令行参数来确定其他参数和日志处理方式,具体参数可以通过–help命令获得,以上代码放在main.py中,则:

1
python main.py --help

会提示如下帮助信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Usage: main.py [OPTIONS]

Options:

  --help                           show this help information

/Users/litao/Documents/LEO/source_code/leo_max_api/.env/lib/python3.4/site-packages/tornado/log.py options:

  --log-file-max-size              max size of log files before rollover
                                   (default 100000000)
  --log-file-num-backups           number of log files to keep (default 10)
  --log-file-prefix=PATH           Path prefix for log files. Note that if you
                                   are running multiple tornado processes,
                                   log_file_prefix must be different for each
                                   of them (e.g. include the port number)
  --log-rotate-interval            The interval value of timed rotating
                                   (default 1)
  --log-rotate-mode                The mode of rotating files(time or size)
                                   (default size)
  --log-rotate-when                specify the type of TimedRotatingFileHandler
                                   interval other options:('S', 'M', 'H', 'D',
                                   'W0'-'W6') (default midnight)
  --log-to-stderr                  Send log output to stderr (colorized if
                                   possible). By default use stderr if
                                   --log_file_prefix is not set and no other
                                   logging is configured.
  --logging=debug|info|warning|error|none 
                                   Set the Python log level. If 'none', tornado
                                   won't touch the logging configuration.
                                   (default info)

main.py options:

  --debug                           (default False)
  --doc                             (default False)
  --port                            (default 9000)
  --timeout                         (default 2)
  --worker                          (default 2)

参数可以用来处理生成人日志,因为官方的按照时间分隔日志的TimedRotatingFileHandler在多进程情况下会丢失日志,所以可以通过Tornado这些参数来给每个进程单独处理日志分隔,示例如下:

1
python main.py --port=9000 --worker=1 --log-file-max-size=0 --log-file-prefix=logs/9000.log --log-rotate-mode=time --log-rotate-when=H --logging=info

以上参数会按照小时来切割9000.log文件,日志写入9000.log时并不检查文件大小(log-file-max-size=0表示无限大),但是在多进程模式下无效。

实际启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/bin/bash

APP_DIR=/home/deploy/leo_max_api
APP_EXEC="/home/deploy/leo_max_api/.env/bin/python /home/deploy/leo_max_api/main.py"

LOG_DIR=$APP_DIR/logs
LOG_LEVEL=info # 测试环境用debug,生产环境用error

# 每个实例worker数量
WORKER_NUM=20
# 每个服务器实例监听端口号,配置数量可以测试下每个worker内存占用情况
# 单核1G内存,建议一个实例,10个worker以内
# 4核16G内存,建议4个实例,每个20个worker
PORTS=(9000 9001 9002 9003)

function start_server() {
    su - deploy & cd $APP_DIR
    export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
    source .env/bin/activate
    # chmod +x main.py
    for port in "${PORTS[@]}";
    do
        $APP_EXEC --port=$port --worker=$WORKER_NUM --logging=$LOG_LEVEL --log-file-prefix=$LOG_DIR/$port.log --log-file-max-size=0 &
    done
}

function stop_server() {
    for port in "${PORTS[@]}";
    do
        ps aux | grep "$APP_EXEC" | grep "$port" | awk '{print $2}' | xargs kill -9
    done
}

case "$1" in
start)
    start_server
;;
stop)
    stop_server
;;
restart)
    stop_server
    start_server
;;
*)
    echo 'Usage: bin/tornado.sh [start|stop|restart]'
esac

以上脚本会启动4个实例(进程),每个实例启动20个workers,我使用的服务器4核16G内存的,建议使用4个实例,worker数要看内存大小了。日志方面,会生成4个日志,分别是9000.log、9001.log、9002.log和9003.log,通过size分隔方式,但是size=0表示可以无限大,也就是不切分文件,由crontab定时任务来切割。尝试过–log-rotate-mode=time,完全无效。官方文档说多进程方式时间切分有问题,但是每个实例单独设置也是不行的。

需要用root用户加在crontab中执行:

1
2
# crontab -e
0 0 * * * /home/deploy/leo_max_api/etc/log.sh > /dev/null 2>&1

下面是log.sh内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
# set path
APP_DIR=/home/deploy/leo_max_api
LOG_DIR=$APP_DIR/logs
PORTS=(9000 9001 9002 9003)
# rename log
for port in "${PORTS[@]}";
do
    mv $LOG_DIR/$port.log $LOG_DIR/$port.log.`date -d yesterday +%Y%m%d`
    touch $LOG_DIR/$port.log
done
# restart tornado
/etc/init.d/your_init_script restart 

在CentOS 6.x 64bit上安装MongoDB 3.2社区版

基本安装步骤

参考: https://docs.mongodb.org/manual/tutorial/install-mongodb-on-red-hat/

1) 创建repo源文件:

1
sudo vim /etc/yum.repos.d/mongodb-org-3.2.repo

内容如下:

1
2
3
4
5
[mongodb-org-3.2]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.2/x86_64/
gpgcheck=0
enabled=1

2) 更新源,并安装

1
2
sudo yum -y update
sudo yum -y install mongodb-org

3) 配置SELinux

1
sudo vim /etc/selinux/config

SELINUX内容改为:

1
SELINUX=disabled

需要重启系统才能生效!

4) 修改防火墙,保证端口可以访问:

1
2
sudo iptables -A INPUT -p tcp --dport 27017 -j ACCEPT
sudo /etc/init.d/iptables save

5) 检查目录权限:

确保 /var/lib/mongo 和 /var/log/mongodb 目录中文件是属于mongod:mongod用户和组,如果不是可以手工修改:

1
2
sudo chown -R mongod:mongod /var/lib/mongo
sudo chown -R mongod:mongod /var/log/mongo

6) 添加到系统服务中:

1
2
sudo chkconfig --add mongod
sudo chkconfig mongod on

7) 关闭THP(Transparent Huge Pages)

1
sudo vim /etc/init.d/disable-transparent-hugepages

内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/sh
### BEGIN INIT INFO
# Provides:          disable-transparent-hugepages
# Required-Start:    $local_fs
# Required-Stop:
# X-Start-Before:    mongod mongodb-mms-automation-agent
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Disable Linux transparent huge pages
# Description:       Disable Linux transparent huge pages, to improve
#                    database performance.
### END INIT INFO

case $1 in
  start)
    if [ -d /sys/kernel/mm/transparent_hugepage ]; then
      thp_path=/sys/kernel/mm/transparent_hugepage
    elif [ -d /sys/kernel/mm/redhat_transparent_hugepage ]; then
      thp_path=/sys/kernel/mm/redhat_transparent_hugepage
    else
      return 0
    fi

    echo 'never' > ${thp_path}/enabled
    echo 'never' > ${thp_path}/defrag

    unset thp_path
    ;;
esac

修改权限并执行

1
2
sudo chmod 755 /etc/init.d/disable-transparent-hugepages
sudo /etc/init.d/disable-transparent-hugepages start

修改ulimit设置

1
ulimit -a

可以看到系统ulimit设置值,需要修改打开文件数和用户最大进程数,需要修改更大:

1
sudo vim /etc/security/limits.d/99-mongodb-nproc.conf

内容如下:

1
2
3
4
mongod soft nofile 64000  
mongod hard nofile 64000  
mongod soft nproc 524288 
mongod hard nproc 524288

其中分为soft配置和hard配置,保证soft<=hard;nofile是打开文件数,nproc是进程数,还需要参考/etc/sysctl.conf中的数据。

启动mongodb

1
sudo service mongod start

尝试登录:

1
mongo

如果没有提示任何WARNING信息说明以上配置参数是符合mongodb建议值了,enjoy!

CentOS 6.x 64bit 内核参数设置

使用服务器是16G内存,4核(Intel® Xeon® CPU E3-1230 V2 @ 3.30GHz)

ulimit设置

1
1048576

查看当前连接情况

1
netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

/etc/sysctl.conf设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296

kernel.sysrq = 0
kernel.core_uses_pid = 1

net.ipv4.ip_forward = 1
net.ipv4.conf.default.accept_source_route = 0

#### 以下优化后会减少占用端口的TIME_WAIT数量
# 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭
net.ipv4.tcp_syncookies = 1
# 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭
net.ipv4.tcp_tw_reuse = 1
# 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.ipv4.tcp_tw_recycle = 1
# 修改系統默认的 TIMEOUT 时间
net.ipv4.tcp_fin_timeout = 10

#### 如果连接数比较多,优化TCP使用端口数
# 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时
net.ipv4.tcp_keepalive_time = 10
# 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为10000到65000。注意:这里不要将最低值设的太低,否则可能会占用掉正常的端口
net.ipv4.ip_local_port_range = 9100 65535
# 表示SYN队列的长度,默认为1024,加大队列长度为204600,可以容纳更多等待连接的网络连接数
net.ipv4.tcp_max_syn_backlog = 204600
# 表示系统同时保持TIME_WAIT的最大数量,如果超过这个数字,TIME_WAIT将立刻被清除并打印警告信息。默认为180000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于 Squid,效果却不大。此项参数可以控制TIME_WAIT的最大数量,避免Squid服务器被大量的TIME_WAIT拖死
net.ipv4.tcp_max_tw_buckets = 10000
# 系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_keepalive_probes = 2
net.ipv4.tcp_keepalive_intvl = 2
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1

net.netfilter.nf_conntrack_max = 1048576
net.nf_conntrack_max = 1048576
# web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而nginx定义的NGX_LISTEN_BACKLOG默认为511,所以有必要调整这个值
net.core.somaxconn = 262144

vm.overcommit_memory = 1

在CentOS 6.x安装和配置OpenResty

下载和安装openresty

下载地址: http://openresty.org/#Installation

下载Lastest release版本:

1
wget https://openresty.org/download/ngx_openresty-VERSION.tar.gz

安装

安装之前要确保已经有必要的库:

1
yum install readline-devel pcre-devel openssl-devel gcc

编译安装openresty,默认会安装在/usr/local/openresty下,可以用–prefix参数指定想安装的位置

1
2
3
./configure --with-pcre-jit --with-ipv6
make
make install

设置启动脚本

可以使用下面脚本自动处理:

1
2
wget --no-check-certificate https://gist.githubusercontent.com/zrong/9c7dfce8f274ee451188/raw/77eada5f92dd5583838390f26cc9790b00e63137/nginxd
wget --no-check-certificate https://gist.githubusercontent.com/zrong/9c7dfce8f274ee451188/raw/a0084d1ae6d5175c913e4593c99d493487d14c75/addnginxservice && source addnginxservice

执行完记得修改/etc/init.d/nginxd中的nginx相关路径

1
2
service nginxd start # 启动nginx
service nginxd stop # 停止nginx

或者直接使用下面脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemin
#
# chkconfig:   - 85 15 
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /usr/local/nginx/conf/nginx.conf
# pidfile:     /usr/local/nginx/logs/nginx.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

nginx="/usr/local/openresty/nginx/sbin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/usr/local/openresty/nginx/conf/nginx.conf"

lockfile=/var/lock/subsys/nginx

start() {
    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    configtest || return $?
    stop
    start
}

reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
esac

通过代理抓取手机客户端数据包

环境要求

建议Linux环境,Python 2.7.x

安装代理软件

1
git clone https://github.com/inaz2/proxy2.git

启动代理

1
2
cd proxy2/
python proxy2.py 5000

配置手机

首先,检查启动proxy2点电脑IP,Windows下输入:

1
ipconfig

Linux / Mac下输入:

1
ifconfig | grep inet

然后,打开手机WiFi,连接一个可以访问proxy2电脑的WiFi热点,长按WiFi名字,可以进入高级设置,选择代理–>手工/人工–>输入上面的IP和端口号5000,有的手机需要重新开关WiFi才能生效。

最后,在proxy2电脑上查看抓取到的数据即可。

Linux Shell脚本控制台设置代理

设置方法

1
2
3
4
5
export http_proxy=http://10.203.0.1:5187/
export https_proxy=$http_proxy
export ftp_proxy=$http_proxy
export rsync_proxy=$http_proxy
export no_proxy="localhost,127.0.0.1,localaddress,.localdomain.com"

然后再执行想执行的bash命令,比如wget,就可以通过代理了。

在Mac OS X上用Homebrew安装ffmpeg和相关编解码库

首先保证已经安装了brew

Homebrew

或者直接执行:

1
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

查看ffmpeg安装参数

1
brew info ffmpeg

推荐安装参数

1
brew install ffmpeg --with-fdk-aac --with-ffplay --with-freetype --with-libass --with-libquvi --with-libvorbis --with-libvpx --with-opus --with-x265

升级

1
brew update && brew upgrade ffmpeg