react+ant design mobile + node + mysql+Linux下项目部署

涉及的内容比较多,简单略过,文章持续更新中,需要前后端项目代码的可添加本人微信

wenjun-react.png
注意:本文讲的是web端,和移动端原生App的代码
没有关系,嵌套到原生的webview中,通过react+ 
antt design mobile 实现移动端的样式效果

本文涉及的技术包含

  • 前端技术栈:

0 react介绍和优点
1 react框架搭建、运行、打包部署到阿里云Linux服务器
2 react性能提升方法、合理设计state
3 react项目中阿里组件antd design mobile的使用

  • 后端技术栈:

node+express+mongo+mysql+soket.io 、pm2的使用

  • Linux技术栈:

0 Linux常用命令、Mac和Linux交互
1 Linux下mysql环境部署
2 Linux下mongo环境部署
3 Linux下node环境部署
4 Linux下nginx环境部署
......


React 介绍

React.js是Facebook在2013年开源的一个JS框架,在目前的前端开发的主流模式MVC和MVVM中,React主要专注于View层的开发,即视图部分。本文中主要介绍React配合and design mobile在webapp中的使用

着重说一下react的优点:

1 Web端、移动端、原生APP通吃,越来越多的react组件化按照原生UI设计,在原生App的webview中嵌套react应用,可以达到更好的用户体验,更重要的一点,可以摆脱频繁打包上架的烦恼。
2 单向数据流:因为单向,所以数据流更清晰,各种变化都是可预计、组件的状态更可控
3 虚拟DOM:它不需要浏览器的DOM API支持。虚拟DOM是在DOM的基础上建立一个抽象层,其实质是一个JavaScript对象,当数据和状态发生了变化,都会被自动高效的同步到虚拟DOM中,最后再将仅变化的部分同步到DOM中
4 项目结构更加清晰:redux、action,分部分别存放,维护性好,出了问题好找原因。
5 组件化:一切都是component,代码更加模块化,重用代码更容易,可维护性高,适合大中型项目。
6 高性能:Facebook在推出react时打出的旗号之一就是高性能。


react框架搭建

1 脚手架创建项目 2 redux设计 3 网络请求封装 4 less使用
  • 准备工作:安装node环境 -> 配置cnpm或yarn

1 create-react-app创建项目

关于脚手架的选择,在这里我使用Facebook官方推荐的脚手架create-react-app,它本身集成了Webpack,并配置了一系列内置的loader和默认的npm的脚本,可以很轻松的实现零配置就可以快速开发React的应用。
# 全局安装
npm install -g create-react-app
# 创建项目
create-react-app demo
cd demo
# 启动编译当前的React项目,并自动打开 http://localhost:3000/
yarn start
自动打开 http://localhost:3000/访问你的应用。
  • 项目的默认目录:
├── package.json
├── public                  # 这个是webpack的配置的静态目录
│   ├── favicon.ico
│   ├── index.html          # 默认是单页面应用,这个是最终的html的基础模板
│   └── manifest.json
├── src
│   ├── App.css             # App根组件的css
│   ├── App.js              # App组件代码
│   ├── App.test.js
│   ├── index.css           # 启动文件样式
│   ├── index.js            # 启动的文件(开始执行的入口)!!!!
│   ├── logo.svg
│   └── serviceWorker.js
└── yarn.lock

2 Redux 设计

  • react主要的关注点是如何创建可复用的视图层组件,对于组件之间的数据传递和状态管理并没有给出很好的解决方案,这时候我们就需要引入额外的类库完成这项工作,redux就是其中的一个代表,它就是一个应用的state管理库,甚至可以说是前端数据库,它的思想继承自Facebook的flux架构更加简洁易用,
  • redux设计的三大原则
 1、单一数据源
redux 只维护一个全局的状态对象,存储在redux的store中,便于监控任意时刻应用的状态,减少出错的可能性。
2、保持应用状态(State)是只读的
唯一改变 state 的方法就是触发 action。
这样确保了 视图 和 网络请求 都不能直接修改 state,当需要修改应用状态时,必须发送一个action,保证了在大型复杂应用中状态管理的有序进行。
3、使用纯函数来修改state
action表明修改应用状态的意图,真正对应用状态作出修改的是reducer。
reducer必须是纯函数,reducer在接收到action时,不能直接修改原来的状态对象,而是返回一个新的状态对象。
  • 使用redux
  • yarn add redux react-redux redux-thunk
  • 使用redux之后的项目结构
│  package.json
│  README.MD
├─dist                              #打包后的文件
├─public                             #公共资源文件
└─src                                #项目源码
    │  index.html                    #index.html模板
    │  index.js                      #入口文件
    │  
    │  App.js                      #入口组件
    │  
    ├─component                      #组建库
    │  └─Hello
    │          Hello.js
    │          
    ├─pages                          #页面目录
    │  ├─Home
    │  │      Home.js
    │  │     Home.less       
    ├─redux                                     #仓库
    │  │  reducers.js
    │  │  store.js
    │  │  
    │  ├─actions                               #actions
    │  │      home.js
    │  │      userInfo.js
    │  │      
    │  ├─middleware
    │  │      promiseMiddleware.js
    │  │      
    │  └─reducers.  
    │          home.js
    │          userInfo.js
    │          
    └─router                        #路由文件
       └─   router.js
│   ├── App.css             # App根组件的css
│   ├── App.js              # App组件代码
│   ├── App.test.js
│   ├── index.css           # 启动文件样式
│   ├── index.js            # 启动的文件(开始执行的入口)!!!!
│   ├── logo.svg
│   └── serviceWorker.js
└── yarn.lock
  • 中间件redux-thunk 用来处理redux中的复杂逻辑,比如异步请求,applyMiddleware将所有中间件组成一个数组,依次执行。
import {createStore,compose,applyMiddleware} from "redux";
import reducer from './reducer'
import thunk from 'redux-thunk'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, composeEnhancers(
    applyMiddleware(thunk)
));

export default store;
  • reducer
import {combineReducers} from "redux";
import counter from './reducers/counter'
import userInfo from './reducers/userInfo'
export default combineReducers({
    counter,
    userInfo
});
  • 单独的reducer
import type from '../actions/actionTypes'
const defaultState = {
    searchlist:[],
  
}

export default function reducer(state = defaultState, action) {
    switch (action.type) {
        case type.REGISTER_SUCCESS:
            return {
                ...state,
                searchlist:action.payload,
            }
        default:
            return state;
    }
}
  • action
import type from './actionTypes'
import api from '../../api/axios'
export function searchlist(title) {

    return (dispatch) => {

        if (title!=='') {
            api.searchlist(true,{title},response=>{
                dispatch(registerSuccess(response.data))
            },error=>{
                console.log('cuo==',error)
            })
        }
    }
}
function registerSuccess(data) {
    return {type:type.REGISTER_SUCCESS,payload:data}
}
  • 组件中使用redux
import React from 'react'
import {List} from "antd-mobile";
import './HomeList.less'
import {connect} from "react-redux";
import {bindActionCreators} from "redux";
import * as CountAction from '../../redux/actions/counter'
const Item = List.Item;
const Brief = Item.Brief;
class HomeList extends React.Component{
    constructor(props){
        super(props)
        this.cancleClick = this.cancleClick.bind(this)
    }
    componentDidMount() {
        this.props.actions.homelist('')
    }

    cancleClick(){
        this.props.history.go(-1)
    }
    render() {
        const {homelist} = this.props.state
        return (
             <div id='homelist'>
                    {
                        homelist.map((item,index)=>(
                            <List key={item.ID}>
                                <Item
                                    multipleLine
                                    platform="android"
                                >
                                    {item.title}
                                    <Brief wrap>{item.content}
                                    </Brief>
                                </Item>
                            </List>
                        ))
                    }
                </div>
        );
    }
}

const mapStateToProps = (state) => {
    return {
        state:state.counter
    }
};
const mapDispatchToProps = (dispatch)=>({
    actions:bindActionCreators(CountAction,dispatch)
})

export default connect(mapStateToProps,mapDispatchToProps)(HomeList);

3 网络请求封装


import axios from 'axios'
import {Toast} from "antd-mobile";
import config from '../utils/config'

// 拦截请求
axios.interceptors.request.use(function(config){
    // Toast.loading('加载中',0)
    return config
})
// 拦截相应
axios.interceptors.response.use(function(config){
    // Toast.hide()
    return config
})
function apiAxios (isLoading,method, url, params, success, failure) {
    if (isLoading) {
        Toast.loading('加载中',0)
    }
    axios({
        method: method,
        url: url,
        headers: {
            'X-Requested-With': 'XMLHttpRequest',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
        },
        data: method === 'POST' || method === 'PUT' ? params : null,
        dataType: 'json',
        params: method === 'GET' || method === 'DELETE' ? params : null,
        baseURL: config.baseURL,
        timeout: 10000,
        // withCredentials: false
    }).then(function (res) {
        console.log('返回结果==',res)
        Toast.hide()
        if (res.status===200&&res.data.code===true) {
            if (success) {
                success(res.data)
            }
        } else {
            if (failure) {
                failure(res.data)
            }
        }
    }).catch(function (err) {
        console.log('err==',err)
        Toast.hide()
        // throw new Error(err)
    })
}

export default {
    /*
     * home接口
     * parmas:参数
     * */
    homelist: function (isLoading,params, success, failure) {
        return apiAxios(isLoading,'GET', '/homelist', params, success, failure)
    }
}

##action中使用
export function homelist(params) {

    return (dispatch) => {
        api. homelist(true,{params},response=>{
            dispatch(registerSuccess(response.data))
        },error=>{
            console.log('cuo==',error)
        })
    }
}
function registerSuccess(data) {
    return {type:type.HOME_SUCCESS,payload:data}
}

##返回新的state对象
import type from '../actions/actionTypes'
const defaultState = {
    homelist:[],
}

export default function reducer(state = defaultState, action) {
    switch (action.type) {
        case type.HOME_SUCCESS:
            return {
                ...state,
                homelist:action.payload,
            }
        default:
            return state;
    }
}


4 less样式的使用

用create-react-app创建的项目 使用less方法

  • yarn add less less-loader
  • yarn run eject 暴漏出webpack.config.js和webpackDevServer.config.js文件,修改webpack.config.js文件
1 配置:
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
2 将sass的配置复制一份 修改为 less
 {
              test: lessRegex,
              exclude: lessModuleRegex,
              use: getStyleLoaders(
                  {
                    importLoaders: 2,
                    sourceMap: isEnvProduction && shouldUseSourceMap,
                  },
                  'less-loader'
              ),
              // Don't consider CSS imports dead code even if the
              // containing package claims to have no side effects.
              // Remove this when webpack adds a warning or an error for this.
              // See https://github.com/webpack/webpack/issues/6571
              sideEffects: true,
            },
            // Adds support for CSS Modules, but using SASS
            // using the extension .module.scss or .module.sass
            {
              test: lessModuleRegex,
              use: getStyleLoaders(
                  {
                    importLoaders: 2,
                    sourceMap: isEnvProduction && shouldUseSourceMap,
                    modules: true,
                    getLocalIdent: getCSSModuleLocalIdent,
                  },
                  'less-loader'
              ),
            },

3 创建less文件 添加样式
.header{
  background-color: white;
    .header-top{
      height: 60px;
      line-height: 60px;
      padding: 0 20px;
      text-align: right;
    }
}
4 使用样式
import './AAA.less'
    render() {
        const { menuName, menuType } = this.props;
        return (
            <div className='header'>
                <Row className='header-top'>
                    <Col span='24'>
                        <span>{this.state.userName}</span>
                        <a href='#'>退出</a>
                    </Col>
                </Row>
            </div>
        );
    }
或者
import styles './AAA.less'
    render() {
        const { menuName, menuType } = this.props;
        return (
            <div className={styles.header}'>
                <Row className={styles.header-top}'>
                    <Col span='24'>
                        <span>{this.state.userName}</span>
                        <a href='#'>退出</a>
                    </Col>
                </Row>
            </div>
        );
    }

运行npm run eject报错解决
https://blog.csdn.net/Amanda_wmy/article/details/83378254
cd到项目-->执行命令
git add .
git commit -m "init"
然后再npm run eject

  • 至此,项目架构已经初步完成,接下来就是今天的重头戏了 antd design mobile

阿里antd design mobile视图组件使用

  • antd-mobileAnt Design 的移动规范的 React 实现,服务于蚂蚁及口碑无线业务。UI 样式高度可配置,拓展性更强,轻松适应各类产品风格。
  • 使用 yarn add antd-mobile
  • 引入样式 import 'antd-mobile/dist/antd-mobile.css';
  • 可以使用按需加载,详情可查看官网教程https://mobile.ant.design/index-cn
  • 样式比较多,在这里简单给大家举例几个原生中常用的控件
  • list列表代码示例:
const Item = List.Item
const Brief = Item.Brief;
const data = ['支付','收藏','相册','卡包','表情','设置']
  render() {

        return (
            <div>
                <div id='Me-Header'>
                    <Item
                        arrow="horizontal"
                        thumb="https://zos.alipayobjects.com/rmsportal/hfVtzEhPzTUewPm.png"
                        multipleLine
                        onClick={() => {}}
                    >
                        徐文俊 <Brief>微信号:xuqq11239302...</Brief>
                    </Item>
                </div>
                <div id='Me'>
                    {
                        data.map((item,index)=>(
                            <Item
                                thumb={this.getthumb(index)}
                                style={this.getstyle(index)}
                                arrow="horizontal"
                                onClick={this.changeClick(index)}
                            >{item}</Item>
                        ))
                    }
                </div>
            </div>
        )
    }
  • grid代码示例
 <Grid data={homegridlist}
                      onClick={(v)=>{this.props.history.push(v.path)}}
                      columnNum={4}
                      hasLine={false}
                      renderItem={dataItem => (
                          <div style={{ padding: '2px' }}>
                              <img src={dataItem.icon} style={{ width: '50px', height: '50px' }} alt="" />
                              <div style={{ color: '##000000', fontSize: '15px', marginTop: '5px' }}>
                                  <span>{dataItem.text}</span>
                              </div>
                          </div>
                      )}
                />
  • list + grid列表效果示例:


    wenjun-list.png
  • alert弹框代码示例:
const data = ['账号与安全','新消息通知','隐私','通用','地区设置','问题反馈','切换账号','退出登录']

loginOut = ()=>{
        const BUTTONS = ['退出登录', '取消'];
        ActionSheet.showActionSheetWithOptions({
                options: BUTTONS,
                cancelButtonIndex: BUTTONS.length - 1,
                destructiveButtonIndex: BUTTONS.length - 2,
                message: '退出后不会删除任何历史数据,下次登录依然可以使用本账号。',
                maskClosable: true,
                'data-seed': 'logId',
            },
            (buttonIndex) => {
                if (buttonIndex == 0) {
                    browserCookie.erase('userid')
                    this.props.userLoginout()
                }
            });
    }
    changeAccount = ()=>{
        const alert = Modal.alert;
        alert('切换提示', '确定要切换账号吗???', [
            { text: '返回', onPress: () => console.log('cancel') },
            {
                text: '确定',
                onPress: () =>
                    new Promise((resolve) => {
                        Toast.info('已经切换', 1);
                        setTimeout(resolve, 1000);
                    }),
            },
        ])
    }
        return this.props.user?(
            <div>
                <NavBar
                    mode="light"
                >设置</NavBar>
                <div>
                        {
                            data.map((item,index)=>(
                                <Item
                                    style={this.getstyle(index)}
                                    arrow="horizontal"
                                    onClick={this.changeClick(index)}>{item}</Item>
                            ))
                        }
                    </div>
            </div>
        ):<Redirect to='/login'></Redirect>
  • 仅这几行代码实现的效果示例:


    webapp-alert.png
  • 动作面板代码示例

 dataList = [
    { url: 'OpHiXAcYzmPQHcdlLFrc', title: '发送给朋友' },
    { url: 'wvEzCMiDZjthhAOcwTOu', title: '新浪微博' },
    { url: 'cTTayShKtEIdQVEMuiWt', title: '生活圈' },
    { url: 'umnHwvEgSyQtXlZjNJTt', title: '微信好友' },
    { url: 'SxpunpETIwdxNjcJamwB', title: 'QQ' },
  ].map(obj => ({
    icon: <img src={`https://gw.alipayobjects.com/zos/rmsportal/${obj.url}.png`} alt={obj.title} style={{ width: 36 }} />,
    title: obj.title,
  }));
 showShareActionSheetMulpitleLine = () => {
    const data = [[...this.dataList, this.dataList[2]], [this.dataList[3], this.dataList[4]]];
    ActionSheet.showShareActionSheetWithOptions({
      options: data,
      message: 'I am description, description, description',
    },
    (buttonIndex, rowIndex) => {
      this.setState({ clicked2: buttonIndex > -1 ? data[rowIndex][buttonIndex].title : 'cancel' });
    });
  }
      <Button onClick={this.showShareActionSheetMulpitleLine}>showShareActionSheetMulpitleLine</Button>
  • 效果示例


    showShareActionSheetMulpitleLine.png
  • 轮播图代码示例:
class App extends React.Component {
  state = {
    data: ['1', '2', '3'],
    imgHeight: 176,
  }
  componentDidMount() {
    // simulate img loading
    setTimeout(() => {
      this.setState({
        data: ['AiyWuByWklrrUDlFignR', 'TekJlZRVCjLFexlOCuWn', 'IJOtIlfsYdTyaDTRVrLI'],
      });
    }, 100);
  }
  render() {
    return (
        <Carousel className="space-carousel"
          frameOverflow="visible"
          cellSpacing={10}
          slideWidth={0.8}
          autoplay
          infinite
          beforeChange={(from, to) => console.log(`slide from ${from} to ${to}`)}
          afterChange={index => this.setState({ slideIndex: index })}
        >
          {this.state.data.map((val, index) => (
            <a
              key={val}
              href="http://www.alipay.com"
              style={{
                display: 'block',
                position: 'relative',
                top: this.state.slideIndex === index ? -10 : 0,
                height: this.state.imgHeight,
                boxShadow: '2px 1px 1px rgba(0, 0, 0, 0.2)',
              }}
            >
              <img
                src={`https://zos.alipayobjects.com/rmsportal/${val}.png`}
                alt=""
                style={{ width: '100%', verticalAlign: 'top' }}
                onLoad={() => {
                  // fire window resize event to change height
                  window.dispatchEvent(new Event('resize'));
                  this.setState({ imgHeight: 'auto' });
                }}
              />
            </a>
          ))}
        </Carousel>
    );
  }
}
  • 效果示例:


    Carousel.png

react中即时通讯socket.io的使用(简单示例,详情官网: https://socket.io

io.on(‘connection’,function(socket));//监听客户端连接,回调函数会传递本次连接的socket
io.sockets.emit(‘String’,data);//给所有客户端广播消息
io.sockets.socket(socketid).emit(‘String’, data);//给指定的客户端发送消息
socket.on(‘String’,function(data));//监听客户端发送的信息
socket.emit(‘String’, data);//给该socket的客户端发送消息
##react.js中
import io from 'socket.io-client'
const socket = io('ws://localhost:9093')
export function recvMsg() {
    return (dispatch) => {
        socket.on('sendquanju',function (data) {
            dispatch(msgRecv(data))
        })
    }
}

export function sendMsg({from,to,msg}) {
    return (dispatch) => {
        socket.emit('sendmsg',{from,to,msg})
    }
}
##node.js中
const server = require('http').Server(app)
const io = require('socket.io')(server)
io.on('connection',function (socket) {
    socket.on('sendmsg',function (data) {
        const {from,to,msg} = data
        const chatid = [from ,to].sort().join('_')
        Chat.create({chatid,from,to,content:msg},function (err,doc) {
            if (!err){
                io.emit('sendquanju',doc)//发送给全局
            }else {
                console.log('报错')
            }
        })
    })
})
  • 效果示例:


    wenjun-chat.png

react打包部署到nginx

  • yarn run build
xuqingbiaodeMacBook-Pro:centame xuqingbiao$ yarn run build
yarn run v1.13.0
warning ../../../package.json: No license field
$ node scripts/build.js
Creating an optimized production build...
Compiled successfully.

File sizes after gzip:

  146.25 KB (+99 B)  build/static/js/2.595dde3c.chunk.js
  18.79 KB           build/static/css/2.4c229ca0.chunk.css
  2.32 KB (+92 B)    build/static/js/main.59061aaa.chunk.js
  885 B              build/static/css/main.999a4040.chunk.css
  764 B              build/static/js/runtime~main.c5541365.js

The project was built assuming it is hosted at the server root.
You can control this with the homepage field in your package.json.
For example, add this to build it for GitHub Pages:

  "homepage" : "http://myname.github.io/myapp",

The build folder is ready to be deployed.
You may serve it with a static server:

  yarn global add serve
  serve -s build

Find out more about deployment here:

  https://bit.ly/CRA-deploy

✨  Done in 22.38s.
xuqingbiaodeMacBook-Pro:centame xuqingbiao$ 
  • 打包成功后。Linux下创建个目录,将build生成的这些东西要放在目录下,在nginx 下配置下路径,网址输入IP即可,详情在下面的ngxin环境部署中。关于后端node 项目部署,在接下来的内容有介绍。

react性能优化

1 将方法的bind一律置于constructor 整个作用域的绑定只会执行一次,避免子组件的渲染。
2 setState 底层为异步,将多次setState结合成一次setState,减少虚拟DOM比对的次数,优化性能
3 react底层用了虚拟DOM,同层比对,key值,提升性能
4 shouldComponentUpdate 当组件的值没有改变时,不进行render渲染,提升组件性能
5 网络请求约定放在componentDidMount里面 只加载一次
6 如果一个组件只有一个render函数,使用无状态组件
7 谨慎将component当作props传入
8 请使用immutable(props、state、store)


node连接mongo和mysql


const express = require('express')
const bodyParser = require('body-parser')
const userRouter = require('./user')
const cookieParser = require('cookie-parser')
const model = require('./model')
const Chat = model.getModel('chat')

//新建app
const app = express()
app.use(cookieParser())
app.use(function(req, res, next){
    //设置跨域访问
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
    res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
    next();
})
const server = require('http').Server(app)
const io = require('socket.io')(server)
io.on('connection',function (socket) {
    socket.on('sendmsg',function (data) {
        const {from,to,msg} = data
        const chatid = [from ,to].sort().join('_')
        Chat.create({chatid,from,to,content:msg},function (err,doc) {
            if (!err){
                io.emit('sendquanju',doc)//发送给全局
            }else {
                console.log('报错')
            }
        })
    })
})
app.use(bodyParser.json())
app.use('/',userRouter)


//端口监听
server.listen(9093,function () {
    console.log('Node app start at port 9093')
})

  • 连接mongo
const mongoose = require('mongoose')
// 链接mongo 并且使用imooc这个集合
const DB_URL = 'mongodb://localhost:27017/manager'
mongoose.connect(DB_URL)
//连接监听
mongoose.connection.on('connected',function () {
    console.log('mongo connect success')
})

const models = {
    user:{
        'name':{type:String, 'require':true},
        'pwd':{type:String, 'require':true},
        'type':{'type':String, 'require':true},
        'avatar':{'type':String},
        'company':{'type':String},
    },
    chat:{
        'chatid':{'type':String},
        'from':{type:String,'require':true},
        'to':{type:String,'require':true},
        'read':{type:Boolean,default:false},
        'content':{type:String,'require':true,default:''},
        'create_time':{type:Number,default: new Date().getTime()}
    },

}

for(let m in models){
    mongoose.model(m, new mongoose.Schema(models[m]))
}

module.exports = {
    getModel:function(name){
        return mongoose.model(name)
    }
}

  • 连接mysql
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('Morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

const bodyParser = require('body-parser')
const cookieSessions = require('cookie-session');
const myConnection  = require('express-myconnection')
const mysql = require('mysql')
const config = require('./config')
const db = {
  host:config.db.host,
  port:config.db.port,
  user:config.db.user,
  password:config.db.password,
  database:config.db.database
}

var app = express();
app.use(myConnection(mysql,db,'single'));
app.use(function(req, res, next){
  //设置跨域访问
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
  res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
  next();
})
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});





module.exports = app;

module.exports = {
    db: {
        host:'mysql的地址',
        port:'端口',
        user:'账户',
        password:'密码',
        database:'表'
    }
};


Linux常用命令

1 Linux下yum 命令

系统更新 yum -y update
安装软件 yum install -y mongodb-org
卸载软件 yum -y remove wget
yum源所有软件包 yum list
本地可更新的软件包 yum list updates
本地已安装的软件包 yum list installed
查看本地已经安装的软件包 yum list installed | grep mongo*
查看本地已经安装的软件包 rpm -qa | grep mongo*
搜索yum源安装包 yum search 名称
搜索本地安装包 rpm -ql httpd
显示包信息 yum info httpd

2 文件 目录操作

当前工作目录 pwd
目录下的内容 ls
指定目录下的所有文件 包含隐藏文件(.文件和..文件) ls -a
显示usr目录下的所有文件 包含隐藏文件(.文件和..文件) ls -a /usr
显示目录下除.文件和..文件之外的所有文件 ls -A
显示文件的详细类型 ls -l
显示目录自身的属性 ls -ld /usr
文本文件查看工具cat
创建文件 touch
重命名 mv aaa.txt aaa.html
移动文件mv /opt/nginx.conf /root
删除文件 rm -rf aaa.html
复制文件 cp ccc.zip /root
复制文件并重命名 cp ccc.zip aaa.zip c
文件搜索 find / -name nginx.conf
编辑文件 vi 或者vim nginx.conf ->I(进入编辑模式)-> esc(进入命令行模式模式)-> :wq(保存退出)

创建目录  mkdir dir1 dir2
目录重命名 mv dir1  dirnew
删除目录 rm -rf dir1
3 用户管理

添加用户 cd /home -> useradd xuwenjun -> passwd xuwenjun
删除用户userdel -r xuwenjun

4 Mac和Linux之间文件传输命令
 1 mac上传文件到Linux服务器
    scp /Users/xuqingbiao/demo root@iptest.com:/work
 2 mac上传文件夹到Linux服务器
    scp -r /Users/xuqingbiao/demo root@iptest.com:/work
 3 Linux服务器下载文件到mac
    scp root@iptest.com:/work/demo /Users/xuqingbiao/
 4 Linux服务器下载文件夹到mac
    scp -r root@iptest.com:/work/demo /Users/xuqingbiao/ 
远程连接失败时:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
SHA256:febs6WhV+vyqocDpgParTocBLO92LCM4DgTAiHIQn7w.
Please contact your system administrator.
Add correct host key in /Users/xuqingbiao/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /Users/xuqingbiao/.ssh/known_hosts:2
RSA host key for 47.105.181.201 has changed and you have requested strict checking.
Host key verification failed.
lost connection
删除/Users/xuqingbiao/.ssh/known_host目录下的缓存
或者
ssh-keygen -R IP地址
5 zip、gz、tar打包压缩
  • yum install -y unzip zip

zip
压缩 zip -r public.zip public
解压 unzip public.zip -d public
gz
压缩 tar czvf public.tar.gz public
解压 tar xzvf public.tar.gz
tar
压缩 tar cvf wwwroot.tar wwwroot
解压 tar xvf wwwroot.tar

6 Linux 内存、cpu、进程、端口、硬盘管 理 top命令
[root@izm5e33l0ge76uqi8nq87az ~]# top

top - 16:10:01 up 3 days, 23:42,  2 users,  load average: 0.00, 0.01, 0.05
Tasks:  74 total,   1 running,  73 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.2 us,  0.2 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  3881688 total,  2243944 free,   235164 used,  1402580 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  3365280 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                
12222 root       0 -20  128644  12144   9324 S   0.7  0.3   8:01.90 AliYunDun              
  473 dbus      20   0   24488   1804   1336 S   0.3  0.0   0:01.81 dbus-daemon            
11269 root      20   0  452840  35936   4628 S   0.3  0.9   8:40.50 mongod                 
11745 root      20   0 1113464  75920  12888 S   0.3  2.0   9:03.17 node /react/rea        
17534 root      20   0  157584   2100   1512 R   0.3  0.1   0:00.01 top                    
    1 root      20   0   43276   3684   2500 S   0.0  0.1   0:03.17 systemd                
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kthreadd     
  • top - 16:10:01 up 3 days, 23:42, 2 users, load average: 0.00, 0.01, 0.05

系统当前时间 up 系统到目前为止 i 运行的时间, 当前登陆系统的用户数量, load average 后 面的三个数字分别表示距离现在一分钟,五分钟,十五分钟的负载情况。如果十五分钟的负载大于5,表情负载压力比较大。

  • Tasks: 74 total, 1 running, 73 sleeping, 0 stopped, 0 zombie

tasks 表示任务(进程),74 total 则表示现在有 74 个进程,其中处于运行中 的有 1 个,73 个在休眠(挂起),stopped 状态即停止的进程数为 0,zombie 状态即僵尸 的进程数为 0 个。

  • %Cpu(s): 0.2 us, 0.2 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

只看空闲就可以了:cpu 空闲率为 99.7%

7 内存、cup 管理 uptime 命令
[root@izm5e33l0ge76uqi8nq87az ~]# uptime
 16:22:44 up 3 days, 23:54,  2 users,  load average: 0.00, 0.01, 0.05
8 看当前登录的账户 who、查看最新操作电脑的用户 last

who 命令:
显示当前正在系统中的所有用户名字,使用终端设备号,注册时间。
whoami :
显示出当前终端上使用的用户。
last:
last 作用是显示近期用户或终端的登录情况

9 进程管理查看、杀死

pstree 查看进程树
pstree -a | grep httpd 搜索httpd进程信息
pstree -ap | grep httpd 搜索mongo进程信息 包含进程号

[root@izm5e33l0ge76uqi8nq87az ~]# pstree -ap | grep mongo
  |-mongod,11269 -f conf/conf.properties
  |   |-{mongod},11270
  |   |-{mongod},11271
  |   |-{mongod},11272
  |   |-{mongod},11273
  |   |-{mongod},11274
  |   |-{mongod},11275
  |   |-{mongod},11276
  |   |-{mongod},11277
  |   |-{mongod},11278
  |   `-{mongod},11279
  |           |-grep,17566 --color=auto mongo
  • 关闭进程四种方法

systemctl stop httpd
pkill httpd pkill 进程的名字 (建议使用pkill 因为pkill可以将主进程结束)
kill 2245 kill 进程号
kill -9 1234 kill -9 进程号 强制杀死

10 端口的查看 添加 删除、
  • yum -y install net-tools
  • netstat -tunpl 查看所有正在监听的端口
  • netstat -tunpl |grep mongo 查看mongo
[root@izm5e33l0ge76uqi8nq87az ~]# netstat -tunpl |grep mongo
tcp        0      0 0.0.0.0:28017           0.0.0.0:*               LISTEN      11269/./binmongod  
tcp        0      0 0.0.0.0:27017           0.0.0.0:*               LISTEN      11269/./binmongod  

t 或--tcp 显示 TCP 传输协议的连线状况。
u 或--udp 显示 UDP 传输协议的连线状况。
n 或--numeric 直接使用 IP 地址,而不通过域名服务器。
p 或--programs 显示正在使用 Socket 的程序识别码和程序名称。
l 或--listening 显示监控中的服务器的 Socket。

添加
firewall-cmd --zone=public --add-port=80/tcp --permanent   
(--permanent永久生效,没有此参数重启后失效)
重新载入
firewall-cmd --reload
查看
firewall-cmd --zone=public --query-port=80/tcp
删除
firewall-cmd --zone=public --remove-port=80/tcp --permanent
查看firewall是否运行,下面两个命令都可以
systemctl status firewalld.service
firewall-cmd --state
查看当前开了哪些端口
其实一个服务对应一个端口,每个服务对应/usr/lib/firewalld/services下面一个xml文件。
firewall-cmd --list-services
查看还有哪些服务可以打开
firewall-cmd --get-services
查看所有打开的端口: 
firewall-cmd --zone=public --list-ports
更新防火墙规则: 
firewall-cmd --reload
11 防火墙firewalld

安装防火墙 yum install firewalld
启动: systemctl start firewalld
开机自动启动 systemctl enable firewalld.service
查看状态: systemctl status firewalld
停止: systemctl disable firewalld
禁用: systemctl stop firewalld
查看版本: firewall-cmd --version
查看帮助: firewall-cmd --help
显示状态: firewall-cmd --state
查看所有打开的端口: firewall-cmd--zone=public --list-ports
更新防火墙规则: firewall-cmd --reload

12 使用 systemctl 管理服务

启动服务:systemctl start httpd
关闭服务:systemctl stop httpd
重启服务:systemctl restart httpd
查看所有服务的开机启动状态: systemctl list-unit-files
查看一个服务的状态:systemctl status httpd
查看一个服务是否在运行:systemctl is-active httpd
查看当前已经运行的服务:systemctl list-units -t service
设置开机自启动: systemctl enable httpd
停止开机自启动: systemctl disable httpd

13 SELinux 防火墙的设置
安全增强型 Linux(Security-Enhanced Linux)简称 SELinux,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统。 SELinux 主要由美国国家安全局开发。2.6 及以上版本的 Linux 内核都已经集成了 SELinux 模块。
SELinux 的结构及配置非常复杂,而且有大量概念性的东西,要学精难度较大。很多 Linux 系统管理员嫌麻烦都把 SELinux 关 闭了。阿里云安装的 centos 默认已经关闭了。西部数码云服务器默认也是关闭的。
  • 查看 SELinux 状态:
1、
/usr/sbin/sestatus -v  ##如果 SELinux status 参数为 enabled 即为开启状态
SELinux status:        enabled
2、getenforce          ##也可以用这个命令检查
  • 关闭 SELinux:
    1、临时关闭(不用重启机器):
setenforce 0 ##设置 SELinux 成为 permissive 模式 setenforce 1 设置 SELinux 成为 enforcing 模式

2、修改配置文件需要重启机器:

修改/etc/selinux/config 文件
将 SELINUX=enforcing 改为 SELINUX=disabled

node环境搭建

1. 配置npm的源
[root@iZm5e33l0ge76uqi8nq87aZ ~]# curl --silent --location https://rpm.nodesource.com/setup_8.x | bash -
## Installing the NodeSource Node.js 8.x LTS Carbon repo...
## Inspecting system...
+ rpm -q --whatprovides redhat-release || rpm -q --whatprovides centos-release || rpm -q --whatprovides cloudlinux-release || rpm -q --whatprovides sl-release
+ uname -m
## Confirming "el7-x86_64" is supported...
+ curl -sLf -o /dev/null 'https://rpm.nodesource.com/pub_8.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm'
## Downloading release setup RPM...
+ mktemp
+ curl -sL -o '/tmp/tmp.AIyIQvYadg' 'https://rpm.nodesource.com/pub_8.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm'
## Installing release setup RPM...
+ rpm -i --nosignature --force '/tmp/tmp.AIyIQvYadg'
## Cleaning up...
+ rm -f '/tmp/tmp.AIyIQvYadg'
## Checking for existing installations...
+ rpm -qa 'node|npm' | grep -v nodesource
## Run `sudo yum install -y nodejs` to install Node.js 8.x LTS Carbon and npm.
## You may also need development tools to build native addons:
     sudo yum install gcc-c++ make
## To install the Yarn package manager, run:
     curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
     sudo yum install yarn
2. 根据提示运行 yum install -y nodejs
  • yum install -y nodejs
已安装:
  nodejs.x86_64 2:8.15.1-1nodesource                                                                   
完毕!
[root@iZm5e33l0ge76uqi8nq87aZ ~]# 
Installed:
  nodejs.x86_64 2:8.15.1-1nodesource                                                                   Complete!
[root@iZm5e33l0ge76uqi8nq87aZ ~]# 
3. 出现以上其一,node环境已经安装完成,检查node版本
[root@iZm5e33l0ge76uqi8nq87aZ ~]# node -v
v8.15.1
[root@iZm5e33l0ge76uqi8nq87aZ ~]# 
4. 安装淘宝镜像
[root@iZm5e33l0ge76uqi8nq87aZ ~]# npm install -g cnpm --registry=https://registry.npm.taobao.org
npm WARN deprecated socks@1.1.10: If using 2.x branch, please upgrade to at least 2.1.6 to avoid a serious bug with socket data flow and an import issue introduced in 2.1.0
/usr/bin/cnpm -> /usr/lib/node_modules/cnpm/bin/cnpm
+ cnpm@6.0.0
added 679 packages from 898 contributors in 15.191s
5. 安装express生成器工具
  • cnpm install express-generator -g
[root@iZm5e33l0ge76uqi8nq87aZ ~]# cnpm install express-generator -g
Downloading express-generator to /usr/lib/node_modules/express-generator_tmp
Copying /usr/lib/node_modules/express-generator_tmp/_express-generator@4.16.0@express-generator to /usr/lib/node_modules/express-generator
Installing express-generator's dependencies to /usr/lib/node_modules/express-generator/node_modules
[1/5] commander@2.13.0 installed at node_modules/_commander@2.13.0@commander
[2/5] sorted-object@2.0.1 installed at node_modules/_sorted-object@2.0.1@sorted-object
[3/5] ejs@2.5.7 installed at node_modules/_ejs@2.5.7@ejs
[4/5] mkdirp@0.5.1 installed at node_modules/_mkdirp@0.5.1@mkdirp
[5/5] minimatch@3.0.4 installed at node_modules/_minimatch@3.0.4@minimatch
All packages installed (9 packages installed from npm registry, used 412ms(network 409ms), speed 240.39kB/s, json 9(16.66kB), tarball 81.66kB)
[express-generator@4.16.0] link /usr/bin/express@ -> /usr/lib/node_modules/express-generator/bin/express-cli.js
6. 服务器下新建一个work文件夹,并在该文件夹下初始化一个express
  • cd ..
  • mkdir work
  • express demo
 create : demo/
   create : demo/public/
   create : demo/public/javascripts/
   create : demo/public/images/
   create : demo/public/stylesheets/
   create : demo/public/stylesheets/style.css
   create : demo/routes/
   create : demo/routes/index.js
   create : demo/routes/users.js
   create : demo/views/
   create : demo/views/error.jade
   create : demo/views/index.jade
   create : demo/views/layout.jade
   create : demo/app.js
   create : demo/package.json
   create : demo/bin/
   create : demo/bin/www

   change directory:
     $ cd demo

   install dependencies:
     $ npm install

   run the app:
     $ DEBUG=demo:* npm start

[root@iZm5e33l0ge76uqi8nq87aZ work]# ls
7.安装对应的依赖
  • cd demo
  • cpm install
[root@iZm5e33l0ge76uqi8nq87aZ work]# cd demo
[root@iZm5e33l0ge76uqi8nq87aZ demo]# cnpm install
✔ Installed 6 packages
✔ Linked 85 latest versions
✔ Run 0 scripts
deprecate jade@~1.11.0 Jade has been renamed to pug, please install the latest version of pug instead of jade
deprecate jade@1.11.0 › constantinople@~3.0.1 Please update to at least constantinople 3.1.1
deprecate jade@1.11.0 › transformers@2.1.0 Deprecated, use jstransformer
✔ All packages installed (100 packages installed from npm registry, used 2s(network 2s), speed 1.08MB/s, json 91(213.77kB), tarball 1.59MB)
8. 启动应用
  • DEBUG=demo:* npm start
[root@iZm5e33l0ge76uqi8nq87aZ demo]# DEBUG=demo:* npm start

> demo@0.0.0 start /work/demo
> node ./bin/www

  demo:server Listening on port 3000 +0ms
9.打开浏览器,输入 Ip地址:3000 即可查看效果
express.png
10. vim编辑器编辑users文件添加用户接口
var express = require('express');
var router = express.Router();
var User = require('./user')
var URL = require('url')
/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});
router.get('/getUserInfo', function(req, res, next) {
  var user = new User();
  var params = URL.parse(req.url, true).query;
  if(params.id == '1') {
    user.name = "徐文俊";
    user.age = "18";
    user.city = "北京";
  } else {
    user.name = "Ms.xu";
    user.age = "2";
    user.city = "广东市";
  }
  var response = {status:1,data:user};
  res.send(JSON.stringify(response))
});
module.exports = router;
11. 启动项目,打开浏览器,输入 Ip地址:3000/users/getUserInfo 即可查看效果
user.png
12. 安装pm2依赖
  • cnpm install pm2 -g
Recently updated (since 2019-03-14): 1 packages (detail see file /usr/lib/node_modules/pm2/node_modules/.recently_updates.txt)
  2019-03-20
    → @pm2/io@4.1.2 › @pm2/agent-node@1.1.8 › proxy-agent@^3.0.3(3.1.0) (12:11:51)
All packages installed (273 packages installed from npm registry, 1 packages installed from remote url, used 4s(network 4s), speed 1.46MB/s, json 235(427.95kB), tarball 5.9MB)
[pm2@3.4.0] link /usr/bin/pm2@ -> /usr/lib/node_modules/pm2/bin/pm2
[pm2@3.4.0] link /usr/bin/pm2-dev@ -> /usr/lib/node_modules/pm2/bin/pm2-dev
[pm2@3.4.0] link /usr/bin/pm2-docker@ -> /usr/lib/node_modules/pm2/bin/pm2-docker
[pm2@3.4.0] link /usr/bin/pm2-runtime@ -> /usr/lib/node_modules/pm2/bin/pm2-runtime
13. 执行相关任务
  • pm2 startup systemd
14. 保存配置

pm2 save

15. cd到项目,pm2启动node项目
 启动  pm2 start ./bin/www
 停止 pm2 stop all
 重启 pm2 start -f ./bin/www
[root@iZm5e33l0ge76uqi8nq87aZ 0321node]# pm2 start ./bin/www
[PM2] Starting /work/0321node/bin/www in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬─────────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐
│ App name │ id │ version │ mode │ pid   │ status │ restart │ uptime │ cpu │ mem       │ user │ watching │
├──────────┼────┼─────────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤
│ www      │ 0  │ 0.0.0   │ fork │ 21200 │ online │ 0       │ 0s     │ 0%  │ 13.8 MB   │ root │ disabled │
└──────────┴────┴─────────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app
16. 查看应用运行情况
  • pm2 show www
[root@iZm5e33l0ge76uqi8nq87aZ 0321node]# pm2 show www
 Describing process with id 0 - name www 
┌───────────────────┬───────────────────────────────┐
│ status            │ online                        │
│ name              │ www                           │
│ version           │ 0.0.0                         │
│ restarts          │ 0                             │
│ uptime            │ 3m                            │
│ script path       │ /work/0321node/bin/www        │
│ script args       │ N/A                           │
│ error log path    │ /root/.pm2/logs/www-error.log │
│ out log path      │ /root/.pm2/logs/www-out.log   │
│ pid path          │ /root/.pm2/pids/www-0.pid     │
│ interpreter       │ node                          │
│ interpreter args  │ N/A                           │
│ script id         │ 0                             │
│ exec cwd          │ /work/0321node                │
│ exec mode         │ fork_mode                     │
│ node.js version   │ 8.15.1                        │
│ node env          │ N/A                           │
│ watch & reload    │ ✘                             │
│ unstable restarts │ 0                             │
│ created at        │ 2019-03-21T07:31:36.690Z      │
└───────────────────┴───────────────────────────────┘
 Code metrics value 
┌────────────────────────┬───────┐
│ Heap Size              │ 13.83 │
│ Heap Usage             │ 71.93 │
│ Used Heap Size         │ 9.95  │
│ Active requests        │ 0     │
│ Active handles         │ 4     │
│ Event Loop Latency     │ 0.62  │
│ Event Loop Latency p95 │ 1.69  │
└────────────────────────┴───────┘
 Add your own code metrics: http://bit.ly/code-metrics
 Use `pm2 logs www [--lines 1000]` to display logs
 Use `pm2 env 0` to display environement variables
 Use `pm2 monit` to monitor CPU and Memory usage www

Linux 下mongodb环境配置

1 配置 yum 源

1)、在路径/etc/yum.repos.d/下创建文件 mongodb-org-4.0.repo

cd /etc/yum.repos.d/
touch mongodb-org-4.0.repo

2)、在文件 mongodb-org-4.0.repo 中写入如下内容(下面内容可以直接复制,也可以复制官方文档)

[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc
2 安装mongodb
  • yum 安装 mongodb(会安装 mongodb-org 包及其依赖包 mongodb-org-server、mongodb-org-mongos、mongodb-org-shell、 mongodb-org-tools)
数据库实例默认在/var/lib/mongo 路径下,日志默认在/var/log/mongodb 路径下,也可以通过修改配置文 件/etc/mongod.conf 文件的 storage.dbPath 和 systemLog.path 配置
安装mongodb            yum install -y mongodb-org
开启 mongodb 服务      systemctl start mongod
设置开机启动 mongodb   systemctl enable mongod
停止 mongodb 服务.     systemctl stop mongod
重启 mongodb 服务.     systemctl restart mongod
测试安装
show dbs 查看mongodb数据库有哪些
查看安装了哪些包  yum list installed | grep mongo*
[root@iZm5e33l0ge76uqi8nq87aZ /]# cd /etc/yum.repos.d/
[root@iZm5e33l0ge76uqi8nq87aZ yum.repos.d]# ls
CentOS-Base.repo  epel.repo
[root@iZm5e33l0ge76uqi8nq87aZ yum.repos.d]# touch mongodb-org-4.0.repo
[root@iZm5e33l0ge76uqi8nq87aZ yum.repos.d]# vim mongodb-org-4.0.repo
[root@iZm5e33l0ge76uqi8nq87aZ yum.repos.d]# yum install -y mongodb-org
......
已安装:
  mongodb-org.x86_64 0:4.0.9-1.el7                                              

作为依赖被安装:
  mongodb-org-mongos.x86_64 0:4.0.9-1.el7                                       
  mongodb-org-server.x86_64 0:4.0.9-1.el7                                       
  mongodb-org-shell.x86_64 0:4.0.9-1.el7                                        
  mongodb-org-tools.x86_64 0:4.0.9-1.el7                                        

完毕!
[root@iZm5e33l0ge76uqi8nq87aZ yum.repos.d]# systemctl start mongod
[root@iZm5e33l0ge76uqi8nq87aZ yum.repos.d]# mongo
MongoDB shell version v4.0.9
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("dc9d28e8-18fb-451e-bbb2-a7965cf265f0") }
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
> use koa
switched to db koa
> db.user.indert({'name':"zhangsan"})
2019-05-06T14:11:50.910+0800 E QUERY    [js] TypeError: db.user.indert is not a function :
@(shell):1:1
>  db.user.insert({'name':"zhangsan"})
WriteResult({ "nInserted" : 1 })
> show dbs
admin   0.000GB
config  0.000GB
koa     0.000GB
local   0.000GB
> use koa
switched to db koa
> show collections
user
> db.user.find()
{ "_id" : ObjectId("5ccfd044a7def7aa24ae67ab"), "name" : "zhangsan" }
> 
3 mongo配置
  • 查看所有服务的开机启动状态: systemctl list-unit-files
  • 查看mongo的开机启动状态: systemctl list-unit-files | grep enable | grep mongod
  • 是否正在运行 systemctl is-active httpd
4 Mongodb4.x 卸载
  • 停止服务 service mongod stop
  • 删除安装的包
    rpm -qa | grep mongodb-org 列出所有的包
    yum remove -y $(rpm -qa | grep mongodb-org)
  • 删除数据及日志.
    rm -r /var/log/mongodb
    rm -r /var/lib/mongo
5 远程连接 mongodb
  • 修改 mongo.conf 文件
    命令:sudo vi /etc/mongod.conf
    将原来 bindIp:127.0.0.1 修改为 0.0.0.0
    (mongodb 的配置文件中的 bind_ip 默认为 127.0.0.1,默认只有本机可以连接。 此时,需要将 bind_ip 配置为 0.0.0.0,表示接受任何 IP 的连接。)
  • 重启动 mongo 服务 service mongod restart
  • 永久开放 27017 端口:
    firewall-cmd --zone=public --add-port=27017/tcp --permanent ; (–permanent 永久生效,没有此参数重启后 失效)
    firewall-cmd --reload

Linux 下配置nginx环境

方式1

[root@izm5e33l0ge76uqi8nq87az /]# sudo rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
获取http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
警告:/var/tmp/rpm-tmp.j7U0Sv: 头V4 RSA/SHA1 Signature, 密钥 ID 7bd9bf62: NOKEY
准备中...                          ################################# [100%]
正在升级/安装...
   1:nginx-release-centos-7-0.el7.ngx ################################# [100%]
[root@izm5e33l0ge76uqi8nq87az /]# 
  • 查看 Nginx 源是否配置成功
[root@izm5e33l0ge76uqi8nq87az /]# cd /etc/yum.repos.d/
[root@izm5e33l0ge76uqi8nq87az yum.repos.d]# ls
CentOS-Base.repo      mysql-community.repo         nodesource-el7.repo
epel.repo             mysql-community-source.repo
mongodb-org-4.0.repo  nginx.repo
  • 安装Nginx
[root@izm5e33l0ge76uqi8nq87az yum.repos.d]# cd /
[root@izm5e33l0ge76uqi8nq87az /]# yum install -y nginx
已加载插件:fastestmirror
nginx                                                    | 2.9 kB     00:00     
nginx/x86_64/primary_db                                    |  45 kB   00:22     
Loading mirror speeds from cached hostfile
正在解决依赖关系
--> 正在检查事务
---> 软件包 nginx.x86_64.1.1.16.0-1.el7.ngx 将被 安装
--> 解决依赖关系完成

依赖关系解决

================================================================================
 Package       架构           版本                          源             大小
================================================================================
正在安装:
 nginx         x86_64         1:1.16.0-1.el7.ngx            nginx         766 k

事务概要
================================================================================
安装  1 软件包

总下载量:766 k
安装大小:2.7 M
Downloading packages:
nginx-1.16.0-1.el7.ngx.x86_64.rpm                          | 766 kB   01:14     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
警告:RPM 数据库已被非 yum 程序修改。
  正在安装    : 1:nginx-1.16.0-1.el7.ngx.x86_64                             1/1 
----------------------------------------------------------------------

Thanks for using nginx!

Please find the official documentation for nginx here:
* http://nginx.org/en/docs/

Please subscribe to nginx-announce mailing list to get
the most important news about nginx:
* http://nginx.org/en/support.html

Commercial subscriptions for nginx are available on:
* http://nginx.com/products/

----------------------------------------------------------------------
  验证中      : 1:nginx-1.16.0-1.el7.ngx.x86_64                             1/1 

已安装:
  nginx.x86_64 1:1.16.0-1.el7.ngx                                               

完毕!
[root@izm5e33l0ge76uqi8nq87az /]# 
  • 启动 Nginx 并设置开机自动运行
[root@izm5e33l0ge76uqi8nq87az /]# systemctl start nginx
[root@izm5e33l0ge76uqi8nq87az /]# systemctl enable nginx
  • 开启80端口
firewall-cmd --zone=public --list-ports
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload
firewall-cmd --zone=public --list-ports
27017/tcp 9093/tcp 8000/tcp 5000/tcp 3306/tcp 8080/tcp
  • 打开浏览器 显示Welcome to nginx! 即配置nginx成功
  • Nginx 反向代理配置
  • 关闭 Selinux

vi etc/selinux/config
修改 SELINUX=enforcing 为 SELINUX=disabled
必须重启 linux init 6

  • 配置反向代理
[root@izm5e33l0ge76uqi8nq87az /]# cd /etc/nginx/conf.d
[root@izm5e33l0ge76uqi8nq87az conf.d]# ls
default.conf
配置default.conf的信息
server {
listen 80;
server_name www.bbb.com; location / {
#设置主机头和客户端真实地址,以便服务器获取客户端真实 IP proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #禁用缓存
proxy_buffering off;
#反向代理的地址
proxy_pass http://127.0.0.1:3001; }
}
或者
server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        #react项目地址
        root /work/build/build;
        index index.html index.htm;

    }
  • 检查并重启nginx
[root@izm5e33l0ge76uqi8nq87az conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@izm5e33l0ge76uqi8nq87az conf.d]# systemctl stop nginx
[root@izm5e33l0ge76uqi8nq87az conf.d]# systemctl start nginx

方式2

  • 安装epel源
  • yum install epel-release -y
[root@iZm5e33l0ge76uqi8nq87aZ /]# yum install epel-release -y
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
正在解决依赖关系
--> 正在检查事务
---> 软件包 epel-release.noarch.0.7-11 将被 安装
--> 解决依赖关系完成
依赖关系解决
======================================================================================================
 Package                      架构                   版本                   源                    大小
=======================================================================================================
正在安装:
 epel-release                 noarch                 7-11                   epel                  15 k
事务概要
=======================================================================================================
安装  1 软件包
总下载量:15 k
安装大小:24 k
Downloading packages:
epel-release-7-11.noarch.rpm                                                    |  15 kB  00:00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  正在安装    : epel-release-7-11.noarch                                                           1/1 
警告:/etc/yum.repos.d/epel.repo 已建立为 /etc/yum.repos.d/epel.repo.rpmnew 
  验证中      : epel-release-7-11.noarch                                                           1/1 
已安装:
  epel-release.noarch 0:7-11                                                                           
完毕!
  • 安装nginx
  • yum -y install nginx
  验证中      : gperftools-libs-2.6.1-1.el7.x86_64                                               20/25 
  验证中      : libX11-common-1.6.5-2.el7.noarch                                                 21/25 
  验证中      : freetype-2.8-12.el7_6.1.x86_64                                                   22/25 
  验证中      : 1:nginx-mod-http-perl-1.12.2-2.el7.x86_64                                        23/25 
  验证中      : 1:nginx-mod-http-image-filter-1.12.2-2.el7.x86_64                                24/25 
  验证中      : freetype-2.4.11-15.el7.x86_64                                                    25/25 

已安装:
  nginx.x86_64 1:1.12.2-2.el7                                                                          
作为依赖被安装:
  dejavu-fonts-common.noarch 0:2.33-6.el7        dejavu-sans-fonts.noarch 0:2.33-6.el7                
  fontconfig.x86_64 0:2.13.0-4.3.el7             fontpackages-filesystem.noarch 0:1.44-8.el7          
  gd.x86_64 0:2.0.35-26.el7                      gperftools-libs.x86_64 0:2.6.1-1.el7                 
  libX11.x86_64 0:1.6.5-2.el7                    libX11-common.noarch 0:1.6.5-2.el7                   
  libXau.x86_64 0:1.0.8-2.1.el7                  libXpm.x86_64 0:3.5.12-1.el7                         
  libjpeg-turbo.x86_64 0:1.2.90-6.el7            libpng.x86_64 2:1.5.13-7.el7_2                       
  libxcb.x86_64 0:1.13-1.el7                     libxslt.x86_64 0:1.1.28-5.el7                        
  nginx-all-modules.noarch 1:1.12.2-2.el7        nginx-filesystem.noarch 1:1.12.2-2.el7               
  nginx-mod-http-geoip.x86_64 1:1.12.2-2.el7     nginx-mod-http-image-filter.x86_64 1:1.12.2-2.el7    
  nginx-mod-http-perl.x86_64 1:1.12.2-2.el7      nginx-mod-http-xslt-filter.x86_64 1:1.12.2-2.el7     
  nginx-mod-mail.x86_64 1:1.12.2-2.el7           nginx-mod-stream.x86_64 1:1.12.2-2.el7               
作为依赖被升级:
  freetype.x86_64 0:2.8-12.el7_6.1                                                                     

完毕!
  • 启动nginx

  • systemctl start nginx.service
    打开IP地址


    nginx.png
  • 创建网站根目录

  • mkdir -p /var/www/test/public_html

  • 编辑根目录下的文件

  • vim /var/www/test/public_html/index.html

<html>
      <body>
              <h1>Hello World</h1>
      </body>
</html>
  • 添加虚拟主机配置文件
  • vim /etc/nginx/conf.d/vitual.conf
server{
listen 80;
server_name 主机地址;
root var/www/test/public_html;
index index.html;
}
  • 查看nginx状态 nginx -t
[root@iZm5e33l0ge76uqi8nq87aZ conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
  • 重启systemctl restart nginx.service
  • 打开网址 配置成功


    nginx.png

Linux下配置mysql环境

1 配置源
[root@izm5e33l0ge76uqi8nq87az]# cd etc/yum.repos.d
[root@izm5e33l0ge76uqi8nq87az yum.repos.d]# ls
CentOS-Base.repo  epel.repo  mongodb-org-4.0.repo  nodesource-el7.repo
  • 安装配置源
[root@izm5e33l0ge76uqi8nq87az yum.repos.d]# rpm -ivh http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
获取http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
警告:/var/tmp/rpm-tmp.RsV9b3: 头V3 DSA/SHA1 Signature, 密钥 ID 5072e1f5: NOKEY
准备中...                          ################################# [100%]
正在升级/安装...
   1:mysql57-community-release-el7-11 ################################# [100%]
[root@izm5e33l0ge76uqi8nq87az yum.repos.d]# ls
CentOS-Base.repo  mongodb-org-4.0.repo  mysql-community-source.repo
epel.repo         mysql-community.repo  nodesource-el7.repo
  • 打开mysql-community.repo 查看默认打开的mysql源默认为5.7

[root@izm5e33l0ge76uqi8nq87az yum.repos.d]# vim mysql-community.repo


[mysql-tools-community]
name=MySQL Tools Community
baseurl=http://repo.mysql.com/yum/mysql-tools-community/el/7/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

# Enable to use MySQL 5.5
[mysql55-community]
name=MySQL 5.5 Community Server
baseurl=http://repo.mysql.com/yum/mysql-5.5-community/el/7/$basearch/
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

# Enable to use MySQL 5.6
[mysql56-community]
name=MySQL 5.6 Community Server
baseurl=http://repo.mysql.com/yum/mysql-5.6-community/el/7/$basearch/
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

[mysql57-community]
name=MySQL 5.7 Community Server
baseurl=http://repo.mysql.com/yum/mysql-5.7-community/el/7/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

[mysql80-community]
name=MySQL 8.0 Community Server
baseurl=http://repo.mysql.com/yum/mysql-8.0-community/el/7/$basearch/
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

[mysql-tools-preview]
name=MySQL Tools Preview
baseurl=http://repo.mysql.com/yum/mysql-tools-preview/el/7/$basearch/
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

[mysql-cluster-7.5-community]
name=MySQL Cluster 7.5 Community
baseurl=http://repo.mysql.com/yum/mysql-cluster-7.5-community/el/7/$basearch/
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

[mysql-cluster-7.6-community]
name=MySQL Cluster 7.6 Community
baseurl=http://repo.mysql.com/yum/mysql-cluster-7.6-community/el/7/$basearch/
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
                                                              64,1         底端
2 安装
  • 安装 yum -y install mysql-server
[root@izm5e33l0ge76uqi8nq87az yum.repos.d]# yum -y install mysql-server
已加载插件:fastestmirror
base                                                     | 3.6 kB     00:00     
epel                                                     | 4.7 kB     00:00     
....
已安装:
  mysql-community-libs.x86_64 0:5.7.26-1.el7                                    
  mysql-community-libs-compat.x86_64 0:5.7.26-1.el7                             
  mysql-community-server.x86_64 0:5.7.26-1.el7                                  

作为依赖被安装:
  libaio.x86_64 0:0.3.109-13.el7                                                
  mysql-community-client.x86_64 0:5.7.26-1.el7                                  
  mysql-community-common.x86_64 0:5.7.26-1.el7                                  

作为依赖被升级:
  postfix.x86_64 2:2.10.1-7.el7                                                 

替代:
  mariadb-libs.x86_64 1:5.5.56-2.el7                                            

完毕!
[root@izm5e33l0ge76uqi8nq87az yum.repos.d]# 
3 配置
  • 启动 systemctl start mysqld
  • 开机启动 systemctl enable mysqld
  • 修改 MySQL root 本地登录密码
  • 登录 mysql -u root -p
  • 查看默认密码 cat /var/log/mysqld.log | grep password
[root@izm5e33l0ge76uqi8nq87az /]# cat /var/log/mysqld.log | grep password
2019-05-16T07:39:07.625478Z 1 [Note] A temporary password is generated for root@localhost: fl.oiCTZY1He
2019-05-16T07:49:40.884287Z 2 [Note] Access denied for user 'root'@'localhost' (using password: NO)
[root@izm5e33l0ge76uqi8nq87az /]# mysql -u root -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
[root@izm5e33l0ge76uqi8nq87az /]# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.26

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
  • 修改密码策略 vim etc/my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html

[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
添加
validate_password = off
  • 配置完成后重启mysql服务并登录修改密码
  • systemctl restart mysqld
  • mysql -u root -p
  • ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';
[root@izm5e33l0ge76uqi8nq87az /]# vim etc/my.cnf
[root@izm5e33l0ge76uqi8nq87az /]# systemctl restart mysqld
[root@izm5e33l0ge76uqi8nq87az /]# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.26

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)

mysql> 
4 远程管理mysql
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from user;
+-----------+---------------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+--------------+------------+-----------------------+------------------+--------------+-----------------+------------------+------------------+----------------+---------------------+--------------------+------------------+------------+--------------+------------------------+----------+------------+-------------+--------------+---------------+-------------+-----------------+----------------------+-----------------------+-------------------------------------------+------------------+-----------------------+-------------------+----------------+
| Host      | User          | Select_priv | Insert_priv | Update_priv | Delete_priv | Create_priv | Drop_priv | Reload_priv | Shutdown_priv | Process_priv | File_priv | Grant_priv | References_priv | Index_priv | Alter_priv | Show_db_priv | Super_priv | Create_tmp_table_priv | Lock_tables_priv | Execute_priv | Repl_slave_priv | Repl_client_priv | Create_view_priv | Show_view_priv | Create_routine_priv | Alter_routine_priv | Create_user_priv | Event_priv | Trigger_priv | Create_tablespace_priv | ssl_type | ssl_cipher | x509_issuer | x509_subject | max_questions | max_updates | max_connections | max_user_connections | plugin                | authentication_string                     | password_expired | password_last_changed | password_lifetime | account_locked |
+-----------+---------------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+--------------+------------+-----------------------+------------------+--------------+-----------------+------------------+------------------+----------------+---------------------+--------------------+------------------+------------+--------------+------------------------+----------+------------+-------------+--------------+---------------+-------------+-----------------+----------------------+-----------------------+-------------------------------------------+------------------+-----------------------+-------------------+----------------+
| localhost | root          | Y           | Y           | Y           | Y           | Y           | Y         | Y           | Y             | Y            | Y         | Y          | Y               | Y          | Y          | Y            | Y          | Y                     | Y                | Y            | Y               | Y                | Y                | Y              | Y                   | Y                  | Y                | Y          | Y            | Y                      |          
mysql> select host, user from user;
+-----------+---------------+
| host      | user          |
+-----------+---------------+
| localhost | mysql.session |
| localhost | mysql.sys     |
| localhost | root          |
+-----------+---------------+
3 rows in set (0.00 sec)

mysql> 
  • 将localhost修改为*
mysql> update user set host = '%' where user = 'root';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select host, user from user;
+-----------+---------------+
| host      | user          |
+-----------+---------------+
| %         | root          |
| localhost | mysql.session |
| localhost | mysql.sys     |
+-----------+---------------+
3 rows in set (0.01 sec)

mysql> exit
Bye
  • 开启mysql端口 并查看所有打开的端口
[root@izm5e33l0ge76uqi8nq87az /]# 
[root@izm5e33l0ge76uqi8nq87az /]# systemctl start firewalld
[root@izm5e33l0ge76uqi8nq87az /]# firewall-cmd --zone=public --add-port=3306/tcp --permanent
success
[root@izm5e33l0ge76uqi8nq87az /]# firewall-cmd --reload
success
[root@izm5e33l0ge76uqi8nq87az /]# firewall-cmd --zone=public --list-ports
27017/tcp 9093/tcp 8000/tcp 5000/tcp 3306/tcp
[root@izm5e33l0ge76uqi8nq87az /]# systemctl restart mysqld
  • 记得配置完成之后,重启mysql
  • 然后就可以通过mysql客户端连接了
  • 卸载mysql
查询mysql安装包 rpm -qa | grep mysql*
rpm -e mysql*
或者yum remove -y mysql*
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容