This commit is contained in:
colben 2021-11-14 15:50:55 +08:00
parent f810ebf1d9
commit 915c231124
27 changed files with 1862 additions and 1890 deletions

View File

@ -34,7 +34,7 @@ RSTART | 被 match 匹配函数匹配的字符串位置
RLENGTH | 被 match 匹配函数匹配的字符串长度
# 函数
### 常用内置函数
## 常用内置函数
函数 | 说明
---- | ----
int(x) | 返回 x 的整数部分
@ -58,7 +58,7 @@ nextfile | 停止处理当前文件,开始处理下一个文件
system(shell-command) | 返回命令退出状态
exit n | 终止 awk返回 n
### 自定义函数
## 自定义函数
- 格式
```awk
function fun_name(arg1, arg2, ...){

View File

@ -8,9 +8,9 @@ categories: ["network"]
---
# bond 概要
### 什么是 bond
## 什么是 bond
- 网卡bond是通过把多张网卡绑定为一个逻辑网卡实现本地网卡的冗余带宽扩容和负载均衡。在应用部署中是一种常用的技术。
### bond的模式种类
## bond的模式种类
- Mode=0(balance-rr) 表示负载分担round-robin和交换机的聚合强制不协商的方式配合
- Mode=1(active-backup) 表示主备模式只有一块网卡是active,另外一块是备的standby
- **如果交换机配的是捆绑,将不能正常工作,因为交换机往两块网卡发包,有一半包是丢弃的**
@ -21,12 +21,12 @@ categories: ["network"]
- Mode=6(balance-alb) 在5的tlb基础上增加了rlb
# CentOS7 配置 bond
### 环境
## 环境
- 操作系统 CentOS7.6,禁用 NetworkManager 服务
- 物理网卡 eth0, eth1 绑定到 bond0
- 物理网卡 eth2, eth3 绑定到 bond1
### 网卡 eth0 配置
## 网卡 eth0 配置
- 修改 /etc/sysconfig/network-scripts/ifcfg-eth0
```
TYPE=Ethernet
@ -38,7 +38,7 @@ categories: ["network"]
MASTER=bond0
```
### 网卡 eth1 配置
## 网卡 eth1 配置
- 修改 /etc/sysconfig/network-scripts/ifcfg-eth1
```
TYPE=Ethernet
@ -50,7 +50,7 @@ categories: ["network"]
MASTER=bond0
```
### 网卡 eth2 配置
## 网卡 eth2 配置
- 修改 /etc/sysconfig/network-scripts/ifcfg-eth2
```
TYPE=Ethernet
@ -62,7 +62,7 @@ categories: ["network"]
MASTER=bond1
```
### 网卡 eth3 配置
## 网卡 eth3 配置
- 修改 /etc/sysconfig/network-scripts/ifcfg-eth3
```
TYPE=Ethernet
@ -74,7 +74,7 @@ categories: ["network"]
MASTER=bond1
```
### 增加网卡 bond0 配置
## 增加网卡 bond0 配置
- 创建 /etc/sysconfig/network-scripts/ifcfg-bond0
```
TYPE=Ethernet
@ -88,7 +88,7 @@ categories: ["network"]
DNS1=114.114.114.114
```
### 增加网卡 bond1 配置
## 增加网卡 bond1 配置
- 创建 /etc/sysconfig/network-scripts/ifcfg-bond1
```
TYPE=Ethernet
@ -102,7 +102,7 @@ categories: ["network"]
#DNS1=114.114.114.114
```
### 配置绑定模式
## 配置绑定模式
- 创建 /etc/modprobe.d/bonding.conf加入以下内容
```
alias bond0 bonding
@ -110,13 +110,13 @@ categories: ["network"]
options bonding miimon=100 mode=1
```
### 载入 bonding 模块,重启 network 服务
## 载入 bonding 模块,重启 network 服务
```bash
modprob bonding
systemctl restart network
```
### 查看网卡绑定状态
## 查看网卡绑定状态
```bash
cat /proc/net/bonding/bond0
cat /proc/net/bonding/bond1

View File

@ -32,6 +32,7 @@ useradd -g oinstall -m oracle
#export NLS_LANG="SIMPLIFIED CHINESE_CHINA.AL32UTF8" #设置Oracle客户端中文utf8
export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK #设置Oracle客户端中文gbk
```
- 使设置立刻生效
```bash
source /.bashrc
@ -55,6 +56,7 @@ chown oracle.oinstall /opt/oracle -R
net.core.wmem_max = 1048576
kernel.sem = 250 32000 100 128
```
- 使设置生效
```bash
sysctl -p
@ -84,12 +86,14 @@ chown oracle.oinstall /opt/oracle -R
unzip linux.x64_11gR2_database_2of2.zip -d /home/oracle/
chown oracle.oinstall /home/oracle/database/ -R
```
- **切换到 oracle 用户下**,运行安装程序
```bash
su - oracle
cd database
./runInstaller
```
- 若提示swap空间不足自行百度解决
# 配置监听器数据库
@ -97,11 +101,13 @@ chown oracle.oinstall /opt/oracle -R
```
netca
```
- 在图形界面中按提示配置监听器
- 执行 dbca 命令安装数据库
```bash
dbca
```
- 在图形界面中按提示安装数据库就可以了。
# 测试运行
@ -111,6 +117,7 @@ dbca
lsnrctl stop
lsnrctl start
```
- 停止和启动实例
```
sqlplus /nolog

View File

@ -1,114 +0,0 @@
---
title: "搭建 Git http 服务"
date: 2019-10-30T17:35:56+08:00
lastmod: 2019-10-30T17:35:56+08:00
tags: ["git", "nginx", "http", "fcgiwrap", "spawn-fcgi"]
categories: ["dev/ops"]
---
# 环境
- Centos/Redhat 6
- 安装好 git
# 安装 fcgiwrap
- 参考 https://github.com/gnosek/fcgiwrap
![](/img/150546_2jE9_2298475.png)
# 安装 spawn-fcgi
- 参考 https://github.com/lighttpd/spawn-fcgi
![](/img/150655_jGEp_2298475.png)
# 编辑 spawn-fcgi/sbin/fcgiwrap 开机启动脚本:
```bash
#! /bin/sh
DESC="fcgiwrap daemon"
DEAMON=/opt/spawn-fcgi/bin/spawn-fcgi
PIDFILE=/tmp/spawn-fcgi.pid
# fcgiwrap socket
FCGI_SOCKET=/tmp/fcgiwrap.socket
# fcgiwrap 可执行文件
FCGI_PROGRAM=/opt/fcgiwrap/sbin/fcgiwrap
# fcgiwrap 执行的用户和用户组
FCGI_USER=nobody
FCGI_GROUP=nobody
FCGI_EXTRA_OPTIONS="-M 0770"
OPTIONS="-u $FCGI_USER -g $FCGI_GROUP -s $FCGI_SOCKET -S $FCGI_EXTRA_OPTIONS -F 1 -P $PIDFILE -- $FCGI_PROGRAM"
do_start() {
$DEAMON $OPTIONS || echo -n "$DESC already running"
}
do_stop() {
kill -INT `cat $PIDFILE` || echo -n "$DESC not running"
}
case "$1" in
start)
echo -n "Starting $DESC: $NAME"
do_start
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME"
do_stop
echo "."
;;
restart)
echo -n "Restarting $DESC: $NAME"
do_stop
do_start
echo "."
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
exit 3
;;
esac
exit 0
```
# 启动 fcgiwrap
```bash
chmod 0755 /opt/spawn-fcgi/sbin/fcgiwrap
/opt/spawn-fcgi/sbin/fcgiwrap start
```
# 安装 nginx
- 参考 http://nginx.org/en/download.html启动 nginx
# 在 nginx 前端目录 html 下创建 git 仓库目录 nginx/html/git/
```bash
mkdir /opt/nginx/html/git/
chown nobody.nobody /opt/nginx/html/git/ -R
```
# 配置 nginx 的 git 服务
```nginx
# 在 server section 中添加 git
location ~ /git(/.*) {
gzip off;
fastcgi_pass unix:/tmp/fcgiwrap.socket;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /usr/libexec/git-core/git-http-backend;
fastcgi_param GIT_HTTP_EXPORT_ALL "";
fastcgi_param GIT_PROJECT_ROOT /opt/nginx/html/git;
fastcgi_param PATH_INFO $1;
fastcgi_param REMOTE_USER $remote_user;
client_max_body_size 500m;
}
```
# 重新加载配置文件
```bash
/opt/nginx/sbin/nginx -s reload
```
# 测试在仓库目录下新建一个空repo
```bash
cd /opt/nginx/html/git/
git init --bare test-repo
chown nobody.nobody test-repo -R
cd test-repo
git config http.reveivepack true
```
# 完成
- 在另一台服务器中可以顺利的进行 clone、push 及 pull 等操作。

View File

@ -9,7 +9,7 @@ categories: ["container"]
# kubeadm 安装 kubernetes
### 全部服务器配置
## 全部服务器配置
IP 地址 | 主机名 | 操作系统 | 内存 | swap | 硬盘 | Internet | firewalld | selinux | /etc/hosts 增加行
--------- | -------- | -------- | ---- | ---- | ---- | -------- | --------- | ------- | ------------------
10.0.2.80 | master80 | CentOS7 | 4GB | 关闭 | 20GB | 可达 | 关闭 | 关闭 | 127.0.0.1 master80
@ -76,7 +76,7 @@ categories: ["container"]
```
### 安装 docker
## 安装 docker
- 各服务器安装 docker
```bash
yum install docker
@ -106,7 +106,7 @@ categories: ["container"]
```
### 安装 kubernetes
## 安装 kubernetes
- 各服务器配置 kubernetes yum 源
```bash
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
@ -132,7 +132,7 @@ categories: ["container"]
```
### 在 master80 服务器上安装 kubernetes master 服务组件
## 在 master80 服务器上安装 kubernetes master 服务组件
- 初始化 kubeadm
```bash
kubeadm init --pod-network-cidr=192.168.0.0/16 --token-ttl 0
@ -148,7 +148,7 @@ categories: ["container"]
```
### 加入其他节点
## 加入其他节点
- 在 node81 和 node82 服务器上执行以下命令,即 master80 服务器 'kuberadm init' 命令的最后一行输出
```bash
kubeadm join --token <token> <master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash>

View File

@ -7,7 +7,7 @@ tags: ["letsencrypt", "certbot", "ssl"]
categories: ["web"]
---
## 安装 certbot
# 安装 certbot
- 在 alpine linux 中安装 certbot
```bash
apk add --no-cache certbot openssl
@ -18,7 +18,7 @@ categories: ["web"]
certbot register --register-unsafely-without-email --agree-tos
```
## 普通域名证书
# 普通域名证书
- 申请 ssl 证书,有效期 90 天
```bash
certbot certonly -n -d x.x.com --standalone
@ -38,7 +38,7 @@ categories: ["web"]
openssl dhparam -out /etc/letsencrypt/dhparam.pem 2048
```
## 通配域名证书
# 通配域名证书
- 申请 ssl 证书,有效期 90 天
```bash
certbot certonly --manual -d '*.x.com' \
@ -61,7 +61,7 @@ categories: ["web"]
openssl dhparam -out /etc/letsencrypt/dhparam.pem 2048
```
## 使用证书
# 使用证书
- nginx 配置 ssl
```
server {

View File

@ -20,7 +20,7 @@ categories: ["storage"]
- iops: 每秒 I/O 的次数
# 同步写测试
### 同步随机写
## 同步随机写
- 使用strace工具查看系统调用
```bash
strace -f -tt -o /tmp/randwrite.log -D fio -name=randwrite -rw=randwrite \
@ -82,7 +82,7 @@ categories: ["storage"]
...
```
### 同步顺序写
## 同步顺序写
- 测试顺序写
```bash
strace -f -tt -o /tmp/write.log -D fio -name=write -rw=write \

View File

@ -7,7 +7,7 @@ categories: ["dev/ops"]
---
# Makefile 介绍
### 介绍
## 介绍
- make命令执行时需要一个 Makefile 文件以告诉make命令需要怎么样的去编译和链接程序。
- 首先我们用一个示例来说明Makefile的书写规则。以便给大家一个感兴认识。这个示例来源于GNU的make使用手册在这个示例中我们的工程有8个C文件和3个头文件我们要写一个Makefile来告诉make命令如何编译和链接这几个文件。我们的规则是
- 如果这个工程没有编译过那么我们的所有C文件都要编译并被链接。
@ -15,7 +15,7 @@ categories: ["dev/ops"]
- 如果这个工程的头文件被改变了那么我们需要编译引用了这几个头文件的C文件并链接目标程序。
- 只要我们的Makefile写得够好所有的这一切我们只用一个make命令就可以完成make命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译从而自己编译所需要的文件和链接目标程序。
### Makefile的规则
## Makefile的规则
- 在讲述这个Makefile之前还是让我们先来粗略地看一看Makefile的规则。
```makefile
target... : prerequisites ...
@ -28,7 +28,7 @@ categories: ["dev/ops"]
- command 也就是make需要执行的命令任意的Shell命令
- 这是一个文件的依赖关系也就是说target这一个或多个的目标文件依赖于prerequisites中的文件其生成规则定义在command中。说白一点就是说prerequisites中如果有一个以上的文件比target文件要新的话command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。
### 一个示例
## 一个示例
- 正如前面所说的如果一个工程有3个头文件和8个C文件我们为了完成前面所述的那三个规则我们的Makefile应该是下面的这个样子的。
```makefile
edit : main.o kbd.o command.o display.o \
@ -61,7 +61,7 @@ categories: ["dev/ops"]
- 在定义好依赖关系后后续的那一行定义了如何生成目标文件的操作系统命令一定要以一个Tab键作为开头。记住make并不管命令是怎么工作的他只管执行所定义的命令。make会比较targets文件和prerequisites文件的修改日期如果prerequisites文件的日期要比targets文件的日期要新或者target不存在的话那么make就会执行后续定义的命令。
- 这里要说明一点的是clean不是一个文件它只不过是一个动作名字有点像C语言中的lable一样其冒号后什么也没有那么make就不会自动去找文件的依赖性也就不会自动执行其后所定义的命令。要执行其后的命令就要在make命令后明显得指出这个lable的名字。这样的方法非常有用我们可以在一个makefile中定义不用的编译或是和编译无关的命令比如程序的打包程序的备份等等。
### make 是如何工作的
## make 是如何工作的
- 在默认的方式下也就是我们只输入make命令。那么
- make会在当前目录下找名字叫"Makefile"或"makefile"的文件。
- 如果找到它会找文件中的第一个目标文件target在上面的例子中他会找到"edit"这个文件,并把这个文件作为最终的目标文件。
@ -73,7 +73,7 @@ categories: ["dev/ops"]
- 于是在我们编程中如果这个工程已被编译过了当我们修改了其中一个源文件比如file.c那么根据我们的依赖性我们的目标file.o会被重编译也就是在这个依性关系后面所定义的命令于是file.o的文件也是最新的啦于是file.o的文件修改时间要比edit要新所以edit也会被重新链接了详见edit目标文件后定义的命令
而如果我们改变了"command.h"那么kdb.o、command.o和files.o都会被重编译并且edit会被重链接。
### makefile中使用变量
## makefile中使用变量
- 在上面的例子中先让我们看看edit的规则
```makefile
edit : main.o kbd.o command.o display.o \
@ -114,7 +114,7 @@ categories: ["dev/ops"]
```
- 如果有新的 .o 文件加入,我们只需简单地修改一下 objects 变量就可以了。
### 让make自动推导
## 让make自动推导
- GNU的make很强大它可以自动推导文件以及文件依赖关系后面的命令于是我们就没必要去在每一个[.o]文件后都写上类似的命令因为我们的make会自动识别并自己推导命令。
- 只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中如果make找到一个whatever.o那么whatever.c就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来于是我们的makefile再也不用写得这么复杂。我们的是新的makefile又出炉了。
```makefile
@ -139,7 +139,7 @@ categories: ["dev/ops"]
```
- 这种方法也就是make的"隐晦规则"。上面文件内容中,".PHONY"表示clean是个伪目标文件。
### 另类风格的makefile
## 另类风格的makefile
- 既然我们的make可以自动推导命令那么我看到那堆[.o]和[.h]的依赖就有点不爽,那么多的重复的[.h]能不能把其收拢起来好吧没有问题这个对于make来说很容易谁叫它提供了自动推导命令和文件的功能呢来看看最新风格的makefile吧。
```makefile
objects = main.o kbd.o command.o display.o \
@ -158,7 +158,7 @@ categories: ["dev/ops"]
```
- 这种风格让我们的makefile变得很简单但我们的文件依赖关系就显得有点凌乱了。鱼和熊掌不可兼得。还看你的喜好了
### 清空目标文件的规则
## 清空目标文件的规则
- 每个Makefile中都应该写一个清空目标文件.o和执行文件的规则这不仅便于重编译也很利于保持文件的清洁。这是一个"修养"(呵呵,还记得我的《编程修养》吗)。一般的风格都是:
```makefile
clean:
@ -174,7 +174,7 @@ categories: ["dev/ops"]
# Makefile 总述
### Makefile里有什么
## Makefile里有什么
- Makefile里主要包含了五个东西显式规则、隐晦规则、变量定义、文件指示和注释。
- 显式规则。显式规则说明了如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出要生成的文件文件的依赖文件生成的命令。
- 隐晦规则。由于我们的make有自动推导的功能所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile这是由make所支持的。
@ -183,11 +183,11 @@ categories: ["dev/ops"]
- 注释。Makefile中只有行注释和UNIX的Shell脚本一样其注释是用"#"字符这个就像C/C++中的"//"一样。如果你要在你的Makefile中使用"#"字符,可以用反斜框进行转义,如:"\#"。
- 最后还值得一提的是在Makefile中的命令必须要以[Tab]键开始。
### Makefile的文件名
## Makefile的文件名
- 默认的情况下make命令会在当前目录下按顺序找寻文件名为"GNUmakefile"、"makefile"、"Makefile"的文件,找到了解释这个文件。在这三个文件名中,最好使用"Makefile"这个文件名,因为,这个文件名第一个字符为大写,这样有一种显目的感觉。最好不要用"GNUmakefile"这个文件是GNU的make识别的。有另外一些make只对全小写的"makefile"文件名敏感但是基本上来说大多数的make都支持"makefile"和"Makefile"这两种默认文件名。
- 当然你可以使用别的文件名来书写Makefile比如"Make.Linux""Make.Solaris""Make.AIX"等如果要指定特定的Makefile你可以使用make的"-f"和"--file"参数make -f Make.Linux或make --file Make.AIX。
### 引用其它的Makefile
## 引用其它的Makefile
- 在Makefile使用include关键字可以把别的Makefile包含进来这很像C语言的#include被包含的文件会原模原样的放在当前文件的包含位置。include的语法是
```makefile
include<filename>filename可以是当前操作系统Shell的文件模式可以保含路径和通配符
@ -209,11 +209,11 @@ categories: ["dev/ops"]
```
- 其表示无论include过程中出现什么错误都不要报错继续执行。和其它版本make兼容的相关命令是sinclude其作用和这一个是一样的。
### 环境变量 MAKEFILES
## 环境变量 MAKEFILES
- 如果你的当前环境中定义了环境变量MAKEFILES那么make会把这个变量中的值做一个类似于include的动作。这个变量中的值是其它的Makefile用空格分隔。只是它和include不同的是从这个环境变中引入的Makefile的"目标"不会起作用如果环境变量中定义的文件发现错误make也会不理。
- 但是在这里我还是建议不要使用这个环境变量因为只要这个变量一被定义那么当你使用make时所有的Makefile都会受到它的影响这绝不是你想看到的。在这里提这个事只是为了告诉大家也许有时候你的Makefile出现了怪事那么你可以看看当前环境中有没有定义这个变量。
### make的工作方式
## make的工作方式
- GNU的make工作时的执行步骤入下
- 读入所有的Makefile。
- 读入被include的其它Makefile。
@ -226,12 +226,12 @@ categories: ["dev/ops"]
- 当然这个工作方式你不一定要清楚但是知道这个方式你也会对make更为熟悉。有了这个基础后续部分也就容易看懂了。
# Makefile书写规则
### 规则
## 规则
- 规则包含两个部分,一个是依赖关系,一个是生成目标的方法。
- 在Makefile中规则的顺序是很重要的因为Makefile中只应该有一个最终目标其它的目标都是被这个目标所连带出来的所以一定要让make知道你的最终目标是什么。一般来说定义在Makefile中的目标可能会有很多但是第一条规则中的目标将被确立为最终的目标。如果第一条规则中的目标有很多个那么第一个目标会成为最终的目标。make所完成的也就是这个目标。
- 好了,还是让我们来看一看如何书写规则。
### 规则举例
## 规则举例
```makefile
foo.o: foo.c defs.h # foo模块
cc -c -g foo.c
@ -240,7 +240,7 @@ categories: ["dev/ops"]
- 文件的依赖关系foo.o依赖于foo.c和defs.h的文件如果foo.c和defs.h的文件日期要比foo.o文件日期要新或是foo.o不存在那么依赖关系发生。
- 如果生成或更新foo.o文件。也就是那个cc命令其说明了如何生成foo.o这个文件。当然foo.c文件include了defs.h文件
### 规则的语法
## 规则的语法
```makefile
targets : prerequisites
command
@ -258,7 +258,7 @@ categories: ["dev/ops"]
- 如果命令太长,你可以使用反斜框(‘\作为换行符。make对一行上有多少个字符没有限制。规则告诉make两件事文件的依赖关系和如何成成目标文件。
- 一般来说make会以UNIX的标准Shell也就是/bin/sh来执行命令。
### 在规则中使用通配符
## 在规则中使用通配符
- 如果我们想定义一系列比较类似的文件我们很自然地就想起使用通配符。make支持三各通配符"\*""?"和"[...]"。这是和Unix的B-Shell是相同的。
- "~" 波浪号("~")字符在文件名中也有比较特殊的用途。如果是"~/test",这就表示当前用户的$HOME目录下的test目录。而"~hchen/test"则表示用户hchen的宿主目录下的test目录。这些都是Unix下的小知识了make也支持而在Windows或是MS-DOS下用户没有宿主目录那么波浪号所指的目录则根据环境变量"HOME"而定。
- "\*" 通配符代替了你一系列的文件,如"\*.c"表示所以后缀为c的文件。一个需要我们注意的是如果我们的文件名中有通配符"\*",那么可以用转义字符"\",如"\*"来表示真实的"\*"字符,而不是任意长度的字符串。
@ -283,7 +283,7 @@ categories: ["dev/ops"]
```
- 这种用法由关键字"wildcard"指出关于Makefile的关键字我们将在后面讨论。
### 文件搜寻
## 文件搜寻
- 在一些大的工程中有大量的源文件我们通常的做法是把这许多的源文件分类并存放在不同的目录中。所以当make需要去找寻文件的依赖关系时你可以在文件前加上路径但最好的方法是把一个路径告诉make让make在自动去找。
- Makefile文件中的特殊变量"VPATH"就是完成这个功能的如果没有指明这个变量make只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量那么make就会在当当前目录找不到的情况下到所指定的目录中去找寻文件了。
```makefile
@ -312,7 +312,7 @@ categories: ["dev/ops"]
```
- 而上面的语句则表示".c"结尾的文件,先在"foo"目录,然后是"bar"目录,最后才是"blish"目录。
### 伪目标
## 伪目标
- 最早先的一个例子中,我们提到过一个"clean"的目标,这是一个"伪目标"
```makefile
clean:
@ -360,7 +360,7 @@ categories: ["dev/ops"]
```
- "makeclean"将清除所有要被清除的文件。"cleanobj"和"cleandiff"这两个伪目标有点像"子程序"的意思。我们可以输入"makecleanall"和"make cleanobj"和"makecleandiff"命令来达到清除不同种类文件的目的
### 多目标
## 多目标
- Makefile的规则中的目标可以不止一个其支持多目标有可能我们的多个目标同时依赖于一个文件并且其生成的命令大体类似。于是我们就能把其合并起来。当然多个目标的生成规则的执行命令是同一个这可能会可我们带来麻烦不过好在我们的可以使用一个自动化变量"$@"(关于自动化变量,将在后面讲述),这个变量表示着目前规则中所有的目标的集合,这样说可能很抽象,还是看一个例子吧。
```makefile
bigoutput littleoutput : text.g
@ -375,7 +375,7 @@ categories: ["dev/ops"]
```
- 其中,-$(subst output,,$@)中的"$"表示执行一个Makefile的函数函数名为subst后面的为参数。关于函数将在后面讲述。这里的这个函数是截取字符串的意思"$@"表示目标的集合,就像一个数组,"$@"依次取出目标,并执于命令。
### 静态模式
## 静态模式
- 静态模式可以更加容易地定义多目标的规则,可以让我们的规则变得更加的有弹性和灵活。我们还是先来看一下语法:
```makefile
<targets...>: <target-pattern>: <prereq-patterns ...>
@ -414,7 +414,7 @@ categories: ["dev/ops"]
```
- $(filter%.o,$(files))表示调用Makefile的filter函数过滤"$filter"集,只要其中模式为"%.o"的内容。其的它内容我就不用多说了吧。这个例字展示了Makefile中更大的弹性。
### 自动生成依赖性
## 自动生成依赖性
- 在Makefile中我们的依赖关系可能会需要包含一系列的头文件比如如果我们的main.c中有一句"#include "defs.h"",那么我们的依赖关系应该是:
```makefile
main.o : main.c defs.h
@ -477,11 +477,11 @@ categories: ["dev/ops"]
- 上述语句中的"$(sources:.c=.d)"中的".c=.d"的意思是做一个替换,把变量$(sources)所有[.c]的字串都替换成[.d],关于这个"替换"的内容在后面我会有更为详细的讲述。当然你得注意次序因为include是按次来载入文件最先载入的[.d]文件中的目标会成为默认目标
# Makefile 书写命令
### 命令
## 命令
- 每条规则中的命令和操作系统Shell的命令行是一致的。make会一按顺序一条一条的执行命令每条命令的开头必须以[Tab]键开头除非命令是紧跟在依赖规则后面的分号后的。在命令行之间中的空格或是空行会被忽略但是如果该空格或空行是以Tab键开头的那么make会认为其是一个空命令。
- 我们在UNIX下可能会使用不同的Shell但是make的命令默认是被"/bin/sh" UNIX的标准Shell解释执行的。除非你特别指定一个其它的Shell。Makefile中"#"是注释符很像C/C++中的"//",其后的本行字符都被注释。
### 显示命令
## 显示命令
- 通常make会把其要执行的命令行在命令执行前输出到屏幕上。当我们用"@"字符在命令行前那么这个命令将不被make显示出来最具代表性的例子是我们用这个功能来像屏幕显示一些信息。如
```makefile
@echo 正在编译XXX模块......
@ -494,7 +494,7 @@ categories: ["dev/ops"]
- 如果make执行时带入make参数"-n"或"--just-print"那么其只是显示命令但不会执行命令这个功能很有利于我们调试我们的Makefile看看我们书写的命令是执行起来是什么样子的或是什么顺序的。
- make参数"-s"或"--slient"则是全面禁止命令的显示。
### 命令执行
## 命令执行
- 当依赖目标新于目标时也就是当规则的目标需要被更新时make会一条一条的执行其后的命令。需要注意的是如果你要让上一条命令的结果应用在下一条命令时你应该使用分号分隔这两条命令。比如你的第一条命令是cd命令你希望第二条命令得在cd之后的基础上运行那么你就不能把这两条命令写在两行上而应该把这两条命令写在一行上用分号分隔。如
```makefile
# 示例一:
@ -509,7 +509,7 @@ categories: ["dev/ops"]
- 当我们执行"make exec"时第一个例子中的cd没有作用pwd会打印出当前的Makefile目录而第二个例子中cd就起作用了pwd会打印出"/home/hchen"。
- make 一般是使用环境变量SHELL中所定义的系统Shell来执行命令默认情况下使用UNIX的标准Shell /bin/sh来执行命令。但在MS-DOS下有点特殊因为MS-DOS下没有SHELL环境变量当然你也可以指定。如果你指定了UNIX风格的目录形式首先make会在SHELL所指定的路径中找寻命令解释器如果找不到其会在当前盘符中的当前目录中寻找如果再找不到其会在PATH环境变量中所定义的所有路径中寻找。MS-DOS中如果你定义的命令解释器没有找到其会给你的命令解释器加上诸如".exe"、".com"、".bat"、".sh"等后缀。
### 命令出错
## 命令出错
- 每当命令运行完后make会检测每个命令的返回码如果命令返回成功那么make会执行下一条命令当规则中所有的命令成功返回后这个规则就算是成功完成了。如果一个规则中的某个命令出错了命令退出码非零那么make就会终止执行当前规则这将有可能终止所有规则的执行。
- 有些时候命令的出错并不表示就是错误的。例如mkdir命令我们一定需要建立一个目录如果目录不存在那么mkdir就成功执行万事大吉如果目录存在那么就出错了。我们之所以使用mkdir的意思就是一定要有这样的一个目录于是我们就不希望mkdir出错而终止规则的运行。
- 为了做到这一点忽略命令的出错我们可以在Makefile的命令行前加一个减号"-"在Tab键之后标记为不管命令出不出错都认为是成功的。如
@ -520,7 +520,7 @@ categories: ["dev/ops"]
- 还有一个全局的办法是给make加上"-i"或是"--ignore-errors"参数那么Makefile中所有命令都会忽略错误。而如果一个规则是以".IGNORE"作为目标的,那么这个规则中的所有命令将会忽略错误。这些是不同级别的防止命令出错的方法,你可以根据你的不同喜欢设置。
- 还有一个要提一下的make的参数的是"-k"或是"--keep-going",这个参数的意思是,如果某规则中的命令出错了,那么就终目该规则的执行,但继续执行其它规则。
### 嵌套执行make
## 嵌套执行make
- 在一些大的工程中我们会把我们不同模块或是不同功能的源文件放在不同的目录中我们可以在每个目录中都书写一个该目录的Makefile这有利于让我们的Makefile变得更加地简洁而不至于把所有的东西全部写在一个Makefile中这样会很难维护我们的Makefile这个技术对于我们模块编译和分段编译有着非常大的好处。
- 例如我们有一个子目录叫subdir这个目录下有个Makefile文件来指明了这个目录下文件的编译规则。那么我们总控的Makefile可以这样书写
```makefile
@ -579,7 +579,7 @@ categories: ["dev/ops"]
```
- 当你使用"-C"参数来指定make下层Makefile时"-w"会被自动打开的。如果参数中有"-s""--slient")或是"--no-print-directory",那么,"-w"总是失效的。
### 定义命令包
## 定义命令包
- 如果Makefile中出现一些相同命令序列那么我们可以为这些相同的命令序列定义一个变量。定义这种命令序列的语法以"define"开始,以"endef"结束,如:
```makefile
define run-yacc
@ -596,7 +596,7 @@ categories: ["dev/ops"]
- 在 Makefile中的定义的变量就像是C/C++语言中的宏一样他代表了一个文本字串在Makefile中执行的时候其会自动原模原样地展开在所使用的地方。其与C/C++所不同的是你可以在Makefile中改变其值。在Makefile中变量可以使用在"目标""依赖目标""命令"或是 Makefile的其它部分中。变量的命名字可以包含字符、数字下划线可以是数字开头但不应该含有":"、"#"、"="或是空字符(空格、回车等)。变量是大小写敏感的,"foo"、"Foo"和"FOO"是三个不同的变量名。传统的Makefile的变量名是全大写的命名方式但我推荐使用大小写搭配的变量名MakeFlags。这样可以避免和系统的变量冲突而发生意外的事情。有一些变量是很奇怪字串如"$<"、"$@"等,这些是自动化变量。
# 变量
### 变量的基础
## 变量的基础
- 变量在声明时需要给予初值,而在使用时,需要给在变量名前加上"$"符号,但最好用小括号""或是大括号"{}"把变量给包括起来。如果你要使用真实的"$"字符,那么你需要用"$$"来表示。变量可以使用在许多地方,如规则中的"目标"、"依赖"、"命令"以及新的变量中。
- 先看一个例子:
```makefile
@ -619,7 +619,7 @@ categories: ["dev/ops"]
```
- 当然千万不要在你的Makefile中这样干这里只是举个例子来表明Makefile中的变量在使用处展开的真实样子。可见其就是一个"替代"的原理。另外,给变量加上括号完全是为了更加安全地使用这个变量,在上面的例子中,如果你不想给变量加上括号,那也可以,但我还是强烈建议你给变量加上括号。
### 变量中的变量
## 变量中的变量
- 在定义变量的值时我们可以使用其它变量来构造变量的值在Makefile中有两种方式来在用变量定义变量的值。
- 先看第一种方式,也就是简单的使用"="号,在"="左侧是变量,右侧是变量的值,右侧变量的值可以定义在文件的任何一处,也就是说,右侧中的变量不一定非要是已定义好
的值,其也可以使用后面定义的值。如:
@ -694,7 +694,7 @@ categories: ["dev/ops"]
endif
```
### 变量高级用法
## 变量高级用法
- 这里介绍两种变量的高级使用方法,第一种是变量值的替换。
- 我们可以替换变量中的共有的部分,其格式是"$(var:a=b)"或是"${var:a=b}",其意思是,把变量"var"中所有以"a"字串"结尾"的"a"替换成"b"字串。这里的"结尾"意思是"空格"或是"结束符"。
- 还是看一个示例吧:
@ -779,7 +779,7 @@ categories: ["dev/ops"]
```
- 这个例子中定义了三个变量:"dir""foo_sources"和"foo_print"。
### 追加变量值
## 追加变量值
- 我们可以使用"+="操作符给变量追加值,如:
```makefile
objects = main.o foo.o bar.o utils.o
@ -809,7 +809,7 @@ categories: ["dev/ops"]
```
- 由于前次的赋值符是"=",所以"+="也会以"="来做为赋值那么岂不会发生变量的递补归定义这是很不好的所以make会自动为我们解决这个问题我们不必担心这个问题。
### override 指示符
## override 指示符
- 如果有变量是通常make的命令行参数设置的那么Makefile中对这个变量的赋值会被忽略。如果你想在Makefile中设置这类参数的值那么你可以使用"override"指示符。其语法是:
```makefile
override <variable> = <value>
@ -826,7 +826,7 @@ categories: ["dev/ops"]
endef
```
### 多行变量
## 多行变量
- 还有一种设置变量值的方法是使用define关键字。使用define关键字设置变量的值可以有换行这有利于定义一系列的命令前面我们讲过"命令包"的技术就是利用这个关键字)。
- define 指示符后面跟的是变量的名字而重起一行定义变量的值定义是以endef关键字结束。其工作方式和"="操作符一样。变量的值可以包含函数、命令、文字,或是其它变量。因为命令需要以[Tab]键开头所以如果你用define定义的命令变量中没有以[Tab]键开头那么make就不会把其认为是命令。
- 下面的这个示例展示了define的用法
@ -837,12 +837,12 @@ categories: ["dev/ops"]
endef
```
### 环境变量
## 环境变量
- make 运行时的系统环境变量可以在make开始运行时被载入到Makefile文件中但是如果Makefile中已定义了这个变量或是这个变量由make命令行带入那么系统的环境变量的值将被覆盖。如果make指定了"-e"参数那么系统环境变量将覆盖Makefile中定义的变量
- 因此,如果我们在环境变量中设置了"CFLAGS"环境变量那么我们就可以在所有的Makefile中使用这个变量了。这对于我们使用统一的编译参数有比较大的好处。如果Makefile中定义了CFLAGS那么则会使用Makefile中的这个变量如果没有定义则使用系统环境变量的值一个共性和个性的统一很像"全局变量"和"局部变量"的特性。 当make嵌套调用时参见前面的"嵌套调用"章节上层Makefile中定义的变量会以系统环境变量的方式传递到下层的Makefile中。当然默认情况下只有通过命令行设置的变量会被传递。而定义在文件中的变量如果要向下层 Makefile传递则需要使用exprot关键字来声明。参见前面章节
- 当然我并不推荐把许多的变量都定义在系统环境中这样在我们执行不用的Makefile时拥有的是同一套系统变量这可能会带来更多的麻烦。
### 目标变量
## 目标变量
- 前面我们所讲的在Makefile中定义的变量都是"全局变量",在整个文件,我们都可以访问这些变量。当然,"自动化变量"除外,如"$<"等这种类量的自动化变量就属于"规则型变量",这种变量的值依赖于规则的目标和依赖目标的定义。
- 当然,我样同样可以为某个目标设置局部变量,这种变量被称为"Target-specific Variable",它可以和"全局变量"同名,因为它的作用范围只在这条规则以及连带规则中,所以其值也只在作用范围内有效。而不会影响规则链以外的全局变量的值。
- 其语法是:
@ -867,7 +867,7 @@ categories: ["dev/ops"]
```
- 在这个示例中,不管全局的$(CFLAGS)的值是什么在prog目标以及其所引发的所有规则中prog.o foo.o bar.o的规则$(CFLAGS)的值都是"-g"
### 模式变量
## 模式变量
- 在GNU的make中还支持模式变量Pattern-specific Variable通过上面的目标变量中我们知道变量可以定义在某个目标上。模式变量的好处就是我们可以给定一种"模式",可以把变量定义在符合这种模式的所有目标上。
- 我们知道make的"模式"一般是至少含有一个"%"的,所以,我们可以以如下方式给所有以[.o]结尾的目标定义目标变量:
```makefile
@ -881,7 +881,7 @@ categories: ["dev/ops"]
- override同样是针对于系统环境传入的变量或是make命令行指定的变量。
# 条件判断
### 一个例子
## 一个例子
- 下面的例子,判断$(CC)变量是否"gcc"如果是的话则使用GNU函数编译目标。
```makefile
libs_for_gcc = -lgnu
@ -921,7 +921,7 @@ categories: ["dev/ops"]
$(CC) -o foo $(objects) $(libs)
```
### 语法
## 语法
- 条件表达式的语法为:
```makefile
<conditional-directive>
@ -995,7 +995,7 @@ categories: ["dev/ops"]
# 函数
### 函数的调用语法
## 函数的调用语法
- 函数调用,很像变量的使用,也是以"$"来标识的,其语法如下:
```makefile
$(<function> <arguments> )
@ -1015,8 +1015,8 @@ categories: ["dev/ops"]
```
- 在这个示例中,$(comma)的值是一个逗号。$(space)使用了$(empty)定义了一个空格,$(foo)的值是"a b c"$(bar)的定义用,调用了函数"subst",这是一个替换函数,这个函数有三个参数,第一个参数是被替换字串,第二个参数是替换字串,第三个参数是替换操作作用的字串。这个函数也就是把$(foo)中的空格替换成逗号,所以$(bar)的值是"a,b,c"。
### 字符串处理函数
##### 字符串替换函数 subst
## 字符串处理函数
### 字符串替换函数 subst
- 功能:把字串\<text\>中的<from>字符串替换成<to>
- 返回:函数返回被替换过后的字符串。
- 语法:
@ -1029,7 +1029,7 @@ categories: ["dev/ops"]
```
- 把"feet on the street"中的"ee"替换成"EE",返回结果是"fEEt on the strEEt"。
##### 模式字符串替换函数 patsubst
### 模式字符串替换函数 patsubst
- 功能:查找\<text\>中的单词(单词以"空格"、"Tab"或"回车""换行"分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符"%",表示任意长度的字串。如果<replacement>中也包含"%",那么,<replacement>中的这个"%"将是<pattern>中的那个"%"所代表的字串。(可以用"\"来转义,以"\%"来表示真实含义的"%"字符)返回:函数返回被替换过后的字符串。
- 语法:
```makefile
@ -1058,7 +1058,7 @@ categories: ["dev/ops"]
```
- 例如有objects = foo.o bar.o baz.o那么"$(objects:.o=.c)"和"$(patsubst %.o,%.c,$(objects))"是一样的。
##### 去空格函数 strip
### 去空格函数 strip
- 功能:去掉<string>字串中开头和结尾的空字符。
- 返回:返回被去掉空格的字符串值。
- 语法
@ -1071,7 +1071,7 @@ categories: ["dev/ops"]
```
- 把字串"a b c "去到开头和结尾的空格,结果是"a b c"。
##### 查找字符串函数findstring
### 查找字符串函数findstring
- 功能:在字串<in>中查找<find>字串。
- 返回:如果找到,那么返回<find>,否则返回空字符串。
- 语法:
@ -1085,7 +1085,7 @@ categories: ["dev/ops"]
```
- 第一个函数返回"a"字符串,第二个返回""字符串(空字符串)
##### 过滤函数 filter
### 过滤函数 filter
- 功能:以<pattern>模式过滤\<text\>字符串中的单词,保留符合模式<pattern>的单词。可以有多个模式。
- 返回:返回符合模式<pattern>的字串。
- 语法:
@ -1101,7 +1101,7 @@ categories: ["dev/ops"]
- $(filter %.c %.s,$(sources))返回的值是"foo.c bar.c baz.s"。
##### 反过滤函数 filter-out
### 反过滤函数 filter-out
- 功能:以<pattern>模式过滤\<text\>字符串中的单词,去除符合模式<pattern>的单词。可以有多个模式。
- 返回:返回不符合模式<pattern>的字串。
- 语法:
@ -1115,7 +1115,7 @@ categories: ["dev/ops"]
```
- $(filter-out $(mains),$(objects)) 返回值是"foo.o bar.o"。
##### 排序函数 sort。
### 排序函数 sort。
- 功能:给字符串<list>中的单词排序(升序)。
- 返回:返回排序后的字符串。
- 语法:
@ -1125,7 +1125,7 @@ categories: ["dev/ops"]
- 示例:$(sort foo bar lose)返回"bar foo lose" 。
- 备注sort函数会去掉<list>中相同的单词。
##### 取单词函数 word
### 取单词函数 word
- 功能:取字符串\<text\>中第<n>个单词。(从一开始)
- 返回:返回字符串\<text\>中第<n>个单词。如果<n>比\<text\>中的单词数要大,那么返回空字符串。
- 语法:
@ -1134,7 +1134,7 @@ categories: ["dev/ops"]
```
- 示例:$(word 2, foo bar baz)返回值是"bar"。
##### 取单词串函数 wordlist
### 取单词串函数 wordlist
- 功能:从字符串\<text\>中取从\<s\>开始到<e>的单词串,\<s\>和<e>是一个数字。
- 返回:返回字符串\<text\>中从\<s\>到<e>的单词字串。如果\<s\>比\<text\>中的单词数要大,那么返回空字符串。如果<e>大于\<text\>的单词数,那么返回从\<s\>开始,到\<text\>结束的单词串。
- 语法:
@ -1143,7 +1143,7 @@ categories: ["dev/ops"]
```
- 示例: $(wordlist 2, 3, foo bar baz)返回值是"bar baz"。
##### 单词个数统计函数 words
### 单词个数统计函数 words
- 功能:统计\<text\>中字符串中的单词个数。
- 返回:返回\<text\>中的单词数。
- 语法:
@ -1156,7 +1156,7 @@ categories: ["dev/ops"]
$(word $(words \<text\>),\<text\> )。
```
##### 首单词函数 firstword
### 首单词函数 firstword
- 功能:取字符串\<text\>中的第一个单词。
- 返回:返回字符串\<text\>的第一个单词。
- 语法:
@ -1166,17 +1166,17 @@ categories: ["dev/ops"]
- 示例:$(firstword foo bar)返回值是"foo"。
- 备注这个函数可以用word函数来实现$(word 1,\<text\> )。
##### 应用例子
### 应用例子
- make使用"VPATH"变量来指定"依赖文件"的搜索路径我们可以利用这个搜索路径来指定编译器对头文件的搜索路径参数CFLAGS
```makefile
override CFLAGS += $(patsubst %,-I%,$(subst :, ,$(VPATH)))
```
- 如果我们的"$(VPATH)"值是"src:../headers",那么"$(patsubst %,-I%,$(subst :, ,$(VPATH)))"将返回"-Isrc -I../headers"这正是cc或gcc搜索头文件路径的参数 。
### 文件名操作函数
## 文件名操作函数
- 下面我们要介绍的函数主要是处理文件名的。每个函数的参数字符串都会被当做一个或是一系列的文件名来对待。
##### 取目录函数 dir
### 取目录函数 dir
- 功能:从文件名序列<names>中取出目录部分。目录部分是指最后一个反斜杠("/")之
- 前的部分。如果没有反斜杠,那么返回"./"。
- 返回:返回文件名序列<names>的目录部分。
@ -1186,7 +1186,7 @@ categories: ["dev/ops"]
```
- 示例: $(dir src/foo.c hacks)返回值是"src/ ./"。
##### 取文件函数 notdir
### 取文件函数 notdir
- 功能:从文件名序列<names>中取出非目录部分。非目录部分是指最后一个反斜杠("/")之后的部分。
- 返回:返回文件名序列<names>的非目录部分。
- 语法:
@ -1195,7 +1195,7 @@ categories: ["dev/ops"]
```
- 示例: $(notdir src/foo.c hacks)返回值是"foo.c hacks"。
##### 取后缀函数 suffix
### 取后缀函数 suffix
- 功能:从文件名序列<names>中取出各个文件名的后缀。
- 返回:返回文件名序列<names>的后缀序列,如果文件没有后缀,则返回空字串。
- 语法:
@ -1204,7 +1204,7 @@ categories: ["dev/ops"]
```
- 示例:$(suffix src/foo.c src-1.0/bar.c hacks)返回值是".c .c"。
##### 取前缀函数 basename
### 取前缀函数 basename
- 功能:从文件名序列<names>中取出各个文件名的前缀部分。
- 返回:返回文件名序列<names>的前缀序列,如果文件没有前缀,则返回空字串。
- 语法:
@ -1213,7 +1213,7 @@ categories: ["dev/ops"]
```
- 示例:$(basename src/foo.c src-1.0/bar.c hacks)返回值是"src/foo src-1.0/bar hacks"。
##### 加后缀函数 addsuffix
### 加后缀函数 addsuffix
- 功能:把后缀<suffix>加到<names>中的每个单词后面。
- 返回:返回加过后缀的文件名序列。
- 语法:
@ -1222,7 +1222,7 @@ categories: ["dev/ops"]
```
- 示例:$(addsuffix .c,foo bar)返回值是"foo.c bar.c"。
##### 加前缀函数 addprefix
### 加前缀函数 addprefix
- 功能:把前缀<prefix>加到<names>中的每个单词后面。
- 返回:返回加过前缀的文件名序列。
- 语法:
@ -1231,7 +1231,7 @@ categories: ["dev/ops"]
```
- 示例:$(addprefix src/,foo bar)返回值是"src/foo src/bar"。
##### 连接函数 join。
### 连接函数 join。
- 功能:把<list2>中的单词对应地加到<list1>的单词后面。如果<list1>的单词个数要比<list2>的多,那么,<list1>中的多出来的单词将保持原样。如果<list2>的单词个数要比<list1>多,那么,<list2>多出来的单词将被复制到<list2>中。
- 返回:返回连接过后的字符串。
- 语法:
@ -1240,7 +1240,7 @@ categories: ["dev/ops"]
```
- 示例:$(join aaa bbb , 111 222 333)返回值是"aaa111 bbb222 333"。
### foreach 函数
## foreach 函数
- foreach 函数和别的函数非常的不一样。因为这个函数是用来做循环用的Makefile中的foreach函数几乎是仿照于Unix标准Shell/bin /sh中的for语句或是C-Shell/bin/csh中的foreach语句而构建的。它的语法是
```makefile
$(foreach <var>,<list>,\<text\> )
@ -1255,7 +1255,7 @@ categories: ["dev/ops"]
- 上面的例子中,$(name)中的单词会被挨个取出,并存到变量"n"中,"$(n).o"每次根据"$(n)"计算出一个值这些值以空格分隔最后作为foreach函数的返回所以$(files)的值是"a.o b.o c.o d.o"。
- 注意foreach中的<var>参数是一个临时的局部变量foreach函数执行完后参数<var>的变量将不在作用其作用域只在foreach函数当中。
### if 函数
## if 函数
- if函数很像GNU的make所支持的条件语句 ifeq参见前面所述的章节if函数的语法是
```makefile
$(if <condition>,<then-part> )
@ -1268,7 +1268,7 @@ categories: ["dev/ops"]
- 而if函数的返回值是如果<condition>为真(非空字符串),那个<then- part>会是整个函数的返回值,如果<condition>为假(空字符串),那么<else-part>会是整个函数的返回值,此时如果<else-part>没有被定义,那么,整个函数返回空字串。
- 所以,<then-part><else-part>只会有一个被计算。
### call函数
## call函数
- call函数是唯一一个可以用来创建新的参数化的函数。你可以写一个非常复杂的表达式这个表达式中你可以定义许多参数然后你可以用call函数来向这个表达式传递参数。其语法是
```makefile
$(call <expression>,<parm1>,<parm2>,<parm3>...)
@ -1285,7 +1285,7 @@ categories: ["dev/ops"]
```
- 此时的foo的值就是"b a"。
### origin 函数
## origin 函数
- origin函数不像其它的函数他并不操作变量的值他只是告诉你你的这个变量是哪里来的其语法是
```makefile
$(origin <variable> )
@ -1308,7 +1308,7 @@ categories: ["dev/ops"]
```
- 当然你也许会说使用override关键字不就可以重新定义环境中的变量了吗为什么需要使用这样的步骤是的我们用override是可以达到这样的效果可是override过于粗暴它同时会把从命令行定义的变量也覆盖了而我们只想重新定义环境传来的而不想重新定义命令行传来的。
### shell函数
## shell函数
- shell 函数也不像其它的函数。顾名思义它的参数应该就是操作系统Shell的命令。它和反引号"`"是相同的功能。这就是说shell函数把执行操作系统命令后的输出作为函数返回。于是我们可以用操作系统命令以及字符串处理命令awksed等等命令来生成一个变量
```makefile
contents := $(shell cat foo)
@ -1317,7 +1317,7 @@ categories: ["dev/ops"]
- 注意这个函数会新生成一个Shell程序来执行命令所以你要注意其运行性能如果你的Makefile中有一些比较复杂的规则并大量使用了这个函数那么对于你的系统性能是有害的。特别是Makefile的隐晦的规则可能会让你的shell函数执行的次数比你想像的多得多。
### 控制make的函数
## 控制make的函数
- make提供了一些函数来控制make的运行。通常你需要检测一些运行Makefile时的运行时信息并且根据这些信息来决定你是让make继续执行还是停止。
```makefile
$(error <text ...> )
@ -1341,14 +1341,14 @@ categories: ["dev/ops"]
```
# make 的运行
### make 退出码
## make 退出码
- make命令执行后有三个退出码
- 0 表示成功执行。
- 1 如果make运行时出现任何错误其返回1。
- 2 如果你使用了make的"-q"选项并且make使得一些目标不需要更新那么返回2。
- Make的相关参数我们会在后续章节中讲述。
### 指定Makefile
## 指定Makefile
- 前面我们说过GNU make找寻默认的Makefile的规则是在当前目录下依次找三个文件 "GNUmakefile"、"makefile"和"Makefile"。其按顺序找这三个文件,一旦找到,就开始读取这个文件并执行。
- 当前我们也可以给make命令指定一个特殊名字的Makefile。要达到这个功能我们要使用make的"-f"或是"--file"参数("-- makefile"参数也行。例如我们有个makefile的名字是"hchen.mk"那么我们可以这样来让make来执行这个文件
```bash
@ -1356,7 +1356,7 @@ categories: ["dev/ops"]
```
- 如果在make的命令行是你不只一次地使用了"-f"参数那么所有指定的makefile将会被连在一起传递给make执行。
### 指定目标
## 指定目标
- 一般来说make的最终目标是makefile中的第一个目标而其它目标一般是由这个目标连带出来的。这是make的默认行为。当然一般来说你的 makefile中的第一个目标是由许多个目标组成你可以指示make让其完成你所指定的目标。要达到这一目的很简单需在make命令后直接跟目标的名字就可以完成如前面提到的"make clean"形式任何在makefile中的目标都可以被指定成终极目标但是除了以"- "打头,或是包含了"="的目标因为有这些字符的目标会被解析成命令行参数或是变量。甚至没有被我们明确写出来的目标也可以成为make的终极目标也就是说只要make可以找到其隐含规则推导规则那么这个隐含目标同样可以被指定成终极目标。
- 有一个make的环境变量叫"MAKECMDGOALS",这个变量中会存放你所指定的终极目标的列表,如果在命令行上,你没有指定目标,那么,这个变量是空值。这个变量可以让你使用在一些比较特殊的情形下。比如下面的例子:
```makefile
@ -1383,7 +1383,7 @@ categories: ["dev/ops"]
- "check"和"test" 这两个伪目标一般用来测试makefile的流程。
- 当然一个项目的makefile中也不一定要书写这样的目标这些东西都是GNU的东西但是我想GNU搞出这些东西一定有其可取之处等你的UNIX下的程序文件一多时你就会发现这些功能很有用了这里只不过是说明了如果你要书写这种功能最好使用这种名字命名你的目标这样规范一些规范的好处就是 不用解释大家都明白。而且如果你的makefile中有这些功能一是很实用二是可以显得你的makefile很专业不是那种初学者的作品
### 检查规则
## 检查规则
- 有时候我们不想让我们的makefile中的规则执行起来我们只想检查一下我们的命令或是执行的序列。于是我们可以使用make命令的下述参数
- "-n" "--just-print" "--dry-run" "--recon" 不执行参数这些参数只是打印命令不管目标是否更新把规则和连带规则下的命令打印出来但不执行这些参数对于我们调试makefile很有用处。
- "-t" "--touch" 这个参数的意思就是把目标文件的时间更新但不更改目标文件。也就是说make假装编译目标但不是真正的编译目标只是把目标变成已编译过的状态。
@ -1391,7 +1391,7 @@ categories: ["dev/ops"]
- "-W <file>" "--what-if=<file>" "--assume-new=<file>" "--new-file=<file>" 这个参数需要指定一个文件。一般是是源文件或依赖文件Make会根据规则推导来运行依赖于这个文件的命令一般来说可以和"-n"参数一同使用,来查看这个依赖文件所发生的规则命令。
- 另外一个很有意思的用法是结合"-p"和"-v"来输出makefile被执行时的信息这个将在后面讲述
### make的参数
## make的参数
- 下面列举了所有GNU make 3.80版的参数定义。其它版本和产商的make大同小异不过其它产商的make的具体参数还是请参考各自的产品文档。
- "-b" "-m" 这两个参数的作用是忽略和其它版本make的兼容性。
- "-B" "--always-make" 认为所有的目标都需要更新(重编译)。
@ -1433,7 +1433,7 @@ categories: ["dev/ops"]
- "隐含规则"会使用一些我们系统变量,我们可以改变这些系统变量的值来定制隐含规则的运行时的参数。如系统变量"CFLAGS"可以控制编译时的编译器参数。
- 我们还可以通过"模式规则"的方式写下自己的隐含规则。用"后缀规则"来定义隐含规则会有许多的限制。使用"模式规则"会更回得智能和清楚,但"后缀规则"可以用来保证我们Makefile的兼容性。
### 使用隐含规则
## 使用隐含规则
- 如果要使用隐含规则生成你需要的目标你所需要做的就是不要写出这个目标的规则。那么make会试图去自动推导产生这个目标的规则和命令如果make可以自动推导生成这个目标的规则和命令那么这个行为就是隐含规则的自动推导。当然隐含规则是make事先约定好的一些东西。例如我们有下面的一个Makefile
```makefile
foo : foo.o bar.o
@ -1456,7 +1456,7 @@ categories: ["dev/ops"]
```
- 依赖文件"foo.p"Pascal程序的源文件有可能变得没有意义。如果目录下存在了"foo.c"文件,那么我们的隐含规则一样会生效,并会通过 "foo.c"调用C的编译器生成foo.o文件。因为在隐含规则中Pascal的规则出现在C的规则之后所以make找到可以生成foo.o的 C的规则就不再寻找下一条规则了。如果你确实不希望任何隐含规则推导那么你就不要只写出"依赖规则",而不写命令。
### 隐含规则一览
## 隐含规则一览
- 这里我们将讲述所有预先设置也就是make内建的隐含规则如果我们不明确地写下规则那么make就会在这些规则中寻找所需要规则和命令。当然我们也可以使用make的参数"-r"或"--no-builtin-rules"选项来取消所有的预设置的隐含规则。
- 当然,即使是我们指定了"-r"参数,某些隐含规则还是会生效,因为有许多的隐含规则都是使用了"后缀规则"来定义的,所以,只要隐含规则中有"后缀列表 "(也就一系统定义在目标.SUFFIXES的依赖目标那么隐含规则就会生效。默认的后缀列表是.out,.a, .ln, .o, .c, .cc, .C, .p, .f, .F, .r, .y, .l, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el。具体的细节我们会在后面讲述。
- 常用的隐含规则
@ -1530,7 +1530,7 @@ categories: ["dev/ops"]
- 从C程序、Yacc文件或Lex文件创建Lint库的隐含规则。
"<n>.ln" lint生成的文件的依赖文件被自动推导为"n.c",其生成命令是:"$(LINT) $(LINTFALGS) $(CPPFLAGS) -i"。对于"<n>.y"和"<n>.l"也是同样的规则。
### 隐含规则使用的变量
## 隐含规则使用的变量
- 在隐含规则中的命令中基本上都是使用了一些预先设置的变量。你可以在你的makefile中改变这些变量的值或是在make的命令行中传入这些值或是在你的环境变量中设置这些值无论怎么样只要设置了这些特定的变量那么其就会对隐含规则起作用。当然你也可以利用make的"-R"或"--no builtin-variables"参数来取消你所定义的变量对隐含规则的作用。
- 例如,第一条隐含规则 编译C程序的隐含规则的命令是"$(CC) c $(CFLAGS) $(CPPFLAGS)"。Make默认的编译命令是"cc",如果你把变量"$(CC)"重定义成"gcc",把变量"$(CFLAGS)"重定义成 "-g",那么,隐含规则中的命令全部会以"gcc c -g $(CPPFLAGS)"的样子来执行了。
- 我们可以把隐含规则中使用的变量分成两种:一种是命令相关的,如"CC";一种是参数
@ -1571,7 +1571,7 @@ categories: ["dev/ops"]
- RFLAGS Ratfor 程序的Fortran 编译器参数。
- YFLAGS Yacc文法分析器参数。
### 隐含规则链
## 隐含规则链
- 有些时候,一个目标可能被一系列的隐含规则所作用。例如,一个[.o]的文件生成可能会是先被Yacc的[.y]文件先成[.c]然后再被C的编译器生成。我们把这一系列的隐含规则叫做"隐含规则链"。
- 在上面的例子中,如果文件[.c]存在那么就直接调用C的编译器的隐含规则如果没有[.c]文件,但有一个[.y]文件那么Yacc的隐含规则会被调用生成[.c]文件然后再调用C编译的隐含规则最终由[.c]生成[.o]文件,达到目标。
- 在默认情况下,对于中间目标,它和一般的目标有两个地方所不同:第一个不同是除非中间的目标不存在,才会引发中间规则。第二个不同的是,只要目标成功产生,那么,产生最终目标过程中,所产生的中间目标文件会被以"rm -f"删除。
@ -1580,11 +1580,11 @@ categories: ["dev/ops"]
- 在"隐含规则链"中禁止同一个目标出现两次或两次以上这样一来就可防止在make自动推导时出现无限递归的情况。
- Make 会优化一些特殊的隐含规则,而不生成中间文件。如,从文件"foo.c"生成目标程序"foo"按道理make会编译生成中间文件"foo.o",然后链接成"foo",但在实际情况下,这一动作可以被一条"cc"的命令完成cc o foo foo.c于是优化过的规则就不会生成中间文件。
### 定义模式规则
## 定义模式规则
- 你可以使用模式规则来定义一个隐含规则。一个模式规则就好像一个一般的规则,只是在规则中,目标的定义需要有"%"字符。"%"的意思是表示一个或多个任意字符。在依赖目标中同样可以使用"%",只是依赖目标中的"%"的取值,取决于其目标。
- 有一点需要注意的是,"%"的展开发生在变量和函数的展开之后变量和函数的展开发生在make载入Makefile时而模式规则中的"%"则发生在运行时。
##### 模式规则介绍
### 模式规则介绍
- 模式规则中,至少在规则的目标定义中要包含"%",否则,就是一般的规则。目标中的"%"定义表示对文件名的匹配,"%"表示长度任意的非空字符串。例如:"%.c"表示以".c"结尾的文件名文件名的长度至少为3而"s.%.c"则表示以"s."开头,".c"结尾的文件名(文件名的长度至少为 5
- 如果"%"定义在目标中,那么,目标中的"%"的值决定了依赖目标中的"%"的值,也就是说,目标中的模式的"%"决定了依赖目标中"%"的样子。例如有一个模式规则如下:
```makefile
@ -1593,7 +1593,7 @@ categories: ["dev/ops"]
- 其含义是,指出了怎么从所有的[.c]文件生成相应的[.o]文件的规则。如果要生成的目标是"a.o b.o",那么"%c"就是"a.c b.c"。
- 一旦依赖目标中的"%"模式被确定那么make会被要求去匹配当前目录下所有的文件名一旦找到make就会规则下的命令所以在模式规则中目标可能会是多个的如果有模式匹配出多个目标make就会产生所有的模式目标此时make关心的是依赖的文件名和生成目标的命令这两件事。
##### 模式规则示例
### 模式规则示例
- 下面这个例子表示了,把所有的[.c]文件都编译成[.o]文件.
```makefile
%.o : %.c
@ -1607,7 +1607,7 @@ categories: ["dev/ops"]
```
- 这条规则告诉make把所有的[.y]文件都以"bison -d <n>.y"执行,然后生成"<n>.tab.c"和"<n>.tab.h"文件。(其中,"<n>" 表示一个任意字符串)。如果我们的执行程序"foo"依赖于文件"parse.tab.o"和"scan.o",并且文件"scan.o"依赖于文件"parse.tab.h",如果"parse.y"文件被更新了,那么根据上述的规则,"bison -d parse.y"就会被执行一次,于是,"parse.tab.o"和"scan.o"的依赖文件就齐了。(假设,"parse.tab.o" 由"parse.tab.c"生成,和"scan.o"由"scan.c"生成,而"foo"由"parse.tab.o"和"scan.o"链接生成而且foo和其[.o]文件的依赖关系也写好,那么,所有的目标都会得到满足)
##### 自动化变量
### 自动化变量
- 在上述的模式规则中,目标和依赖文件都是一系例的文件,那么我们如何书写一个命令来完成从不同的依赖文件生成相应的目标?因为在每一次的对模式规则的解析时,都会是不同的目标和依赖文件。
- 自动化变量就是完成这个功能的。在前面,我们已经对自动化变量有所提涉,相信你看到这里已对它有一个感性认识了。所谓自动化变量,就是这种变量会把模式中所定义的一系列的文件自动地挨个取出,直至所有的符合模式的文件都取完了。这种自动化变量只应出现在规则的命令中。
- 下面是所有的自动化变量及其说明:
@ -1636,11 +1636,11 @@ categories: ["dev/ops"]
- 最后想提醒一下的是,对于"$<",为了避免产生不必要的麻烦,我们最好给$后面的那个特定字符都加上圆括号,比如,"$(< )"就要比"$<"要好一些。
- 还得要注意的是,这些变量只使用在规则的命令中,而且一般都是"显式规则"和"静态模式规则"(参见前面"书写规则"一章)。其在隐含规则中并没有意义。
### 模式的匹配
## 模式的匹配
- 一般来说,一个目标的模式有一个有前缀或是后缀的"%",或是没有前后缀,直接就是一个"%"。因为"%"代表一个或多个字符,所以在定义好了的模式中,我们把"%"所匹配的内容叫做"茎",例如"%.c"所匹配的文件"test.c"中"test"就是"茎"。因为在目标和依赖目标中同时有"%"时,依赖目标的"茎"会传给目标,当做目标中的"茎"。
- 当一个模式匹配包含有斜杠(实际也不经常包含)的文件时,那么在进行模式匹配时,目录部分会首先被移开,然后进行匹配,成功后,再把目录加回去。在进行"茎"的传递时,我们需要知道这个步骤。例如有一个模式"e%t",文件"src/eat" 匹配于该模式,于是"src/a"就是其"茎",如果这个模式定义在依赖目标中,而被依赖于这个模式的目标中又有个模式"c%r",那么,目标就是"src/car"。("茎"被传递)
### 重载内建隐含规则
## 重载内建隐含规则
- 你可以重载内建的隐含规则(或是定义一个全新的),例如你可以重新构造和内建隐含规则不同的命令,如:
```makefile
%.o : %.c
@ -1699,7 +1699,7 @@ categories: ["dev/ops"]
# 使用make更新函数库文件
- 函数库文件也就是对Object文件程序编译的中间文件的打包文件。在Unix下一般是由命令"ar"来完成打包工作。
### 函数库文件的成员
## 函数库文件的成员
- 一个函数库文件由多个文件组成。你可以以如下格式指定函数库文件及其组成:
- archive(member) 这个不是一个命令,而一个目标和依赖的定义。一般来说,这种用法基本上就是为了"ar"命令来服务的。如:
```makefile
@ -1719,7 +1719,7 @@ categories: ["dev/ops"]
foolib(*.o)
```
### 函数库成员的隐含规则
## 函数库成员的隐含规则
- 当 make搜索一个目标的隐含规则时一个特殊的特性是如果这个目标是"a(m)"形式的,其会把目标变成"(m)"。于是,如果我们的成员是"%.o" 的模式定义,并且如果我们使用"make foo.a(bar.o)"的形式调用Makefile时隐含规则会去找"bar.o"的规则如果没有定义bar.o的规则那么内建隐含规则生效make会去找bar.c文件来生成bar.o如果找得到的话make执行的命令大致如下
```makefile
cc -c bar.c -o bar.o
@ -1728,7 +1728,7 @@ categories: ["dev/ops"]
```
- 还有一个变量要注意的是"$%",这是专属函数库文件的自动化变量,有关其说明请参见"自动化变量"一节。
### 函数库文件的后缀规则
## 函数库文件的后缀规则
- 你可以使用"后缀规则"和"隐含规则"来生成函数库打包文件,如:
```makefile
.c.a:

View File

@ -9,7 +9,6 @@ categories: ["database"]
环境centos 5.4/6.2/6.5/7.2 x64
1、下载官方编译好的 linux 通用安装包,解压之自定义目录(如/opt
```bash
# rhel 7 地址:
wget https://mirrors.tuna.tsinghua.edu.cn/mariadb//mariadb-10.1.19/bintar-linux-glibc_214-x86_64/mariadb-10.1.19-linux-glibc_214-x86_64.tar.gz
@ -20,8 +19,7 @@ cd /opt;mv mariadb-10.1.19-linux* mariadb
```
2、创建服务文件和配置文件创建日志目录
```
```bash
cd /opt/mariadb
mv support_files/my-large.cnf ./my.cnf
mv support_files/mysql.server ./mysqld
@ -29,7 +27,6 @@ mkdir -p log
```
3、修改服务文件 mysqld
```
vim /opt/mariadb/mysqld
# 在打开的文件中修改开头的basedir和datadirdatadir是数据库文件目录建议指定一个大分区中的目录
@ -38,12 +35,10 @@ datadir=/mnt/sdb1/mariadb_db
# 修改开头的lockdir和lock-file-path
lockdir='/opt/mariadb/log'
lock-file-path="$lockdir/mysql.lock"
```
4、修改配置文件 /opt/mariadb/my.cnf
```
```ini
[mysqld]
datadir=/mnt/sdb1/mariadb_db
log-error=/opt/mariadb/log/error.log
@ -55,26 +50,21 @@ skip-networking # 取消监听端口,适合本地数据库使用
skip-name-resolve # 取消域名解析
max-connections = 3000
max-connect-errors = 1000
#如果系统中存在 /etc/my.cnf 且不可写, 可以在 /opt/mariadb/my.cnf 中重新设置冲突项。
```
5、修改数据库程序数据目录的权限:
```bash
chown mysql.mysql /opt/mariadb/ -R
chown mysql.mysql /mnt/sdb1/mariadb_db/ -R
```
6、安装数据库
```bash
/opt/mariadb/scripts/mysql_install_db --basedir=/opt/mariadb --datadir=/mnt/sdb1/mariadb_db --user=mysql
```
7、根据提示修改mariadb的root帐号密码禁用root登陆删除匿名用户及test库
```bash
# 启动 mariadb
/opt/mariadb/mysqld start
@ -85,7 +75,6 @@ chown mysql.mysql /mnt/sdb1/mariadb_db/ -R
```
8、增加系统动态库配置
```bash
echo '/opt/mariadb/lib' >> /etc/ld.so.conf
ldconfig

View File

@ -15,7 +15,7 @@ cpu | mem | hostname | public ip | cluster ip | CentOS | MariaDB
# 安装数据库
### 离线安装
## 离线安装
- [下载 rpm](http://yum.mariadb.org/10.1/centos7-amd64/rpms/)
- MariaDB-10.1.33-centos7-x86_64-client.rpm
- MariaDB-10.1.33-centos7-x86_64-common.rpm
@ -33,7 +33,7 @@ cpu | mem | hostname | public ip | cluster ip | CentOS | MariaDB
mysql_install_db --user=mysql
```
### yum 安装
## yum 安装
- 创建 MariaDB-10.1 的 yum 源文件(就近选择一个)
```bash
#官方
@ -61,6 +61,7 @@ cpu | mem | hostname | public ip | cluster ip | CentOS | MariaDB
gpgcheck=1
END
```
- 安装 MariaDB
```bash
yum install MariaDB-client MariaDB-server

View File

@ -8,7 +8,7 @@ categories: ["database"]
---
# 数据迁移
### 导出集合数据到 json 或 csv 文件
## 导出集合数据到 json 或 csv 文件
- 命令
```
mongoexport -d dbname -c collectionname -o file --type json/csv -f "field1,field2,...,fieldN"
@ -20,7 +20,7 @@ categories: ["database"]
- --type 输出格式,默认 json
- -f 输出字段,如果导出 csv需指定字段名
### 导入数据到集合
## 导入数据到集合
- 命令
```
mongoimport -d dbname -c collectionname --file filename --headerline --type json/csv -f "field1,field2,...,fieldN"
@ -33,7 +33,7 @@ categories: ["database"]
- --headerline 导入csv时使用第一行的标题作为导入字段
- --file 导入的文件
### 备份数据库
## 备份数据库
- 命令
```
mongodump -h dbhost -d dbname -o backup_dir
@ -43,7 +43,7 @@ categories: ["database"]
- -d 数据库名
- -o 备份数据存放目录,需提前建立
### 恢复数据库
## 恢复数据库
- 命令
```
mongorestore -h dbhost -d dbname --dir backup_dir
@ -63,20 +63,20 @@ categories: ["database"]
- 删除数据库 use dbname; db.dropDatabase()
# 操作集合
### 创建
## 创建
```
db.createCollection("集合名", {capped:false, autoIndexId:false, size:最大字节, max:文档最多数量})
# 或者在插入文档时自动创建
db.集合名.inert({})
```
### 删除
## 删除
```
db.集合名.drop()
```
# 操作文档
### insert
## insert
- 插入一个文档
```
db.集合名.insert({})
@ -90,7 +90,7 @@ db.集合名.drop()
db.集合名.insertMany([{},{},{},...,{}])
```
### find
## find
- 查询匹配的文档
```
db.集合名.find({}).pretty()
@ -124,7 +124,7 @@ db.集合名.drop()
db.集合名.find({}).sort({"key":1})
```
### update
## update
- 更新一个文档
```
db.集合名.update({},{$set:{}})
@ -134,12 +134,12 @@ db.集合名.drop()
db.集合名.update({},{$set:{},{multi:true}})
```
### save
## save
```
db.集合名.save({,...})
```
### remove
## remove
- 删除多条记录
```
db.集合名.remove({})
@ -153,19 +153,19 @@ db.集合名.save({,...})
db.集合名.remove()
```
### 索引
## 索引
- 创建索引1升序-1降序
```
db.集合名.createIndex({"key1":1,"key2":-1})
```
### 聚合
## 聚合
```
db.集合名.aggregate([{}])
```
# 用户
### 创建用户
## 创建用户
- 管理员权限
```
use admin
@ -189,23 +189,23 @@ db.集合名.aggregate([{}])
)
```
### 验证身份
## 验证身份
```
db.auth("username", "password")
```
### 列出所有用户
## 列出所有用户
```
db.getUsers()
```
### 删除数据库用户
## 删除数据库用户
```
use testdb
db.dropUser("username")
```
### 更改用户密码
## 更改用户密码
```
db.updateUser(
"username",

View File

@ -22,7 +22,7 @@ name = Galera
baseurl = http://releases.galeracluster.com/galera-3/centos/7/x86_64/
gpgkey = http://releases.galeracluster.com/GPG-KEY-galeracluster.com
gpgcheck = 1
#
[mysql-wsrep]
name = MySQL-wsrep
baseurl = http://releases.galeracluster.com/mysql-wsrep-5.7/centos/7/x86_64/
@ -56,11 +56,11 @@ wsrep-sst-method=rsync
wsrep-node-name=mysql_1 #当前节点名字
wsrep-node-address="10.10.10.1" #当前节点 cluster ip
#wsrep-auto-increment-control=OFF #只通过一个节点做增删改时使用
#
[mysql_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
#
!includedir /etc/my.cnf.d/
```
@ -103,11 +103,13 @@ show status like 'wsrep_cluster_size';
-CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 \
-out server-cert.pem
```
- 修改配置文件 my.cnf
```
# 在 wsrep_provider_options 中添加如下选项,选项间用分号";"间隔
socket.ssl_key=/etc/my.cnf.d/ssl/server-key.pem; socket.ssl_cert=/etc/my.cnf.d/ssl/server-cert.pem; socket.ssl_ca=/etc/my.cnf.d/ssl/ca-cert.pem; socket.checksum=2; socket.ssl_cipher=AES128-SHA
```
- 重新启动集群
# ssl 加密客户端(不推荐,存在性能损失)

View File

@ -83,6 +83,7 @@ group-replication-exit-state-action = OFFLINE_MODE
```bash
systemctl restart mysqld
```
- 创建同步用户
```sql
SET SQL_LOG_BIN = 0;
@ -92,6 +93,7 @@ group-replication-exit-state-action = OFFLINE_MODE
FLUSH PRIVILEGES;
SET SQL_LOG_BIN = 1;
```
- 配置同步信息
```sql
CHANGE MASTER TO
@ -99,16 +101,19 @@ group-replication-exit-state-action = OFFLINE_MODE
MASTER_PASSWORD='password'
FOR CHANNEL 'group_replication_recovery';
```
- 启动集群
```sql
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
```
- 查看集群成员(只有一个)
```sql
SELECT * FROM performance_schema.replication_group_members;
```
- 修改 my.cnf配置 group-replication-start-on-boot = ON
# 增加节点
@ -116,6 +121,7 @@ group-replication-exit-state-action = OFFLINE_MODE
```bash
systemctl restart mysql_22
```
- 创建同步用户,与 mysql_11 相同
```sql
SET SQL_LOG_BIN = 0;
@ -125,6 +131,7 @@ group-replication-exit-state-action = OFFLINE_MODE
FLUSH PRIVILEGES;
SET SQL_LOG_BIN = 1;
```
- 配置同步信息
```sql
CHANGE MASTER TO
@ -132,15 +139,18 @@ group-replication-exit-state-action = OFFLINE_MODE
MASTER_PASSWORD='password'
FOR CHANNEL 'group_replication_recovery';
```
- 启动组复制
```sql
START GROUP_REPLICATION;
```
- 在 mysql_33 上重复 mysql_22 的步骤
- 查看集群成员(有三个)
```sql
SELECT * FROM performance_schema.replication_group_members;
```
- 修改 mysql_22 和 mysql_33 的 my.cnf配置 group-replication-start-on-boot = ON
# 注意

View File

@ -240,21 +240,25 @@ relay-log-recovery = TRUE
master_info_repository = table
relay_log_info_repository = table
```
- 导出主库数据
```bash
mysqldump -uroot -h<主库1> -p --single-transaction --set-gtid-purged=on --databases db1 > 1_db1.sql
mysqldump -uroot -h<主库2> -p --single-transaction --set-gtid-purged=on --databases db2 > 2_db2.sql
```
- 在导出的文件(1_db1.sql,2_db2.sql)中找到 "SET @@GLOBAL.gtid_purged ..." 语句,记录下来,并在该文件中删除
- 导入 1_db1.sql 和 2_db2.sql
```bash
mysql -uroot -p < 1_db1.sql
mysql -uroot -p < 2_db2.sql
```
- 合并这两个 "SET @@GLOBAL.gtid_purged ..." 语句(gtid set 做并集),导入 gtid set 并集
```sql
set @@global.gtid_purged = '<gtid set 并集>'
```
- 加入两个主库的同步配置
```sql
change master to master_host='<主库1>',
@ -268,16 +272,19 @@ relay-log-recovery = TRUE
master_password='<主库上的 replication 账户的密码>',
master_auto_position=1 for channel '<master_2>';
```
- 启动从库
```sql
start slave for channel '<master_1>';
start slave for channel '<master_2>';
```
- 查看从库
```sql
show slave status for channel '<master_1>'\G
show slave status for channel '<master_2>'\G
```
- 停止从库
```sql
-- 停止全部 slave
@ -285,6 +292,7 @@ relay-log-recovery = TRUE
-- 停止指定 slave
stop slave for channel '...';
```
- 重置从库
```sql
-- 重置全部 slave
@ -292,5 +300,6 @@ relay-log-recovery = TRUE
-- 重置指定 slave
reset slave for channel '...';
```
- 监控表: performance_schema.replication_connection_status

View File

@ -75,10 +75,12 @@ insert into db2.t2(column1, column2 ...)
```sql
create table db2.t1 like db1.t1;
```
- 丢弃表空间
```sql
alter table db2.t1 discard tablespace;
```
- 复制 t1 的表数据文件
```bash
#关闭数据库
@ -89,6 +91,7 @@ insert into db2.t2(column1, column2 ...)
#启动数据库
systemctl start mysqld
```
- 导入表空间
```sql
alter table db2.t1 import tablespace;
@ -142,27 +145,32 @@ mysql -uroot -p -hsever_ip -Ddb_name
from information_schema.partitions
where table_name = 'table_name';
```
- 建表时指定
```sql
create table table_name(...)
partition by range columns(column_name)
(partition part_name values less than(some_value));
```
- 修改成分区表
```sql
alter table table_name
partition by range(column_name)
(partition part_name values less than(som_value));
```
- 增加分区
```sql
alter table table_name add partition
(partition part_name values less than(som_value));
```
- 删除分区
```sql
alter table table_name drop partition part_name;
```
- 合并/拆分分区
```sql
alter table table_name
@ -170,26 +178,31 @@ mysql -uroot -p -hsever_ip -Ddb_name
(partition part_new_1 values less than(value_1),
partition part_new_2 values less than(value_2));
```
- 重建分区,整理分区碎片
```sql
alter table table_name
rebuild partition part_name_1, part_name_2;
```
- 优化分区,回收空间,整理碎片
```sql
alter table table_name
optimize partition part_name_1, part_name_2;
```
- 分析分区,读取并保存分区的健分布
```sql
alter table table_name
analyze partition part_name_1, part_name_2;
```
- 修复分区
```sql
alter table table_name
repair partition part_name_1, part_name_2;
```
- 检查分区
```sql
alter table table_name
@ -244,12 +257,14 @@ UPDATE user SET password=password('newpassword') WHERE user='root';
```sql
SHOW VARIABLES LIKE 'character_set%';
```
- 数据库连接参数中characterEncoding=utf8 会被自动识别为 utf8mb4但是 autoReconnect=true 必须指定
- 更改数据库编码
```sql
ALTER DATABASE db_name
CHARSET UTF8MB4 COLLATE UTF8MB4_GENERAL_CI;
```
- 更改表编码
```sql
ALTER TABLE table_name
@ -266,15 +281,18 @@ mysql_upgrade -u root -p
```bash
systemctl stop mysqld
```
- 修改 my.cnf
```
# 添加如下一行
skip-grant-tables
```
- 启动 mysql 服务
```bash
systemctl start mysqld
```
- 重建 root 账户,并授权
```sql
insert into user
@ -317,15 +335,18 @@ mysql_upgrade -u root -p
where user='root';
flush privileges;
```
- 停止 mysql 服务
```bash
systemctl stop mysqld
```
- 修改 my.cnf
```
# 删除刚添加的如下一行
#skip-grant-tables
# 删除或注释刚添加的如下一行
skip-grant-tables
```
- 启动 mysql 服务root 账户正常可用
```bash
systemctl start mysqld
@ -336,6 +357,7 @@ mysql_upgrade -u root -p
```sql
explain sql
```
- select_type 查询类型
- SIMPLE 简单表,没有表连接或子查询
- PRIMARY 最外层的查询
@ -386,6 +408,7 @@ show global status where Variable_name in
escaped by '\\'
lines terminated by '\n';
```
- 导入
```
# Shell 终端

View File

@ -50,6 +50,7 @@ mysql -uroot -p
```sql
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'Pass-1234';
```
- 或者直接在终端修改
```bash
mysqladmin -uroot -p password 'Pass-1234'

View File

@ -309,11 +309,13 @@ verb 3
./easyrsa gen-crl
cp pki/crl.pem /etc/openvpn-server/server/my-server0/
```
- 修改 openvpn-server 的配置文件,追加/修改下面一行
```
```bash
# 注意: 该 crl.pem 文件本身及其上级目录,均需对 openvpn 运行用户可读
crl-verify my-server0/crl.pem
```
- 重启 openvpn-server 服务
# 参考链接

View File

@ -45,6 +45,7 @@ parser.add_option(opt_str, ..., attr = value, ...)
help = 'Don\'t print status message to stdout.')
(options, args) = parser.parse_args()
```
- action 默认 store 表示将参数值保存到 options 对象里
```python
from optparse import OptionParser
@ -54,6 +55,7 @@ parser.add_option(opt_str, ..., attr = value, ...)
(options, args) = parser.parse_args(args)
print options.filename
```
- type 默认 'string',也可以是 'int' 或 'float' 等长参数名可选dest 未指定时将用命令行的参数名来存取 options 对象的值
- store 其他两种形式store_true 和 store_false还有 store_const、append、count、callback
```python
@ -61,6 +63,7 @@ parser.add_option(opt_str, ..., attr = value, ...)
parser.add_option('-q', action = 'store_false', dest = 'verbose')
#当解析到 '-v', options.verbose 为 True解析到 '-q'options.verbose 为 False
```
- default 设置参数默认值
```
parser.add_option('-f', action = 'store', dest = 'filename', default = 'foo.txt')
@ -70,6 +73,7 @@ parser.add_option(opt_str, ..., attr = value, ...)
parser.add_option(...)
(options, args) = parser.parse_args()
```
- help 生成帮助信息
```python
usage = 'usage: %prog [options] arg1 arg2'
@ -95,6 +99,7 @@ group = OptionGroup(parser, 'Dangerous Options',
group.add_option('-g', action = 'store_true', help = 'Group option.')
parser.add_option_group(group)
```
- version 创建OptionParser对象时指定该参数会解释成 --version 命令行参数
- optparser 可以自动探测并处理一些用户异常,也可以使用 parser.error() 方法来自定义部分异常的处理
```

View File

@ -201,7 +201,7 @@ END
# 普通用户(username)免密 sudo
```bash
echo "username ALL = (root) NOPASSWD:ALL" >> /etc/sudoers
#
echo "cephdeploy ALL = (root) NOPASSWD:ALL" > /etc/sudoers.d/username
chmod 0400 /etc/sudoers.d/username
```
@ -212,13 +212,14 @@ chmod 0400 /etc/sudoers.d/username
mkdir /var/log/user_history -p
chmod 0777 /var/log/user_history -R
```
- 配置 history 历史文件 /etc/profile.d/history.sh
```bash
#!/bin/bash
#
export HISTSIZE=10000
export HISTTIMEFORMAT="[%F %T] "
#
LOG_DIR=/var/log/user_history
mkdir -p $LOG_DIR/$USER
if [ 0 -eq $? ]; then

View File

@ -215,7 +215,7 @@ Runlevel 6 | runlevel6.target | reboot.target
- loginctl
# Unit 配置文件
### [Unit]
## [Unit]
- Description: 简短描述
- Documentation: 文档地址
- Requires: 当前 Unit 依赖的其他 Unit如果它们没有运行当前 Unit 会启动失败
@ -226,7 +226,7 @@ Runlevel 6 | runlevel6.target | reboot.target
- Conflicts: 这里指定的 Unit 不能与当前 Unit 同时运行
- Condition...: 当前 Unit 运行必须满足的条件,否则不会运行
- Assert...: 当前 Unit 运行必须满足的条件,否则会报启动失败
### [Service]
## [Service]
- WorkingDirectory: 设置进程的工作目录
- 特殊值 "~" 表示 User= 用户的家目录
- 设为一个以 RootDirectory= 为基准的绝对路径
@ -271,7 +271,7 @@ Runlevel 6 | runlevel6.target | reboot.target
- on-watchdog: 超时退出,才会重启
- always: 不管是什么退出原因,总是重启
- RestartSec: 系统重启前等待的秒数
### [Install]
## [Install]
- WantedBy: 它的值是一个或多个 Target当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system目录下面以 Target 名 + .wants 后缀构成的子目录中
- RequiredBy: 它的值是一个或多个 Target当前 Unit 激活时,符号链接会放入/etc/systemd/system目录下面以 Target 名 + .required 后缀构成的子目录中
- Alias: 当前 Unit 可用于启动的别名

View File

@ -7,21 +7,22 @@ categories: ["os"]
---
# CentOS 配置本地 ISO 镜像源
### 上传 iso 文件
## 上传 iso 文件
- 上传 CentOS7 的 DVD iso 镜像文件到目标服务器,例如 /home/centos7.4.iso
### 挂载 iso 文件
## 挂载 iso 文件
- 挂载该 iso 文件到操作系统的一个空目录中,例如 /mnt/ 下
```bash
mount -o loop /home/centos7.4.iso /mnt/
```
### 修改软件源文件
## 修改软件源文件
- 备份全部的 .repo 文件
```bash
cd /etc/yum.repos.d/
ls *.repo|xargs -i mv {} {}_bak
```
- 创建 centos-base.repo 空文件,写入下面几行
```
[base]
@ -31,16 +32,17 @@ categories: ["os"]
gpgcheck=0
```
### 重新创建 yum 缓存
## 重新创建 yum 缓存
- 清空以前的 yum cache
```bash
yum clean all
```
- 生成新的 yum 缓存
```bash
yum makecache fast
```
### 其他 yum 源汇总
## 其他 yum 源汇总
- [pkgs.org](https://pkgs.org/)

View File

@ -14,6 +14,7 @@ categories: ["zabbix"]
JavaGatewayPort=10052
StartJavaPollers=5
```
- 配置 tomcat catalina 启动参数
```bash
export CATALINA_OPTS="
@ -24,12 +25,14 @@ categories: ["zabbix"]
-Djava.rmi.server.hostname={tomcat_server_ip}
"
```
- 重启 tomcat
- 启动 JavaGateway
```bash
# 进入 zabbix_server 安装目录,执行
./sbin/zabbix_java/startup.sh
```
- 重启 zabbix-server
```
# 进入 zabbix_server 安装目录,执行

View File

@ -36,11 +36,14 @@ categories: ["zabbix"]
# 解压
tar jxf php-5.6.31.tar.bz2 -C /root/
cd /root/php-5.6.31/
# 安装依赖包
yum install gcc make gd-devel libjpeg-devel libpng-devel libxml2-devel bzip2-devel libcurl-devel
# 创建安装目录
mkdir /opt/php-5.6.31/etc/ -p
ln -s /opt/php-5.6.31 /opt/php
# 检查编译环境
./configure --prefix=/opt/php \
--with-config-file-path=/opt/php/etc --with-bz2 --with-curl \
@ -51,15 +54,18 @@ categories: ["zabbix"]
--with-gettext --with-libxml-dir=/usr/local --with-zlib \
--with-pdo-mysql=mysqlnd --with-mysqli=mysqlnd \
--enable-dom --enable-xml --enable-fpm --with-libdir=lib64 --enable-bcmath
# 编译安装
make
make install
```
- 配置
```ini
# 复制配置文件
cp php.ini-production /opt/php/etc/php.ini
cp /opt/php/etc/php-fpm.conf.default /opt/php/etc/php-fpm.conf
# 修改 /opt/php/etc/php.ini 的下面选项
max_execution_time = 300
memory_limit = 128M
@ -68,12 +74,15 @@ categories: ["zabbix"]
max_input_time = 300
date.timezone PRC
always_populate_raw_post_data = -1
# php 与 mysql 同机可指定 mysql 本地套接字
pdo_mysql.default_socket = /tmp/mysql.sock #指定数据库本地套接字地址
mysqli.default_socket = /tmp/mysql.sock #指定数据库本地套接字地址
# 修改 /opt/php/etc/php-fpm.conf 的下面选项
user = nobody
group = nobody
# php 与 nginx 同机可指定 php 套接字,供 nginx 配置使用
#listen = 127.0.0.1:9000
listen = /dev/shm/phpfpm.sock
@ -81,6 +90,7 @@ categories: ["zabbix"]
listen.group = nobody
listen.mode = 0660
```
- 启动
```bash
/opt/php/sbin/php-fpm
@ -96,21 +106,26 @@ categories: ["zabbix"]
# 解压
tar zxf nginx-1.12.1.tar.gz -C /root/
cd /root/nginx-1.12.1/
# 安装依赖包
yum install pcre pcre-devel openssl openssl-devel
# 创建安装目录
mkdir /opt/nginx-1.12.1
ln -s /opt/nginx-1.12.1 /opt/nginx
# 检查编译环境
./configure --prefix=/opt/nginx \
--with-http_ssl_module --with-pcre \
--with-http_stub_status_module
# 编译安装
make
make install
```
- 配置
```c
```
# 在 /opt/nginx/conf/nginx.conf 中配置 php
server {
listen 80;
@ -135,6 +150,7 @@ categories: ["zabbix"]
}
}
```
- 启动
```bash
/opt/nginx/sbin/nginx
@ -149,18 +165,23 @@ categories: ["zabbix"]
# 解压
tar zxf zabbix-3.0.10.tar.gz -C /root/
cd /root/zabbix-3.0.10/
# 安装依赖包
yum install snmp-devel curl-devel
# 创建安装目录
mkdir /opt/zabbix-server-3.0.10
ln -s /opt/zabbix-server-3.0.10 /opt/zabbix-server
# 检查编译环境
./configure --prefix=/opt/zabbix-server/ --enable-server \
--enable-agent --with-mysql --with-net-snmp --with-libcurl --with-libxml2
# 编译安装
make
make install
```
- 创建数据库
```bash
mysql -uroot -p12345678
@ -174,6 +195,7 @@ categories: ["zabbix"]
mysql -uzbx -pzbx_pass db_zbx < database/mysql/images.sql
mysql -uzbx -pzbx_pass db_zbx < database/mysql/date.sql
```
- 配置
```ini
# 在 /opt/zabbix-server/etc/zabbix_server.conf 中,修改如下配置
@ -181,10 +203,12 @@ categories: ["zabbix"]
DBName=db_zbx
DBUser=zbx
DBPassword=zbx_pass
# 这里的数据库是 mysql 且 DBHost 配置为 localhostzabbix 会使用 mysql.sock 连接 mysql
DBSocket=/tmp/mysql.sock
DBPort=3306
AllowRoot=1
# 在 /opt/zabbix-server/etc/zabbix_agentd.conf 中,修改如下配置
EnableRemoteCommands=1
Server=127.0.0.1
@ -192,6 +216,7 @@ categories: ["zabbix"]
Hostname=127.0.0.1
AllowRoot=1
```
- 启动
```bash
/opt/zabbix-server/sbin/zabbix_server
@ -203,6 +228,7 @@ categories: ["zabbix"]
```bash
cp -ar frontends/php /opt/nginx/html/zabbix
```
- 浏览器打开 http://192.168.1.100/zabbix/
- 根据界面提示配置数据库及相关 zabbix 信息,生成配置文件 /opt/nginx/html/zabbix/conf/zabbix.conf.php
- 修改 /opt/nginx/html/zabbix/conf/zabbix.conf.php
@ -216,7 +242,7 @@ categories: ["zabbix"]
- 浏览器输入 http://192.168.1.100/zabbix/
- 默认用户名: admin ,默认密码: zabbix
# 在被监控服务器 (192.168.1.101) 上安装 Zabbix Agent
# 安装 Zabbix Agent
- 推荐 Zabbix 3.0 及以上版本。
- 安装方式很多,这里使用官方源码编译:
- 下载 [zabbix-3.0.10.tar.gz](https://jaist.dl.sourceforge.net/project/zabbix/ZABBIX%20Latest%20Stable/3.0.10/zabbix-3.0.10.tar.gz) (同 server)
@ -225,14 +251,18 @@ categories: ["zabbix"]
# 解压
tar zxf zabbix-3.0.10.tar.gz -C /root/
cd /root/zabbix-3.0.10/
# 创建安装目录
mkdir /opt/zabbix
# 检查编译环境
./configure --prefix=/opt/zabbix --enable-agent
# 编译安装
make
make install
```
- 配置
```ini
# 在 /opt/zabbix/etc/zabbix-agentd.conf 中,修改如下配置
@ -242,6 +272,7 @@ categories: ["zabbix"]
Hostname=192.168.1.101
AllowRoot=1
```
- 启动
```bash
/opt/zabbix/sbin/zabbix_agentd