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 匹配函数匹配的字符串长度 RLENGTH | 被 match 匹配函数匹配的字符串长度
# 函数 # 函数
### 常用内置函数 ## 常用内置函数
函数 | 说明 函数 | 说明
---- | ---- ---- | ----
int(x) | 返回 x 的整数部分 int(x) | 返回 x 的整数部分
@ -58,7 +58,7 @@ nextfile | 停止处理当前文件,开始处理下一个文件
system(shell-command) | 返回命令退出状态 system(shell-command) | 返回命令退出状态
exit n | 终止 awk返回 n exit n | 终止 awk返回 n
### 自定义函数 ## 自定义函数
- 格式 - 格式
```awk ```awk
function fun_name(arg1, arg2, ...){ function fun_name(arg1, arg2, ...){
@ -68,15 +68,15 @@ exit n | 终止 awk返回 n
``` ```
# 判断语句 # 判断语句
```awk ```awk
if(条件){ if(条件){
# 语句 # 语句
}else if(条件){ }else if(条件){
# 语句 # 语句
}else{ }else{
# 语句 # 语句
} }
``` ```
# 循环语句 # 循环语句
- for - for
@ -104,23 +104,23 @@ if(条件){
- continue 退出本次循环,继续下一次循环 - continue 退出本次循环,继续下一次循环
# 脚本 # 脚本
```awk ```awk
#!/usr/bin/awk -f #!/usr/bin/awk -f
# 自定义的变量和函数 # 自定义的变量和函数
# ... # ...
# 从这里开始执行 # 从这里开始执行
BEGIN{ BEGIN{
# 语句 # 语句
} }
条件{ 条件{
# 语句 # 语句
} }
END{ END{
# 语句 # 语句
} }
``` ```
# 其他说明 # 其他说明
- 变量在使用时直接赋值即可,无需提前声明或定义 - 变量在使用时直接赋值即可,无需提前声明或定义

View File

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

View File

@ -7,19 +7,19 @@ categories: ["database"]
--- ---
# 安装依赖 # 安装依赖
```bash ```bash
yum install binutils compat-libstdc++-33 compat-libstdc++-33.i686 \ yum install binutils compat-libstdc++-33 compat-libstdc++-33.i686 \
elfutils-libelf elfutils-libelf-devel gcc gcc-c++ glibc glibc.i686 \ elfutils-libelf elfutils-libelf-devel gcc gcc-c++ glibc glibc.i686 \
glibc-common glibc-devel glibc-devel.i686 glibc-headers ksh libaio \ glibc-common glibc-devel glibc-devel.i686 glibc-headers ksh libaio \
libaio.i686 libaio-devel libaio-devel.i686 libgcc libgcc.i686 libstdc++ \ libaio.i686 libaio-devel libaio-devel.i686 libgcc libgcc.i686 libstdc++ \
libstdc++.i686 libstdc++-devel make sysstat unixODBC unixODBC-devel libstdc++.i686 libstdc++-devel make sysstat unixODBC unixODBC-devel
``` ```
# 创建用户和用户组 # 创建用户和用户组
```bash ```bash
groupadd dba oinstall groupadd dba oinstall
useradd -g oinstall -m oracle useradd -g oinstall -m oracle
``` ```
# 配置oracle用户环境变量 # 配置oracle用户环境变量
- 打开 oracle 用户的的默认shell配置文件 ~/.bashrc在最后添加以下代码 - 打开 oracle 用户的的默认shell配置文件 ~/.bashrc在最后添加以下代码
@ -32,16 +32,17 @@ useradd -g oinstall -m oracle
#export NLS_LANG="SIMPLIFIED CHINESE_CHINA.AL32UTF8" #设置Oracle客户端中文utf8 #export NLS_LANG="SIMPLIFIED CHINESE_CHINA.AL32UTF8" #设置Oracle客户端中文utf8
export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK #设置Oracle客户端中文gbk export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK #设置Oracle客户端中文gbk
``` ```
- 使设置立刻生效 - 使设置立刻生效
```bash ```bash
source /.bashrc source /.bashrc
``` ```
# 创建oracle 11g软件安装路径 # 创建oracle 11g软件安装路径
```bash ```bash
mkdir /opt/oracle/app/product/11.2.0/db_home1 -p mkdir /opt/oracle/app/product/11.2.0/db_home1 -p
chown oracle.oinstall /opt/oracle -R chown oracle.oinstall /opt/oracle -R
``` ```
# 配置内核参数 # 配置内核参数
- 编辑 /etc/sysctl.conf在文件尾追加下面的参数设置 - 编辑 /etc/sysctl.conf在文件尾追加下面的参数设置
@ -55,6 +56,7 @@ chown oracle.oinstall /opt/oracle -R
net.core.wmem_max = 1048576 net.core.wmem_max = 1048576
kernel.sem = 250 32000 100 128 kernel.sem = 250 32000 100 128
``` ```
- 使设置生效 - 使设置生效
```bash ```bash
sysctl -p sysctl -p
@ -84,39 +86,44 @@ chown oracle.oinstall /opt/oracle -R
unzip linux.x64_11gR2_database_2of2.zip -d /home/oracle/ unzip linux.x64_11gR2_database_2of2.zip -d /home/oracle/
chown oracle.oinstall /home/oracle/database/ -R chown oracle.oinstall /home/oracle/database/ -R
``` ```
- **切换到 oracle 用户下**,运行安装程序 - **切换到 oracle 用户下**,运行安装程序
```bash ```bash
su - oracle su - oracle
cd database cd database
./runInstaller ./runInstaller
``` ```
- 若提示swap空间不足自行百度解决 - 若提示swap空间不足自行百度解决
# 配置监听器数据库 # 配置监听器数据库
- Oracle软件安装完后执行 netca 命令配置监听器 - Oracle软件安装完后执行 netca 命令配置监听器
``` ```
netca netca
``` ```
- 在图形界面中按提示配置监听器 - 在图形界面中按提示配置监听器
- 执行 dbca 命令安装数据库 - 执行 dbca 命令安装数据库
```bash ```bash
dbca dbca
``` ```
- 在图形界面中按提示安装数据库就可以了。 - 在图形界面中按提示安装数据库就可以了。
# 测试运行 # 测试运行
- 数据库安装完后监听器与数据库实例就已启动, - 数据库安装完后监听器与数据库实例就已启动,
- 停止和启动监听器 - 停止和启动监听器
```bash ```bash
lsnrctl stop lsnrctl stop
lsnrctl start lsnrctl start
``` ```
- 停止和启动实例
``` - 停止和启动实例
sqlplus /nolog ```
SQL> connect / as sysdba; sqlplus /nolog
SQL> shutdown SQL> connect / as sysdba;
SQL> startup SQL> shutdown
#执行其它SQL语句测试数据库 SQL> startup
``` # 执行其它SQL语句测试数据库
```

View File

@ -12,9 +12,9 @@ categories: ["storage"]
- 关闭 selinux - 关闭 selinux
# 安装 vsftpd 服务 # 安装 vsftpd 服务
```bash ```bash
yum install vsftpd yum install vsftpd
``` ```
# 常用客户端 # 常用客户端
- ftp - ftp
@ -54,69 +54,69 @@ yum install vsftpd
``` ```
# 匿名用户配置 # 匿名用户配置
```ini ```ini
# 控制是否允许匿名用户登入 # 控制是否允许匿名用户登入
# 匿名用户使用的登陆名为 ftp 或 anonymous口令为空 # 匿名用户使用的登陆名为 ftp 或 anonymous口令为空
# 匿名用户不能离开匿名用户家目录/var/ftp且只能下载不能上传 # 匿名用户不能离开匿名用户家目录/var/ftp且只能下载不能上传
anonymous_enable=YES/NO(YES) anonymous_enable=YES/NO(YES)
# 匿名登入时,不会询问密码 # 匿名登入时,不会询问密码
no_anon_password=YES/NO(NO) no_anon_password=YES/NO(NO)
# 定义匿名登入的使用者名称默认值为ftp # 定义匿名登入的使用者名称默认值为ftp
ftp_username=ftp ftp_username=ftp
# 是否允许登陆用户有写权限,属于全局设置 # 是否允许登陆用户有写权限,属于全局设置
write_enable=YES/NO(YES) write_enable=YES/NO(YES)
# 使用匿名登入时,所登入的目录,默认值为/var/ftp # 使用匿名登入时,所登入的目录,默认值为/var/ftp
# 注意ftp目录不能是777的权限属性即匿名用户的家目录不能有777的权限 # 注意ftp目录不能是777的权限属性即匿名用户的家目录不能有777的权限
anon_root=/var/ftp anon_root=/var/ftp
# 是否允许匿名者有上传文件(非目录)的权限 # 是否允许匿名者有上传文件(非目录)的权限
# 只有在write_enable=YES时此项才有效 # 只有在write_enable=YES时此项才有效
# 匿名用户必须要有对上层目录的写入权 # 匿名用户必须要有对上层目录的写入权
anon_upload_enable=YES/NO(NO) anon_upload_enable=YES/NO(NO)
# 是否允许匿名者下载可阅读的档案 # 是否允许匿名者下载可阅读的档案
anon_world_readable_only=YES/NO(YES) anon_world_readable_only=YES/NO(YES)
# 是否允许匿名者有新增目录的权限 # 是否允许匿名者有新增目录的权限
# 只有在write_enable=YES时此项才有效 # 只有在write_enable=YES时此项才有效
# 匿名用户必须要有对上层目录的写入权 # 匿名用户必须要有对上层目录的写入权
anon_mkdir_write_enable=YES/NO(NO) anon_mkdir_write_enable=YES/NO(NO)
# 是否允许匿名入者拥有其他权限,譬如删除或者重命名 # 是否允许匿名入者拥有其他权限,譬如删除或者重命名
# 如果anon_upload_enable=NO则匿名用户不能上传文件但可以删除或者重命名已经存在的文件 # 如果anon_upload_enable=NO则匿名用户不能上传文件但可以删除或者重命名已经存在的文件
# 如果anon_mkdir_write_enable=NO则匿名用户不能上传或者新建文件夹但可以删除或者重命名已经存在的目录 # 如果anon_mkdir_write_enable=NO则匿名用户不能上传或者新建文件夹但可以删除或者重命名已经存在的目录
anon_other_write_enable=YES/NO(NO) anon_other_write_enable=YES/NO(NO)
# 是否改变匿名用户上传文件(非目录)的属主 # 是否改变匿名用户上传文件(非目录)的属主
chown_uploads=YES/NO(NO) chown_uploads=YES/NO(NO)
# 设置匿名用户上传文件(非目录)的属主名 # 设置匿名用户上传文件(非目录)的属主名
# 建议不要设置为root # 建议不要设置为root
chown_username=username chown_username=username
# 设置匿名登入者新增或上传档案时的 umask 值,默认值为 077 # 设置匿名登入者新增或上传档案时的 umask 值,默认值为 077
anon_umask=077 anon_umask=077
``` ```
# 配置 # 配置
## 常用配置 ## 常用配置
```ini ```ini
#允许匿名用户登陆 #允许匿名用户登陆
anonymous_enable=YES anonymous_enable=YES
#允许本地用户登陆 #允许本地用户登陆
local_enable=YES local_enable=YES
#允许登陆用户写可访问的目录或文件 #允许登陆用户写可访问的目录或文件
write_enable=YES write_enable=YES
#指定用户登陆后直接进入系统的/mnt目录 #指定用户登陆后直接进入系统的/mnt目录
local_root=/mnt local_root=/mnt
chroot_list_enable=YES chroot_list_enable=YES
#限定登陆用户可访问的目录只有自己的家目录或指定的local_root目录 #限定登陆用户可访问的目录只有自己的家目录或指定的local_root目录
chroot_list_file=/etc/vsftpd/chroot_list chroot_list_file=/etc/vsftpd/chroot_list
``` ```
## 允许 vsftpd 匿名用户上传和下载 ## 允许 vsftpd 匿名用户上传和下载
- 创建匿名用户登陆目录 - 创建匿名用户登陆目录

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

@ -7,103 +7,103 @@ categories: ["os"]
--- ---
# 常用设置 # 常用设置
```bash ```bash
# 关闭左上角热响应 # 关闭左上角热响应
gsettings set org.gnome.desktop.interface enable-hot-corners false gsettings set org.gnome.desktop.interface enable-hot-corners false
# 缩放系统字体 # 缩放系统字体
gsettings set org.gnome.desktop.interface text-scaling-factor 1.5 gsettings set org.gnome.desktop.interface text-scaling-factor 1.5
# monospace 字体 # monospace 字体
gsettings set org.gnome.desktop.interface monospace-font-name 'YaHei Consolas Hybrid 15' gsettings set org.gnome.desktop.interface monospace-font-name 'YaHei Consolas Hybrid 15'
# gtk 主题 # gtk 主题
gsettings set org.gnome.desktop.interface gtk-theme 'Vertex-Dark' gsettings set org.gnome.desktop.interface gtk-theme 'Vertex-Dark'
# gnome-shell 主题 # gnome-shell 主题
gsettings set org.gnome.shell.extensions.user-theme name 'Vertex' gsettings set org.gnome.shell.extensions.user-theme name 'Vertex'
# 图标主题 # 图标主题
gsettings set org.gnome.desktop.interface icon-theme 'Faenza' gsettings set org.gnome.desktop.interface icon-theme 'Faenza'
# 调整 gnome3 桌面(包括 gdm )放大级别 # 调整 gnome3 桌面(包括 gdm )放大级别
# 0 系统自动缩放 # 0 系统自动缩放
# n > 0 放大 n 倍 # n > 0 放大 n 倍
gsettings set org.gnome.desktop.interface scaling-factor 1 gsettings set org.gnome.desktop.interface scaling-factor 1
# 启用用户扩展 # 启用用户扩展
gsettings set org.gnome.shell disable-user-extensions false gsettings set org.gnome.shell disable-user-extensions false
gsettings set org.gnome.shell enabled-extensions "['user-theme@gnome-shell-extensions.gcampax.github.com', 'workspace-indicator@gnome-shell-extensions.gcampax.github.com', 'dash-to-panel@jderose9.github.com']" gsettings set org.gnome.shell enabled-extensions "['user-theme@gnome-shell-extensions.gcampax.github.com', 'workspace-indicator@gnome-shell-extensions.gcampax.github.com', 'dash-to-panel@jderose9.github.com']"
# 工作区 # 工作区
gsettings set org.gnome.mutter dynamic-workspaces false gsettings set org.gnome.mutter dynamic-workspaces false
gsettings set org.gnome.desktop.wm.preferences num-workspaces 4 gsettings set org.gnome.desktop.wm.preferences num-workspaces 4
gsettings set org.gnome.desktop.wm.preferences workspace-names "['乾坤', '巽震', '坎离', '艮兑']" gsettings set org.gnome.desktop.wm.preferences workspace-names "['乾坤', '巽震', '坎离', '艮兑']"
# 窗口按钮 # 窗口按钮
gsettings set org.gnome.desktop.wm.preferences button-layout 'appmenu:minimize,maximize,close' gsettings set org.gnome.desktop.wm.preferences button-layout 'appmenu:minimize,maximize,close'
``` ```
# 在 "活动" 中创建 "文件夹" # 在 "活动" 中创建 "文件夹"
```bash ```bash
# 创建文件夹 # 创建文件夹
gsettings set org.gnome.desktop.app-folders folder-children "['Office','VirtualBox']" gsettings set org.gnome.desktop.app-folders folder-children "['Office','VirtualBox']"
# 指定文件夹名字 # 指定文件夹名字
gsettings set org.gnome.desktop.app-folders.folder:/org/gnome/desktop/app-folders/folders/Office/ name "Office" gsettings set org.gnome.desktop.app-folders.folder:/org/gnome/desktop/app-folders/folders/Office/ name "Office"
gsettings set org.gnome.desktop.app-folders.folder:/org/gnome/desktop/app-folders/folders/VirtualBox/ name "VirtualBox" gsettings set org.gnome.desktop.app-folders.folder:/org/gnome/desktop/app-folders/folders/VirtualBox/ name "VirtualBox"
# 指定文件夹包含的应用类别 # 指定文件夹包含的应用类别
gsettings set org.gnome.desktop.app-folders.folder:/org/gnome/desktop/app-folders/folders/Office/ categories "['Office']" gsettings set org.gnome.desktop.app-folders.folder:/org/gnome/desktop/app-folders/folders/Office/ categories "['Office']"
gsettings set org.gnome.desktop.app-folders.folder:/org/gnome/desktop/app-folders/folders/VirtualBox/ categories "['Emulator']" gsettings set org.gnome.desktop.app-folders.folder:/org/gnome/desktop/app-folders/folders/VirtualBox/ categories "['Emulator']"
``` ```
# 快捷键 # 快捷键
```bash ```bash
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 "[]" gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 "[]"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-last "[]" gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-last "[]"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-up "['<Super>Up']" gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-up "['<Super>Up']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-down "['<Super>Down']" gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-down "['<Super>Down']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-left "['<Super>Left']" gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-left "['<Super>Left']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-right "['<Super>Right']" gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-right "['<Super>Right']"
gsettings set org.gnome.desktop.wm.keybindings switch-applications "[]" gsettings set org.gnome.desktop.wm.keybindings switch-applications "[]"
gsettings set org.gnome.desktop.wm.keybindings switch-applications-backward "[]" gsettings set org.gnome.desktop.wm.keybindings switch-applications-backward "[]"
gsettings set org.gnome.desktop.wm.keybindings switch-windows "['<Alt>Tab']" gsettings set org.gnome.desktop.wm.keybindings switch-windows "['<Alt>Tab']"
gsettings set org.gnome.desktop.wm.keybindings switch-windows-backward "['<Shift><Alt>Tab']" gsettings set org.gnome.desktop.wm.keybindings switch-windows-backward "['<Shift><Alt>Tab']"
gsettings set org.gnome.shell.window-switcher current-workspace-only true gsettings set org.gnome.shell.window-switcher current-workspace-only true
gsettings set org.gnome.shell.window-switcher app-icon-mode both gsettings set org.gnome.shell.window-switcher app-icon-mode both
gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-down "['<Alt><Super>Down']" gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-down "['<Alt><Super>Down']"
gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-up "['<Alt><Super>Up']" gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-up "['<Alt><Super>Up']"
gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-last "[]" gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-last "[]"
gsettings set org.gnome.desktop.wm.keybindings move-to-monitor-up "[]" gsettings set org.gnome.desktop.wm.keybindings move-to-monitor-up "[]"
gsettings set org.gnome.desktop.wm.keybindings move-to-monitor-right "[]" gsettings set org.gnome.desktop.wm.keybindings move-to-monitor-right "[]"
gsettings set org.gnome.desktop.wm.keybindings move-to-monitor-left "[]" gsettings set org.gnome.desktop.wm.keybindings move-to-monitor-left "[]"
gsettings set org.gnome.desktop.wm.keybindings move-to-monitor-down "[]" gsettings set org.gnome.desktop.wm.keybindings move-to-monitor-down "[]"
gsettings set org.gnome.desktop.wm.keybindings show-desktop "['<Super>d']" gsettings set org.gnome.desktop.wm.keybindings show-desktop "['<Super>d']"
gsettings set org.gnome.desktop.wm.keybindings toggle-maximized "['<Primary><Super>Up']" gsettings set org.gnome.desktop.wm.keybindings toggle-maximized "['<Primary><Super>Up']"
gsettings set org.gnome.desktop.wm.keybindings minimize "['<Primary><Super>Down']" gsettings set org.gnome.desktop.wm.keybindings minimize "['<Primary><Super>Down']"
gsettings set org.gnome.desktop.wm.keybindings maximize "[]" gsettings set org.gnome.desktop.wm.keybindings maximize "[]"
``` ```
# 在 CentOS6 下安装 gnome 桌面 # 在 CentOS6 下安装 gnome 桌面
```bash ```bash
yum groupinstall 'X Window System' yum groupinstall 'X Window System'
yum groupinstall Desktop yum groupinstall Desktop
sed -i '/^id/id:5:initdefault:' /etc/inittab sed -i '/^id/id:5:initdefault:' /etc/inittab
``` ```
# 在 CentOS7 下安装 gnome3 桌面 # 在 CentOS7 下安装 gnome3 桌面
```bash ```bash
yum groupinstall 'X Window System' yum groupinstall 'X Window System'
yum groupinstall 'Gnome Desktop' yum groupinstall 'Gnome Desktop'
systemctl set-default graphical.target systemctl set-default graphical.target
systemctl enable gdm systemctl enable gdm
# 创建一个可登陆的普通用户 # 创建一个可登陆的普通用户
``` ```
# 在 gdm 中隐藏用户名 # 在 gdm 中隐藏用户名
- 修改文件/etc/gdm/gdm.schemas找到这一段 - 修改文件/etc/gdm/gdm.schemas找到这一段

View File

@ -9,7 +9,7 @@ categories: ["container"]
# kubeadm 安装 kubernetes # kubeadm 安装 kubernetes
### 全部服务器配置 ## 全部服务器配置
IP 地址 | 主机名 | 操作系统 | 内存 | swap | 硬盘 | Internet | firewalld | selinux | /etc/hosts 增加行 IP 地址 | 主机名 | 操作系统 | 内存 | swap | 硬盘 | Internet | firewalld | selinux | /etc/hosts 增加行
--------- | -------- | -------- | ---- | ---- | ---- | -------- | --------- | ------- | ------------------ --------- | -------- | -------- | ---- | ---- | ---- | -------- | --------- | ------- | ------------------
10.0.2.80 | master80 | CentOS7 | 4GB | 关闭 | 20GB | 可达 | 关闭 | 关闭 | 127.0.0.1 master80 10.0.2.80 | master80 | CentOS7 | 4GB | 关闭 | 20GB | 可达 | 关闭 | 关闭 | 127.0.0.1 master80
@ -76,7 +76,7 @@ categories: ["container"]
``` ```
### 安装 docker ## 安装 docker
- 各服务器安装 docker - 各服务器安装 docker
```bash ```bash
yum install docker yum install docker
@ -106,7 +106,7 @@ categories: ["container"]
``` ```
### 安装 kubernetes ## 安装 kubernetes
- 各服务器配置 kubernetes yum 源 - 各服务器配置 kubernetes yum 源
```bash ```bash
cat <<EOF > /etc/yum.repos.d/kubernetes.repo cat <<EOF > /etc/yum.repos.d/kubernetes.repo
@ -132,7 +132,7 @@ categories: ["container"]
``` ```
### 在 master80 服务器上安装 kubernetes master 服务组件 ## 在 master80 服务器上安装 kubernetes master 服务组件
- 初始化 kubeadm - 初始化 kubeadm
```bash ```bash
kubeadm init --pod-network-cidr=192.168.0.0/16 --token-ttl 0 kubeadm init --pod-network-cidr=192.168.0.0/16 --token-ttl 0
@ -148,7 +148,7 @@ categories: ["container"]
``` ```
### 加入其他节点 ## 加入其他节点
- 在 node81 和 node82 服务器上执行以下命令,即 master80 服务器 'kuberadm init' 命令的最后一行输出 - 在 node81 和 node82 服务器上执行以下命令,即 master80 服务器 'kuberadm init' 命令的最后一行输出
```bash ```bash
kubeadm join --token <token> <master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash> 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"] categories: ["web"]
--- ---
## 安装 certbot # 安装 certbot
- 在 alpine linux 中安装 certbot - 在 alpine linux 中安装 certbot
```bash ```bash
apk add --no-cache certbot openssl apk add --no-cache certbot openssl
@ -18,7 +18,7 @@ categories: ["web"]
certbot register --register-unsafely-without-email --agree-tos certbot register --register-unsafely-without-email --agree-tos
``` ```
## 普通域名证书 # 普通域名证书
- 申请 ssl 证书,有效期 90 天 - 申请 ssl 证书,有效期 90 天
```bash ```bash
certbot certonly -n -d x.x.com --standalone certbot certonly -n -d x.x.com --standalone
@ -38,7 +38,7 @@ categories: ["web"]
openssl dhparam -out /etc/letsencrypt/dhparam.pem 2048 openssl dhparam -out /etc/letsencrypt/dhparam.pem 2048
``` ```
## 通配域名证书 # 通配域名证书
- 申请 ssl 证书,有效期 90 天 - 申请 ssl 证书,有效期 90 天
```bash ```bash
certbot certonly --manual -d '*.x.com' \ certbot certonly --manual -d '*.x.com' \
@ -61,7 +61,7 @@ categories: ["web"]
openssl dhparam -out /etc/letsencrypt/dhparam.pem 2048 openssl dhparam -out /etc/letsencrypt/dhparam.pem 2048
``` ```
## 使用证书 # 使用证书
- nginx 配置 ssl - nginx 配置 ssl
``` ```
server { server {

View File

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

View File

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

View File

@ -9,85 +9,74 @@ categories: ["database"]
环境centos 5.4/6.2/6.5/7.2 x64 环境centos 5.4/6.2/6.5/7.2 x64
1、下载官方编译好的 linux 通用安装包,解压之自定义目录(如/opt 1、下载官方编译好的 linux 通用安装包,解压之自定义目录(如/opt
```bash
```bash # rhel 7 地址:
# 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
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 # rhel 5/6 地址:
# rhel 5/6 地址: wget https://mirrors.tuna.tsinghua.edu.cn/mariadb//mariadb-10.1.19/bintar-linux-x86_64/mariadb-10.1.19-linux-x86_64.tar.gz
wget https://mirrors.tuna.tsinghua.edu.cn/mariadb//mariadb-10.1.19/bintar-linux-x86_64/mariadb-10.1.19-linux-x86_64.tar.gz tar zxf mariadb-10.1.19-linux*-x86_64.tar.gz -C /opt/
tar zxf mariadb-10.1.19-linux*-x86_64.tar.gz -C /opt/ cd /opt;mv mariadb-10.1.19-linux* mariadb
cd /opt;mv mariadb-10.1.19-linux* mariadb ```
```
2、创建服务文件和配置文件创建日志目录 2、创建服务文件和配置文件创建日志目录
```bash
``` cd /opt/mariadb
cd /opt/mariadb mv support_files/my-large.cnf ./my.cnf
mv support_files/my-large.cnf ./my.cnf mv support_files/mysql.server ./mysqld
mv support_files/mysql.server ./mysqld mkdir -p log
mkdir -p log ```
```
3、修改服务文件 mysqld 3、修改服务文件 mysqld
```
``` vim /opt/mariadb/mysqld
vim /opt/mariadb/mysqld # 在打开的文件中修改开头的basedir和datadirdatadir是数据库文件目录建议指定一个大分区中的目录
# 在打开的文件中修改开头的basedir和datadirdatadir是数据库文件目录建议指定一个大分区中的目录 basedir=/opt/mariadb
basedir=/opt/mariadb datadir=/mnt/sdb1/mariadb_db
datadir=/mnt/sdb1/mariadb_db # 修改开头的lockdir和lock-file-path
# 修改开头的lockdir和lock-file-path lockdir='/opt/mariadb/log'
lockdir='/opt/mariadb/log' lock-file-path="$lockdir/mysql.lock"
lock-file-path="$lockdir/mysql.lock" ```
```
4、修改配置文件 /opt/mariadb/my.cnf 4、修改配置文件 /opt/mariadb/my.cnf
```ini
``` [mysqld]
[mysqld] datadir=/mnt/sdb1/mariadb_db
datadir=/mnt/sdb1/mariadb_db log-error=/opt/mariadb/log/error.log
log-error=/opt/mariadb/log/error.log pid-file=/opt/mariadb/log/mysql.pid
pid-file=/opt/mariadb/log/mysql.pid user = mysql
user = mysql #port = 3306
#port = 3306 socket = /tmp/mysql.sock
socket = /tmp/mysql.sock skip-networking # 取消监听端口,适合本地数据库使用
skip-networking # 取消监听端口,适合本地数据库使用 skip-name-resolve # 取消域名解析
skip-name-resolve # 取消域名解析 max-connections = 3000
max-connections = 3000 max-connect-errors = 1000
max-connect-errors = 1000 #如果系统中存在 /etc/my.cnf 且不可写, 可以在 /opt/mariadb/my.cnf 中重新设置冲突项。
```
#如果系统中存在 /etc/my.cnf 且不可写, 可以在 /opt/mariadb/my.cnf 中重新设置冲突项。
```
5、修改数据库程序数据目录的权限: 5、修改数据库程序数据目录的权限:
```bash
```bash chown mysql.mysql /opt/mariadb/ -R
chown mysql.mysql /opt/mariadb/ -R chown mysql.mysql /mnt/sdb1/mariadb_db/ -R
chown mysql.mysql /mnt/sdb1/mariadb_db/ -R ```
```
6、安装数据库 6、安装数据库
```bash
```bash /opt/mariadb/scripts/mysql_install_db --basedir=/opt/mariadb --datadir=/mnt/sdb1/mariadb_db --user=mysql
/opt/mariadb/scripts/mysql_install_db --basedir=/opt/mariadb --datadir=/mnt/sdb1/mariadb_db --user=mysql ```
```
7、根据提示修改mariadb的root帐号密码禁用root登陆删除匿名用户及test库 7、根据提示修改mariadb的root帐号密码禁用root登陆删除匿名用户及test库
```bash
```bash # 启动 mariadb
# 启动 mariadb /opt/mariadb/mysqld start
/opt/mariadb/mysqld start # 修改 root 密码
# 修改 root 密码 /opt/mariadb/bin/mysqladmin -u root password '12345678'
/opt/mariadb/bin/mysqladmin -u root password '12345678' # 安全设置
# 安全设置 /opt/mariadb/bin/mysql_secure_install --basedir=/opt/mariadb
/opt/mariadb/bin/mysql_secure_install --basedir=/opt/mariadb ```
```
8、增加系统动态库配置 8、增加系统动态库配置
```bash
```bash echo '/opt/mariadb/lib' >> /etc/ld.so.conf
echo '/opt/mariadb/lib' >> /etc/ld.so.conf ldconfig
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/) - [下载 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-client.rpm
- MariaDB-10.1.33-centos7-x86_64-common.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 mysql_install_db --user=mysql
``` ```
### yum 安装 ## yum 安装
- 创建 MariaDB-10.1 的 yum 源文件(就近选择一个) - 创建 MariaDB-10.1 的 yum 源文件(就近选择一个)
```bash ```bash
#官方 #官方
@ -61,6 +61,7 @@ cpu | mem | hostname | public ip | cluster ip | CentOS | MariaDB
gpgcheck=1 gpgcheck=1
END END
``` ```
- 安装 MariaDB - 安装 MariaDB
```bash ```bash
yum install MariaDB-client MariaDB-server yum install MariaDB-client MariaDB-server
@ -68,9 +69,9 @@ cpu | mem | hostname | public ip | cluster ip | CentOS | MariaDB
``` ```
# 启动server # 启动server
```bash ```bash
systemctl start mariadb systemctl start mariadb
``` ```
# 安全设置 # 安全设置
- 设置root账户密码推荐 - 设置root账户密码推荐

View File

@ -13,116 +13,116 @@ categories: ["database"]
- 忽略系统数据库: information_schema, mysql, performance_schema - 忽略系统数据库: information_schema, mysql, performance_schema
# 在两个主服务器上创建用于备份的用户 replicator # 在两个主服务器上创建用于备份的用户 replicator
```sql ```sql
grant replication slave on *.* to 'replicator'@'%' identified by 'password'; grant replication slave on *.* to 'replicator'@'%' identified by 'password';
flush privileges; flush privileges;
``` ```
# 在两个主服务器上修改 my.cnf # 在两个主服务器上修改 my.cnf
``` ```
# 唯一 ID # 唯一 ID
# 192.168.1.141 配置 # 192.168.1.141 配置
server-id = 141 server-id = 141
# 192.168.1.142 配置 # 192.168.1.142 配置
server-id = 142 server-id = 142
read-only = 0 read-only = 0
# binlog # binlog
# MariaDB 默认已开启 GTID # MariaDB 默认已开启 GTID
log-bin = /var/lib/mysql-bin/master log-bin = /var/lib/mysql-bin/master
binlog-format = row binlog-format = row
sync_binlog = 1 sync_binlog = 1
expire-logs-days = 3 expire-logs-days = 3
gtid-strict-mode = ON gtid-strict-mode = ON
# relay log # relay log
replicate-wild-ignore-table = information_schema.% replicate-wild-ignore-table = information_schema.%
replicate-wild-ignore-table = init_sql.% replicate-wild-ignore-table = init_sql.%
replicate-wild-ignore-table = mysql.% replicate-wild-ignore-table = mysql.%
replicate-wild-ignore-table = performance_schema.% replicate-wild-ignore-table = performance_schema.%
relay-log = /var/lib/mysql-bin/slave relay-log = /var/lib/mysql-bin/slave
relay-log-recovery = TRUE relay-log-recovery = TRUE
# 复制线程数不超过 cpu 核数 # 复制线程数不超过 cpu 核数
slave-parallel-threads = 4 slave-parallel-threads = 4
# 双主或多主互备时,可能会用到以下配置 # 双主或多主互备时,可能会用到以下配置
# 自增主键初始值,与其他互备服务器一致 # 自增主键初始值,与其他互备服务器一致
#auto-increment-offset = #auto-increment-offset =
# 自增主键等差值,与其他互备服务器均不一致 # 自增主键等差值,与其他互备服务器均不一致
#auto-increment-increment = #auto-increment-increment =
# 该环境中,双主配合 keepalived 实现高可用,无需配置自增 # 该环境中,双主配合 keepalived 实现高可用,无需配置自增
``` ```
# 开启互主同步 # 开启互主同步
```sql ```sql
-- 在 192.168.1.141 上启动 mariadb配置同步 192.168.1.142: -- 在 192.168.1.141 上启动 mariadb配置同步 192.168.1.142:
change master to master_host = '192.168.1.142', change master to master_host = '192.168.1.142',
master_port = 3306, master_port = 3306,
master_user = 'replicator', master_user = 'replicator',
master_password = 'password', master_password = 'password',
master_use_gtid = slave_pos; master_use_gtid = slave_pos;
-- 在 192.168.1.142 上启动 mariadb配置同步 192.168.1.141: -- 在 192.168.1.142 上启动 mariadb配置同步 192.168.1.141:
change master to master_host = '192.168.1.141', change master to master_host = '192.168.1.141',
master_port = 3306, master_port = 3306,
master_user = 'replicator', master_user = 'replicator',
master_password = 'password', master_password = 'password',
master_use_gtid = slave_pos; master_use_gtid = slave_pos;
``` ```
# 在两个主服务器上启动 slave ,查看 slave 状态 # 在两个主服务器上启动 slave ,查看 slave 状态
```sql ```sql
start slave; start slave;
-- 查看 slave 状态 -- 查看 slave 状态
show slave status\G show slave status\G
-- 如果看到 -- 如果看到
-- Slave_IO_Running: Yes -- Slave_IO_Running: Yes
-- Slave_SQL_Running: Yes -- Slave_SQL_Running: Yes
-- 则表示 slave 开启成功! -- 则表示 slave 开启成功!
``` ```
# 在从服务器上编辑 my.cnf # 在从服务器上编辑 my.cnf
``` ```
# 唯一 ID # 唯一 ID
server-id = 143 server-id = 143
# 从服务器只做查询,无增删改 # 从服务器只做查询,无增删改
read-only = 1 read-only = 1
# 忽略的数据表 # 忽略的数据表
#replicate-ignore-table = db1.t1 #replicate-ignore-table = db1.t1
replicate-wild-ignore-table = information_schema.% replicate-wild-ignore-table = information_schema.%
replicate-wild-ignore-table = init_sql.% replicate-wild-ignore-table = init_sql.%
replicate-wild-ignore-table = mysql.% replicate-wild-ignore-table = mysql.%
replicate-wild-ignore-table = performance_schema.% replicate-wild-ignore-table = performance_schema.%
relay-log = /var/log/mysql-bin/slave relay-log = /var/log/mysql-bin/slave
slave-parallel-threads = 4 slave-parallel-threads = 4
``` ```
# 开启同步 # 开启同步
```sql ```sql
change master 'db141' to master_host = '192.168.1.141', change master 'db141' to master_host = '192.168.1.141',
master_port = 3306, master_port = 3306,
master_user = 'replicator', master_user = 'replicator',
master_password = 'password', master_password = 'password',
master_use_gtid = slave_pos; master_use_gtid = slave_pos;
change master 'db142' to master_host = '192.168.1.142', change master 'db142' to master_host = '192.168.1.142',
master_port = 3306, master_port = 3306,
master_user = 'replicator', master_user = 'replicator',
master_password = 'password', master_password = 'password',
master_use_gtid = slave_pos; master_use_gtid = slave_pos;
``` ```
# 在从服务器上启动 slave ,查看 slave 状态 # 在从服务器上启动 slave ,查看 slave 状态
```sql ```sql
start all slaves; start all slaves;
-- 在从服务器上查看 slave 状态 -- 在从服务器上查看 slave 状态
show all slaves status\G show all slaves status\G
-- 如果看到 -- 如果看到
-- Slave_IO_Running: Yes -- Slave_IO_Running: Yes
-- Slave_SQL_Running: Yes -- Slave_SQL_Running: Yes
-- 则表示 slave 开启成功! -- 则表示 slave 开启成功!
``` ```
# 参考 # 参考
- [MariaDB 复制](https://mariadb.com/kb/en/standard-replication/) - [MariaDB 复制](https://mariadb.com/kb/en/standard-replication/)

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

View File

@ -15,79 +15,79 @@ cpu | mem | hostname | public ip | cluster ip | CentOS | MySQL
双核 | 2GB | mysql_3 | 10.0.0.233 | 10.10.10.3 | 7.5 | 5.7 双核 | 2GB | mysql_3 | 10.0.0.233 | 10.10.10.3 | 7.5 | 5.7
# 创建 galera yum 源文件 # 创建 galera yum 源文件
```bash ```bash
cat > /etc/yum.repos.d/galera.repo <<-END cat > /etc/yum.repos.d/galera.repo <<-END
[galera] [galera]
name = Galera name = Galera
baseurl = http://releases.galeracluster.com/galera-3/centos/7/x86_64/ baseurl = http://releases.galeracluster.com/galera-3/centos/7/x86_64/
gpgkey = http://releases.galeracluster.com/GPG-KEY-galeracluster.com gpgkey = http://releases.galeracluster.com/GPG-KEY-galeracluster.com
gpgcheck = 1 gpgcheck = 1
#
[mysql-wsrep] [mysql-wsrep]
name = MySQL-wsrep name = MySQL-wsrep
baseurl = http://releases.galeracluster.com/mysql-wsrep-5.7/centos/7/x86_64/ baseurl = http://releases.galeracluster.com/mysql-wsrep-5.7/centos/7/x86_64/
gpgkey = http://releases.galeracluster.com/GPG-KEY-galeracluster.com gpgkey = http://releases.galeracluster.com/GPG-KEY-galeracluster.com
gpgcheck = 1 gpgcheck = 1
END END
``` ```
# 安装 # 安装
```bash ```bash
yum install galera-3 mysql-wsrep-5.7 rsync yum install galera-3 mysql-wsrep-5.7 rsync
``` ```
# 修改 /etc/my.cnf # 修改 /etc/my.cnf
``` ```
[mysqld] [mysqld]
datadir=/var/lib/mysql datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock socket=/var/lib/mysql/mysql.sock
user=mysql user=mysql
binlog-format=ROW binlog-format=ROW
bind-address=0.0.0.0 bind-address=0.0.0.0
default-storage-engine=innodb default-storage-engine=innodb
innodb-autoinc-lock-mode=2 innodb-autoinc-lock-mode=2
innodb-flush-log-at-trx-commit=0 innodb-flush-log-at-trx-commit=0
innodb-buffer-pool-size=1024M #物理内存一半 innodb-buffer-pool-size=1024M #物理内存一半
wsrep-provider=/usr/lib64/galera-3/libgalera_smm.so wsrep-provider=/usr/lib64/galera-3/libgalera_smm.so
wsrep-provider-options="gcache.dir=/var/lib/gcache;gcache.size=1G;gcache.recover=yes;pc.recovery=TRUE" wsrep-provider-options="gcache.dir=/var/lib/gcache;gcache.size=1G;gcache.recover=yes;pc.recovery=TRUE"
wsrep-cluster-name="mysql_galera_cluster" #集群名字 wsrep-cluster-name="mysql_galera_cluster" #集群名字
wsrep-cluster-address="gcomm://10.10.10.1,10.10.10.2,10.10.10.3" wsrep-cluster-address="gcomm://10.10.10.1,10.10.10.2,10.10.10.3"
wsrep-sst-method=rsync wsrep-sst-method=rsync
wsrep-node-name=mysql_1 #当前节点名字 wsrep-node-name=mysql_1 #当前节点名字
wsrep-node-address="10.10.10.1" #当前节点 cluster ip wsrep-node-address="10.10.10.1" #当前节点 cluster ip
#wsrep-auto-increment-control=OFF #只通过一个节点做增删改时使用 #wsrep-auto-increment-control=OFF #只通过一个节点做增删改时使用
#
[mysql_safe] [mysql_safe]
log-error=/var/log/mysqld.log log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid pid-file=/var/run/mysqld/mysqld.pid
#
!includedir /etc/my.cnf.d/ !includedir /etc/my.cnf.d/
``` ```
# 随机选择一个节点,使用专用脚本 mysqld_bootstrap 初始化集群 # 随机选择一个节点,使用专用脚本 mysqld_bootstrap 初始化集群
```bash ```bash
/usr/bin/mysqld_bootstrap /usr/bin/mysqld_bootstrap
#该命令会启动本机的 mysqld 服务 # 该命令会启动本机的 mysqld 服务
systemctl status mysqld systemctl status mysqld
``` ```
# 查找密码,修改初始密码 # 查找密码,修改初始密码
```bash ```bash
grep -i password /var/log/messages grep -i password /var/log/messages
#记录输出的密码 # 记录输出的密码
mysqladmin -uroot -p password 'P@sswo2d' mysqladmin -uroot -p password 'P@sswo2d'
#根据提示输入上一步输出的密码 # 根据提示输入上一步输出的密码
``` ```
# 在其他节点上启动 mysqld 服务 # 在其他节点上启动 mysqld 服务
```bash ```bash
systemctl start mysqld systemctl start mysqld
``` ```
# 查看集群节点数量 # 查看集群节点数量
```sql ```sql
show status like 'wsrep_cluster_size'; show status like 'wsrep_cluster_size';
``` ```
# ssl 加密同步数据(不推荐,存在性能损失) # ssl 加密同步数据(不推荐,存在性能损失)
- 生成证书 - 生成证书
@ -103,11 +103,13 @@ show status like 'wsrep_cluster_size';
-CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 \ -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 \
-out server-cert.pem -out server-cert.pem
``` ```
- 修改配置文件 my.cnf - 修改配置文件 my.cnf
``` ```
#在 wsrep_provider_options 中添加如下选项,选项间用分号";"间隔 # 在 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 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 加密客户端(不推荐,存在性能损失) # ssl 加密客户端(不推荐,存在性能损失)

View File

@ -17,72 +17,73 @@ mysql_33 | 192.168.1.33 | centos7.7 | 8.0.19
- 懒得写了 ... - 懒得写了 ...
# 修改 my.cnf # 修改 my.cnf
``` ```
# mysql_11(选择一个) # mysql_11(选择一个)
server-id = 11 server-id = 11
# mysql_22(选择一个) # mysql_22(选择一个)
server-id = 22 server-id = 22
# mysql_33(选择一个) # mysql_33(选择一个)
server-id = 33 server-id = 33
# 开启 binlog # 开启 binlog
log-bin = /var/log/mysql-bin/master log-bin = /var/log/mysql-bin/master
binlog-format = ROW binlog-format = ROW
# 关闭 binlog 校验 # 关闭 binlog 校验
binlog-checksum = NONE binlog-checksum = NONE
# 保留 2 天的 binlog # 保留 2 天的 binlog
binlog-expire-logs-seconds = 172800 binlog-expire-logs-seconds = 172800
# 开启 gtid # 开启 gtid
gtid-mode = ON gtid-mode = ON
enforce-gtid-consistency = TRUE enforce-gtid-consistency = TRUE
# 指定 relay-log 存储位置 # 指定 relay-log 存储位置
relay-log = /var/lib/mysql-bin/slave relay-log = /var/lib/mysql-bin/slave
# relay-log 更新计入 binlog # relay-log 更新计入 binlog
log-slave-updates = TRUE log-slave-updates = TRUE
# 多线程执行从库日志(可选) # 多线程执行从库日志(可选)
slave-parallel-workers = 2 slave-parallel-workers = 2
slave-parallel-type = LOGICAL_CLOCK slave-parallel-type = LOGICAL_CLOCK
slave-preserve-commit-order = ON slave-preserve-commit-order = ON
# 存储引擎只能用 InnoDB # 存储引擎只能用 InnoDB
disabled-storage-engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY" disabled-storage-engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
# 加载插件,克隆插件用于快速 state transfer # 加载插件,克隆插件用于快速 state transfer
plugin-load-add = "group_replication.so;mysql_clone.so" plugin-load-add = "group_replication.so;mysql_clone.so"
# 集群 uuid # 集群 uuid
group-replication-group-name = "aaaa1111-bbbb-2222-cccc-3333dddd4444" group-replication-group-name = "aaaa1111-bbbb-2222-cccc-3333dddd4444"
# mysql_11(选择一个) # mysql_11(选择一个)
group-replication-local-address = "192.168.1.11:33061" group-replication-local-address = "192.168.1.11:33061"
# mysql_22(选择一个) # mysql_22(选择一个)
group-replication-local-address = "192.168.1.22:33061" group-replication-local-address = "192.168.1.22:33061"
# mysql_33(选择一个) # mysql_33(选择一个)
group-replication-local-address = "192.168.1.33:33061" group-replication-local-address = "192.168.1.33:33061"
# 种子节点 # 种子节点
group-replication-group-seeds = "192.168.1.11:33061,192.168.1.22:33061,192.168.1.33:33061" group-replication-group-seeds = "192.168.1.11:33061,192.168.1.22:33061,192.168.1.33:33061"
# 新主库在执行完自己的从库日志后,再处理用户的写请求 # 新主库在执行完自己的从库日志后,再处理用户的写请求
group-replication-consistency = BEFORE_ON_PRIMARY_FAILOVER group-replication-consistency = BEFORE_ON_PRIMARY_FAILOVER
# 启动时,不自动创建/初始化新集群 # 启动时,不自动创建/初始化新集群
group-replication-bootstrap-group = OFF group-replication-bootstrap-group = OFF
# 新节点启动时,先不启动组复制,待手动配置完成并确认正常后,再把 OFF 改成 ON # 新节点启动时,先不启动组复制,待手动配置完成并确认正常后,再把 OFF 改成 ON
group-replication-start-on-boot = OFF group-replication-start-on-boot = OFF
# 怀疑某节点不可用2秒内如果该嫌疑节点依旧无响应则开除它(可选) # 怀疑某节点不可用2秒内如果该嫌疑节点依旧无响应则开除它(可选)
group-replication-member-expel-timeout = 2 group-replication-member-expel-timeout = 2
# 2秒内依旧连接不上主网(majority),则退出组复制,进入 ERROR 状态(可选) # 2秒内依旧连接不上主网(majority),则退出组复制,进入 ERROR 状态(可选)
group-replication-unreachable-majority-timeout = 2 group-replication-unreachable-majority-timeout = 2
# 退出组复制后,不再尝试重新加入组复制,直接执行指定的退出动作(默认) # 退出组复制后,不再尝试重新加入组复制,直接执行指定的退出动作(默认)
group-replication-autorejoin-tries = 0 group-replication-autorejoin-tries = 0
# 指定退出动作: 数据库设置超级只读并关闭客户端连接(推荐) # 指定退出动作: 数据库设置超级只读并关闭客户端连接(推荐)
group-replication-exit-state-action = OFFLINE_MODE group-replication-exit-state-action = OFFLINE_MODE
``` ```
# 初始化集群 # 初始化集群
- 重新启动节点 mysql_11 - 重新启动节点 mysql_11
```bash ```bash
systemctl restart mysqld systemctl restart mysqld
``` ```
- 创建同步用户 - 创建同步用户
```sql ```sql
SET SQL_LOG_BIN = 0; SET SQL_LOG_BIN = 0;
@ -92,6 +93,7 @@ group-replication-exit-state-action = OFFLINE_MODE
FLUSH PRIVILEGES; FLUSH PRIVILEGES;
SET SQL_LOG_BIN = 1; SET SQL_LOG_BIN = 1;
``` ```
- 配置同步信息 - 配置同步信息
```sql ```sql
CHANGE MASTER TO CHANGE MASTER TO
@ -99,16 +101,19 @@ group-replication-exit-state-action = OFFLINE_MODE
MASTER_PASSWORD='password' MASTER_PASSWORD='password'
FOR CHANNEL 'group_replication_recovery'; FOR CHANNEL 'group_replication_recovery';
``` ```
- 启动集群 - 启动集群
```sql ```sql
SET GLOBAL group_replication_bootstrap_group=ON; SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION; START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF; SET GLOBAL group_replication_bootstrap_group=OFF;
``` ```
- 查看集群成员(只有一个) - 查看集群成员(只有一个)
```sql ```sql
SELECT * FROM performance_schema.replication_group_members; SELECT * FROM performance_schema.replication_group_members;
``` ```
- 修改 my.cnf配置 group-replication-start-on-boot = ON - 修改 my.cnf配置 group-replication-start-on-boot = ON
# 增加节点 # 增加节点
@ -116,6 +121,7 @@ group-replication-exit-state-action = OFFLINE_MODE
```bash ```bash
systemctl restart mysql_22 systemctl restart mysql_22
``` ```
- 创建同步用户,与 mysql_11 相同 - 创建同步用户,与 mysql_11 相同
```sql ```sql
SET SQL_LOG_BIN = 0; SET SQL_LOG_BIN = 0;
@ -125,6 +131,7 @@ group-replication-exit-state-action = OFFLINE_MODE
FLUSH PRIVILEGES; FLUSH PRIVILEGES;
SET SQL_LOG_BIN = 1; SET SQL_LOG_BIN = 1;
``` ```
- 配置同步信息 - 配置同步信息
```sql ```sql
CHANGE MASTER TO CHANGE MASTER TO
@ -132,15 +139,18 @@ group-replication-exit-state-action = OFFLINE_MODE
MASTER_PASSWORD='password' MASTER_PASSWORD='password'
FOR CHANNEL 'group_replication_recovery'; FOR CHANNEL 'group_replication_recovery';
``` ```
- 启动组复制 - 启动组复制
```sql ```sql
START GROUP_REPLICATION; START GROUP_REPLICATION;
``` ```
- 在 mysql_33 上重复 mysql_22 的步骤 - 在 mysql_33 上重复 mysql_22 的步骤
- 查看集群成员(有三个) - 查看集群成员(有三个)
```sql ```sql
SELECT * FROM performance_schema.replication_group_members; SELECT * FROM performance_schema.replication_group_members;
``` ```
- 修改 mysql_22 和 mysql_33 的 my.cnf配置 group-replication-start-on-boot = ON - 修改 mysql_22 和 mysql_33 的 my.cnf配置 group-replication-start-on-boot = ON
# 注意 # 注意

View File

@ -12,186 +12,186 @@ categories: ["database"]
- 要复制的数据库有 data_db、conf_db - 要复制的数据库有 data_db、conf_db
# 在主服务器上创建用于备份的用户 replicator # 在主服务器上创建用于备份的用户 replicator
```sql ```sql
grant replication slave on *.* to 'replicator'@'192.168.1.6' identified by 'password'; grant replication slave on *.* to 'replicator'@'192.168.1.6' identified by 'password';
flush privileges; flush privileges;
``` ```
# 在主服务器上修改 my.cnf # 在主服务器上修改 my.cnf
``` ```
# 建议与本机ip地址最后一位一致,与其他互备服务器均不一致 # 建议与本机ip地址最后一位一致,与其他互备服务器均不一致
server-id = 10 server-id = 10
read-only = 0 read-only = 0
# 开启 binlog # 开启 binlog
log-bin = /var/log/mysql-bin/master log-bin = /var/log/mysql-bin/master
binlog-format = row binlog-format = row
#关注要复制的数据库,存在跨库问题 # 关注要复制的数据库,存在跨库问题
binlog-do-db = data-db binlog-do-db = data-db
binlog-do-db = conf-db binlog-do-db = conf-db
#忽略的数据库,存在跨库问题 # 忽略的数据库,存在跨库问题
#binlog-ignore-db = #binlog-ignore-db =
#binlog 有效时间 #binlog 有效时间
expire-logs-days = expire-logs-days =
#GTID 复制模式 # GTID 复制模式
#gtid-mode = ON #gtid-mode = ON
#enforce-gtid-consistency=true #enforce-gtid-consistency=true
#双主或多主互备时,会用到以下配置 # 双主或多主互备时,会用到以下配置
#自增主键初始值,与其他互备服务器一致 # 自增主键初始值,与其他互备服务器一致
#auto-increment-offset = #auto-increment-offset =
#自增主键等差值,与其他互备服务器均不一致 # 自增主键等差值,与其他互备服务器均不一致
#auto-increment-increment = #auto-increment-increment =
``` ```
# 在主服务器上重启 mysql获取 master 状态 # 在主服务器上重启 mysql获取 master 状态
```sql ```sql
-- 如果 mysql 是全新安装,则无须导出数据库初态,直接查看 binlog pos 即可 -- 如果 mysql 是全新安装,则无须导出数据库初态,直接查看 binlog pos 即可
-- 锁定要导出的数据库表 -- 锁定要导出的数据库表
flush tables with read lock; flush tables with read lock;
``` ```
# 导出数据库初态 # 导出数据库初态
```bash ```bash
#在主服务器的另一个终端中运行 # 在主服务器的另一个终端中运行
mysqldump -uroot -p data_db > /tmp/data_db.sql mysqldump -uroot -p data_db > /tmp/data_db.sql
mysqldump -uroot -p conf_db > /tmp/conf_db.sql mysqldump -uroot -p conf_db > /tmp/conf_db.sql
#复制到从服务器上 # 复制到从服务器上
scp /tmp/data_db.sql /tmp/conf_db.sql 192.168.1.6:/tmp/ scp /tmp/data_db.sql /tmp/conf_db.sql 192.168.1.6:/tmp/
``` ```
# 查看 binary 日志位置 # 查看 binary 日志位置
```sql ```sql
show master status\G show master status\G
-- 记住输出里的如下类似两行不记录也可以这两个信息已经写入了导出的sql文件中 -- 记住输出里的如下类似两行不记录也可以这两个信息已经写入了导出的sql文件中
-- File: mysql-bin.000001 -- File: mysql-bin.000001
-- Position: 137103822 -- Position: 137103822
-- 解锁数据库表 -- 解锁数据库表
unlock tables; unlock tables;
``` ```
# 在从服务器上编辑 my.cnf # 在从服务器上编辑 my.cnf
``` ```
# 建议与本机ip地址最后一位一致,与其他互备服务器均不一致 # 建议与本机ip地址最后一位一致,与其他互备服务器均不一致
server-id = 6 server-id = 6
read-only = 1 read-only = 1
# 如果该 slave 中也运行了 master或者使用了 gtid 模式复制,则开启 binlog # 如果该 slave 中也运行了 master或者使用了 gtid 模式复制,则开启 binlog
#log-bin = mysql-bin #log-bin = mysql-bin
#binlog-format = row #binlog-format = row
# 把 slave 操作也计入 binlog用于链式同步 # 把 slave 操作也计入 binlog用于链式同步
#log-slave-updates = ON #log-slave-updates = ON
# 指定要复制的数据库,存在跨库问题 # 指定要复制的数据库,存在跨库问题
#replicate-do-db = data_db #replicate-do-db = data_db
#replicate-do-db = conf_db #replicate-do-db = conf_db
# 指定要复制的数据表,无跨库问题 # 指定要复制的数据表,无跨库问题
replicate-do-table = db1.t1 replicate-do-table = db1.t1
replicate-wild-do-table = db1.% replicate-wild-do-table = db1.%
# 忽略的数据库,存在跨库问题 # 忽略的数据库,存在跨库问题
#replicate-ignore-db = #replicate-ignore-db =
# 忽略的数据表,无跨库问题 # 忽略的数据表,无跨库问题
#replicate-ignore-table = db1.t1 #replicate-ignore-table = db1.t1
#replicate-wild-ignore-table = db1.% #replicate-wild-ignore-table = db1.%
# 中继日志 # 中继日志
relay-log = /var/lib/mysql-bin/slave relay-log = /var/lib/mysql-bin/slave
# 多线程复制 # 多线程复制
slave-parallel-type = logical-clock slave-parallel-type = logical-clock
slave-parallel-workers = 4 slave-parallel-workers = 4
# GTID 模式 # GTID 模式
#gtid-mode = ON #gtid-mode = ON
#enforce-gtid-consistency=true #enforce-gtid-consistency=true
# 双主或多主互备时,会用到以下配置 # 双主或多主互备时,会用到以下配置
# 自增主键初始值,与其他互备服务器一致 # 自增主键初始值,与其他互备服务器一致
#auto-increment-offset = #auto-increment-offset =
# 自增主键等差值,与其他互备服务器均不一致 # 自增主键等差值,与其他互备服务器均不一致
#auto-increment-increment = #auto-increment-increment =
``` ```
# 在从服务器上重启 mysql导入初态 # 在从服务器上重启 mysql导入初态
```sql ```sql
-- 创建要导入的数据库 -- 创建要导入的数据库
create database data_db default charset utf8mb4; create database data_db default charset utf8mb4;
create database conf_db default charset utf8mb4; create database conf_db default charset utf8mb4;
``` ```
# 导入数据库 # 导入数据库
```bash ```bash
msyql -uroot -p data_db < /tmp/data_db.sql msyql -uroot -p data_db < /tmp/data_db.sql
mysql -uroot -p conf_db < /tmp/conf_db.sql mysql -uroot -p conf_db < /tmp/conf_db.sql
``` ```
# 开启同步 # 开启同步
```sql ```sql
-- 基于 binlog 文件位置复制 -- 基于 binlog 文件位置复制
change master to master_host = '192.168.1.10', change master to master_host = '192.168.1.10',
master_port = 3306, master_port = 3306,
master_user = 'replicator', master_user = 'replicator',
master_password = 'password', master_password = 'password',
master_log_file = 'mysql-bin.000001', master_log_file = 'mysql-bin.000001',
master_log_pos = 137103822; master_log_pos = 137103822;
flush privileges; flush privileges;
-- 基于 gtid 复制 -- 基于 gtid 复制
change master to master_host = '192.168.1.10', change master to master_host = '192.168.1.10',
master_port = 3306, master_port = 3306,
master_user = 'replicator', master_user = 'replicator',
master_password = 'password', master_password = 'password',
master_auto_position = 1; master_auto_position = 1;
``` ```
# 启动 slave查看 slave 状态 # 启动 slave查看 slave 状态
```sql ```sql
start slave; start slave;
-- 在从服务器上查看 slave 状态 -- 在从服务器上查看 slave 状态
show slave status\G show slave status\G
-- 如果看到 -- 如果看到
-- Slave_IO_Running: Yes -- Slave_IO_Running: Yes
-- Slave_SQL_Running: Yes -- Slave_SQL_Running: Yes
-- 则表示 slave 开启成功! -- 则表示 slave 开启成功!
``` ```
# MySQL8 gtid 互为主从配置 # MySQL8 gtid 互为主从配置
``` ```
[mysqld] [mysqld]
# ---- 固定配置 ---- # ---- 固定配置 ----
datadir = /var/lib/mysql datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock socket = /var/lib/mysql/mysql.sock
pid-file = /var/lib/mysql/mysql.pid pid-file = /var/lib/mysql/mysql.pid
log-timestamps = SYSTEM log-timestamps = SYSTEM
log-error = /var/log/mysql/error.log log-error = /var/log/mysql/error.log
slow-query-log = TRUE slow-query-log = TRUE
slow-query-log-file = /var/log/mysql/slow.log slow-query-log-file = /var/log/mysql/slow.log
default-authentication-plugin = mysql_native_password default-authentication-plugin = mysql_native_password
# ---- 动态配置 ---- # ---- 动态配置 ----
mysqlx = OFF mysqlx = OFF
character-set-server = utf8mb4 character-set-server = utf8mb4
default-storage-engine = innodb default-storage-engine = innodb
lower-case-table-names = 1 lower-case-table-names = 1
#skip-name-resolve = 1 #skip-name-resolve = 1
#max-user-connections = 600 #max-user-connections = 600
#innodb-buffer-pool-size = 8G #innodb-buffer-pool-size = 8G
#innodb-buffer-pool-instances = 8 #innodb-buffer-pool-instances = 8
# master # master
# 确认不同节点该 id 唯一 # 确认不同节点该 id 唯一
server-id = 1 server-id = 1
log-bin = /var/lib/mysql-bin/master log-bin = /var/lib/mysql-bin/master
binlog-format = ROW binlog-format = ROW
#binlog-do-db = db1 #binlog-do-db = db1
binlog-expire-logs-seconds = 172800 binlog-expire-logs-seconds = 172800
gtid-mode = ON gtid-mode = ON
enforce-gtid-consistency = TRUE enforce-gtid-consistency = TRUE
# slave # slave
replicate-wild-ignore-table = information_schema.% replicate-wild-ignore-table = information_schema.%
replicate-wild-ignore-table = mysql.% replicate-wild-ignore-table = mysql.%
replicate-wild-ignore-table = performance_schema.% replicate-wild-ignore-table = performance_schema.%
replicate-wild-ignore-table = sys.% replicate-wild-ignore-table = sys.%
slave-parallel-workers = 2 slave-parallel-workers = 2
log-slave-updates = FALSE log-slave-updates = FALSE
relay-log = /var/lib/mysql-bin/slave relay-log = /var/lib/mysql-bin/slave
relay-log-recovery = TRUE relay-log-recovery = TRUE
#read-only = ON #read-only = ON
``` ```
# MySQL8 gtid 多源复制从库配置 # MySQL8 gtid 多源复制从库配置
- 修改 my.cnf - 修改 my.cnf
@ -240,21 +240,25 @@ relay-log-recovery = TRUE
master_info_repository = table master_info_repository = table
relay_log_info_repository = table relay_log_info_repository = table
``` ```
- 导出主库数据 - 导出主库数据
```bash ```bash
mysqldump -uroot -h<主库1> -p --single-transaction --set-gtid-purged=on --databases db1 > 1_db1.sql 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 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)中找到 "SET @@GLOBAL.gtid_purged ..." 语句,记录下来,并在该文件中删除
- 导入 1_db1.sql 和 2_db2.sql - 导入 1_db1.sql 和 2_db2.sql
```bash ```bash
mysql -uroot -p < 1_db1.sql mysql -uroot -p < 1_db1.sql
mysql -uroot -p < 2_db2.sql mysql -uroot -p < 2_db2.sql
``` ```
- 合并这两个 "SET @@GLOBAL.gtid_purged ..." 语句(gtid set 做并集),导入 gtid set 并集 - 合并这两个 "SET @@GLOBAL.gtid_purged ..." 语句(gtid set 做并集),导入 gtid set 并集
```sql ```sql
set @@global.gtid_purged = '<gtid set 并集>' set @@global.gtid_purged = '<gtid set 并集>'
``` ```
- 加入两个主库的同步配置 - 加入两个主库的同步配置
```sql ```sql
change master to master_host='<主库1>', change master to master_host='<主库1>',
@ -268,16 +272,19 @@ relay-log-recovery = TRUE
master_password='<主库上的 replication 账户的密码>', master_password='<主库上的 replication 账户的密码>',
master_auto_position=1 for channel '<master_2>'; master_auto_position=1 for channel '<master_2>';
``` ```
- 启动从库 - 启动从库
```sql ```sql
start slave for channel '<master_1>'; start slave for channel '<master_1>';
start slave for channel '<master_2>'; start slave for channel '<master_2>';
``` ```
- 查看从库 - 查看从库
```sql ```sql
show slave status for channel '<master_1>'\G show slave status for channel '<master_1>'\G
show slave status for channel '<master_2>'\G show slave status for channel '<master_2>'\G
``` ```
- 停止从库 - 停止从库
```sql ```sql
-- 停止全部 slave -- 停止全部 slave
@ -285,6 +292,7 @@ relay-log-recovery = TRUE
-- 停止指定 slave -- 停止指定 slave
stop slave for channel '...'; stop slave for channel '...';
``` ```
- 重置从库 - 重置从库
```sql ```sql
-- 重置全部 slave -- 重置全部 slave
@ -292,5 +300,6 @@ relay-log-recovery = TRUE
-- 重置指定 slave -- 重置指定 slave
reset slave for channel '...'; reset slave for channel '...';
``` ```
- 监控表: performance_schema.replication_connection_status - 监控表: performance_schema.replication_connection_status

View File

@ -7,78 +7,80 @@ categories: ["database"]
--- ---
# MySQL 5.7 配置文件 my.cnf # MySQL 5.7 配置文件 my.cnf
``` ```
[mysqld] [mysqld]
datadir = /db/mysql datadir = /db/mysql
socket = /var/lib/mysql/mysql.sock socket = /var/lib/mysql/mysql.sock
symbolic-links = 0 symbolic-links = 0
log-timestamps = SYSTEM log-timestamps = SYSTEM
slow-query-log = 1 slow-query-log = 1
slow-query-log-file = /var/log/mysqld/slow.log slow-query-log-file = /var/log/mysqld/slow.log
long-query-time = 8 long-query-time = 8
#log-queries-not-using-indexes = 1 #log-queries-not-using-indexes = 1
log-error = /var/log/mysqld/error.log log-error = /var/log/mysqld/error.log
pid-file = /var/run/mysqld/mysqld.pid pid-file = /var/run/mysqld/mysqld.pid
max-connections = 1000 max-connections = 1000
max-connect-errors = 1000 max-connect-errors = 1000
max-user-connections = 600 max-user-connections = 600
interactive-timeout = 3600 interactive-timeout = 3600
wait-timeout = 3600 wait-timeout = 3600
skip-name-resolve = 1 skip-name-resolve = 1
lower-case-table-names = 1 lower-case-table-names = 1
default-time-zone = '+08:00' default-time-zone = '+08:00'
character-set-server = utf8mb4 character-set-server = utf8mb4
sql-mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES sql-mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
bind-address = 0.0.0.0 bind-address = 0.0.0.0
table-open-cache = 2048 table-open-cache = 2048
default-storage-engine = innodb default-storage-engine = innodb
innodb-autoinc-lock-mode = 2 innodb-autoinc-lock-mode = 2
innodb-flush-log-at-trx-commit = 0 innodb-flush-log-at-trx-commit = 0
# 建议物理内存一半 # 建议物理内存一半
innodb-buffer-pool-size = 8G innodb-buffer-pool-size = 8G
innodb-buffer-pool-instances = 8 innodb-buffer-pool-instances = 8
max-allowed-packet = 512M max-allowed-packet = 512M
query-cache-size = 0 query-cache-size = 0
query-cache-type = 0 query-cache-type = 0
# 建议点分 ip 的最后一个数字 # 建议点分 ip 的最后一个数字
server-id = 123 server-id = 123
# bin log # bin log
#binlog-format = ROW #binlog-format = ROW
#log-bin = /var/lib/mysql/mysql-bin #log-bin = /var/lib/mysql/mysql-bin
#expire-logs-days = 3 #expire-logs-days = 3
# relay log # relay log
#read-only = 1 #read-only = 1
#replicate-wild-do-table = db1.% #replicate-wild-do-table = db1.%
#relay-log = /var/lib/mysql/mysql-relay-bin #relay-log = /var/lib/mysql/mysql-relay-bin
#slave-parallel-type = logical-clock #slave-parallel-type = logical-clock
``` ```
# 复制表结构 # 复制表结构
```sql ```sql
create table db1.t1 like db2.t2; create table db1.t1 like db2.t2;
create table db1.t1 select db2.t2 where 1=2; create table db1.t1 select db2.t2 where 1=2;
``` ```
# 复制表结构及其数据 # 复制表结构及其数据
```sql ```sql
create table db1.t1 select db2.t2 [where ...] create table db1.t1 select db2.t2 [where ...]
``` ```
# 复制表数据 # 复制表数据
``` ```
insert into db2.t2(column1, column2 ...) insert into db2.t2(column1, column2 ...)
select column1, column2 ... from db1.t1 [where ...] select column1, column2 ... from db1.t1 [where ...]
``` ```
# 通过复制表文件来复制表数据 # 通过复制表文件来复制表数据
- 在db2中创建同结构表 - 在db2中创建同结构表
```sql ```sql
create table db2.t1 like db1.t1; create table db2.t1 like db1.t1;
``` ```
- 丢弃表空间 - 丢弃表空间
```sql ```sql
alter table db2.t1 discard tablespace; alter table db2.t1 discard tablespace;
``` ```
- 复制 t1 的表数据文件 - 复制 t1 的表数据文件
```bash ```bash
#关闭数据库 #关闭数据库
@ -89,51 +91,52 @@ insert into db2.t2(column1, column2 ...)
#启动数据库 #启动数据库
systemctl start mysqld systemctl start mysqld
``` ```
- 导入表空间 - 导入表空间
```sql ```sql
alter table db2.t1 import tablespace; alter table db2.t1 import tablespace;
``` ```
# 设置一个表的空列自增 # 设置一个表的空列自增
```sql ```sql
-- 删除可能存在的主键 -- 删除可能存在的主键
alter table 表名 drop primary key; alter table 表名 drop primary key;
alter table 表名 modify 列名 auto_increment primary key; alter table 表名 modify 列名 auto_increment primary key;
``` ```
# 查看数据库中每个表的全部列名 # 查看数据库中每个表的全部列名
```sql ```sql
select table_name, column_name from select table_name, column_name from
information_schema.columns information_schema.columns
where table_schema = '数据库名'; where table_schema = '数据库名';
``` ```
# 查看数据库中每个表的行数 # 查看数据库中每个表的行数
```sql ```sql
select table_name, table_rows select table_name, table_rows
from information_schema.tables from information_schema.tables
where table_schema = '数据库名'; where table_schema = '数据库名';
``` ```
# 查看数据库中每个表的索引 # 查看数据库中每个表的索引
```sql ```sql
select table_name, column_name, index_name select table_name, column_name, index_name
from INFORMATION_SCHEMA.STATISTICS from INFORMATION_SCHEMA.STATISTICS
where table_schema = '数据库名'; where table_schema = '数据库名';
``` ```
# 表的部分列数据到另一个表 # 表的部分列数据到另一个表
```sql ```sql
update db2.t2(column1, column2 ...) = ( update db2.t2(column1, column2 ...) = (
select column1, column2 from db1.t1 select column1, column2 from db1.t1
where db1.t1.id = db2.t2.id); where db1.t1.id = db2.t2.id);
``` ```
# 把语句执行结果写到文件 # 把语句执行结果写到文件
```bash ```bash
mysql -uroot -p -hsever_ip -Ddb_name mysql -uroot -p -hsever_ip -Ddb_name
-Ne "select ... from table_name;" > file_name -Ne "select ... from table_name;" > file_name
``` ```
# 表分区 # 表分区
- 查看表的分区情况 - 查看表的分区情况
@ -142,27 +145,32 @@ mysql -uroot -p -hsever_ip -Ddb_name
from information_schema.partitions from information_schema.partitions
where table_name = 'table_name'; where table_name = 'table_name';
``` ```
- 建表时指定 - 建表时指定
```sql ```sql
create table table_name(...) create table table_name(...)
partition by range columns(column_name) partition by range columns(column_name)
(partition part_name values less than(some_value)); (partition part_name values less than(some_value));
``` ```
- 修改成分区表 - 修改成分区表
```sql ```sql
alter table table_name alter table table_name
partition by range(column_name) partition by range(column_name)
(partition part_name values less than(som_value)); (partition part_name values less than(som_value));
``` ```
- 增加分区 - 增加分区
```sql ```sql
alter table table_name add partition alter table table_name add partition
(partition part_name values less than(som_value)); (partition part_name values less than(som_value));
``` ```
- 删除分区 - 删除分区
```sql ```sql
alter table table_name drop partition part_name; alter table table_name drop partition part_name;
``` ```
- 合并/拆分分区 - 合并/拆分分区
```sql ```sql
alter table table_name 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_1 values less than(value_1),
partition part_new_2 values less than(value_2)); partition part_new_2 values less than(value_2));
``` ```
- 重建分区,整理分区碎片 - 重建分区,整理分区碎片
```sql ```sql
alter table table_name alter table table_name
rebuild partition part_name_1, part_name_2; rebuild partition part_name_1, part_name_2;
``` ```
- 优化分区,回收空间,整理碎片 - 优化分区,回收空间,整理碎片
```sql ```sql
alter table table_name alter table table_name
optimize partition part_name_1, part_name_2; optimize partition part_name_1, part_name_2;
``` ```
- 分析分区,读取并保存分区的健分布 - 分析分区,读取并保存分区的健分布
```sql ```sql
alter table table_name alter table table_name
analyze partition part_name_1, part_name_2; analyze partition part_name_1, part_name_2;
``` ```
- 修复分区 - 修复分区
```sql ```sql
alter table table_name alter table table_name
repair partition part_name_1, part_name_2; repair partition part_name_1, part_name_2;
``` ```
- 检查分区 - 检查分区
```sql ```sql
alter table table_name alter table table_name
@ -197,59 +210,61 @@ mysql -uroot -p -hsever_ip -Ddb_name
``` ```
# MySQL 5.7 从库多线程同步 # MySQL 5.7 从库多线程同步
```sql ```sql
stop slave; stop slave;
set global slave_parallel_type='logical_clock'; set global slave_parallel_type='logical_clock';
set global slave_parallel_workers=4; set global slave_parallel_workers=4;
start slave; start slave;
show processlist; show processlist;
``` ```
# MySQL 5.7 提示密码复杂度不够 # MySQL 5.7 提示密码复杂度不够
```sql ```sql
set global validate_password_policy=0; set global validate_password_policy=0;
``` ```
# MySQL 5.7 从库复制失败跳过指定数量的事务 # MySQL 5.7 从库复制失败跳过指定数量的事务
```sql ```sql
stop slave; stop slave;
-- 跳过一个事务 -- 跳过一个事务
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
start slave; start slave;
-- 修改 my.cnf -- 修改 my.cnf
slave-skip-errors=1062,1053,1146,1032 #跳过指定error no类型的错误 slave-skip-errors=1062,1053,1146,1032 #跳过指定error no类型的错误
slave-skip-errors=all #跳过所有错误 slave-skip-errors=all #跳过所有错误
``` ```
# MySQL 5.7 查看全部任务 # MySQL 5.7 查看全部任务
```sql ```sql
-- 分号换成 \G 显示完整 sql -- 分号换成 \G 显示完整 sql
show processlist; show processlist;
show full processlist; show full processlist;
SELECT command FROM information_schema.processlist; SELECT command FROM information_schema.processlist;
``` ```
# MySQL 5.7 ssl 连接 # MySQL 5.7 ssl 连接
``` ```
--ssl-mode=REQUIRED --ssl-mode=REQUIRED
``` ```
# MariaDB 10.1 修改密码 # MariaDB 10.1 修改密码
```sql ```sql
UPDATE user SET password=password('newpassword') WHERE user='root'; UPDATE user SET password=password('newpassword') WHERE user='root';
``` ```
# MySQL 5.7 编码 # MySQL 5.7 编码
- 查看 - 查看
```sql ```sql
SHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'character_set%';
``` ```
- 数据库连接参数中characterEncoding=utf8 会被自动识别为 utf8mb4但是 autoReconnect=true 必须指定 - 数据库连接参数中characterEncoding=utf8 会被自动识别为 utf8mb4但是 autoReconnect=true 必须指定
- 更改数据库编码 - 更改数据库编码
```sql ```sql
ALTER DATABASE db_name ALTER DATABASE db_name
CHARSET UTF8MB4 COLLATE UTF8MB4_GENERAL_CI; CHARSET UTF8MB4 COLLATE UTF8MB4_GENERAL_CI;
``` ```
- 更改表编码 - 更改表编码
```sql ```sql
ALTER TABLE table_name ALTER TABLE table_name
@ -257,24 +272,27 @@ UPDATE user SET password=password('newpassword') WHERE user='root';
``` ```
# MySQL 5.7 升级数据库管理表结构 # MySQL 5.7 升级数据库管理表结构
```bash ```bash
mysql_upgrade -u root -p mysql_upgrade -u root -p
``` ```
# MySQL 5.7 误删 root 后恢复 root 账户 # MySQL 5.7 误删 root 后恢复 root 账户
- 停止 mysql 服务 - 停止 mysql 服务
```bash ```bash
systemctl stop mysqld systemctl stop mysqld
``` ```
- 修改 my.cnf - 修改 my.cnf
``` ```
# 添加如下一行 # 添加如下一行
skip-grant-tables skip-grant-tables
``` ```
- 启动 mysql 服务 - 启动 mysql 服务
```bash ```bash
systemctl start mysqld systemctl start mysqld
``` ```
- 重建 root 账户,并授权 - 重建 root 账户,并授权
```sql ```sql
insert into user insert into user
@ -317,15 +335,18 @@ mysql_upgrade -u root -p
where user='root'; where user='root';
flush privileges; flush privileges;
``` ```
- 停止 mysql 服务 - 停止 mysql 服务
```bash ```bash
systemctl stop mysqld systemctl stop mysqld
``` ```
- 修改 my.cnf - 修改 my.cnf
``` ```
# 删除刚添加的如下一行 # 删除或注释刚添加的如下一行
#skip-grant-tables skip-grant-tables
``` ```
- 启动 mysql 服务root 账户正常可用 - 启动 mysql 服务root 账户正常可用
```bash ```bash
systemctl start mysqld systemctl start mysqld
@ -336,6 +357,7 @@ mysql_upgrade -u root -p
```sql ```sql
explain sql explain sql
``` ```
- select_type 查询类型 - select_type 查询类型
- SIMPLE 简单表,没有表连接或子查询 - SIMPLE 简单表,没有表连接或子查询
- PRIMARY 最外层的查询 - PRIMARY 最外层的查询
@ -363,10 +385,10 @@ mysql_upgrade -u root -p
- Using Flesort 依靠索引顺序达不到排序效果,需额外排序 - Using Flesort 依靠索引顺序达不到排序效果,需额外排序
# 统计 insert、delete、update 和 select 次数 # 统计 insert、delete、update 和 select 次数
```sql ```sql
show global status where Variable_name in show global status where Variable_name in
('com_insert', 'com_delete', 'com_update', 'com_select'); ('com_insert', 'com_delete', 'com_update', 'com_select');
``` ```
# csv 文件 # csv 文件
- 导出 - 导出
@ -386,6 +408,7 @@ show global status where Variable_name in
escaped by '\\' escaped by '\\'
lines terminated by '\n'; lines terminated by '\n';
``` ```
- 导入 - 导入
``` ```
# Shell 终端 # Shell 终端

View File

@ -11,47 +11,48 @@ categories: ["database"]
- MySQL 5.7.20 - MySQL 5.7.20
# 下载 mysql 源安装包 # 下载 mysql 源安装包
```bash ```bash
#repo 地址: https://repo.mysql.com/ # repo 地址: https://repo.mysql.com/
cd /root/ cd /root/
curl -O https://repo.mysql.com/mysql57-community-release-el7.rpm curl -O https://repo.mysql.com/mysql57-community-release-el7.rpm
``` ```
# 安装 mysql 源 # 安装 mysql 源
```bash ```bash
rpm -ivh /root/mysql57-community-release-el7.rpm rpm -ivh /root/mysql57-community-release-el7.rpm
``` ```
# 更新 yum 缓存 # 更新 yum 缓存
```bash ```bash
yum clean all yum clean all
yum makecache fast yum makecache fast
``` ```
# 安装 mysql # 安装 mysql
```bash ```bash
yum install mysql-community-server yum install mysql-community-server
``` ```
# 启动 mysql # 启动 mysql
```bash ```bash
systemctl start mysqld systemctl start mysqld
``` ```
# 查找 mysql 默认密码 # 查找 mysql 默认密码
```bash ```bash
grep 'temporary password' /var/log/mysqld.log grep 'temporary password' /var/log/mysqld.log
mysql -uroot -p mysql -uroot -p
# 输入查找到的密码 # 输入查找到的密码
``` ```
# 修改 mysql 本地密码 # 修改 mysql 本地密码
- 在 mysql 下修改 - 在 mysql 下修改
```sql ```sql
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'Pass-1234'; mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'Pass-1234';
``` ```
- 或者直接在终端修改
```bash - 或者直接在终端修改
mysqladmin -uroot -p password 'Pass-1234' ```bash
``` mysqladmin -uroot -p password 'Pass-1234'
```

View File

@ -8,299 +8,299 @@ categories: ["network"]
--- ---
# 服务端配置文件 server.conf # 服务端配置文件 server.conf
``` ```
################################################# #################################################
# 针对多客户端的OpenVPN 2.0 的服务器端配置文件示例 # 针对多客户端的OpenVPN 2.0 的服务器端配置文件示例
# #
# 本文件用于多客户端<->单服务器端的OpenVPN服务器端配置 # 本文件用于多客户端<->单服务器端的OpenVPN服务器端配置
# #
# OpenVPN也支持单机<->单机的配置(更多信息请查看网站上的示例页面) # OpenVPN也支持单机<->单机的配置(更多信息请查看网站上的示例页面)
# #
# 该配置支持Windows或者Linux/BSD系统。此外在Windows上记得将路径加上双引号 # 该配置支持Windows或者Linux/BSD系统。此外在Windows上记得将路径加上双引号
# 并且使用两个反斜杠,例如:"C:\\Program Files\\OpenVPN\\config\\foo.key" # 并且使用两个反斜杠,例如:"C:\\Program Files\\OpenVPN\\config\\foo.key"
# #
# '#' or ';'开头的均为注释内容 # '#' or ';'开头的均为注释内容
################################################# #################################################
#OpenVPN应该监听本机的哪些IP地址 #OpenVPN应该监听本机的哪些IP地址
#该命令是可选的如果不设置则默认监听本机的所有IP地址。 #该命令是可选的如果不设置则默认监听本机的所有IP地址。
;local a.b.c.d ;local a.b.c.d
# OpenVPN应该监听哪个TCP/UDP端口 # OpenVPN应该监听哪个TCP/UDP端口
# 如果你想在同一台计算机上运行多个OpenVPN实例你可以使用不同的端口号来区分它们。 # 如果你想在同一台计算机上运行多个OpenVPN实例你可以使用不同的端口号来区分它们。
# 此外,你需要在防火墙上开放这些端口。 # 此外,你需要在防火墙上开放这些端口。
port 1194 port 1194
#OpenVPN使用TCP还是UDP协议? #OpenVPN使用TCP还是UDP协议?
;proto tcp ;proto tcp
proto udp proto udp
# 指定OpenVPN创建的通信隧道类型。 # 指定OpenVPN创建的通信隧道类型。
# "dev tun"将会创建一个路由IP隧道 # "dev tun"将会创建一个路由IP隧道
# "dev tap"将会创建一个以太网隧道。 # "dev tap"将会创建一个以太网隧道。
# #
# 如果你是以太网桥接模式,并且提前创建了一个名为"tap0"的与以太网接口进行桥接的虚拟接口,则你可以使用"dev tap0" # 如果你是以太网桥接模式,并且提前创建了一个名为"tap0"的与以太网接口进行桥接的虚拟接口,则你可以使用"dev tap0"
# #
# 如果你想控制VPN的访问策略你必须为TUN/TAP接口创建防火墙规则。 # 如果你想控制VPN的访问策略你必须为TUN/TAP接口创建防火墙规则。
# #
# 在非Windows系统中你可以给出明确的单位编号(unit number),例如"tun0"。 # 在非Windows系统中你可以给出明确的单位编号(unit number),例如"tun0"。
# 在Windows中你也可以使用"dev-node"。 # 在Windows中你也可以使用"dev-node"。
# 在多数系统中除非你部分禁用或者完全禁用了TUN/TAP接口的防火墙否则VPN将不起作用。 # 在多数系统中除非你部分禁用或者完全禁用了TUN/TAP接口的防火墙否则VPN将不起作用。
;dev tap ;dev tap
dev tun dev tun
# 如果你想配置多个隧道你需要用到网络连接面板中TAP-Win32适配器的名称(例如"MyTap")。 # 如果你想配置多个隧道你需要用到网络连接面板中TAP-Win32适配器的名称(例如"MyTap")。
# 在XP SP2或更高版本的系统中你可能需要有选择地禁用掉针对TAP适配器的防火墙 # 在XP SP2或更高版本的系统中你可能需要有选择地禁用掉针对TAP适配器的防火墙
# 通常情况下非Windows系统则不需要该指令。 # 通常情况下非Windows系统则不需要该指令。
;dev-node MyTap ;dev-node MyTap
# 设置SSL/TLS根证书(ca)、证书(cert)和私钥(key)。 # 设置SSL/TLS根证书(ca)、证书(cert)和私钥(key)。
# 每个客户端和服务器端都需要它们各自的证书和私钥文件。 # 每个客户端和服务器端都需要它们各自的证书和私钥文件。
# 服务器端和所有的客户端都将使用相同的CA证书文件。 # 服务器端和所有的客户端都将使用相同的CA证书文件。
# #
# 通过easy-rsa目录下的一系列脚本可以生成所需的证书和私钥。 # 通过easy-rsa目录下的一系列脚本可以生成所需的证书和私钥。
# 记住服务器端和每个客户端的证书必须使用唯一的Common Name。 # 记住服务器端和每个客户端的证书必须使用唯一的Common Name。
# #
# 你也可以使用遵循X509标准的任何密钥管理系统来生成证书和私钥。 # 你也可以使用遵循X509标准的任何密钥管理系统来生成证书和私钥。
# OpenVPN 也支持使用一个PKCS #12格式的密钥文件(详情查看站点手册页面的"pkcs12"指令) # OpenVPN 也支持使用一个PKCS #12格式的密钥文件(详情查看站点手册页面的"pkcs12"指令)
ca ca.crt ca ca.crt
cert server.crt cert server.crt
key server.key # 该文件应该保密 key server.key # 该文件应该保密
# 指定迪菲·赫尔曼参数。 # 指定迪菲·赫尔曼参数。
# 你可以使用如下名称命令生成你的参数: # 你可以使用如下名称命令生成你的参数:
# openssl dhparam -out dh1024.pem 1024 # openssl dhparam -out dh1024.pem 1024
# 如果你使用的是2048位密钥使用2048替换其中的1024。 # 如果你使用的是2048位密钥使用2048替换其中的1024。
dh dh1024.pem dh dh1024.pem
# 设置服务器端模式并提供一个VPN子网以便于从中为客户端分配IP地址。 # 设置服务器端模式并提供一个VPN子网以便于从中为客户端分配IP地址。
# 在此处的示例中服务器端自身将占用10.8.0.1,其他的将提供客户端使用。 # 在此处的示例中服务器端自身将占用10.8.0.1,其他的将提供客户端使用。
# 如果你使用的是以太网桥接模式,请注释掉该行。更多信息请查看官方手册页面。 # 如果你使用的是以太网桥接模式,请注释掉该行。更多信息请查看官方手册页面。
server 10.8.0.0 255.255.255.0 server 10.8.0.0 255.255.255.0
# 指定用于记录客户端和虚拟IP地址的关联关系的文件。 # 指定用于记录客户端和虚拟IP地址的关联关系的文件。
# 当重启OpenVPN时再次连接的客户端将分配到与上一次分配相同的虚拟IP地址 # 当重启OpenVPN时再次连接的客户端将分配到与上一次分配相同的虚拟IP地址
ifconfig-pool-persist ipp.txt ifconfig-pool-persist ipp.txt
# 该指令仅针对以太网桥接模式。 # 该指令仅针对以太网桥接模式。
# 首先你必须使用操作系统的桥接能力将以太网网卡接口和TAP接口进行桥接。 # 首先你必须使用操作系统的桥接能力将以太网网卡接口和TAP接口进行桥接。
# 然后你需要手动设置桥接接口的IP地址、子网掩码 # 然后你需要手动设置桥接接口的IP地址、子网掩码
# 在这里我们假设为10.8.0.4和255.255.255.0。 # 在这里我们假设为10.8.0.4和255.255.255.0。
# 最后我们必须指定子网的一个IP范围(例如从10.8.0.50开始到10.8.0.100结束),以便于分配给连接的客户端。 # 最后我们必须指定子网的一个IP范围(例如从10.8.0.50开始到10.8.0.100结束),以便于分配给连接的客户端。
# 如果你不是以太网桥接模式,直接注释掉这行指令即可。 # 如果你不是以太网桥接模式,直接注释掉这行指令即可。
;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100 ;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100
# 该指令仅针对使用DHCP代理的以太网桥接模式 # 该指令仅针对使用DHCP代理的以太网桥接模式
# 此时客户端将请求服务器端的DHCP服务器从而获得分配给它的IP地址和DNS服务器地址。 # 此时客户端将请求服务器端的DHCP服务器从而获得分配给它的IP地址和DNS服务器地址。
# #
# 在此之前你也需要先将以太网网卡接口和TAP接口进行桥接。 # 在此之前你也需要先将以太网网卡接口和TAP接口进行桥接。
# 注意该指令仅用于OpenVPN客户端并且该客户端的TAP适配器需要绑定到一个DHCP客户端上。 # 注意该指令仅用于OpenVPN客户端并且该客户端的TAP适配器需要绑定到一个DHCP客户端上。
;server-bridge ;server-bridge
# 推送路由信息到客户端,以允许客户端能够连接到服务器背后的其他私有子网。 # 推送路由信息到客户端,以允许客户端能够连接到服务器背后的其他私有子网。
# (简而言之就是允许客户端访问VPN服务器自身所在的其他局域网) # (简而言之就是允许客户端访问VPN服务器自身所在的其他局域网)
# 记住这些私有子网也要将OpenVPN客户端的地址池(10.8.0.0/255.255.255.0)反馈回OpenVPN服务器。 # 记住这些私有子网也要将OpenVPN客户端的地址池(10.8.0.0/255.255.255.0)反馈回OpenVPN服务器。
;push "route 192.168.10.0 255.255.255.0" ;push "route 192.168.10.0 255.255.255.0"
;push "route 192.168.20.0 255.255.255.0" ;push "route 192.168.20.0 255.255.255.0"
# 为指定的客户端分配指定的IP地址或者客户端背后也有一个私有子网想要访问VPN # 为指定的客户端分配指定的IP地址或者客户端背后也有一个私有子网想要访问VPN
# 那么你可以针对该客户端的配置文件使用ccd子目录。 # 那么你可以针对该客户端的配置文件使用ccd子目录。
# (简而言之就是允许客户端所在的局域网成员也能够访问VPN) # (简而言之就是允许客户端所在的局域网成员也能够访问VPN)
# 举个例子假设有个Common Name为"Thelonious"的客户端背后也有一个小型子网想要连接到VPN该子网为192.168.40.128/255.255.255.248。 # 举个例子假设有个Common Name为"Thelonious"的客户端背后也有一个小型子网想要连接到VPN该子网为192.168.40.128/255.255.255.248。
# 首先,你需要去掉下面两行指令的注释: # 首先,你需要去掉下面两行指令的注释:
;client-config-dir ccd ;client-config-dir ccd
;route 192.168.40.128 255.255.255.248 ;route 192.168.40.128 255.255.255.248
# 然后创建一个文件ccd/Thelonious该文件的内容为 # 然后创建一个文件ccd/Thelonious该文件的内容为
# iroute 192.168.40.128 255.255.255.248 # iroute 192.168.40.128 255.255.255.248
#这样客户端所在的局域网就可以访问VPN了 #这样客户端所在的局域网就可以访问VPN了
# 注意,这个指令只能在你是基于路由、而不是基于桥接的模式下才能生效。 # 注意,这个指令只能在你是基于路由、而不是基于桥接的模式下才能生效。
# 比如,你使用了"dev tun"和"server"指令。 # 比如,你使用了"dev tun"和"server"指令。
# 再举个例子假设你想给Thelonious分配一个固定的IP地址10.9.0.1。 # 再举个例子假设你想给Thelonious分配一个固定的IP地址10.9.0.1。
# 首先,你需要去掉下面两行指令的注释: # 首先,你需要去掉下面两行指令的注释:
;client-config-dir ccd ;client-config-dir ccd
;route 10.9.0.0 255.255.255.252 ;route 10.9.0.0 255.255.255.252
# 然后在文件ccd/Thelonious中添加如下指令 # 然后在文件ccd/Thelonious中添加如下指令
# ifconfig-push 10.9.0.1 10.9.0.2 # ifconfig-push 10.9.0.1 10.9.0.2
# 如果你想要为不同群组的客户端启用不同的防火墙访问策略,你可以使用如下两种方法: # 如果你想要为不同群组的客户端启用不同的防火墙访问策略,你可以使用如下两种方法:
# (1)运行多个OpenVPN守护进程每个进程对应一个群组并为每个进程(群组)启用适当的防火墙规则。 # (1)运行多个OpenVPN守护进程每个进程对应一个群组并为每个进程(群组)启用适当的防火墙规则。
# (2) (进阶)创建一个脚本来动态地修改响应于来自不同客户的防火墙规则。 # (2) (进阶)创建一个脚本来动态地修改响应于来自不同客户的防火墙规则。
# 关于learn-address脚本的更多信息请参考官方手册页面。 # 关于learn-address脚本的更多信息请参考官方手册页面。
;learn-address ./script ;learn-address ./script
# 如果启用该指令所有客户端的默认网关都将重定向到VPN这将导致诸如web浏览器、DNS查询等所有客户端流量都经过VPN。 # 如果启用该指令所有客户端的默认网关都将重定向到VPN这将导致诸如web浏览器、DNS查询等所有客户端流量都经过VPN。
# (为确保能正常工作OpenVPN服务器所在计算机可能需要在TUN/TAP接口与以太网之间使用NAT或桥接技术进行连接) # (为确保能正常工作OpenVPN服务器所在计算机可能需要在TUN/TAP接口与以太网之间使用NAT或桥接技术进行连接)
;push "redirect-gateway def1 bypass-dhcp" ;push "redirect-gateway def1 bypass-dhcp"
# 某些具体的Windows网络设置可以被推送到客户端例如DNS或WINS服务器地址。 # 某些具体的Windows网络设置可以被推送到客户端例如DNS或WINS服务器地址。
# 下列地址来自opendns.com提供的Public DNS 服务器。 # 下列地址来自opendns.com提供的Public DNS 服务器。
;push "dhcp-option DNS 208.67.222.222" ;push "dhcp-option DNS 208.67.222.222"
;push "dhcp-option DNS 208.67.220.220" ;push "dhcp-option DNS 208.67.220.220"
# 去掉该指令的注释将允许不同的客户端之间相互"可见"(允许客户端之间互相访问)。 # 去掉该指令的注释将允许不同的客户端之间相互"可见"(允许客户端之间互相访问)。
# 默认情况下,客户端只能"看见"服务器。为了确保客户端只能看见服务器你还可以在服务器端的TUN/TAP接口上设置适当的防火墙规则。 # 默认情况下,客户端只能"看见"服务器。为了确保客户端只能看见服务器你还可以在服务器端的TUN/TAP接口上设置适当的防火墙规则。
;client-to-client ;client-to-client
# 如果多个客户端可能使用相同的证书/私钥文件或Common Name进行连接那么你可以取消该指令的注释。 # 如果多个客户端可能使用相同的证书/私钥文件或Common Name进行连接那么你可以取消该指令的注释。
# 建议该指令仅用于测试目的。对于生产使用环境而言,每个客户端都应该拥有自己的证书和私钥。 # 建议该指令仅用于测试目的。对于生产使用环境而言,每个客户端都应该拥有自己的证书和私钥。
# 如果你没有为每个客户端分别生成Common Name唯一的证书/私钥,你可以取消该行的注释(但不推荐这样做)。 # 如果你没有为每个客户端分别生成Common Name唯一的证书/私钥,你可以取消该行的注释(但不推荐这样做)。
;duplicate-cn ;duplicate-cn
# keepalive指令将导致类似于ping命令的消息被来回发送以便于服务器端和客户端知道对方何时被关闭。 # keepalive指令将导致类似于ping命令的消息被来回发送以便于服务器端和客户端知道对方何时被关闭。
# 每10秒钟ping一次如果120秒内都没有收到对方的回复则表示远程连接已经关闭。 # 每10秒钟ping一次如果120秒内都没有收到对方的回复则表示远程连接已经关闭。
keepalive 10 120 keepalive 10 120
# 出于SSL/TLS之外更多的安全考虑创建一个"HMAC 防火墙"可以帮助抵御DoS攻击和UDP端口淹没攻击。 # 出于SSL/TLS之外更多的安全考虑创建一个"HMAC 防火墙"可以帮助抵御DoS攻击和UDP端口淹没攻击。
# 你可以使用以下命令来生成: # 你可以使用以下命令来生成:
# openvpn --genkey --secret ta.key # openvpn --genkey --secret ta.key
# #
# 服务器和每个客户端都需要拥有该密钥的一个拷贝。 # 服务器和每个客户端都需要拥有该密钥的一个拷贝。
# 第二个参数在服务器端应该为'0',在客户端应该为'1'。 # 第二个参数在服务器端应该为'0',在客户端应该为'1'。
;tls-auth ta.key 0 # 该文件应该保密 ;tls-auth ta.key 0 # 该文件应该保密
# 选择一个密码加密算法。 # 选择一个密码加密算法。
# 该配置项也必须复制到每个客户端配置文件中。 # 该配置项也必须复制到每个客户端配置文件中。
;cipher BF-CBC # Blowfish (默认) ;cipher BF-CBC # Blowfish (默认)
;cipher AES-128-CBC # AES ;cipher AES-128-CBC # AES
;cipher DES-EDE3-CBC # Triple-DES ;cipher DES-EDE3-CBC # Triple-DES
# 在VPN连接上启用压缩。 # 在VPN连接上启用压缩。
# 如果你在此处启用了该指令,那么也应该在每个客户端配置文件中启用它。 # 如果你在此处启用了该指令,那么也应该在每个客户端配置文件中启用它。
comp-lzo comp-lzo
# 允许并发连接的客户端的最大数量 # 允许并发连接的客户端的最大数量
;max-clients 100 ;max-clients 100
# 在完成初始化工作之后降低OpenVPN守护进程的权限是个不错的主意。 # 在完成初始化工作之后降低OpenVPN守护进程的权限是个不错的主意。
# 该指令仅限于非Windows系统中使用。 # 该指令仅限于非Windows系统中使用。
;user nobody ;user nobody
;group nobody ;group nobody
# 持久化选项可以尽量避免访问那些在重启之后由于用户权限降低而无法访问的某些资源。 # 持久化选项可以尽量避免访问那些在重启之后由于用户权限降低而无法访问的某些资源。
persist-key persist-key
persist-tun persist-tun
# 输出一个简短的状态文件,用于显示当前的连接状态,该文件每分钟都会清空并重写一次。 # 输出一个简短的状态文件,用于显示当前的连接状态,该文件每分钟都会清空并重写一次。
status openvpn-status.log status openvpn-status.log
# 默认情况下日志消息将写入syslog(在Windows系统中如果以服务方式运行日志消息将写入OpenVPN安装目录的log文件夹中)。 # 默认情况下日志消息将写入syslog(在Windows系统中如果以服务方式运行日志消息将写入OpenVPN安装目录的log文件夹中)。
# 你可以使用log或者log-append来改变这种默认情况。 # 你可以使用log或者log-append来改变这种默认情况。
# "log"方式在每次启动时都会清空之前的日志文件。 # "log"方式在每次启动时都会清空之前的日志文件。
# "log-append"这是在之前的日志内容后进行追加。 # "log-append"这是在之前的日志内容后进行追加。
# 你可以使用两种方式之一(但不要同时使用)。 # 你可以使用两种方式之一(但不要同时使用)。
;log openvpn.log ;log openvpn.log
;log-append openvpn.log ;log-append openvpn.log
# 为日志文件设置适当的冗余级别(0~9)。冗余级别越高,输出的信息越详细。 # 为日志文件设置适当的冗余级别(0~9)。冗余级别越高,输出的信息越详细。
# #
# 0 表示静默运行,只记录致命错误。 # 0 表示静默运行,只记录致命错误。
# 4 表示合理的常规用法。 # 4 表示合理的常规用法。
# 5 和 6 可以帮助调试连接错误。 # 5 和 6 可以帮助调试连接错误。
# 9 表示极度冗余,输出非常详细的日志信息。 # 9 表示极度冗余,输出非常详细的日志信息。
verb 3 verb 3
# 重复信息的沉默度。 # 重复信息的沉默度。
# 相同类别的信息只有前20条会输出到日志文件中。 # 相同类别的信息只有前20条会输出到日志文件中。
;mute 20 ;mute 20
``` ```
# 客户端配置文件 # 客户端配置文件
``` ```
############################################## ##############################################
# 针对多个客户端的OpenVPN 2.0 的客户端配置文件示例 # 针对多个客户端的OpenVPN 2.0 的客户端配置文件示例
# #
# 该配置文件可以被多个客户端使用,当然每个客户端都应该有自己的证书和密钥文件 # 该配置文件可以被多个客户端使用,当然每个客户端都应该有自己的证书和密钥文件
# #
# 在Windows上此配置文件的后缀应该是".ovpn"在Linux/BSD系统中则是".conf" # 在Windows上此配置文件的后缀应该是".ovpn"在Linux/BSD系统中则是".conf"
############################################## ##############################################
# 指定这是一个客户端,我们将从服务器获取某些配置文件指令 # 指定这是一个客户端,我们将从服务器获取某些配置文件指令
client client
# 在大多数系统中除非你部分禁用或者完全禁用了TUN/TAP接口的防火墙否则VPN将不起作用。 # 在大多数系统中除非你部分禁用或者完全禁用了TUN/TAP接口的防火墙否则VPN将不起作用。
;dev tap ;dev tap
dev tun dev tun
# 在Windows系统中如果你想配置多个隧道则需要该指令。 # 在Windows系统中如果你想配置多个隧道则需要该指令。
# 你需要用到网络连接面板中TAP-Win32适配器的名称(例如"MyTap")。 # 你需要用到网络连接面板中TAP-Win32适配器的名称(例如"MyTap")。
# 在XP SP2或更高版本的系统中你可能需要禁用掉针对TAP适配器的防火墙。 # 在XP SP2或更高版本的系统中你可能需要禁用掉针对TAP适配器的防火墙。
;dev-node MyTap ;dev-node MyTap
# 指定连接的服务器是采用TCP还是UDP协议。 # 指定连接的服务器是采用TCP还是UDP协议。
# 这里需要使用与服务器端相同的设置。 # 这里需要使用与服务器端相同的设置。
;proto tcp ;proto tcp
proto udp proto udp
# 指定服务器的主机名(或IP)以及端口号。 # 指定服务器的主机名(或IP)以及端口号。
# 如果有多个VPN服务器为了实现负载均衡你可以设置多个remote指令。 # 如果有多个VPN服务器为了实现负载均衡你可以设置多个remote指令。
remote my-server-1 1194 remote my-server-1 1194
;remote my-server-2 1194 ;remote my-server-2 1194
# 如果指定了多个remote指令启用该指令将随机连接其中的一台服务器 # 如果指定了多个remote指令启用该指令将随机连接其中的一台服务器
# 否则,客户端将按照指定的先后顺序依次尝试连接服务器。 # 否则,客户端将按照指定的先后顺序依次尝试连接服务器。
;remote-random ;remote-random
# 启用该指令,与服务器连接中断后将自动重新连接,这在网络不稳定的情况下(例如:笔记本电脑无线网络)非常有用。 # 启用该指令,与服务器连接中断后将自动重新连接,这在网络不稳定的情况下(例如:笔记本电脑无线网络)非常有用。
resolv-retry infinite resolv-retry infinite
# 大多数客户端不需要绑定本机特定的端口号 # 大多数客户端不需要绑定本机特定的端口号
nobind nobind
# 在初始化完毕后降低OpenVPN的权限(该指令仅限于非Windows系统中使用) # 在初始化完毕后降低OpenVPN的权限(该指令仅限于非Windows系统中使用)
;user nobody ;user nobody
;group nobody ;group nobody
# 持久化选项可以尽量避免访问在重启时由于用户权限降低而无法访问的某些资源。 # 持久化选项可以尽量避免访问在重启时由于用户权限降低而无法访问的某些资源。
persist-key persist-key
persist-tun persist-tun
# 如果你是通过HTTP代理方式来连接到实际的VPN服务器请在此处指定代理服务器的主机名(或IP)和端口号。 # 如果你是通过HTTP代理方式来连接到实际的VPN服务器请在此处指定代理服务器的主机名(或IP)和端口号。
# 如果你的代理服务器需要身份认证,请参考官方手册页面。 # 如果你的代理服务器需要身份认证,请参考官方手册页面。
;http-proxy-retry # 连接失败时自动重试 ;http-proxy-retry # 连接失败时自动重试
;http-proxy [proxy server] [proxy port #] ;http-proxy [proxy server] [proxy port #]
# 无线网络通常会产生大量的重复数据包。设置此标识将忽略掉重复数据包的警告信息。 # 无线网络通常会产生大量的重复数据包。设置此标识将忽略掉重复数据包的警告信息。
;mute-replay-warnings ;mute-replay-warnings
# SSL/TLS 参数配置。 # SSL/TLS 参数配置。
# 更多描述信息请参考服务器端配置文件。 # 更多描述信息请参考服务器端配置文件。
# 最好为每个客户端单独分配.crt/.key文件对。 # 最好为每个客户端单独分配.crt/.key文件对。
# 单个CA证书可以供所有客户端使用。 # 单个CA证书可以供所有客户端使用。
ca ca.crt ca ca.crt
cert client.crt cert client.crt
key client.key key client.key
# 指定通过检查证书的nsCertType字段是否为"server"来验证服务器端证书。 # 指定通过检查证书的nsCertType字段是否为"server"来验证服务器端证书。
# 这是预防潜在攻击的一种重要措施。 # 这是预防潜在攻击的一种重要措施。
# #
# 为了使用该功能你需要在生成服务器端证书时将其中的nsCertType字段设为"server" # 为了使用该功能你需要在生成服务器端证书时将其中的nsCertType字段设为"server"
# easy-rsa文件夹中的build-key-server脚本文件可以达到该目的。 # easy-rsa文件夹中的build-key-server脚本文件可以达到该目的。
ns-cert-type server ns-cert-type server
# 如果服务器端使用了tls-auth密钥那么每个客户端也都应该有该密钥。 # 如果服务器端使用了tls-auth密钥那么每个客户端也都应该有该密钥。
;tls-auth ta.key 1 ;tls-auth ta.key 1
# 指定密码的加密算法。 # 指定密码的加密算法。
# 如果服务器端启用了cipher指令选项那么你必须也在这里指定它。 # 如果服务器端启用了cipher指令选项那么你必须也在这里指定它。
;cipher x ;cipher x
# 在VPN连接中启用压缩。 # 在VPN连接中启用压缩。
# 该指令的启用/禁用应该与服务器端保持一致。 # 该指令的启用/禁用应该与服务器端保持一致。
comp-lzo comp-lzo
# 设置日志文件冗余级别(0~9)。 # 设置日志文件冗余级别(0~9)。
# 0 表示静默运行,只记录致命错误。 # 0 表示静默运行,只记录致命错误。
# 4 表示合理的常规用法。 # 4 表示合理的常规用法。
# 5 和 6 可以帮助调试连接错误。 # 5 和 6 可以帮助调试连接错误。
# 9 表示极度冗余,输出非常详细的日志信息。 # 9 表示极度冗余,输出非常详细的日志信息。
verb 3 verb 3
# 忽略过多的重复信息。 # 忽略过多的重复信息。
# 相同类别的信息只有前20条会输出到日志文件中。 # 相同类别的信息只有前20条会输出到日志文件中。
;mute 20 ;mute 20
``` ```
# 撤销客户端证书 # 撤销客户端证书
- 生成/更新 crl.pem - 生成/更新 crl.pem
@ -309,11 +309,13 @@ verb 3
./easyrsa gen-crl ./easyrsa gen-crl
cp pki/crl.pem /etc/openvpn-server/server/my-server0/ cp pki/crl.pem /etc/openvpn-server/server/my-server0/
``` ```
- 修改 openvpn-server 的配置文件,追加/修改下面一行 - 修改 openvpn-server 的配置文件,追加/修改下面一行
``` ```bash
# 注意: 该 crl.pem 文件本身及其上级目录,均需对 openvpn 运行用户可读 # 注意: 该 crl.pem 文件本身及其上级目录,均需对 openvpn 运行用户可读
crl-verify my-server0/crl.pem crl-verify my-server0/crl.pem
``` ```
- 重启 openvpn-server 服务 - 重启 openvpn-server 服务
# 参考链接 # 参考链接

View File

@ -35,309 +35,309 @@ clob | 4GB | 字符串
bfile | 视操作系统 | 存储非结构化数据到数据库外的文件中 bfile | 视操作系统 | 存储非结构化数据到数据库外的文件中
# 创建表 # 创建表
```sql ```sql
CREATE TABLE table_name CREATE TABLE table_name
( (
column_name datatype [NULL|NOT NULL], column_name datatype [NULL|NOT NULL],
..., ...,
PRIMARY KEY(), PRIMARY KEY(),
CONSTRAINT table_name constraint_name FOREIGN KEY (column_name) REFERENCE table_name(column_name) ON DELETE CASCADE, CONSTRAINT table_name constraint_name FOREIGN KEY (column_name) REFERENCE table_name(column_name) ON DELETE CASCADE,
CONSTRAINT constraint_name CHECK(condition), CONSTRAINT constraint_name CHECK(condition),
CONSTRAINT constraint_name UNIQUE(column_name) CONSTRAINT constraint_name UNIQUE(column_name)
) )
|AS SELECT column_name1,column_name2,...FROM source_table; |AS SELECT column_name1,column_name2,...FROM source_table;
DROP TABLE table_name; DROP TABLE table_name;
``` ```
# 删除表 # 删除表
```bash ```bash
DROP TABLE table_name; DROP TABLE table_name;
# 执行最快删除数据、结构、索引、约束、触发器和索引存储过程和索引invalid状态直接生效不可回滚不释放空间 # 执行最快删除数据、结构、索引、约束、触发器和索引存储过程和索引invalid状态直接生效不可回滚不释放空间
TRUNCATE TABLE table_name; TRUNCATE TABLE table_name;
# 执行较快,只删除数据,直接生效,不可回滚,释放空间 # 执行较快,只删除数据,直接生效,不可回滚,释放空间
DELETE FROM table_name [WHERE condition]; DELETE FROM table_name [WHERE condition];
# 执行最慢只删除数据commit 后生效,可回滚,不释放空间 # 执行最慢只删除数据commit 后生效,可回滚,不释放空间
``` ```
# 操作表列 # 操作表列
```sql ```sql
ALTER TABLE table_name ALTER TABLE table_name
ADD column_name datatype [NULL|NOT NULL] ADD column_name datatype [NULL|NOT NULL]
|MODIFY column_name new_datatype|NULL|NOT NULL |MODIFY column_name new_datatype|NULL|NOT NULL
|DROP COLUMN column_name; |DROP COLUMN column_name;
-- 删除列时通常追加 CASCADE CONSTRAINTS ,以删除于该列有关的约束 -- 删除列时通常追加 CASCADE CONSTRAINTS ,以删除于该列有关的约束
``` ```
# 操作主键 # 操作主键
```sql ```sql
ALTER TABLE table_name ALTER TABLE table_name
ADD CONSTRAINTS constraint_name PRIMARY KEY(column_name) ADD CONSTRAINTS constraint_name PRIMARY KEY(column_name)
|DROP CONSTRAINTS constraint_name; |DROP CONSTRAINTS constraint_name;
``` ```
# 操作外键 # 操作外键
```sql ```sql
ALTER TABLE table_name ALTER TABLE table_name
ADD CONSTRAINT constraint_name FOREIGN KEY(column_name) REFERENCE table_name(column_name) ON DELETE CASCADE ADD CONSTRAINT constraint_name FOREIGN KEY(column_name) REFERENCE table_name(column_name) ON DELETE CASCADE
|DROP CONSTRAINT constraint_name; |DROP CONSTRAINT constraint_name;
``` ```
# 操作CHECK约束 # 操作CHECK约束
```sql ```sql
ALTER TABLE table_name ALTER TABLE table_name
ADD CONSTRAINT constraint_name CHECK(condition) ADD CONSTRAINT constraint_name CHECK(condition)
|DROP CONSTRAINT constraint_name; |DROP CONSTRAINT constraint_name;
``` ```
# 操作UNIQUE约束 # 操作UNIQUE约束
```sql ```sql
ALTER TABLE table_name ALTER TABLE table_name
ADD CONSTRAINT constraint_name UNIQUE(column_name) ADD CONSTRAINT constraint_name UNIQUE(column_name)
|DROP CONSTRAINT constraint_name; |DROP CONSTRAINT constraint_name;
``` ```
# 添加数据 # 添加数据
```sql ```sql
INSERT INTO table_name(column_name1,column_name2,...) INSERT INTO table_name(column_name1,column_name2,...)
VALUES(data1,data2,...) VALUES(data1,data2,...)
|SELECT column_name1,column_name2...FROM table_name2; |SELECT column_name1,column_name2...FROM table_name2;
``` ```
# 修改数据 # 修改数据
```sql ```sql
UPDATE table_name SET column_name1=data1,column_name2=data2,...[WHERE condition]; UPDATE table_name SET column_name1=data1,column_name2=data2,...[WHERE condition];
``` ```
# 删除数据 # 删除数据
```sql ```sql
DELETE FROM table_name [WHERE condition]; DELETE FROM table_name [WHERE condition];
TRUNCATE TABLE table_name; TRUNCATE TABLE table_name;
``` ```
# 查询数据 # 查询数据
```sql ```sql
SELECT column_name1,column_name2,...FROM table_name [WHERE condition]; SELECT column_name1,column_name2,...FROM table_name [WHERE condition];
``` ```
# MERGE语句 # MERGE语句
```sql ```sql
MERGE INTO table_name1 USING table_name2 ON(condition) WHEN MATCHED THEN ... WHEN NOT MATCHED THEN ...; MERGE INTO table_name1 USING table_name2 ON(condition) WHEN MATCHED THEN ... WHEN NOT MATCHED THEN ...;
``` ```
# SELECT 语句 # SELECT 语句
```sql ```sql
SELECT [DISTINCT|ALL] select_list FROM table_list [WHERE ...] [GROUP BY ...] [HAVING ...] [ORDER BY ...]; SELECT [DISTINCT|ALL] select_list FROM table_list [WHERE ...] [GROUP BY ...] [HAVING ...] [ORDER BY ...];
``` ```
# select_list # select_list
```sql ```sql
*|[schema.] {table|view} .*|expr[ [AS ]c_alias] *|[schema.] {table|view} .*|expr[ [AS ]c_alias]
``` ```
# expr # expr
```sql ```sql
"||" 连接的字符串 | 函数 "||" 连接的字符串 | 函数
``` ```
# ORDER BY ... # ORDER BY ...
```sql ```sql
{expr|positon|c_alias} {ASC|DESC} {NULLS FIRST|NULLS LAST}[ {expr|positon|c_alias} {ASC|DESC} {NULLS FIRST|NULLS LAST},...] {expr|positon|c_alias} {ASC|DESC} {NULLS FIRST|NULLS LAST}[ {expr|positon|c_alias} {ASC|DESC} {NULLS FIRST|NULLS LAST},...]
``` ```
# 模糊查询关键字like # 模糊查询关键字like
```sql ```sql
'_'替代一个字符,'%'替代多个字符 '_'替代一个字符,'%'替代多个字符
``` ```
# 从给定值中选取查询 # 从给定值中选取查询
```sql ```sql
IN(data1,data2,...) IN(data1,data2,...)
``` ```
# 连接 # 连接
```sql ```sql
-- 连接,只能查询匹配记录 -- 连接,只能查询匹配记录
SELECT select_list FROM table_name1 INNER JOIN table_name2 ON condition; SELECT select_list FROM table_name1 INNER JOIN table_name2 ON condition;
-- 左外连接 -- 左外连接
SELECT select_list FROM table_name1 LEFT JOIN table_name2 ON condition; SELECT select_list FROM table_name1 LEFT JOIN table_name2 ON condition;
-- 右外连接 -- 右外连接
SELECT select_list FROM table_name1 RIGHT JOIN table_name2 ON condition; SELECT select_list FROM table_name1 RIGHT JOIN table_name2 ON condition;
-- 全外连接 -- 全外连接
SELECT select_list FROM table_name1 FULL JOIN table_name2 ON condition; SELECT select_list FROM table_name1 FULL JOIN table_name2 ON condition;
``` ```
# 内置函数 # 内置函数
```sql ```sql
ABS(n) -- n绝对值 ABS(n) -- n绝对值
MOD(n2,n1) -- n2对n1取余 MOD(n2,n1) -- n2对n1取余
SIGN(n) -- n的符号 SIGN(n) -- n的符号
CEIL(n) -- 大于等于n的最小整数 CEIL(n) -- 大于等于n的最小整数
FLOOR(n) -- 小于等于n的最大整数 FLOOR(n) -- 小于等于n的最大整数
SQRT(n) -- n的平方根 SQRT(n) -- n的平方根
POWER(n2,n1) -- n2的n1次幂 POWER(n2,n1) -- n2的n1次幂
EXP(n) -- e的n次幂 EXP(n) -- e的n次幂
LOG(n1,n2) -- n1为底n2的对数 LOG(n1,n2) -- n1为底n2的对数
LN(n) -- n的自然对数 LN(n) -- n的自然对数
ROUND(n2,n1) -- n2小数部分四舍五入至n1位 ROUND(n2,n1) -- n2小数部分四舍五入至n1位
TRUNC(n2,n1) -- n2截取至n1位 TRUNC(n2,n1) -- n2截取至n1位
CHR(n) -- 把n根据ASCII转换成字符 CHR(n) -- 把n根据ASCII转换成字符
ASCII(char) -- 参数首字母的ASCII值 ASCII(char) -- 参数首字母的ASCII值
LENGTH(char) -- 字符串长度 LENGTH(char) -- 字符串长度
SUBSTR(char,position[,substring_length]) -- 截取字符串 SUBSTR(char,position[,substring_length]) -- 截取字符串
CONCAT(char1,char2) -- 连接字符串 CONCAT(char1,char2) -- 连接字符串
INSTR(string,substring[,position[,occurrence]]) -- 查找字符串 INSTR(string,substring[,position[,occurrence]]) -- 查找字符串
UPPER(char) -- 转换成大写 UPPER(char) -- 转换成大写
LOWER(char) -- 转换成小些 LOWER(char) -- 转换成小些
INITCAP(char) -- 单词首字母大写 INITCAP(char) -- 单词首字母大写
NLSSORT(char[,nslparam]) -- 按指定方式排序'NLS_SORT=SCHINESE_PINYIN_M' NLSSORT(char[,nslparam]) -- 按指定方式排序'NLS_SORT=SCHINESE_PINYIN_M'
REPLACE(char,search_string[,replacement_string]) -- 字符串替换,默认删除 REPLACE(char,search_string[,replacement_string]) -- 字符串替换,默认删除
RPAD(expr1,n[,expr2]) -- 用expr2右填充expr1至长度为n默认空格 RPAD(expr1,n[,expr2]) -- 用expr2右填充expr1至长度为n默认空格
LPAD(expr1,n[,expr2]) -- 用expr2左填充expr1至长度为n默认空格 LPAD(expr1,n[,expr2]) -- 用expr2左填充expr1至长度为n默认空格
TRIM([LEADING|TRAILING|BOTH] [trim_character FROM] trim_source) -- 删除字符串首尾指定字符 TRIM([LEADING|TRAILING|BOTH] [trim_character FROM] trim_source) -- 删除字符串首尾指定字符
SYSDATE -- 获取系统当前日期 SYSDATE -- 获取系统当前日期
SYSTIMESTAMP -- 获取系统当前时间 SYSTIMESTAMP -- 获取系统当前时间
DBTIMEZONE -- 获取数据库当前时区 DBTIMEZONE -- 获取数据库当前时区
ADD_MONTHS(date,integer) -- 指定日期增加指定月份数 ADD_MONTHS(date,integer) -- 指定日期增加指定月份数
SESSIONTIMEZONE -- 获取当前会话的时区 SESSIONTIMEZONE -- 获取当前会话的时区
LAST_DAY(date) -- 获取指定日期对应月份的最后一天 LAST_DAY(date) -- 获取指定日期对应月份的最后一天
NEXT_DAY(date,char) -- 获取下周char的日期 NEXT_DAY(date,char) -- 获取下周char的日期
CURRENT_DATE -- 获取会话时区的当前日期 CURRENT_DATE -- 获取会话时区的当前日期
EXTRACT(datetime) -- 从指定时间中获取指定部分 EXTRACT(datetime) -- 从指定时间中获取指定部分
MONTHS_BETWEEN(date1,date2) -- 获取两个时间之间的月份数 MONTHS_BETWEEN(date1,date2) -- 获取两个时间之间的月份数
NET_TIME(date,timezone1,timezone2) -- 获取时区1中的时间转换到时区2后的时间 NET_TIME(date,timezone1,timezone2) -- 获取时区1中的时间转换到时区2后的时间
TO_CHAR(n[,fmt]) -- 转换为字符类型 TO_CHAR(n[,fmt]) -- 转换为字符类型
TO_DATE(n[,fmt]) -- 转换为时间类型 TO_DATE(n[,fmt]) -- 转换为时间类型
TO_NUMBER(n[,fmt]) -- 转换为数字类型 TO_NUMBER(n[,fmt]) -- 转换为数字类型
LNNVL(condition) -- 排除指定条件函数 LNNVL(condition) -- 排除指定条件函数
NVL(expr1,expr2) -- expr1为空时返回expr2 NVL(expr1,expr2) -- expr1为空时返回expr2
NVL2(expr1,expr2,expr3) -- expr1为空时返回expr3不为空返回expr2 NVL2(expr1,expr2,expr3) -- expr1为空时返回expr3不为空返回expr2
AVG([DISTINCT|ALL ]expr) -- 获取平均值 AVG([DISTINCT|ALL ]expr) -- 获取平均值
COUNT(*|[DISTINCT|ALL ]expr) -- 获取数量 COUNT(*|[DISTINCT|ALL ]expr) -- 获取数量
SUM([DISTINCT|ALL ]expr) -- 获取和 SUM([DISTINCT|ALL ]expr) -- 获取和
SELECT USER FROM DUAL; -- 返回当前会话的登录名 SELECT USER FROM DUAL; -- 返回当前会话的登录名
USERENV(param) -- 返回当前会话的信息 USERENV(param) -- 返回当前会话的信息
SYS_CONTEXT(namespace,param) -- 返回oracle已创建的context SYS_CONTEXT(namespace,param) -- 返回oracle已创建的context
DECODE(expr,search,result[,search1,result1...]) -- expr结果是search返回result DECODE(expr,search,result[,search1,result1...]) -- expr结果是search返回result
``` ```
# 查看所有默认表空间 # 查看所有默认表空间
```sql ```sql
SELECT TABLESPACE_NAME FROM DBA_TABLESPACES; SELECT TABLESPACE_NAME FROM DBA_TABLESPACES;
``` ```
# 查看指定用户默认表空间 # 查看指定用户默认表空间
```sql ```sql
SELECT DEFAULT_STAPCE,USERNAME FROM DBA_USERS WHERE USERNAME='username'; SELECT DEFAULT_STAPCE,USERNAME FROM DBA_USERS WHERE USERNAME='username';
``` ```
# 创建表空间 # 创建表空间
```sql ```sql
CREATE TABLESPACE tablespace_name CREATE TABLESPACE tablespace_name
DATAFILE filename DATAFILE filename
SIZE size SIZE size
[AUTOEXTEND [ON NEXT size|OFF]] [AUTOEXTEND [ON NEXT size|OFF]]
[MAXSIZE size] [MAXSIZE size]
[PERMANENT|TEMPORARY] 永久/临时表空间,默认永久 [PERMANENT|TEMPORARY] 永久/临时表空间,默认永久
[EXTENT MANAGEMENT [DICTIONARY|LOCAL 字典/本地管理方式,默认本地 [EXTENT MANAGEMENT [DICTIONARY|LOCAL 字典/本地管理方式,默认本地
[AUTOALLOCATE|UNIFORM. [SIZE integer[K|M]]]]; [AUTOALLOCATE|UNIFORM. [SIZE integer[K|M]]]];
``` ```
# 重命名表空间 # 重命名表空间
```sql ```sql
ALTER TABLESPACE oldname RENAME TO newname; ALTER TABLESPACE oldname RENAME TO newname;
``` ```
# 修改表空间大小 # 修改表空间大小
```sql ```sql
ALTER DATABASE DATAFILE filename RESIZE size; ALTER DATABASE DATAFILE filename RESIZE size;
``` ```
# 增加表空间大小 # 增加表空间大小
```sql ```sql
ALTER TABLESPACE tablespace_name ADD DATAFILE filename SIZE size; ALTER TABLESPACE tablespace_name ADD DATAFILE filename SIZE size;
``` ```
# 设置表空间读写状态 # 设置表空间读写状态
```sql ```sql
ALTER TABLESPACE tablespace_name READ {ONLY|WRITE}; ALTER TABLESPACE tablespace_name READ {ONLY|WRITE};
``` ```
# 设置表空间可用状态 # 设置表空间可用状态
```sql ```sql
ALTER TABLESPACE tablespace_name {ONLINE|OFFLINE [NORMAL|TEMPORARY|IMMEDIATE]}; ALTER TABLESPACE tablespace_name {ONLINE|OFFLINE [NORMAL|TEMPORARY|IMMEDIATE]};
``` ```
# 创建大文件表空间 # 创建大文件表空间
```sql ```sql
CREATE BIGFILE TABLESPACE tablespace_name DATAFILE filename SIZE size; CREATE BIGFILE TABLESPACE tablespace_name DATAFILE filename SIZE size;
``` ```
# 删除表空间 # 删除表空间
```sql ```sql
DROP TABLESPACE tablespace_name DROP TABLESPACE tablespace_name
[INCLUDING CONTENTS AND DATAFILES] 数据文件删除 [INCLUDING CONTENTS AND DATAFILES] 数据文件删除
[CASCADE CONSTRAINTS]; 完整性删除 [CASCADE CONSTRAINTS]; 完整性删除
``` ```
# 查看表空间大小 # 查看表空间大小
```sql ```sql
SELECT TABLESPACE_NAME,FILE_NAME,BYTES FROM DBA_DATA_FILES WHERE TABLESPACE_NAME=tablespace_name; SELECT TABLESPACE_NAME,FILE_NAME,BYTES FROM DBA_DATA_FILES WHERE TABLESPACE_NAME=tablespace_name;
``` ```
# 查看表空间剩余 空间 # 查看表空间剩余 空间
```sql ```sql
SELECT TABLESPACE_NAME,BYTES FROM DBA_FREE_SPACES; SELECT TABLESPACE_NAME,BYTES FROM DBA_FREE_SPACES;
``` ```
# 创建/修改用户 # 创建/修改用户
```sql ```sql
CREATE|ALTER CREATE|ALTER
USER user_name USER user_name
IDENTIFIED BY password IDENTIFIED BY password
[DEFAULT TABLESPACE tablespace_name ] [DEFAULT TABLESPACE tablespace_name ]
[QUOTA size|UNLIMITED ON tablespace_name ] 用户使用表空间的最大值 [QUOTA size|UNLIMITED ON tablespace_name ] 用户使用表空间的最大值
[PROFILE profile ] 概要文件 [PROFILE profile ] 概要文件
[PASSWORD EXPIRE ] 用户密码过期 [PASSWORD EXPIRE ] 用户密码过期
[ACCOUNT LOCK|UNLOCK]; 默认锁定状态 [ACCOUNT LOCK|UNLOCK]; 默认锁定状态
``` ```
# 删除用户 # 删除用户
```sql ```sql
DROP USER user_name CASCADE; DROP USER user_name CASCADE;
``` ```
# 授予系统权限 # 授予系统权限
```sql ```sql
GRANT GRANT
system_privileges|ALL PRIVILEGES 权限 system_privileges|ALL PRIVILEGES 权限
TO {user IDENTIFIED BY password|role } 用户/角色 TO {user IDENTIFIED BY password|role } 用户/角色
[WITH ADMIN OPTION]; 授予其他用户或角色系统权限 [WITH ADMIN OPTION]; 授予其他用户或角色系统权限
``` ```
# 授予对象权限 # 授予对象权限
```sql ```sql
GRANT GRANT
object_privilege|ALL 权限 object_privilege|ALL 权限
ON schema.object 对象 ON schema.object 对象
TO user_name|role_name 用户/角色 TO user_name|role_name 用户/角色
[WITH ADMIN OPTION ] 授予其他用户或角色系统权限 [WITH ADMIN OPTION ] 授予其他用户或角色系统权限
[WITH THE GRANT ANY OBJECT]; 授予其他用户或角色对象权限 [WITH THE GRANT ANY OBJECT]; 授予其他用户或角色对象权限
``` ```
# 撤销系统权限 # 撤销系统权限
```sql ```sql
REVOKE system_privilege FROM REVOKE system_privilege FROM
user|role; user|role;
``` ```
# 撤销对象权限 # 撤销对象权限
```sql ```sql
REVOKE REVOKE
object_privilege |ALL object_privilege |ALL
ON schema.object FROM ON schema.object FROM
user_name|role_name user_name|role_name
[CASCADE CONSTRAINTS]; [CASCADE CONSTRAINTS];
``` ```
# 数据字典 # 数据字典
数据 | 字典 数据 | 字典
@ -347,150 +347,150 @@ user_name|role_name
用户角色 | DBA_ROLE_PRIVS 用户角色 | DBA_ROLE_PRIVS
# 创建角色 # 创建角色
```sql ```sql
CREATE|ALTER //创建/修改 CREATE|ALTER //创建/修改
ROLE role_name ROLE role_name
[NOT IDENTIFIED|IDENDIFIED BY [password]]; [NOT IDENTIFIED|IDENDIFIED BY [password]];
GRANT //填充权限 GRANT //填充权限
system_privilege|ALL PRIVILEGES system_privilege|ALL PRIVILEGES
TO role_name TO role_name
[WITH ADMIN OPTION]; [WITH ADMIN OPTION];
-- 角色创建完成后不能直接使用,需将角色赋予用户才能使用 -- 角色创建完成后不能直接使用,需将角色赋予用户才能使用
GRANT role_name TO user_name; GRANT role_name TO user_name;
SET ROLE role_name -- 设置角色生效 SET ROLE role_name -- 设置角色生效
SET ROLE ALL -- 设置所有角色生效 SET ROLE ALL -- 设置所有角色生效
SET ROLE ALL EXCEPT role_name -- 设置只有role_name失效 SET ROLE ALL EXCEPT role_name -- 设置只有role_name失效
SET ROLE NONE -- 设置所有角色失效 SET ROLE NONE -- 设置所有角色失效
``` ```
# 删除角色 # 删除角色
```sql ```sql
DROP ROLE role_name; DROP ROLE role_name;
``` ```
# 脱机备份(冷备份)/恢复 # 脱机备份(冷备份)/恢复
```sql ```sql
关闭数据库服务后直接复制需要的文件,包括数据文件和控制文件 关闭数据库服务后直接复制需要的文件,包括数据文件和控制文件
``` ```
# 联机备份(热备份) # 联机备份(热备份)
```sql ```sql
ARCHIVE LOG LIST 查看本机数据库的日志状态 ARCHIVE LOG LIST 查看本机数据库的日志状态
ALTER SYSTEM SET LOG_ARCHIVE_START=TRUE SCOPE=SPFILE; 设置日志模式为归档 ALTER SYSTEM SET LOG_ARCHIVE_START=TRUE SCOPE=SPFILE; 设置日志模式为归档
SHUTDOWN IMMEDIATE; 关闭数据库 SHUTDOWN IMMEDIATE; 关闭数据库
STARTUP MOUNT; 启动mount实例 STARTUP MOUNT; 启动mount实例
ALTER DATABASE ARCHIVELOG; 更改数据库为归档日志模式 ALTER DATABASE ARCHIVELOG; 更改数据库为归档日志模式
ALTER DATABASE OPEN; 更改数据库状态为打开模式 ALTER DATABASE OPEN; 更改数据库状态为打开模式
ALTER TABLESPACE tablespace_name BEGIN BACKUP; 开始备份数据库 ALTER TABLESPACE tablespace_name BEGIN BACKUP; 开始备份数据库
复制文件到其他目录 复制文件到其他目录
ALTER TABLESPACE tablespace_name END BACKUP; 结束备份操作 ALTER TABLESPACE tablespace_name END BACKUP; 结束备份操作
``` ```
# 恢复 # 恢复
```sql ```sql
ALTER SYSTEM ARCHIVE LOG CURRENT; 归档当前日志 ALTER SYSTEM ARCHIVE LOG CURRENT; 归档当前日志
ALTER SYSTEM SWITCH LOGFILE; 切换日志文件 ALTER SYSTEM SWITCH LOGFILE; 切换日志文件
SELECT * FROM v$RECOVER_FILE 获取文件编号 SELECT * FROM v$RECOVER_FILE 获取文件编号
ALTER DATABASE DATAFILE file_id OFFLINE DROP; 把要恢复的数据文件脱机 ALTER DATABASE DATAFILE file_id OFFLINE DROP; 把要恢复的数据文件脱机
ALTER DATABASE OPEN; 更改数据库状态为打开模式 ALTER DATABASE OPEN; 更改数据库状态为打开模式
RECOVER DATAFILE file_id; 恢复数据文件 RECOVER DATAFILE file_id; 恢复数据文件
ALTER DATABASE DATAFILE file_id ONLINE; 设置数据文件联机 ALTER DATABASE DATAFILE file_id ONLINE; 设置数据文件联机
``` ```
# EXP工具导出数据 # EXP工具导出数据
```bash ```bash
exp db_user/password 登陆数据库的用户名和密码非SYS exp db_user/password 登陆数据库的用户名和密码非SYS
``` ```
# EXP工具直接导出表 # EXP工具直接导出表
```bash ```bash
exp db_user/password file="filename.dmp" tables="table_name,..." exp db_user/password file="filename.dmp" tables="table_name,..."
``` ```
# EXP工具导出表空间 # EXP工具导出表空间
```bash ```bash
exp db_user/password file="filename.dmp" tablespaces="tablespaces_name" exp db_user/password file="filename.dmp" tablespaces="tablespaces_name"
``` ```
# EXPDP导出数据 # EXPDP导出数据
```sql ```sql
CREATE DIRECTORY directory_name AS 'file_name'; 目录名称 文件名称 CREATE DIRECTORY directory_name AS 'file_name'; 目录名称 文件名称
GRANT READ,WRITE ON DIRECTORY directory_name TO db_user; 授权用户使用该目录 GRANT READ,WRITE ON DIRECTORY directory_name TO db_user; 授权用户使用该目录
#expdp db_user/password directory=directory_name dumpfile=file_name tables=table_name; #expdp db_user/password directory=directory_name dumpfile=file_name tables=table_name;
``` ```
# IMP导入数据 # IMP导入数据
```sql ```sql
imp db_user/password imp db_user/password
``` ```
# IMP直接导入表 # IMP直接导入表
```sql ```sql
imp db_user/password file="filename.dmp" tables="table_name,..." imp db_user/password file="filename.dmp" tables="table_name,..."
``` ```
# IMPDP导入数据 # IMPDP导入数据
```sql ```sql
impdp db_user_password impdp db_user_password
``` ```
# IMPDP直接导入表 # IMPDP直接导入表
```bash ```bash
impdp db_user/password directory=dir dumpfile=filename.dmp tables=table_name; impdp db_user/password directory=dir dumpfile=filename.dmp tables=table_name;
``` ```
# RMAN工具配置 # RMAN工具配置
```sql ```sql
CONN /AS SYSDBA; 连接恢复目录数据库 CONN /AS SYSDBA; 连接恢复目录数据库
CREATE USER rman_user IDENTIFIED BY password DEFAULT TABLESPACE tablespace_name; 创建恢复用户 CREATE USER rman_user IDENTIFIED BY password DEFAULT TABLESPACE tablespace_name; 创建恢复用户
GRANT RECOVERY_CATALOG_OWNER TO rman_user; 为新创建的用户授权 GRANT RECOVERY_CATALOG_OWNER TO rman_user; 为新创建的用户授权
#rman #rman
CONN CATALOG rman_user/password; 连接新创建的用户 CONN CATALOG rman_user/password; 连接新创建的用户
CREATE CATALOG; 创建恢复目录 CREATE CATALOG; 创建恢复目录
``` ```
# RMAN工具使用 # RMAN工具使用
```sql ```sql
#rman target db_user/password@servicename catalog rman_user/password 连接恢复目录数据库 #rman target db_user/password@servicename catalog rman_user/password 连接恢复目录数据库
CONNECT TARGET db_user/password@servicename; 连接目标数据库 CONNECT TARGET db_user/password@servicename; 连接目标数据库
CONNECT CATALOG rman_user/password@servicename; 连接恢复目录数据库 CONNECT CATALOG rman_user/password@servicename; 连接恢复目录数据库
REGISTER database; 在恢复目录数据库中注册数据库 REGISTER database; 在恢复目录数据库中注册数据库
``` ```
# 手动分配通道 # 手动分配通道
```sql ```sql
关闭目标数据库启动到mount状态运行 关闭目标数据库启动到mount状态运行
run run
{ {
ALLOCATE CHANNEL channel_name1 DEVICE TYPE {sbt|disk}; ALLOCATE CHANNEL channel_name1 DEVICE TYPE {sbt|disk};
... ...
BACKUP [level] [backup type] [option] BACKUP [level] [backup type] [option]
} }
``` ```
# 自动分配通道 # 自动分配通道
```sql ```sql
CONFIGURE DEVICE TYPE {sbt|disk} PARALLELISM n; 指定通道类型和名称 CONFIGURE DEVICE TYPE {sbt|disk} PARALLELISM n; 指定通道类型和名称
CONFIGURE DEFAULT DEVICE TYPE {sbt|disk}; 指定默认设备类型 CONFIGURE DEFAULT DEVICE TYPE {sbt|disk}; 指定默认设备类型
BACKUP [level] [backup type] [option]; BACKUP [level] [backup type] [option];
``` ```
# BACKUP 参数 # BACKUP 参数
```sql ```sql
level 备份增量1、2、3、4或者FULL全备份 level 备份增量1、2、3、4或者FULL全备份
backup type 对象类型database、datafile、tablespace、controlfilecopy、archivelog all backup type 对象类型database、datafile、tablespace、controlfilecopy、archivelog all
option channel备份使用的通道 maxsetsize定义备份集的最大值 option channel备份使用的通道 maxsetsize定义备份集的最大值
``` ```
# RESTORE还原 # RESTORE还原
```sql ```sql
RESTORE database_object; RESTORE database_object;
database_object: DATABASE(mount),TABLESPACE(open),DATAFILE,CONTROLFILE(mount),ARCHIVELOG,SPFILE(mount) database_object: DATABASE(mount),TABLESPACE(open),DATAFILE,CONTROLFILE(mount),ARCHIVELOG,SPFILE(mount)
``` ```
# RECOVER同步恢复 # RECOVER同步恢复
```sql ```sql
RECOVER database_object; RECOVER database_object;
database_object: DATABASE(mount),TABLESPACE(open),DATAFILE database_object: DATABASE(mount),TABLESPACE(open),DATAFILE
``` ```

View File

@ -7,30 +7,30 @@ categories: ["python"]
--- ---
# 生成标准的、符合Unix/Posix 规范的命令行说明 # 生成标准的、符合Unix/Posix 规范的命令行说明
```python ```python
from optparse import OptionParser from optparse import OptionParser
parser = OptionParser() parser = OptionParser()
parser.add_option('-p', '--pdbk', action = 'store_true', dest = 'pdcl', default = False, parser.add_option('-p', '--pdbk', action = 'store_true', dest = 'pdcl', default = False,
help = 'write pdbk data to oracle db') help = 'write pdbk data to oracle db')
parser.add_option('-z', '--zdbk', action = 'store_true', dest = 'zdcl', default = False, parser.add_option('-z', '--zdbk', action = 'store_true', dest = 'zdcl', default = False,
help = 'write zdbk data to oracle db') help = 'write zdbk data to oracle db')
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
if options.pdcl == True: if options.pdcl == True:
print 'pdcl is true.' print 'pdcl is true.'
if options.zdcl == True: if options.zdcl == True:
print 'zdcl is True.' print 'zdcl is True.'
``` ```
# 简单流程 # 简单流程
```python ```python
#引入OptionParser类创建OptionParser对象 # 引入OptionParser类创建OptionParser对象
from optparse import OptionParser from optparse import OptionParser
parser = OptionParser() parser = OptionParser()
# 定义命令行参数 # 定义命令行参数
parser.add_option(opt_str, ..., attr = value, ...) parser.add_option(opt_str, ..., attr = value, ...)
# 解析命令行参数 # 解析命令行参数
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
``` ```
# parse_args 和 add_options 函数 # parse_args 和 add_options 函数
- parse_args() 接收一个命令行列表,默认使用 sys.argv\[:-1\] - parse_args() 接收一个命令行列表,默认使用 sys.argv\[:-1\]
@ -45,6 +45,7 @@ parser.add_option(opt_str, ..., attr = value, ...)
help = 'Don\'t print status message to stdout.') help = 'Don\'t print status message to stdout.')
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
``` ```
- action 默认 store 表示将参数值保存到 options 对象里 - action 默认 store 表示将参数值保存到 options 对象里
```python ```python
from optparse import OptionParser from optparse import OptionParser
@ -54,6 +55,7 @@ parser.add_option(opt_str, ..., attr = value, ...)
(options, args) = parser.parse_args(args) (options, args) = parser.parse_args(args)
print options.filename print options.filename
``` ```
- type 默认 'string',也可以是 'int' 或 'float' 等长参数名可选dest 未指定时将用命令行的参数名来存取 options 对象的值 - type 默认 'string',也可以是 'int' 或 'float' 等长参数名可选dest 未指定时将用命令行的参数名来存取 options 对象的值
- store 其他两种形式store_true 和 store_false还有 store_const、append、count、callback - store 其他两种形式store_true 和 store_false还有 store_const、append、count、callback
```python ```python
@ -61,6 +63,7 @@ parser.add_option(opt_str, ..., attr = value, ...)
parser.add_option('-q', action = 'store_false', dest = 'verbose') parser.add_option('-q', action = 'store_false', dest = 'verbose')
#当解析到 '-v', options.verbose 为 True解析到 '-q'options.verbose 为 False #当解析到 '-v', options.verbose 为 True解析到 '-q'options.verbose 为 False
``` ```
- default 设置参数默认值 - default 设置参数默认值
``` ```
parser.add_option('-f', action = 'store', dest = 'filename', default = 'foo.txt') 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(...) parser.add_option(...)
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
``` ```
- help 生成帮助信息 - help 生成帮助信息
```python ```python
usage = 'usage: %prog [options] arg1 arg2' usage = 'usage: %prog [options] arg1 arg2'
@ -89,12 +93,13 @@ parser.add_option(opt_str, ..., attr = value, ...)
- metavar 提醒用户该参数期待的参数,如 metavar = 'mode' 会在帮助中显示成 -m MODE, --mode=MODE - metavar 提醒用户该参数期待的参数,如 metavar = 'mode' 会在帮助中显示成 -m MODE, --mode=MODE
# OptionGroup 参数分组 # OptionGroup 参数分组
```python ```python
group = OptionGroup(parser, 'Dangerous Options', group = OptionGroup(parser, 'Dangerous Options',
'Caution: use these options at your own risk. It is believed that some of them bite.') 'Caution: use these options at your own risk. It is believed that some of them bite.')
group.add_option('-g', action = 'store_true', help = 'Group option.') group.add_option('-g', action = 'store_true', help = 'Group option.')
parser.add_option_group(group) parser.add_option_group(group)
``` ```
- version 创建OptionParser对象时指定该参数会解释成 --version 命令行参数 - version 创建OptionParser对象时指定该参数会解释成 --version 命令行参数
- optparser 可以自动探测并处理一些用户异常,也可以使用 parser.error() 方法来自定义部分异常的处理 - optparser 可以自动探测并处理一些用户异常,也可以使用 parser.error() 方法来自定义部分异常的处理
``` ```

View File

@ -17,126 +17,126 @@ categories: ["shell"]
- $1...$n #shell 位置参数 - $1...$n #shell 位置参数
# BASH 字符串处理 # BASH 字符串处理
```bash ```bash
#字符串 str 长度 # 字符串 str 长度
${#str} ${#str}
expr length "$str" expr length "$str"
#子串 substr 出现位置,找不到返回 0 # 子串 substr 出现位置,找不到返回 0
expr index "$str" "$substr" expr index "$str" "$substr"
#子串 substr 开头匹配,找不到返回 0 # 子串 substr 开头匹配,找不到返回 0
expr match "$str" "$substr" expr match "$str" "$substr"
#字符串 str 抽取左起位置 pos 后 长度 len 的子串 # 字符串 str 抽取左起位置 pos 后 长度 len 的子串
${str:$pos} ${str:$pos}
${str:$pos:$len} ${str:$pos:$len}
expr substr "$str" $pos $len expr substr "$str" $pos $len
#字符串 str 抽取右起位置 pos 前的子串 # 字符串 str 抽取右起位置 pos 前的子串
${str: -pos} ${str: -pos}
${str:(pos)} ${str:(pos)}
#正则 pat 抽取字符串 str 开头子串 # 正则 pat 抽取字符串 str 开头子串
expr match "$str" "\($pat\)" expr match "$str" "\($pat\)"
expr "$str" : "\($pat\)" expr "$str" : "\($pat\)"
#正则 pat 抽取字符串 str 结尾子串 # 正则 pat 抽取字符串 str 结尾子串
expr match "$str" ".*\($pat\)" expr match "$str" ".*\($pat\)"
expr "$str" : ".*\($pat\)" expr "$str" : ".*\($pat\)"
#删除字符串 str 开头的最短子串 sub # 删除字符串 str 开头的最短子串 sub
${str#$sub} ${str#$sub}
#删除字符串 str 开头的最长子串 sub # 删除字符串 str 开头的最长子串 sub
${str##$sub} ${str##$sub}
#删除字符串 str 结尾的最短子串 sub # 删除字符串 str 结尾的最短子串 sub
${str%$sub} ${str%$sub}
#删除字符串 str 结尾的最长子串 sub # 删除字符串 str 结尾的最长子串 sub
${str%%$sub} ${str%%$sub}
#替换字符串 str 第一个子串 sub 为字符串 rep # 替换字符串 str 第一个子串 sub 为字符串 rep
${str/"$sub"/"$rep"} ${str/"$sub"/"$rep"}
#替换字符串 str 所有子串 sub 为字符串 rep # 替换字符串 str 所有子串 sub 为字符串 rep
${str//"$sub"/"$rep"} ${str//"$sub"/"$rep"}
#替换字符串 str 开头的子串 sub 为字符串 rep # 替换字符串 str 开头的子串 sub 为字符串 rep
${str/#"$sub"/"$rep"} ${str/#"$sub"/"$rep"}
#替换字符串 str 结尾的子串 sub 为字符串 rep # 替换字符串 str 结尾的子串 sub 为字符串 rep
${str/%"$sub"/"$rep"} ${str/%"$sub"/"$rep"}
#var为空或没有设置代入word否则代入var值 # var为空或没有设置代入word否则代入var值
${var:-word} ${var:-word}
#如果var已经被设置且不为空则代入它的值否则代入word并且在后面var始终为word的值。位置参量不能用这种方式赋值。 # 如果var已经被设置且不为空则代入它的值否则代入word并且在后面var始终为word的值。位置参量不能用这种方式赋值。
${variable:=word} ${variable:=word}
#如果变量var已被设置且值为非空代入word值否则什么也不代入 # 如果变量var已被设置且值为非空代入word值否则什么也不代入
${variable:+word} ${variable:+word}
#如果变量var已被设置值且为非空就代入它的值否则输出word并从shell中退出如果有省略了word,就会显示信息parameter null or not set. # 如果变量var已被设置值且为非空就代入它的值否则输出word并从shell中退出如果有省略了word,就会显示信息parameter null or not set.
${var:?word} ${var:?word}
``` ```
# BASH 数组 # BASH 数组
```bash ```bash
#定义数组,有三种方式 # 定义数组,有三种方式
declare -a array declare -a array
array=() array=()
array[0]='value0' array[0]='value0'
#打印数组第一个元素 # 打印数组第一个元素
echo ${array[0]} echo ${array[0]}
#打印数组所有元素,有两种方式 # 打印数组所有元素,有两种方式
echo ${array[@]} echo ${array[@]}
echo ${array[*]} echo ${array[*]}
#打印数组所有索引,有两种方式 # 打印数组所有索引,有两种方式
echo ${!array[@]} echo ${!array[@]}
echo ${!array[*]} echo ${!array[*]}
#打印数组的元素个数,有两种方式 # 打印数组的元素个数,有两种方式
echo ${#array[@]} echo ${#array[@]}
echo ${#array[*]} echo ${#array[*]}
#移除数组中索引为2的元素 # 移除数组中索引为2的元素
unset array[2] unset array[2]
#添加id为3的元素 # 添加id为3的元素
array[3]="" array[3]=""
``` ```
# BASH 字典 # BASH 字典
```bash ```bash
#定义字典 # 定义字典
declare -A dict declare -A dict
#新增或修改键 k1 的值 # 新增或修改键 k1 的值
dict['k1']='v1' dict['k1']='v1'
#打印对应键的值 # 打印对应键的值
echo $['k1'] echo $['k1']
#打印字典所有元素,有两种方式 # 打印字典所有元素,有两种方式
echo ${dict[@]} echo ${dict[@]}
echo ${dict[*]} echo ${dict[*]}
#打印字典所有键,有两种方式 # 打印字典所有键,有两种方式
echo ${!dict[@]} echo ${!dict[@]}
echo ${!dict[*]} echo ${!dict[*]}
#打印字典的元素个数,有两种方式 # 打印字典的元素个数,有两种方式
echo ${#dict[@]} echo ${#dict[@]}
echo ${#dict[*]} echo ${#dict[*]}
#移除键 k1 # 移除键 k1
unset dict['k1'] unset dict['k1']
``` ```
# 终端环境变量 PS1 参数 # 终端环境变量 PS1 参数
- \d 日期格式为weekday month date例如"Mon Aug 1" - \d 日期格式为weekday month date例如"Mon Aug 1"
@ -187,24 +187,24 @@ unset dict['k1']
- 去掉头部 AA 和尾部 ZZ - 去掉头部 AA 和尾部 ZZ
# expect 自动输入密码 # expect 自动输入密码
```bash ```bash
expect<<END expect<<END
spawn ssh $DEST_HOST "REMOTE_COMMAND" spawn ssh $DEST_HOST "REMOTE_COMMAND"
expect { expect {
"*yes/no*" { send "yes\r"; exp_continue } "*yes/no*" { send "yes\r"; exp_continue }
"*assword*" { send "password\r" } "*assword*" { send "password\r" }
} }
expect eof expect eof
END END
``` ```
# 普通用户(username)免密 sudo # 普通用户(username)免密 sudo
```bash ```bash
echo "username ALL = (root) NOPASSWD:ALL" >> /etc/sudoers echo "username ALL = (root) NOPASSWD:ALL" >> /etc/sudoers
#
echo "cephdeploy ALL = (root) NOPASSWD:ALL" > /etc/sudoers.d/username echo "cephdeploy ALL = (root) NOPASSWD:ALL" > /etc/sudoers.d/username
chmod 0400 /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 mkdir /var/log/user_history -p
chmod 0777 /var/log/user_history -R chmod 0777 /var/log/user_history -R
``` ```
- 配置 history 历史文件 /etc/profile.d/history.sh - 配置 history 历史文件 /etc/profile.d/history.sh
```bash ```bash
#!/bin/bash #!/bin/bash
#
export HISTSIZE=10000 export HISTSIZE=10000
export HISTTIMEFORMAT="[%F %T] " export HISTTIMEFORMAT="[%F %T] "
#
LOG_DIR=/var/log/user_history LOG_DIR=/var/log/user_history
mkdir -p $LOG_DIR/$USER mkdir -p $LOG_DIR/$USER
if [ 0 -eq $? ]; then if [ 0 -eq $? ]; then

View File

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

View File

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

View File

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

View File

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