Shipit Node App with Docker

上面提到如何在代码部署到 Remote Server 后,将 Sercert file link 到相应位置,然后通过 PM2 启动服务。

但我们真实的项目,是构建 Docker 镜像然后启动镜像来实现最终的发布。

这里的流程又是什么样子呢?

  1. 将代码放到 remote server 指定位置(已完成)。
  2. 在 remote server 上将 shared dirs/files 放到指定位置。
  3. 在代码目录下 build docker image。
  4. 启动。

但实践中,发现一件很麻烦的事:docker dislike symbolic link 😓

shiptit-shared-copy

首先的是,app 目录中不能含有 soft link 文件,不然不会被 copy 到 docker 镜像中。

像 config/application.yml 这种通过 link 方式存在的,就不行了。

所以,直接 fork shipit-shared 项目,把 symbolic link 改成 copy。

每次都会把文件复制到 current 对应的 release 版本中。

配置文件和 shipit-shared 保持不变:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = function (shipit) {
require('shipit-deploy')(shipit);
require('shipit-shared')(shipit);
shipit.initConfig({
default: {
shared: {
overwrite: true,
files: [
'config/application.yml',
'config/database.yml'
],
}
}
});
};

deploy-duplicate

解决完 app 内部 soft link 的问题后,然后在 current 下用 docker-compose 构建镜像,然后启动。发现不能重复,原因是,每次构建的目录并不是 current 这个 soft link 的目录。而是 releases/[version] 这个目录。

目录名变化后,构建出的镜像就不一致了,这就导致无法重复的在一个目录下进行多次构建。

compose 构建后的镜像是用 目录名+service 名。

同时也会引发无法销毁的问题,端口被占用。

解决办法也有,就是把releases/[version] 物理复制到另一个 current 一样的固定的位置。起名叫 deploy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.
|-- current -> releases/20170228072117
|-- deploy
| |-- app
| |-- bin
| |-- config
| |-- docker-compose.yml
| |-- Dockerfile
| |-- lib
| |-- package.json
| |-- process.yml
| |-- REVISION
| `-- yarn.lock
|-- releases
| |-- 20170228062744
| `-- 20170228072117
`-- shared
`-- config

这样,每次在 published 后,都将最新的 releases 版本复制到 deploy。然后在 deploy 下执行 docker-compose up -d --build

没有做成单独的 npm,直接放在 shipitfile 中即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = function (shipit) {
// Docker dislike soft link
// So make a physical copy (deploy) instead of softlink (current)
shipit.blTask('deploy-clean', function () {
console.log('cp -R ' + shipit.releasePath + ' ' + shipit.config.deployTo + '/deploy');
return shipit.remote('rm -rf ' + shipit.config.deployTo + '/deploy');
});
shipit.blTask('deploy-duplicate', function () {
return shipit.remote('cp -R ' + shipit.releasePath + ' ' + shipit.config.deployTo + '/deploy');
});
shipit.on('published', function () {
shipit.start(['deploy-clean', 'deploy-duplicate']);
});
}

完美。


REF::

Shipit Node App with PM2

在上一篇中,已经将项目放置在 Remote Server 上了。

在如何启动时,我们有多个选择,现在,看下如何直接用 pm2 在目录下直接启动。

服务器上的目录如下:

1
2
3
4
5
6
7
.
|-- current -> releases/20170228072117
|-- releases
| |-- 20170228062744
| `-- 20170228072117
`-- shared
`-- config

配置

有了上面两个插件的配合,就省力了很多。

在项目中 config 下有两个文件,需要被忽略,所以这里通过 shipit-shared 来配置。

在这之前还有几个问题要被解决:

shiptit-shared

项目中有一些配置文件,里面会存有服务器,DB 的相关安全信息,而且这些信息是跟环境相关,也就是说在不同的环境,它的内容是不一样的。

shipit-shared 就是帮我们做这件事情的。

它可以,在 Remote Server 上建一个公共的目录,手工在里面建立起上述的文件。再在 shipitfile.js 中加入这些文件或目录的配置。

每次 deploy 时,就会自动的将这些文件或目录软链到 current 下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = function (shipit) {
require('shipit-deploy')(shipit);
require('shipit-shared')(shipit);
shipit.initConfig({
default: {
shared: {
overwrite: true,
files: [
'config/application.yml',
'config/database.yml'
],
}
}
});
};

shipit-pm2

如果项目是在代码发布完之后,直接通过 pm2 来启动的,那这个插件就很适合。

1
2
3
4
5
6
7
8
9
10
11
12
module.exports = function (shipit) {
require('shipit-deploy')(shipit);
require('shipit-pm2')(shipit);
shipit.initConfig({
default: {
pm2: {
json: '/data/repos/app-koa2boil/process.json'
}
}
});
};


REF::

使用 Shipit 来自动化部署 Node 应用

之前一直想为 node 的发布整理出一个流程,但一直没有太多实践,后来就忙给忘却了,不过最近做了几个小东西,每次发布都要登陆服务器,终于下决心自动化这个流程。

项目结构

Node 的项目结构是这样子的,可参考 github: Koa2-Boilerplate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
├── app
│   ├── apis
│   ├── models
│   └── services
├── bin
├── config
│   ├── application.yml
│   └── database.yml
├── lib
│   └── middleware
├── Dockerfile
├── docker-compose.yml
├── process.yml
├── shipitfile.js
└── package.json


整理现在的发布流程

目前仍有 ES Module 不是 Node 支持,所以发布时需要 build 生成发布代码,然后将发布用的代码放到服务器,通过 pm2 启动,或构建 Docker 镜像。

为此,我们构建了两个 repo:

  1. 项目的源码,编译后,生成 dist 为发布用的代码
  2. 编译后的代码,包含各种配置文件,dockerfile, docker-compose 文件。

流程:

  • 源码项目更新,然后 build 出 dist 目录
  • 将 dist 复制到 发布项目,然后迁入 git
  • 服务器拉取发布 git
  • Docker build
  • Docker run

小的项目中,如果不需要对 docker 进行版本说明,以上流程将是一个很简单的事。

如果想要自动化的话,就需要考虑以下两个构建步骤:

  • 代码构建服务器:因为是小的项目,可以不需要中间的构建服务器,直接由本机的另一个路径,或者是服务器的一个路径来承担,建议放在本机,这样服务器就不需要 node 相关的软件了。
  • Docker 构建服务器:docker image 一定要在远程服务器本机处理的,不然传输成本就太高了,这就要求构建服务器,


什么是 Shipit?

Shipit 是一个用 Node 写的自动化引擎,也是一个发布工具。

说白点就是 Universal automation and deployment tool,通用自动化部署工具而已。

和 Capistrano 对比

作为 Capistrano 的 Node 版,有什么区别:

Capistrano

  • Ruby 语言(这个对我来说没问题)
  • 在服务器端拉代码,然后进行 build 的。
  • 插件多,社区完善。

Shipit

  • Pure JavaScript,在 Node 上体验会更好。
  • 本地拉取 git repo,本地打包(好处是服务器上不需要配置 node.js 了),然后 rsync 指定目录到 Server
  • 3个月未更新。
  • 支持的插件少,但可以自己写,很简单。

对比完这些,觉得还是 Shipit 更适合一些。


Shipit Configuration

接下来,就在本机尝试安装和配置 Shipit。

安装

1
2
$ npm install --global shipit-cli
$ npm install --save-dev shipit-cli shipit-deploy shipit-shared

Create a shipitfile.js

Shipit 的运行依赖于配置文件,在项目的根目录,创建 shipitfile.js 就可以开始了。

一个简单的示例(为 staging 环境配置一台远程服务器,并新建一个叫 pwd 的 task):

1
2
3
4
5
6
7
8
9
10
11
module.exports = function (shipit) {
shipit.initConfig({
staging: {
servers: 'root@project.com'
}
});
shipit.task('pwd', function () {
return shipit.remote('pwd');
});
};

这时,就可以通过以下命令 shipit+服务器+task 来运行了。

1
$ shipit staging pwd


发布实战:

基于 shipit-deploy 的发布流程

当然一个完整的发布流程,会有多个 task 进行顺序执行,而 shipit 自身也只是定位于一个编排引擎,它提供了 task 的组合能力(基于: Orchestrator)同时,还提供了钩子的能力,能在一些 task 前后加入自己的task(event),这称为 Emit,接下来会用到这些功能。

我们完全有能力基于这些编排组合能力和钩子实现发布的所有流程,但重复从来都是应当被吐槽的。社区也早有一些最佳实践,shipit-deploy 就是 shipit 自己做的一个发布实践。

利用它可以很快速的完成自己的发布流程,同时,它也提供了大量的 Emitter,供我们进行扩展。

更多的可以查看官方文档:

实际项目 deploy 的扩展

对比下 shipit-deploy 的 task flow,我们需要的是在 fetch 完代码后加入以下流程:

  • npm install
  • npm run build

通过 emit 就可以实现,代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
shipit.blTask('npm-install', function () {
shipit.log('yarn install.');
return shipit.local('yarn install', { cwd: '/tmp/app-koa2boilerplate' })
});
shipit.blTask('npm-build', function () {
shipit.log('npm build start.');
return shipit.local('npm run build', { cwd: '/tmp/app-koa2boilerplate' })
});
shipit.on('fetched', function () {
console.log('itis npm build');
shipit.start(['npm-install', 'npm-build']);
});

运行以下命令,就能完成代码获取,构建,发布代码到 Server 上的流程。

1
$ shipit staging deploy

真实的启动流程

经过上面的步骤,可用于线上发布的代码已被放置在服务器上了。那项目中的一些被 gitignore 的配置文件呢。

请看下面两篇:


REF::

逛街引发的数码购物单

今天陪 LD 去逛街,本想去 Line Friends 里转转,但队伍实在是太长了,瞬间没了兴趣,还没有吃到好吃的东西,感觉淮海路是为数不多的不适合吃饭的地方。

期待新 iPad Pro

新开了一家 Apple 店,是之前没有转过的,刚好转去看了一下, LD 是一位艺术家,随手画了几笔,立即把我打动了,本着每一个爱好都应被呵护的想法,准备送一个 iPad Pro + Pencil,回家做了下功课,感觉三月新品发布会应该有新款发布,取消 Home 键,更快的处理器,更大的内存,买新不买旧,那就再等等 😄😂

iMac 5K

说话,前天没有开车,坐地铁时带上了 Kindle,原来放了一年还有电,厉害。中间看了一路的书,快到 站时收起书,换上手机,竟然被 iPhone 的细腻感动到了。

这就是我对 iMac 5K 的期待吧,别挤牙膏了,出个让人满意的吧。真的想入了。

Apple-3月春季发布会-预测::Devices

设备 更新介绍 价格 上市时间
MacBook Pro 小更新 Kabylake CPU -.– 2017.03.21
iMac 27 KKK,今年终于赶上 Intel 的节奏了,KabyLake,DDR 4,USBC,AMD显卡 -.– 2017.03.21
iPad Pro 2 据说更新三款 iPad Pro 2 (12.9/10.5) 去除Home键,同时采用极窄边框。 -.– 2017.03.21
iPad Mini 应该也会更新一下。 -.– 2017.03.21

LG UltraFine 5K

除了旧例体验 iMac 27外,还多看了一眼边上的 LG 5K,比 DELL 5K 便宜了一半,效果和 iMac 27 上的一样,其实就是同一块屏。

可以上下,左右调节。不支持 DELL 那种竖屏,不过也从没有竖起用过。外观,有点太一般了,边框很宽,看起来没精神,不像 U2717d 那般好看。

相对于 iMac 的好外是,可以调节,方便外接,想想之前的 TDM 模式,真难用。
缺点就是没有 iMac 的金属边框的质感,价格也不便宜。7638。额,,有点小贵。

更多 LG UltraFine 5K 看官网:

DELL U2717d

说到 2717d,上周,我把它出掉了,原因是入了 OSMO+ 运动套件,资金有不小压力。当然不是了,只是显示器多,2515 也没怎么用到,就想出一个。

出之前,经常把笔记本背回家,现在没了显示器,也再没背过了,又开始了研究如何同步的问题。

OSMO+

话说,年前放假前两天,入了一个 OSMO+ 运动套装,本想去日本时用,结果今年临时决定在上海过年。

一直说要评价一下 OSMO+ 的,毕竟这一块没人做过,我也是用了好久,才有一些经验的。

所以,就不在这里讲了,回头有机会,专门长篇去测评一下。

如果非要给个一句话总结,就是有钱想玩,真的挺好玩,如果想干专业的事,拍照,一般,拍视频,也一般 。

Webpack 2 in Action

webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

传统工具中,流程是,将 js, css, html 各自合并,压缩,形式一个或多个文件,分别在各处引用。

但 webpack 相对于之前的工具区别于,所有的东西都是资源,像 css, js, image 亦或 json 等,可以通过 loader 来进行加载。
同时,它有模块机制,会根据依赖,去把代码自动放在一起,而不用开发的配置。
接下来,一起来走一个流程,来熟悉下配置。


安装使用 Webpack

1
2
3
4
# 更推荐使用 yarn 来进行依赖库的操作
$ yarn add --dev webpack webpack-dev-server
# 为了更方便使用 webpack,建议全局安装
$ yarn global add --dev webpack webpack-dev-server

在项目中创建 webpack.config.js 即可开启使用。

可以依据不同环境,增设不同的配置文件 webpack.production.config.js


一切都在配置文件

Webpack 所有的配置都在 webpack.config.js 文件中。其中包括以下几个大的类别:

Context/Entry/Output

这是几个必备基础配置,我们来一一讲解:

  • context: 配置 entryloader 工作所在的根目录。
  • entry: 应用的入口文件,该文件和其依赖,最终会被编译到一个文件。(可以配置为多个对象,编译出对应个数的结果文件。)
  • output: 入口文件编译后的配置项,可以是一个固定字符串,也可是以一个 [name].[hash].bundle.js 的变量配置。
1
2
3
4
5
6
7
8
9
10
11
12
13
let config = {
context: path.resolve(__dirname, 'src'),
entry: {
app: './main.jsx'
},
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
filename: "[name].[hash].bundle.js"
}
}

Module

Webpack 是设计为处理 JavaScript 文件的,但其也可以处理任何的文件类型,这归功于强大的 Loaders 机制。

Loader 的使用方法是,通过正则匹配到一些类型的文件,然后对其依次经过配置 loader 的处理。Loader 可以配置多个,倒序依次处理。

示例中,是对 scss 文件的处理,先由 sass-loader 进行编译,然后交由 css-loader,最后由 style-loader 来处理。

1
2
3
4
5
6
7
8
9
10
11
let config = {
module: {
rules: [{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
]}
]}
}

Plugins

和 Module 针对文件类型不同的是 Plugin 处理的是:下面,主要讲几个常用的 Plugin 和配置:

- webpack.HotModuleReplacementPlugin

webpack 内置 Plugin,自动热加载,就是在开发时,一旦有文件改动,浏览器会自动刷新。

- webpack.optimize.CommonsChunkPlugin

正如其名,它会让引用模块中重复的地方取出,做成一个单独的文件,这样可以将一些公共的库取出,降低改动带来的更新成本。

如果你正在将应用拆解,打包成多个 output 的话(如果应用的某部分有大量不需要提前加载的 JS 的话,这样做会很有用),那么在这些文件里就有可能出现重复的代码,因为在解决依赖问题的时候它们是互相不干预的。幸好,Webpack 有一个内建插件 CommonsChunk 来处理这个问题:

现在,在 output 的文件里,如果有任意模块加载了两次或更多(通过 minChunks 设置该值),它就会被打包进一个叫 commons.js 的文件里,后面你就可以在客户端缓存这个文件了。当然,这肯定会造成一次额外的请求,但是却避免了客户端多次下载相同库的问题。所以在很多场景下,这都是提升速度的举措。

- webpack.optimize.UglifyJsPlugin

代码压缩,用于生产环境。

- webpack.ProvidePlugin

全局挂载插件,用于挂载老的代码,如 jQuery 之类的。

- Extract Text Plugin

把 CSS 从 JS 中的 import/reuqre 中取出来,放到一个单独的 CSS 文件中。

- HtmlWebpackPlugin

不用开发人员自己在 index.html 中加 bundle.js, bundle.css 等 output 文件,因为这可能是一个 hash 值,这个插件会帮你搞定。

效果:

1
2
3
<link href="/app.4683be2.css" rel="stylesheet"></head>
...
<script type="text/javascript" src="/app.2e17047c719b4525dc77.bundle.js"></script>

- CopyWebpackPlugin

拷贝资源插件
像用了 ant.design,这里也会产生一些文件。

Resolve

最常用的,就是 alias,给一个模块路径起上一个别名,这样在每次 import 时,可以少写很多代码。

Webpack DevServer

DevServer 是一个内建的 HTTP 服务器的独立程序,可通过 webpack-dev-server 命令启动,为开发时提供方便。

它也可以使用 webpack.config 文件来进行配置,或通过命令行参数来进行配置,但有点参数只能通过命令行参数。

一种是命令行配置:

1
$ webpack-dev-server --open --host 0.0.0.0 --port 5000

另一种是在 webpack.config.js 中加入配置项目

1
2
3
4
5
6
7
let config = {
devServer: {
contentBase: path.resolve(__dirname, 'src'),
historyApiFallback: true,
hot: true
}
}

Other Devtool/Externals

Devtool 主要是配置生成何种方式的 Source Mpas。


其它事项

ECMAScript 2015 new syntax

一个有着代码洁癖的人,是不会让整个项目中再出现 ES 2015 前风格的代码的,如何解决 webpack.config 呢?

其实有个很简单的办法,把 webpack.config.js 改名成 webpack.config.babel.js 就可以了。

Webpack 在执行时会先用 Babel 把配置文件转成 ES5 代码再继续处理。一切 Babel 支持的语言特性都可以用。


REF::


Git 201 - Multiple Users Config



公司用 git commit 来统计数据后,一台电脑上的 git 就有了多种配置。


方案一、单独配置

除了 global 外,每个 repo 都会有自己的配置项,可以进行单独配置。

1
$ git config user.name "Lanvige Jiang" && git config user.email lanvige@example.com

The values will then be stored in in the .git/config for that repo rather than your global configuration file.

原理是 add following information in your local .git/config file

1
2
3
[user]
name = Your Name
email = your.email@gmail.com

Check,确保

1
2
3
4
5
$ git config user.name
$ git config user.email
# 或者查看全部,包括 global 和 local
$ git config --list

但这个很繁琐,每个新项目都要设置一次,而且提交时没有报警,很容易忘记。


方案二、每次提交时带上配置

1
git -c user.name='Lanvige Jiang' -c user.email='lanvige@example.com' commit -m '...'

REF::

Koa2 Boilerplate

这是我整理的一个 koa2 + es7 的一个最佳实践,用了一些新的 Feature,完成了全部流程,从 request 到 service 和 DB(Sequlize)到 response。


Features

koa2 & koa-router

koa 相对于 express 更吸引开发者的地方莫过于 U 型 Middleware 机制。

Babel

目前 node v6 已经支持了绝大多数新的语法,http://node.green/

目前用下来只有两个 feature,就是 asyncFuncation 和 module,所以在配置项中,只需要开启这两项就够了。async 会被编译为 generater。

1
2
3
4
{
"presets": ["es2017"],
"sourceMaps": "both"
}

AsyncFuncation

通过 babel 来实现了 async-await (为了 async 的美可以做出任何牺牲)。

Module

ES 6 中模块化有一些显著的变化,像 import/export,具体见

标准已经制定:修改文件名后缀为 .mjs 但目前仍需要 babel 来转。

DI Container

因为没有模块,所以大量的引用散落在各处,一量修改,真的是痛不堪言。

DI 可以统一管理这些依赖,只需要修改一处,当然最大的好处莫过于解耦,便于测试。

这里用的是 Awilix

Environment

通过 yenv 来实现环境变量管理。

Sequlize

我们在项目中大量的使用了 Sequlize,也吐槽了很多,这里只是一个最简单的结合示例。


Directory structure

一般通过 node 创建的 web 项目,通用的作法是将源码等放在一个 src 的目录下,这样的好处是为了方便编译,感谢 babel,可以提前享受 ES 新语法。

后端项目也有一些这样的实践,但这里并没有采用,原因是随着 node 对标准的支持,在不久的将来,我们线上的代码是不再需要编译的。可以像 rails 一下直接运行(好期待那天)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.
├── app
│   ├── apis
│   ├── beapis
│   ├── models
│   ├── services
│   └── validators
├── bin
│   ├── _babel.js
│   └── server.js
├── config
│   ├── application.yml
│   ├── database.yml
│   └── redis.yml.example
├── db
├── lib
│   ├── createContainer.js
│   ├── createServer.js
│   └── middleware
├── .babelrc
├── Dockerfile
├── yarn.lock
└── package.json

当然目前还是需要编译的,这样就不需要在服务器上跑 babel-runtime。dist 是编译后的目录,通过 npm 对具体目录做了一些单独的编译。

  • app: 项目主要的业务逻辑代码。
    • api: 本层主要处理到达的请求,将参数做整理,然后交由 service 层。
    • services: 服务层从 repo 层取数据,然后拼接加工,最后返回 api 层。
    • model: 项目的 models。
  • bin: babel 需要一个启动文件。
  • config: 环境变量配置目录。
  • db: 数据库的一些资源。
  • dist: 编译后的文件。
  • lib: 一些系统类库,处理环境变量。和工具类。
    • middleware: middleware。
  • test: 测试用例。


npm run scripts

这里定义了一些常用的启动命令:

  • start: Used by the production environment to start the app. This will run a compiled version, so you need to execute build first.
  • build: Runs the babel CLI to compile the app. Files are emitted to dist/.
  • dev: Runs the app in development mode - uses babel-register to compile on-the-fly. Also uses nodemon to automatically restart when stuff changes.
  • debug: Runs the app in development mode with icebug (a combo of nodemon + node-inspector).
  • test: Runs mocha tests.
  • test-watch: Runs mocha tests in watch-mode.
  • lint: Lints the code in src and test with eslint.
  • lint-watch: Same as above, in watch-mode.

Tip: to pass additional arguments to the actual CLI’s being called, do it like in this example:

1
npm run test -- --debug

2017

正月15前的最后一个工作日,路上依然是假日状态的通畅,不过也是仅有的一天了。毕竟张江的道路已经堵了一周了。

谈谈正事吧,是时候跟旧的一年完全说再见,投入到新的一年中了。

做更好的自己

最近苦恼的事情,经常在一些地方发现白发,虽然少白已是事实,但掉的头发还几乎都是黑发。有种忽然老去的赶脚。这赶脚一来,影响了整个冬天。

有一种时光不再的感觉。忽然觉得过的很不够好,不够硬气,不够阳光。

看了下镜子,有种浪费身材的感觉。决定来年穿出精神来。

头发也是叭着,虽然白了一些,但更可怕的是没有精神。

做成一件小事情

这跟今年的年终奖有关,确实是伤心,毕竟努力了这一年,到头都没有个认可。可想想,这也许是技术人的共悲之处,有人说,三年技术,余下运营。在这个运营主导的公司,确实挺形象。

但,事实就是事实,今年的事实还会成为明年的现实。要这样吗。

所以,今天要做一件小事,当年,事情还不知道,只是有几个 side project 计划。

但凡坚持,总有回报。

MySQL - Users and Permissions

  1. 1. 1. MySQL 用户管理
    1. 1.1. 1.1 查看用户
      1. 1.1.1. > Host 中有两种情况 localhost, %
    2. 1.2. 1.2 创建用户
  2. 2. 2. 权限基本操作
    1. 2.1. 2.1 查看 root 的权限
    2. 2.2. 2.2 自定义用户的权限
      1. 2.2.1. 给 dbman 用户配置权限。
    3. 2.3. 2.3 验证
    4. 2.4. 2.4 删除用户
    5. 2.5. 2.5 Disable remote root logins into MySQL
  3. 3. 3. 权限的级别定义
  4. 4. REF::

MySQL 用户、权限基本操作


1. MySQL 用户管理

MySQL 的用户管理是在一张系统数据库 mysql > user 里进行管理的。

用户的操作,都是对该库该表进行操作。

1.1 查看用户

1
SELECT User, Host FROM mysql.user;
1
2
3
4
5
6
7
+--------+-----------+
| User | Host |
+--------+-----------+
| dbman | % |
| root | % |
| root | localhost |
+--------+-----------+

> Host 中有两种情况 localhost, %

  • localhost 表示只能本地登录
  • % 表示支持远程登录

1.2 创建用户

1
CREATE USER 'dbman'@'%' IDENTIFIED BY 'password';


2. 权限基本操作

因为一个用户在远程和本地登录时可以有不同的权限,所以这里查看权限时,要加上 Host 条件的。

2.1 查看 root 的权限

1
SHOW GRANTS FOR 'root'@'%';

显示 root 在远程访问中有着所有的权限。

1
2
3
4
5
+-------------------------------------------------------------+
| Grants for root@% |
+-------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION |
+-------------------------------------------------------------+

2.2 自定义用户的权限

给 dbman 用户配置权限。

1
2
3
4
5
6
7
8
9
10
11
-- 远程连接,所有数据库,所有权限
GRANT ALL PRIVILEGES ON *.* TO 'dbman'@'%';
-- 本地连接,指定数据库 (db_test),所有权限,并设连接密码
GRANT ALL PRIVILEGES ON db_test.* To 'dbman'@'localhost' IDENTIFIED BY 'password';
-- 远程连接,指定数据库,指定权限,并设连接密码
GRANT SELECT,UPDATE ON db_test.* To 'dbman'@'%' IDENTIFIED BY 'password';
-- After making changes to permissions/user accounts, make sure you flush the provilege tables using the following command:
FLUSH PRIVILEGES;

2.3 验证

1
SHOW GRANTS FOR 'dbman'@'%';
1
2
3
4
5
+------------------------------------+
| Grants for d2team@% |
+------------------------------------+
| GRANT USAGE ON *.* TO 'd2team'@'%' |
+------------------------------------+

2.4 删除用户

Just as you can delete databases with DROP, you can use DROP to delete a user altogether:

1
DROP USER ‘demo’@‘localhost’;

2.5 Disable remote root logins into MySQL

新的 DB 里都会给两个 root 的,一个是 % 另一个是 localhost,而 remote 是最危险的,别人可以通过该用户来进行攻击。

1
2
3
4
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
-- After making changes to permissions/user accounts, make sure you flush the provilege tables using the following command:
FLUSH PRIVILEGES;


3. 权限的级别定义

Here is a short list of other common possible permissions that users can enjoy.

  • ALL PRIVILEGES - as we saw previously, this would allow a MySQL user all access to a designated database (or if no database is selected, across the system)
  • CREATE - allows them to create new tables or databases
  • DROP - allows them to them to delete tables or databases
  • DELETE - allows them to delete rows from tables
  • INSERT - allows them to insert rows into tables
  • SELECT - allows them to use the Select command to read through databases
  • UPDATE - allow them to update table rows
  • GRANT OPTION - allows them to grant or remove other users’ privileges. To provide a specific user with a permission, you can use this framework:
1
GRANT [type of permission] ON [database name].[table name] TO ‘[username]’@'localhost’;


REF::

NAS

我觉得 双12 最大的做用是让人认清 双11 到底哪些东西没买后悔,哪些买了后悔。

于是在 0点0分,拿到了念念许久的 Synology 716+II

起因是网盘各家纷倒,最后百度也在限流,而且上传的东西不属于自己,也让人反感。

最后,这个小结写于一个月后,早已没有对设备的新鲜感,但更好的是可以有一些使用感受。

说到 NAS 有很多种方案

  • 在路由器上外挂个硬盘,现在就是这样做的,只是路由器把硬盘弄坏了。
  • 买个带功能的硬盘,像西数的 3T,价格便宜不少。
  • Synology,说实话买之前我不知道群晖有多好,而且价格超级贵。不过我只记得同事说的一句,群晖是卖软件的。

感受

群晖真的是卖软件的。

场景

个人有收藏照片,经典电影的习惯,虽然电影不怎么更新了,但照片的数量和大小是剧增。要感谢手机相机的提升。

之前,硬盘里的照片只是用来存的,而不是用来看的。没有功能,也就没有需求。

群晖中的一个功能,DS Photos,一下子打开了这种需求。因为无论是在手机上,电脑上,看照片太方便了。

然后就是由此产生的一堆的问题,比如照片归类,排序。之前一堆照片是没有用的,所以乱放也不知道,现在随便一点一看,全是问题。其实