yaml 入门

  |  

yaml介绍

官网介绍如下:

1
2
3
4
5
6
7
%YAML 1.2
---
YAML: YAML Ain't Markup Language™

What It Is:
YAML is a human-friendly data serialization
language for all programming languages.

语法

这里的语法使用python举例,python使用的库是PyYAML

所有的 YAML 文件开始行都应该是 —。这是 YAML 格式的一部分, 表明一个文件的开始。

基本语法规则如下:

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进时不允许使用Tab键,只允许使用空格。
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • # 表示注释,从这个字符一直到行尾,都会被解析器忽略。

YAML 支持的数据结构有三种:

  1. 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
  2. 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
  3. 纯量(scalars):单个的、不可再分的值

对象 key-value键值对

使用格式为key: value。冒号后面要加一个空格。

简单展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import yaml

# yaml 文件内容
yaml_context = """
---
# 表示url属性值
url: https://www.iluvatar.com
"""

# 解析 yaml 文件
value = yaml.safe_load(yaml_context)

print(type(value))
print(value)

打印结果:

1
2
<class 'dict'>
{'url': 'https://www.iluvatar.com'}

使用缩进代表层级结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import yaml

# yaml 文件内容
yaml_context = """
---
# 可以使用缩进表示层级结构
host:
# 这样没有层级结构,所以解析的时候会报错
# ip:
# 172.16.0.1
ip:
172.16.0.1
# 定义相同的key并不报错,而是覆盖之前的相同key中的value
ip:
172.16.0.2
# 没有空格的话会被认为是一个键,并且报错没有检测到: 以及value
# ip:172.16.0.3
mask: 255.255.255.0
"""

# 解析 yaml 文件
value = yaml.safe_load(yaml_context)

print(type(value))
print(value)

打印结果:

1
2
<class 'dict'>
{'host': {'ip': '172.16.0.2', 'mask': '255.255.255.0'}}

一行显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import yaml

# yaml 文件内容
yaml_context = """
---
# yaml 也支持将所有的对象写在一行的写法
# 注意: 如果键值对没有使用空格分开会被认为是一个键
host: {ip: 172.16.0.1,ip: 172.16.0.2, ip:172.16.0.3 ,mask: 255.255.255.0}
"""

# 解析 yaml 文件
value = yaml.safe_load(yaml_context)

print(type(value))
print(value)

打印结果:

1
2
<class 'dict'>
{'host': {'ip': '172.16.0.2', 'ip:172.16.0.3': None, 'mask': '255.255.255.0'}}

数组 Array/List

简单展示

列表中的所有成员都开始于相同的缩进级别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import yaml

# yaml 文件内容
yaml_context = """
---
ipaddr:
# IP地址列表
- 192.168.10.1
- 192.168.10.2
- 192.168.10.3
"""

value = yaml.safe_load(yaml_context)

print(value)

打印结果:

1
{'ipaddr': ['192.168.10.1', '192.168.10.2', '192.168.10.3']}

缩进显示

子成员是一个数组,则可以在该项下面缩进一个空格。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from pprint import pprint

import yaml

# yaml 文件内容
yaml_context = """
ipaddr:
- ens192:
# 下一级的定义要空两个空格以上
- 192.168.10.1
- 192.168.10.2
- 192.168.10.3
file:
# 数组的子成员还是一个数组,空一个空格即可
-
- etc
- sysconfig
- network-scripts
- ifcfg-ens192

"""

value = yaml.safe_load(yaml_context)

print(value)
# 这里使用pprint打印稍微美观一些
pprint(value)

打印结果:

1
2
3
{'ipaddr': [{'ens192': ['192.168.10.1', '192.168.10.2', '192.168.10.3']}], 'file': [['etc', 'sysconfig', 'network-scripts', 'ifcfg-ens192']]}
{'file': [['etc', 'sysconfig', 'network-scripts', 'ifcfg-ens192']],
'ipaddr': [{'ens192': ['192.168.10.1', '192.168.10.2', '192.168.10.3']}]}

行内表示

因为程序差不多,之后只提供yaml文件内容以及pprint打印的结果

1
2
3
4
5
yaml_context = """
ipaddr:
# 行内表示格式正确就行,中间的空格位数不影响
- ens192: [ 192.168.10.1, 192.168.10.2, 192.168.10.3 ]
"""

打印结果:

1
{'ipaddr': [{'ens192': ['192.168.10.1', '192.168.10.2', '192.168.10.3']}]}

常量

yaml中的常量包含以下几种

  • 字符串
  • 布尔值
  • 整数
  • 浮点数
  • Null
  • 时间
  • 日期

具体看以下示例应该就清楚了,不过多解释了

其中字符串有几个规则需要注意

  • 字符串默认不使用引号表示,如:str: 这是一行字符串
  • 如果字符串之中包含空格或特殊字符,需要放在引号之中,如:str: '内容:字符串'
  • 单引号和双引号都可以使用,双引号不会对特殊字符转义,如:str: {s1: '内容\n字符串', s2: "内容\n字符串"}
  • 单引号之中如果还有单引号,必须连续使用两个单引号转义,如:str: 'labor''s day'
  • 字符串可以写成多行,从第二行开始,必须有一个单空格缩进。换行符会被转为空格
  • 多行字符串可以使用 | 保留换行符,也可以使用 > 折叠换行,下一节会介绍
    • 表示保留文字块末尾的换行,- 表示删除字符串末尾的换行,下一节会介绍
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
yaml_context = """
boolean:
# true,True都可以
- TRUE
# false,False都可以
- FALSE
float:
- 3.14
# 可以使用科学计数法
- 6.8523015e+5
int:
- 123
# 二进制表示
- 0b1010_0111_0100_1010_1110
null:
nodeName: 'node'
# 使用~表示null
parent: ~
string:
- 字符串行
- newline
# 可以使用双引号或者单引号包裹特殊字符
- 'Hello world'
# 字符串可以拆成多行,每一行会被转化成一个空格
- one_line
two_line
date:
# 日期必须使用ISO 8601格式,即yyyy-MM-dd
- 2018-02-17
datetime:
# 时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
- 2018-02-17T15:02:31+08:00
"""

打印结果:

1
2
3
4
5
6
7
{None: {'nodeName': 'node', 'parent': None},
'boolean': [True, False],
'date': [datetime.date(2018, 2, 17)],
'datetime': [datetime.datetime(2018, 2, 17, 15, 2, 31, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800)))],
'float': [3.14, 685230.15],
'int': [123, 685230],
'string': ['字符串行', 'newline', 'Hello world', 'one_line two_line']}

特殊符号

!! 类型强转

1
2
3
4
yaml_context = """
int2string: !!str 123
boolean2string: !!str true
"""

打印结果:

1
{'boolean2string': 'true', 'int2string': '123'}

… 和 —

… 和—配合使用,在一个配置文件中代表一个文件的结束:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pprint import pprint

import yaml

# yaml 文件内容
yaml_context = """
---
time: 10:05:07
user: userA
action: 'delete job (id: 13579)'
...
---
time: 11:13:45
user: userB
action: download dataset A
...
"""

values = yaml.safe_load_all(yaml_context)

print(values)
for value in values:
pprint(value)

打印结果:

1
2
3
<generator object load_all at 0x000001C786A58C80>
{'action': 'delete job (id: 13579)', 'time': 36307, 'user': 'userA'}
{'action': 'download dataset A', 'time': 40425, 'user': 'userB'}

| 控制符 和 > 控制符

这两个符号是YAML中字符串经常使用的符号

| 控制符

这个控制符的作用是保留文本每一行尾部的换行符。

  • | 保证整段文本最后有且只有一个换行符
  • |+ 保留整段文本最后的所有换行符
  • |- 删除整段文本最后的所有换行符
  1. 最后有且只有一个换行符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    yaml_context = """
    cmd: |
    bash
    -c


    sleep 3600




    """

    打印结果:

    1
    {'cmd': 'bash\n-c \n\n\nsleep 3600\n'}
  2. 保留整段文本最后的所有换行符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    yaml_context = """
    cmd: |+
    bash
    -c


    sleep 3600




    """

    打印结果:

    1
    {'cmd': 'bash\n-c \n\n\nsleep 3600\n\n\n\n\n'}
  3. 删除整段文本最后的所有换行符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    yaml_context = """
    cmd: |-
    bash
    -c


    sleep 3600




    """

    打印结果:

    1
    {'cmd': 'bash\n-c \n\n\nsleep 3600'}

> 控制符

这个控制符的作用是将每一行尾部的换行符替换为空格,也就是将多行文本视为一行

  • 保证文本最后有且只有一个换行符

    • 保留文本最后的所有换行符
    • 删除文本最后的所有换行符
  1. 最后有且只有一个换行符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    yaml_context = """
    cmd: >
    bash
    -c


    sleep 3600




    """

    打印结果:

    1
    {'cmd': 'bash -c \n\nsleep 3600\n'}
  2. 保留整段文本最后的所有换行符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    yaml_context = """
    cmd: >+
    bash
    -c


    sleep 3600




    """

    打印结果:

    1
    {'cmd': 'bash -c \n\nsleep 3600\n\n\n\n\n'}
  3. 删除整段文本最后的所有换行符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    yaml_context = """
    cmd: >-
    bash
    -c


    sleep 3600




    """

    打印结果:

    1
    {'cmd': 'bash -c \n\nsleep 3600'}

引用 & 和 *

重复的内容在YAML中可以使用&来完成锚点定义,使用*来完成锚点引用,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
yaml_context = """
defaults: &defaults
host: localhost
db: postgres

production:
<<: *defaults
host: 10.10.10.123

development:
db: mysql
<<: *defaults

staging:
env: *defaults
"""

打印结果:

1
2
3
4
{'defaults': {'db': 'postgres', 'host': 'localhost'},
'development': {'db': 'mysql', 'host': 'localhost'},
'production': {'db': 'postgres', 'host': '10.10.10.123'},
'staging': {'env': {'db': 'postgres', 'host': 'localhost'}}}

CentOS 搭建 nfs server

服务端部署

  1. 安装软件包

    1
    # yum install -y rpcbind nfs-utils
  2. 创建共享目录

    1
    2
    # mkdir -p /srv/data/nfs_data
    # chmod 777 /srv/data/nfs_data
  3. 修改配置文件

    将配置文件exports填写以下内容

    1
    2
    3
    # cat /etc/exports

    /data/nfs_data/data *(insecure,rw,sync,no_root_squash,fsid=0)
  4. 启动 nfs 服务

    1
    2
    3
    4
    5
    systemctl enable rpcbind
    systemctl enable nfs-server

    systemctl start rpcbind
    systemctl start nfs-server
  5. 检查配置是否生效

    使用 exportfs 命令,会显示共享的目录

    1
    2
    3
    # exportfs
    /srv/data/nfs_data
    <world>
  6. 开发防火墙

    服务器端开放 111、662、875、892、2049 的 tcp / udp 端口即可

客户端挂载

  1. 客户端安装软件

    1
    yum install -y nfs-utils
  2. 执行命令检查共享目录

    使用命令 showmount 进行显示,注意替换成当前的服务器地址,这里是 10.6.70.4

    1
    2
    3
    4
    # showmount -e 10.6.70.4
    Export list for 10.6.70.4:
    /srv/data/nfs_data *

  3. 挂载并测试

    客户端挂载并创建测试文件

    1
    2
    3
    4
    # ls /mnt/
    # mount -t nfs 10.6.70.4:/ /mnt/
    # ls /mnt/
    # echo 'aaa' > /mnt/a.txt

    服务器端查看目录,可以看到已经生成文件

    1
    2
    # cat /srv/data/nfs_data/a.txt
    aaa
文章目录
  1. 1. yaml介绍
  2. 2. 语法
    1. 2.1. 对象 key-value键值对
      1. 2.1.1. 简单展示
      2. 2.1.2. 使用缩进代表层级结构
      3. 2.1.3. 一行显示
    2. 2.2. 数组 Array/List
      1. 2.2.1. 简单展示
      2. 2.2.2. 缩进显示
      3. 2.2.3. 行内表示
    3. 2.3. 常量
    4. 2.4. 特殊符号
      1. 2.4.1. !! 类型强转
      2. 2.4.2. … 和 —
      3. 2.4.3. | 控制符 和 > 控制符
        1. 2.4.3.1. | 控制符
        2. 2.4.3.2. > 控制符
      4. 2.4.4. 引用 & 和 *
  3. 3. 服务端部署
  4. 4. 客户端挂载