nodebb安装配置使用

centos下面进行安装配置使用

我的服务器上面已经部署了lnmp运行环境、使用的是lnmp.org军哥的shell包
redis直接使用lnmp包里面编译安装的

首先我们应该更新CentOS到最新的版本,我们可以使用这个命令这样做:

1
yum -y update

安装nodebb基础软件包依赖:

1
yum -y install ImageMagick npm

使用nvm来安装node版本。

1
2
3
4
curl https://raw.githubusercontent.com/creationix/nvm/v0.13.1/install.sh | bash
source ~/.bash_profile
nvm list-remote
nvm install v0.12.7 # as of this writing check the result of the list-remote to see all choices

down最新的nodebb源代码到本地

1
2
mkdir /home/node
git clone -b v1.0.0 https://github.com/NodeBB/NodeBB nodebb

安装nodebb的依赖库

1
2
cd nodebb
npm install

启动nodebb安装脚本:

1
./nodebb setup

运行nodebb论坛:

1
./nodebb start

配置nginx作为代理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server {
listen 80;
server_name forum.example.org;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:4567;
proxy_redirect off;
# Socket.IO Support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

安福照耀我的人生之路

安福照耀我的人生之路

2013年1月4日(小寒的前一天),也是我命运改变的一天!我来到了,一间简单的办公室、除了几位妙龄少女,就剩下几位即将成为IT界的码农和一些静止的办公用品。人生只有2个字(奋斗)、我就这样登上了、一条行驶在黑暗里的小船、正经历着那黑暗里波涛汹涌的骇浪。
2014年3月在我们辛苦努力的一年里,我们迎来了第一次黎明的曙光,业务起来了。这样的征兆也预示的我们,又一个夜幕即将降临,所以我们要加强防护,努力形成自己的壁垒。这一次的征兆,警示着我们努力的张开眼睛,不能碰到黑暗里的冰山!我们就这样继续前行着……
安福的互联网风雨路,谱写着一个个快速成长的黑马,日渐壮大的团队,不断的挑头,寻找下一个前行的方向,不禁地让人困乏!风不停的咆哮着,寒气刺骨,自己只能咬牙切齿!就是不断的寻找阳光的彼岸。恶劣的环境,使人不断的出现幻想;内心的使命,使人一次次的惊醒。就这样我坚持不住了,病倒了,这份固有的坚持,使我明白了,活着的意义!
原谅自私的我、毕竟也曾努力去做一个骄傲的安福人……

laravel数据库迁移

生成迁移文件 命令

  • 生成文件路径是:database/imgrations
  • 每个迁移文件名都包含时间戳从而允许laravel判断其顺序
    *–table–create选项可以用于指定表名以及该迁移是否要创建一个新的数据表

    1
    php artisan make:migration users --create=users

    *–migration选项会生成对应的数据表模型

    1
    php artisan make:migration users --migration

执行所有未执行的迁移

1
php artisan migrate

回滚上一次的迁移

1
php artisan migrate:rollback

回滚所有迁移

1
php artisan migrate:reset

数据填充

*生成文件路径是databases/seeds

1
php artisan make:seeder UserTableSeeder

执行数据填充代码

1
php artisan db:seed

laravel的任务调度(cron)和队列一起使用制作采集器

说明!注意事项!

  • 看下面的教程!还是看一遍laravel中文文档是很有必要的!因为我是看中文文档、写出来的程序
  • 本人使用的是阿里云(1核CPU|1GB内存|1M带宽|centos6.5-64位系统|系统盘20G|laravel5.2)的配置
  • 所有的队列(queue)和任务调度(console)里面的数据库DB操作!都需要使用 DB类库!不可以使用orm!区别是mysql长链接和短链接……
  • 任务调度(console)里面只做数据库的查询——处理抛给队列处理!因为这样你的系统进程会很干净!不会又出现挂断或者假死等等!注意一点 程序结束必须有 return
  • 队列(queue)里面也是每一个 function 都要书写 return
  • 不管是在任务调度里面、队列任务里面、队列任务里面再次调用队列任务!都使用全局队列任务推送函数:dispatch!如何使用看下面操练代码
  • 重要一点!要排除所以的bug
  • 看代码为主!文字为辅助

    队列(queue)

  • 很多文档都在说队列、使用数据库、如果真正上线了使用数据库是不行的!一定修改成redis的!###一会说一下修改redis的流程
  • 做队列调试直接使用!数据库队列进行调试!

    数据库队列——开发与调试

  • 以下操作可以直接在现有项目上面执行!

    1
    2
    3
    php artisan queue:table #为数据库队列生成数据库表
    php artisan migrate #为数据库队列创建数据库表
    php artisan make:job ArtCaiji #创一个队列工作任务!这个是处理文章内容的采集
  • 以下是队列工作任务文件里面的代码 注意看!我给大家注释

    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
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    <?php
    namespace App\Jobs;
    use App\Jobs\Job;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Queue\ShouldQueue;
    //以上都是自动生成的代码不需要管理
    use DB, phpQuery, Log; //这里调用了3个类库!DB是数据库操作类库、phpquery是采集类库、log是日志类库
    /*
    log类库主要是用来做调试 打印输出
    phpquery类库主要是用来做 网页上面的信息采集
    db类库主要是用来做 数据库的处理
    代码里面没有使用中间件!怕大家晕……
    类里面的
    public function __construct($row)
    {
    //
    $this->row = $row;
    }
    不能省略这是队列工作任务类最重要的、传值方式!变量$row我传入的是一个对象值!然后把它赋给ArtCaiji类里面的私有对象$row;
    */
    class ArtCaiji extends Job implements ShouldQueue
    {
    use InteractsWithQueue, SerializesModels;
    protected $row;
    /**
    * Create a new job instance.
    *
    * @return void
    */
    public function __construct($row)
    {
    //
    $this->row = $row;
    }
    /**
    * 下面是我们要执行的代码
    *
    * @return void
    */
    public function handle()
    {
    //
    $metas = array();
    $res = array();
    if($this->row){
    $html = $this->get_url_content($this->row['href']);
    if($html){
    phpQuery::newDoclamb($html);
    foreach(pq('meta') as $meta){
    $key = pq($meta)->attr('name');
    $value= pq($meta)->attr('content');
    $metas[strtolower($key)] = $value;
    }
    $title = trim(pq('.head-wrap .title')->text());
    $articles = DB::table('articles')->where('art_title', $title)->first();
    if($articles){
    //Log::info('文章已经存在===='.$title);
    phpQuery::$documents = array();
    return true;
    }else{
    $insertedId = DB::table('articles')->insertGetId([
    'user_id' => '10000',
    'cate_id' => $this->row['cate_id'],
    'art_title' => $title,
    'art_tags' => $metas['keywords'],
    'copy_from' => '本站原创',
    'copy_url' => 'http://www.webshowu.com',
    'art_intro' => $metas['description'],
    'art_content' => $this->ImgFindShift_5118(pq('.content')->html()),
    'art_views' => '10',
    'art_status' => '3',
    'created_at' => date('Y-m-d H:i:s',time()),
    'updated_at' => date('Y-m-d H:i:s',time()),
    ]);
    if($insertedId){
    $result = $this->zhanzhang_push_baidu("http://www.webshowu.com/artinfo-".$insertedId.".html");
    }
    }
    phpQuery::$documents = array();
    return true;
    }else{
    Log::info(var_export($this->row,true));
    return true;
    }
    }else{
    Log::info('对象是空值');
    return true;
    }
    }
    /*专业处理5118文章图片*/
    function ImgFindShift_5118($html){
    if($html){
    $array = array();
    $dochtml = phpQuery::newDoclamb($html);
    foreach(pq('img') as $img){
    $val['src1'] = pq($img)->attr('data-original');
    $val['src2'] = pq($img)->attr('src');
    $array[] = $val;
    }
    foreach($array as $key => $str){
    pq("img:eq($key)")->attr('src',$str['src1']);
    }
    return $dochtml;
    }else{
    return false;
    }
    }
    /** 获取指定URL内容 */
    function get_url_content($url, $proxy = true) {
    $data = '';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER ,0);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,60);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // 设置不将爬取代码写到浏览器,而是转化为字符串
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    if($proxy){
    //AppKey 信息,请替换
    $appKey = 'xxx';
    //AppSecret 信息,请替换
    $secret = 'xxxx';
    //示例请求参数
    $paramMap = array(
    'app_key' => $appKey,
    'timestamp' => date('Y-m-d H:i:s'),
    'enable-simulate' => 'false',
    );
    //按照参数名排序
    ksort($paramMap);
    //连接待加密的字符串
    $codes = $secret;
    //请求的URL参数
    $auth = 'MYH-AUTH-MD5 ';
    foreach ($paramMap as $key => $val) {
    $codes .= $key . $val;
    $auth .= $key . '=' . $val . '&';
    }
    $codes .= $secret;
    //签名计算
    $auth .= 'sign=' . strtoupper(md5($codes));
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Proxy-Authorization: {$auth}"));
    curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); //代理认证模式
    curl_setopt($ch, CURLOPT_PROXY, 'xxxx'); //代理服务器地址
    curl_setopt($ch, CURLOPT_PROXYPORT, 'xxx'); //代理服务器端口
    curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); //使用http代理模式
    }
    $data = curl_exec($ch);
    if ($data === FALSE) {
    return false;
    }
    curl_close($ch);
    if (!$data) {
    return false;
    } else {
    $encode = mb_detect_encoding($data, array('ascii', 'gb2312', 'utf-8', 'gbk'));
    if($encode != 'utf-8'){
    if($encode == 'EUC-CN' || $encode == 'CP936'){
    $data = @mb_convert_encoding($data, 'utf-8', 'gb2312');
    }else{
    $data = @mb_convert_encoding($data, 'utf-8', $encode);
    }
    }
    return $data;
    }
    }
    /** 百度站长工具推送代码 **/
    function zhanzhang_push_baidu($url){
    $urls = array($url);
    $api = 'http://data.zz.baidu.com/urls?site=www.webshowu.com&token=6ujhg0alnRLbwZr7';
    $ch = curl_init();
    $options = array(
    CURLOPT_URL => $api,
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POSTFIELDS => implode("\n", $urls),
    CURLOPT_HTTPHEADER => array('Content-Type: text/plain'),
    );
    curl_setopt_array($ch, $options);
    $result = curl_exec($ch);
    return $result;
    }
    }

上线之后修改成redis

  • 必须安装好redis
  • 把代码 “predis/predis”: “~1.0” 添加到composer.conf文件的require里面:代码如下

    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
    {
    "name": "laravel/laravel",
    "description": "The Laravel Framework.",
    "keywords": ["framework", "laravel"],
    "license": "MIT",
    "type": "project",
    "require": {
    "php": ">=5.5.9",
    "laravel/framework": "5.2.*",
    "jenssegers/agent": "^2.3",
    "stevenyangecho/laravel-u-editor": "~1.3",
    "overtrue/laravel-lang": "1.0.*",
    "predis/predis": "~1.0"
    },
    "require-dev": {
    "fzaninotto/faker": "~1.4",
    "mockery/mockery": "0.9.*",
    "phpunit/phpunit": "~4.0",
    "symfony/css-selector": "2.8.*|3.0.*",
    "symfony/dom-crawler": "2.8.*|3.0.*"
    },
    "autoload": {
    "classmap": [
    "database",
    "app/libs/phpQuery"
    ],
    "psr-4": {
    "App\\": "app/"
    }
    },
    "autoload-dev": {
    "classmap": [
    "tests/TestCase.php"
    ]
    },
    "scripts": {
    "post-root-package-install": [
    "php -r \"copy('.env.example', '.env');\""
    ],
    "post-create-project-cmd": [
    "php artisan key:generate"
    ],
    "post-install-cmd": [
    "php artisan clear-compiled",
    "php artisan optimize"
    ],
    "post-update-cmd": [
    "php artisan clear-compiled",
    "php artisan optimize"
    ]
    },
    "config": {
    "preferred-install": "dist"
    }
    }
  • 执行 composer update 代码!

  • 修改 redis 的配置信息 文件位置是:config/database.php 里面的 redis数组
  • 修改 队列 的配置信息 文件位置是: config/queue.php 里面的 default 值修改成redis
  • 如果你看到的都是这样书写代码 env(‘QUEUE_DRIVER’, ‘sync’) 请到项目跟目录下面修改 .env 文件
  • 啊……!就这样简单!是的

    执行队列

  • 建议调试的时候直接使用 php artisan queue:listen
  • 线上直接使用supervisor安装配置使用都在这个网址里面https://phphub.org/topics/2126

    任务调度(cron)

  • 重要的是要保证进程不会假死!挂掉!不能有一丝丝php错误信息!每一个 function 都需要return !正常执行完毕程序、进程会自动推出!我强烈建议每一个调度任务都建立一个console

    建立调度任务并编写代码

  • 下面的程序可以直接执行

    1
    php artisan make:console CaiJiQi #创建调度任务命令文件 位置是 app/Console/Commands 文件里面
  • 下面是CaiJiQi.php文件里面的代码

    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
    <?php
    namespace App\Console\Commands;
    use Illuminate\Console\Command;
    //以上是自动生成的
    use App\Jobs\RegList; //这里我调用了队列RegList 采集规则 处理程序
    use DB, Log; //这里调用了2个类库!DB是数据库类库、log是日志类库
    class caijiqi extends Command
    {
    /**
    * 设置用 php的artisan工具调用名字
    * 调用代码直接在命令这样写 php artisan caiji 就执行现在这个文件
    * @var string
    */
    protected $signature = 'caiji';
    /**
    * 设置写 这个命令工具的描述
    * 只能写英文的 中文会乱码 因为编码的问题
    * @var string
    */
    protected $description = 'zhu yao shi yong lai zuo ding shi cai ji';
    /**
    * 这一行可能有些朋友基础不好的!是看不明白!
    * 加载这个类的时候、直接执行父类的析构函数方法
    * @return void
    */
    public function __construct()
    {
    parent::__construct();
    }
    /**
    * 这才是我们的关键!可以开始写要执行的代码了!
    * 因为我使用不到传值!所以先不写了!你们需要那就去看laravel中文文档
    * @return mixed
    */
    public function handle()
    {
    //
    $reg_list = DB::table('Reg_List')->where('reg_status','3')->get(); //读取采集规则表里面所以规则
    foreach($reg_list as $str){
    dispatch(new RegList($str)); //然后遍历把它 推送给 RegList 采集规则队列
    }
    return true; //不能减少return啊!
    }
    }
  • 由于处理采集规则是一个长耗时的工作!所以我又创建了一个队列文件 RegList

  • 下面是RegList.php文件里面的代码
    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
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    <?php
    namespace App\Jobs;
    use App\Jobs\Job;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Queue\ShouldQueue;
    //以上代码是自动生成的
    use App\Jobs\ArtCaiji;///这里我调用了队列ArtCaiji 采集文章 处理程序
    use DB, phpQuery, Log;
    /*
    log类库主要是用来做调试 打印输出
    phpquery类库主要是用来做 网页上面的信息采集
    db类库主要是用来做 数据库的处理
    代码里面没有使用中间件!怕大家晕……
    类里面的
    public function __construct($row)
    {
    //
    $this->row = $row;
    }
    不能省略这是队列工作任务类最重要的、传值方式!变量$row我传入的是一个对象值!然后把它赋给RegList类里面的私有对象$row;
    */
    class RegList extends Job implements ShouldQueue
    {
    use InteractsWithQueue, SerializesModels;
    protected $row;
    /**
    * Create a new job instance.
    *
    * @return void
    */
    public function __construct($row)
    {
    //
    $this->row = $row;
    }
    /**
    * Execute the job.
    *
    * @return void
    */
    public function handle()
    {
    //
    Log::info('调用了一次==='.$this->row->reg_url);
    $html = $this->get_url_content($this->row->reg_url);
    if($html){
    $data = array();
    phpQuery::newDoclamb($html);
    foreach(pq($this->row->reg_list) as $res){
    $title = trim(pq($res)->text());
    if($this->row->reg_ishost){
    $href = $this->row->reg_host.pq($res)->attr('href');
    }else{
    $href = pq($res)->attr('href');
    }
    $data[] = $title.'======'.$href;
    }
    phpQuery::$documents = array();
    if($this->row->reg_content == json_encode($data)){
    //Log::info('采集结果一样=='.$this->row->reg_url);
    }else{
    $result = $this->ArtCaiji_array_diff($data,json_decode($this->row->reg_content,true));
    if($result){
    DB::table('Reg_List')->where('reg_id',$this->row->reg_id)->update(array('updated_at'=> date('Y-m-d H:i:s',time()),'reg_content'=>json_encode($data)));
    $this->ArtCaiji_queue($result,$this->row->cate_id);
    return true;
    }
    }
    }else{
    Log::info('这个网址已经失去效果=='.$this->row->reg_url);
    }
    }
    /*文章一维数组进行对比返回不一样的值*/
    function ArtCaiji_array_diff($array1,$array2){
    if($array2!='' && $array1!=''){
    $result = array_diff($array1,$array2);
    return $result;
    }
    if($array2 == '' && $array1 !=''){}
    {
    $result = $array1;
    return $result;
    }
    return false;
    }
    /*文章队列提交*/
    function ArtCaiji_queue($array,$cate_id){
    if($array){
    foreach ($array as $value) {
    $str = explode('======',$value);
    $result['title'] = $str['0'];
    $result['href'] = $str['1'];
    $result['cate_id'] = $cate_id;
    if($result['title'] != '' && $result['href'] != '' && $result['cate_id']){
    dispatch(new ArtCaiji($result));
    }
    }
    return true;
    }else{
    return true;
    }
    }
    /** 获取指定URL内容 */
    function get_url_content($url, $proxy = true) {
    $data = '';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER ,0);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,60);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // 设置不将爬取代码写到浏览器,而是转化为字符串
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    if($proxy){
    //AppKey 信息,请替换
    $appKey = 'xx';
    //AppSecret 信息,请替换
    $secret = 'xxxx';
    //示例请求参数
    $paramMap = array(
    'app_key' => $appKey,
    'timestamp' => date('Y-m-d H:i:s'),
    'enable-simulate' => 'false',
    );
    //按照参数名排序
    ksort($paramMap);
    //连接待加密的字符串
    $codes = $secret;
    //请求的URL参数
    $auth = 'MYH-AUTH-MD5 ';
    foreach ($paramMap as $key => $val) {
    $codes .= $key . $val;
    $auth .= $key . '=' . $val . '&';
    }
    $codes .= $secret;
    //签名计算
    $auth .= 'sign=' . strtoupper(md5($codes));
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Proxy-Authorization: {$auth}"));
    curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); //代理认证模式
    curl_setopt($ch, CURLOPT_PROXY, 'xxx'); //代理服务器地址
    curl_setopt($ch, CURLOPT_PROXYPORT, 'xxx'); //代理服务器端口
    curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); //使用http代理模式
    }
    $data = curl_exec($ch);
    if ($data === FALSE) {
    return false;
    }
    curl_close($ch);
    if (!$data) {
    return false;
    } else {
    $encode = mb_detect_encoding($data, array('ascii', 'gb2312', 'utf-8', 'gbk'));
    if($encode != 'utf-8'){
    if($encode == 'EUC-CN' || $encode == 'CP936'){
    $data = @mb_convert_encoding($data, 'utf-8', 'gb2312');
    }else{
    $data = @mb_convert_encoding($data, 'utf-8', $encode);
    }
    }
    return $data;
    }
    }
    }

git的安装配置

第一次使用github

github注册账号、使用邮箱注册账号

先不要创建版本库

安装git

linux系统一般都已经自带安装好了!这里就不说了
windows系统从https://git-for-windows.github.io 下载、然后按默认选项安装即可
这里给大家说一下为什么node很多操作都需要在git bash下面执行命令呢?git命令操作和Linux命令差不多,很多命令可以直接使用,比如cd,vi 可以说是简易的cygwin了

安装完成后,还需要最后一步设置,在命令行输入

1
2
git config --global user.name "Your Name"
git config --global user.email "email@example.com"

创建ssh key

在用户主目录下,看看有没有.ssh目录,

1
2
cd ~/.ssh #切换目录至ssh配置目录
ls #查看一下有没有ssh配置文件信息

再看看目录下有没有id_rsa和id_rsa.pub这两个文件、如果已经有了、可直接跳到下一步
如果没有、打开Shell(Windows下打开Git Bash),创建SSH Key:

1
ssh-keygen -t rsa -C "youremail@example.com"

会让您输入.ssh/id_rsa目录文件的路径、默认即可
然后输入新密码、确认即可

配置github的ssh key

登陆github、打开https://github.com/settings/profile 里面的 ssh and gpg keys
然后点击右上角的 new ssh key 、填上任意title、在key文本框里粘贴文件id_rsa.pub里面的内容

cnpm安装配置给npm加速

同理nvm,npm默认是从国外的源获取和下载包信息、不慢才奇怪那
可以通过简单的 —registry 参数、使用国内的镜像 https://registry.npm.taobao.org

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
npm --registry=https://registry.npm.taobao.org install koa
npm http GET https://registry.npm.taobao.org/koa
npm http 200 https://registry.npm.taobao.org/koa
...
npm http 200 https://registry.npm.taobao.org/negotiator
npm http 200 https://registry.npm.taobao.org/keygrip
koa[@0](/user/0).5.2 node_modules/koa
├── koa-compose[@2](/user/2).2.0
├── statuses[@1](/user/1).0.2
├── finished[@1](/user/1).1.1
├── escape-html[@1](/user/1).0.1
├── only[@0](/user/0).0.2
├── debug[@0](/user/0).8.0
├── fresh[@0](/user/0).2.2
├── type-is[@1](/user/1).0.1
├── delegates[@0](/user/0).0.3
├── mime[@1](/user/1).2.11
├── co[@3](/user/3).0.5
├── accepts[@1](/user/1).0.1 (negotiator[@0](/user/0).4.2)
└── cookies[@0](/user/0).4.0 (keygrip[@1](/user/1).0.0)

但是毕竟镜像跟官方的 npm 源还是会有一个同步时间差异、目前 cnpm 的默认同步时间间隔是 15 分钟. 如果你是模块发布者、或者你想马上同步一个模块、那么推荐你安装 cnpm cli:

1
npm --registry=https://registry.npm.taobao.org install cnpm -g

通过 cnpm 命令行, 你可以快速同步任意模块

1
cnpm sync koa connect mocha

快速搭建node.js开发环境

osx、linux环境搭建

如果你是windows环境开发、请跳过这里,直接查看下一章

git clone nvm

直接从 github clone nvm到本地、这里建议大家都使用 ~/git 目录存放git项目

1
2
3
4
5
pwd #这是查看当前目录、如果不在用户目录下面、请切换。我使用的root所以切换到root下面。
cd /root #切换目录至root下面
mkdir git #建立一个git目录
cd ~/git #切换到更才建立的git目录下面
git clone https://github.com/creationix/nvm.git #从github把nvm代码down到本地

配置终端启动时自动执行 source ~/git/nvm/nvm.sh
在 ~/.bashrc 或者 ~/.bash_profile 或者 ~/.profile 或者 ~/.zshrc 文件添加以下命令

1
source ~/git/nvm/nvm.sh

重新打开您的终端输入 nvm

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
nvm
Node Version Manager
Usage:
nvm help Show this message
nvm --version Print out the latest released version of nvm
nvm install [-s] <version> Download and install a <version>, [-s] from source
nvm uninstall <version> Uninstall a version
nvm use <version> Modify PATH to use <version>
nvm run <version> [<args>] Run <version> with <args> as arguments
nvm current Display currently activated version
nvm ls List installed versions
nvm ls <version> List versions matching a given description
nvm ls-remote List remote versions available for install
nvm deactivate Undo effects of NVM on current shell
nvm alias [<pattern>] Show all aliases beginning with <pattern>
nvm alias <name> <version> Set an alias named <name> pointing to <version>
nvm unalias <name> Deletes the alias named <name>
nvm copy-packages <version> Install global NPM packages contained in <version> to current version
Example:
nvm install v0.10.24 Install a specific version number
nvm use 0.10 Use the latest available 0.10.x release
nvm run 0.10.24 myApp.js Run myApp.js using node v0.10.24
nvm alias default 0.10.24 Set default node version on a shell
Note:
to remove, delete or uninstall nvm - just remove ~/.nvm, ~/.npm and ~/.bower folders

通过nvm安装任意版本的node

nvm默认是从 http://nodejs.org/dist/ 下载的、国外服务器、必然很慢
好在nvm以及支持从镜像服务器下载包、于是我们可以方便的从七牛或者淘宝的node-dist镜像下载:

1
2
3
vi ~/.bash_profile #电脑从新启动加载的shell脚本或者命令然后把下面的命令添加到文件里面最后一行保存文件
export NVM_NODEJS_ORG_MIRROR=https://npm.taobao.org/mirrors/node
source ~/git/nvm/nvm.sh

以上的行为是为了让每一次从新启动都不需要再次输入这些命令了、下面我们把那命令从新输入一下

1
2
export NVM_NODEJS_ORG_MIRROR=https://npm.taobao.org/mirrors/node && source ~/git/nvm/nvm.sh
nvm install 5.9.1 #可以安装多个不同的版本node!这里我安装的是5.9.1版本

然后您可以继续非常方便的安装各个版本的node了、您可以查看一下您当前已经安装的版本:

1
2
nvm ls
-> v5.9.1

于是你就会看到一段非常快速进度条

1
2
######################################################################## 100.0%
Now using node v4.3.2

windows环境搭建

首先看安装git工具

git clone nvmw

直接从 github clone nvmw 到本地、这里建议大家都使用 d:\git 目录存放git项目!还有重要的一点说明一下!就是我们所有的关于node方面的操作都要在git bash环境下面操作

1
2
cd /d/git #切换目录至git
git clone https://github.com/hakobera/nvmw.git

设置 d:\git\nvmw 目录到您的 path 环境变量中

1
set "PATH=d:\git\nvmw;%PATH%"

从新打开您的终端输入 nvmw

1
2
3
4
5
6
7
8
9
10
nvmw
Usage:
nvmw help Show this message
nvmw install [version] Download and install a [version]
nvmw uninstall [version] Uninstall a [version]
nvmw use [version] Modify PATH to use [version]
nvmw ls List installed versions
Example:
nvmw install v0.6.0 Install a specific version number
nvmw use v0.6.0 Use the specific version

通过nvmw安装任意版本的node

nvmw默认是从 http://nodejs.org/dist/ 下载的、国外服务器、必然很慢
好在nvmw以及支持从镜像服务器下载包、于是我们可以方便的从七牛或者淘宝的node-dist镜像下载:

1
2
set "NVMW_NODEJS_ORG_MIRROR=https://npm.taobao.org/mirrors/node"
nvmw install 5.9.1

于是你就会看到一段非常快速进度条

1
2
######################################################################## 100.0%
Now using node v4.3.2

supervisor安装配置使用

1.supervisor简介

1.1官网

supervisor官网

1.2介绍

Supervisor是一个进程控制系统。
它是一个C/S系统(注意: 其提供WEB接口给用户查询和控制)。
它允许用户去监控和控制在类UNIX系统的进程。
它的目标与launchd、daemontools和runit有些相似。
但是与它们不一样的是、它不是作为init(进程号pid是1)运行。
它是被用来控制进程、并且它在启动的时候和一般程序并无二致。
那么通俗点,它的作用是什么?
你的Nginx,Tomcat,memcache,Redis…会崩么?
那你自己写的服务器监测脚本呢?
好吧、不要再纠结了、交给Supervisor吧!
它会帮你维护这些、即使它们不小心崩了、Supervisor会帮你看住它们、维护它们。

2.安装和配置

2.1安装

我们这里只介绍centos安装方式

1
2
3
yum install python-setuptools
easy_install supervisor
echo_supervisord_conf > /etc/supervisord.conf

2.2配置

1
vi /etc/supervisord.conf

2.3(program)配置模版

1
2
3
4
5
6
7
8
9
[program:laravel-worker1]
process_name=%(program_name)s_%(process_num)02d
command=php /home/wwwroot/site.webshowu.com/artisan queue:work redis --sleep=3 --tries=3 --daemon
autostart=true
autorestart=true
user=root
numprocs=3
redirect_stderr=true
stdout_logfile=/home/wwwlogs/worker1.log

2.4(program)配置说明

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
;*为必须填写项
;*[program:应用名称]
[program:cat]
;*命令路径,如果使用python启动的程序应该为 python /home/test.py,
;不建议放入/home/user/, 对于非user用户一般情况下是不能访问
command=/bin/cat
;当numprocs为1时,process_name=%(program_name)s
;当numprocs>=2时,%(program_name)s_%(process_num)02d
process_name=%(program_name)s
;进程数量
numprocs=1
;执行目录,若有/home/supervisor_test/test1.py
;将directory设置成/home/supervisor_test
;则command只需设置成python test1.py
;否则command必须设置成绝对执行目录
directory=/tmp
;掩码:--- -w- -w-, 转换后rwx r-x w-x
umask=022
;优先级,值越高,最后启动,最先被关闭,默认值999
priority=999
;如果是true,当supervisor启动时,程序将会自动启动
autostart=true
;*自动重启
autorestart=true
;启动延时执行,默认1秒
startsecs=10
;启动尝试次数,默认3次
startretries=3
;当退出码是0,2时,执行重启,默认值0,2
exitcodes=0,2
;停止信号,默认TERM
;中断:INT(类似于Ctrl+C)(kill -INT pid),退出后会将写文件或日志(推荐)
;终止:TERM(kill -TERM pid)
;挂起:HUP(kill -HUP pid),注意与Ctrl+Z/kill -stop pid不同
;从容停止:QUIT(kill -QUIT pid)
;KILL, USR1, USR2其他见命令(kill -l),说明1
stopsignal=TERM
stopwaitsecs=10
;*以root用户执行
user=root
;重定向
redirect_stderr=false
stdout_logfile=/a/path
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
stdout_capture_maxbytes=1MB
stderr_logfile=/a/path
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=10
stderr_capture_maxbytes=1MB
;环境变量设置
environment=A="1",B="2"
serverurl=AUTO

2.5(inet_http_server)配置说明

可以使用浏览器查看和控制进程状态

1
2
3
4
[inet_http_server] ; inet (TCP) server disabled by default
port=0.0.0.0:9001 ; (ip_address:port specifier, *:port for all iface)
username=user ; 用户名 (default is no username (open server))
password=123 ; 密码 (default is no password (open server))

3.启动与关闭

3.1启动supervisor

1
supervisord -c /etc/supervisord.conf

3.2关闭supervisor

1
supervisorctl shutdown

3.3重新载入配置

1
supervisorctl reload

#说明unix系统进程信号

1
2
3
4
5
6
7
kill -1 //终端挂起或控制进程终止。当用户退出Shell时,由该进程启动的所有进程都会收到这个信号,默认动作为终止进程。
kill -2 //键盘中断。当用户按下组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号。默认动作为终止进程。
kill -3 //键盘退出键被按下。当用户按下或组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号。默认动作为退出程序。
kill -8 //发生致命的运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为0等所有的算法错误。默认动作为终止进程并产生core文件。
kill -9 //无条件终止进程。进程接收到该信号会立即终止,不进行清理和暂存工作。该信号不能被忽略、处理和阻塞,它向系统管理员提供了可以杀死任何进程的方法。
kill -14 //定时器超时,默认动作为终止进程。
kill -15 //程序结束信号,可以由 kill 命令产生。与SIGKILL不同的是,SIGTERM 信号可以被阻塞和终止,以便程序在退出前可以保存工作或清理临时文件等。

svn安装配置使用

centos-6.5下面进行安装配置使用

1、判断是否安装成功

1
subversion -v

svnserve, version 1.6.11 (r934486)
出现上面的提示,说明安装成功。

2、svn版本查询

1
svnserve --version

3、安装svn

1
yum install subversion

4、安装完成之后需要建立svn库

1
2
mkdir /opt/svn/repos
svnadmin create /opt/svn/repos

执行上面的命令后,自动在repos下建立多个文件, 分别是conf, db,format,hooks, locks, README.txt

5、配置svn文件基本上都是conf文件下面

1、passwd文件(用户密码管理文件)

1
2
3
4
[users]
# harry = harry
# sally = sally
xxx = xxx

2、authz文件(用户权限管理文件)

1
2
3
4
[/]
xxx=rw
x=r
x=w

3、svnserve.conf文件(svn管理配置文件)

1
2
3
4
5
anon-access = none # 使非授权用户无法访问
auth-access = write # 使授权用户有写权限
password-db = password #密码配置
authz-db = authz # 访问控制文件
realm = /opt/svn/repos # 认证命名空间

subversion会在认证提示里显示,并且作为凭证缓存的关键字。

6、启动svn服务

1
svnserve -d -r /opt/svn

7、svn提交自动更新插件代码如何配置

之前我们建立了一个代码库之后有一个文件夹名字叫:hooks
下面建立一个文件 post-commit 这个文件必须为可执行程序文件权限必须是777
格式如下:

1
2
3
4
#!/bin/sh
SVN=/usr/bin/svn
WEB=/home/wwwroot/cbter
$SVN update $WEB --username 用户名 --password 密码

8、svn客户端执行代码

1
svn co svn://xxx ./