runc系列(2)——specification(config.json)文件详解

1. Specification概述

  • The Open Container Initiative develops specifications for standards on Operating System process and application containers.——OCI的specification是对操作系统的进程以及应用容器的标准化
  • The Open Container Initiative Runtime Specification aims to specify the configuration, execution environment, and lifecycle of a container.——OCI specification包括对容器配置、容器执行环境、容器生命周期的说明以及限定
  • A container's configuration is specified as the config.json for the supported platforms and details the fields that enable the creation of a container.——容器的配置文件会被组织为一个config.json文件,其中对容器的启动以及创建进行了详细的说明
  • The execution environment is specified to ensure that applications running inside a container have a consistent environment between runtimes along with common actions defined for the container's lifecycle.——执行环境的构建保证容器在运行期间具有一致的环境,同时执行环境也为容器的生命周期提供了一般的工具(actions)
  • platforms
  • 主体内容:contents

2. 各组件介绍

2.1 总介绍(Introduction)

  • Notational Conventions:该部分对spec中出现的MUST,REQUIED等关键字的含义进行了说明;注意:一个spec只有满足了全部的MUST,REQUIED以及SHALL的需求才是正确的
  • Container Principles:
    • 容器表征了一个“易交付软件单元”,而标准化容器就是为了对一个应用的组件以及其所有依赖进行包装,使其维持在一种自我描述的(self-describing)以及便携的格式——因此所有满足要求的runtime(例如runc)就可以直接运行该容器
    • 五个组成部分:
      • 1 Standard Operation(容器应该具有的标准操作):包括使用标准的容器工具创建,开始以及暂停一个容器;使用标准的文件系统工具对容器进行复制以及快照;使用标准的网络工具对容器进行打包以及传输
      • 2 Content-agnostic(容器的内容不可知性):无论容器中的内容为何,所有的标准化操作应该具有相当的功能
      • 3 Infrastructure-agnostic(系统不可知性):即容器应该可以部署在“任何”满足OCI标准的系统上(无论是laptop还是server)
      • 4 Designed for automation(为自动化部署的设计):由于满足上述几点要求,容器应该能够满足自动化部署的要求(也就是说针对容器的操作应该十分简单)
      • 5 Industrail-grade delivery(为工业级传输的设计):容器应该具备的易于传输以及流程化的优势

2.2 术语约定(Glossary)

  • Bundle:是一个提前写入的,分布式的目录结构,为容器运行以及在其内运行应用创造了基本条件
  • Configuration:也就是一个config.json文件,对容器及其内部运行的应用进行了描述
  • Container:是一个可以运行进程的具备可配置隔离以及资源限制的环境;例如namespace,resource limits以及挂载等
  • Container namespace:是Linux提供的功能,可以使进程以隔离的方式运行
  • JSON:所有的配置信息以json的方式描述(UTF-8编码格式),不能有重复的属性;属性的顺序不重要
  • Runtime:一个runtime指的是一个满足OCI标准的工具(例如runc),它可以读取bundle中的配置文件,对容器进行创建,在容器中运行进程,执行生命周期管理等
  • Runtime namespace:是container namespace的父命名空间

2.3 Filesystem Bundle

  • 本篇文章不对该部分进行介绍,目前为止我们可以直接通过docker export得到一个可用的bundle,如果感兴趣可以参考这里

2.4 Runtime and Lifecycle

  • State:一个容器的state包含以下属性
    • 1 ociVersion(string,REQUIED):表明了OCI specification版本
    • 2 id(string,REQUIED):即容器的id;同一台主机上的容器id一定(MUST)不相同(跨主机无要求)
    • 3 status(string,REQUIED):表明了容器的运行状态,可能(MAY)是以下几种之一
      • creating:正在创建容器(整个生命周期的第二步)
      • created:容器已经创建好了,但是还没有开始运行程序
      • running:正在执行容器指定的程序(整个生命周期的第八步之后)
      • stopped:容器内程序已经执行完毕(整个生命周期的第十步)
      • 补充:除了上述四种状态外,根据runtime的不同可能(MAY)还有其他的状态,且它们都必须(MUST)用于对应相应的状态
    • 4 pid(int,在Linux系统上,如果容器处于created或者running状态则该属性为REQUIED,其他平台则为OPTIONAL):表征了容器进程的pid;对于运行在runtime namespace的hooks而言,是runtime可见的pid;对于运行在container namespace的hooks而言,是container可见的pid
    • 5 bundle(string,REQUIED):是容器bundle目录的绝对路径——便于找到位于host主机上的配置文件以及容器根文件系统目录
    • 6 annotations(map,OPTIONAL):是一组与容器相关的注释;是OPTIONAL的
    •   {   # 需要遵从一下格式
            "ociVersion": "0.2.0",
            "id": "oci-container1",
            "status": "running",
            "pid": 4422,
            "bundle": "/containers/redis",
            "annotations": {
                "myKey": "myValue"
            }
        }
      
  • Lifecycle:对容器从被创建开始到程序执行结束为止的一系列事件做出了定义
    • 1 runtime的create指令被触发(伴随着指定的路径以及特定的标识符)
    • 2 依据config.json对容器运行的环境进行创建,如果runtime无法满足要求会触发一个错误;指定的容器内程序在此时还不能运行;在经过该步骤之后,任何对config.json的修改都不能影响到容器
    • 3 runtime必须执行预启动(prestart)钩子,如果不能成功执行那么触发一个错误,停止容器并跳转到第12步
    • 4 runtime必须执行createRuntime钩子,如果不成功那么发出错误停止容器并跳转到第12步
    • 5 runtime必须执行createContainer钩子,如果不成功那么发出错误停止容器并跳转到第12步
    • 6 runtime基于特定的标识符执行start命令
    • 7 runtime必须执行startContainer钩子,如果不成功那么发出错误停止容器并跳转到第12步
    • 8 runtime启动指定的运行于容器内的应用(process)
    • 9 runtime必须执行postStart钩子,如果不成功那么runtime必须记录一个warning,但是剩余的生命周期还是会继续进行
    • 10 容器退出,这可能由于error、正常退出、应用崩溃(crashing)、runtime出发kill操作等原因造成
    • 11 runtime基于特定的标识符执行delete命令
    • 12 执行第2步的反步骤以destroy容器
    • 13 runtime必须执行postStop钩子,如果不成功那么runtime必须记录一个warning,但是剩余的操作还是继续进行
  • Operations:容器必须支持的操作
    • 1 状态查询(State Query):返回容器的State段(上面提到的ociVersion等),如果对一个不存在的容器进行查询那么必须发出一个错误
    • 2 创建(Create):create <container-id> <path-to-bundle>——通过create命令,指定id以及bundle的路径可以创建一个容器;如果id冲突或者bundle路径不正确必须触发一个错误;config.json中处理process之外的所有请求都需要在这里被实现;
    • 3 启动(Start):start <container-id>——依据id启动一个容器;该步会运行process指定的程序
    • 4 强制结束(Kill):kill <container-id> <signal>——依据signal想指定的容器发送对应信号;只能向处于created以及running状态的容器发送信号
    • 5 删除(Delete):delete <container-id>——删除指定的容器;只能删除处于stopped状态的容器;与容器相关联的资源会在此时被释放;注意:容器在运行过程中创建的资源不会再这里被释放(例如如果容器运行的程序创建了一些文件那么这些文件一定不能被删除)
  • Hooks:hook操作是指在指定操作(例如Start等)执行之前或之后执行一些额外工作,具体信息可以参考这里
  • 其他的内容不再这里赘述,想要查找可以参考这里

3. Configuration——配置(主要针对Linux平台)

  • This configuration file contains metadata necessary to implement standard operations against the container. This includes the process to run, environment variables to inject, sandboxing features to use, etc.——配置文件中包含有一系列用于实现标准容器操作的元数据,包括需要运行的程序,环境信息,属性信息等

3.1 版本信息(Specification Version)

  • ociVersion(string,REQUIED):表明了bundle遵从的OCI specification的版本;注意如果一个bundle是依据1.1版本构建的,那么只要是遵从1.1版本及其之后所有版本构建runtime都能够执行该容器,但是不会反向支持
  • 例如:"ociVersion": "1.1.1"

3.2 根文件系统(Root)

  • root(object,OPTIONAL):指定了容器的根文件系统;除了Hyper-Ⅴ系统一定不能设置外,其余所有系统对于该属性的需求都是REQUIED:
    • path(string,REQUIED):在windows系统中是一个卷GUID路径;在POSIX平台上,path既可以是相对路径也可以是绝对路径;对应的文件夹一定要存在
    • readonly(bool,OPTIONAL):是否只读;windows系统中一定为false(或者不设置)
  •   # POSIX
      "root": {
          "path": "rootfs",
          "readonly": true
      }
      # Windows
      "root": {
      	  "path": "\\\\?\\Volume{ec84d99e-3f02-11e7-ac6c-00155d7682cf}\\"
      }
    

3.3 POSIX平台挂载信息(POSIX-platform Mounts)

  • mount(array of objects, OPTIONAL):指定除根文件系统之外的挂载点;容器创建时会依据列表的顺序进行挂载;对于Linux而言,参数可以参考mount(2)的man page:
    • destination(string,REQUIED):目的挂载点(容器内);绝对路径;
    • source(string,OPTIONAL):一般而言是设备名,但是对于一个bind mounts而言可以是一个文件或目录名(或者是一个dummy)
    • options(array of strings):挂载选项
    • type(string,OPTIONAL):文件系统类型(kernel支持的文件系统类型列在/proc/filesystems下)
  •   "mounts": [
          {
              "destination": "/tmp",
              "type": "tmpfs",
              "source": "tmpfs",
              "options": ["nosuid","strictatime","mode=755","size=65536k"]
          },
          {
              "destination": "/data",
              "type": "none",
              "source": "/volumes/testing",
              "options": ["rbind","rw"]
          }
      ]
    

3.4 Linux程序(Linux Process)

  • process(object,OPTIONAL):指明了容器运行的程序,当runtime执行start指令时,该属性是REQUIED
    • terminal(bool,OPTIONAL):指明是否有一个终端与进程相关联,默认是false;
    • consoleSize(object,OPTIONAL):窗口大小
    • cwd(string,REQUIED):工作文件夹,绝对路径
    • env(array of strings,OPTIONAL):环境变量
    • args(array of strings,OPTIONAL):参量
    • commandLine(string,OPTIONAL):Windows系统下需要执行的指令
    • rlimits(array of objects,OPTIONAL):允许对进程的资源进行限制,每一个条目都由以下结构组成:
      • type(string,REQUIED):资源类型,可以通过man getrlimit查看可以限制的资源类型
      • soft(uint64,REQUIED):对应资源的限制值,rlim.rlim_cur的值与该值相对应
      • hard(uint64,REQUIED):对应资源的最大值,该值可以被非特权进程设置,但只能够被特权进程提高,与rlim.rlim_max值相对应
    • apparmorProfile(string,OPTIONAL,Linux平台特有属性):指定该进程的AppArmor profile的名称。(AppArmor是一个kernel的增强组件,全称为Mandatory Access Control,同样用于资源限制
    • capabilities(object,OPTIONAL,Linux):指定进程的“能力”;可以通过man capabilities查看支持的进程能力;注意如果指定的能力不能满足,容器不会发错error信息,只会给出warning;包括:
      • effective(array of strings,OPTIONAL)
      • bounding(array of strings,OPTIONAL)
      • inheritable(array of strings,OPTIONAL)
      • permitted(array of strings,OPTIONAL)
      • ambient(array of strings,OPTIONAL)
    • noNewPrivileges(bool,OPTIONAL):如果设置为true,那么进程不会在过程中获得新的特权,实现原理可以参考这里
    • oomScoreAdj(int,OPTIONAL):对应/proc/【pid】/oom_score_adj的值;(补充:对于内存不足的情况,内核会触发OOM Killer杀死相关的进程,但是内核如何决定杀死那个进程呢——通过oom_score_adj,也就是OOM killer会给每个进程打个分数,当出现OOM问题时,Killer会首先杀死分数最高的进程以释放部分内存来满足使用要求;oom_score_adj的值范围为-1000~1000,如果将一个进程的oom_score_adj的值设置为-1000,那么表示该进程不能被OOM Killer杀死
    • selinuxLable(string,OPTIONAL):制定了进程的SELinux标签(SELinux是一个安全控制系统,是对Linux原基于用户,组管理模式的补充

3.5 用户信息(User)

  • user:是一个平台相关的属性,指明了进程应该以什么样的身份来运行(以实现特定的控制),具有一下属性
    • uid(int,REQUIED):指明了进程在Container namespace下的user ID
    • gid(int, REQUIED):指明了进程在container namespace下的group ID
    • umask(int, OPTIONAL):指明了user的umask,如果未指定,那么继承父进程的umask(补充:umask用于控制目录以及文件创建的默认权限,可以通过umask指令查看,以补码形式表现
    • additionalGids(array of ints, OPTIONAL):指明了为进程添加的container namespace下的其他group IDs
  •   "process": {
          "terminal": true,
          "consoleSize": {
              "height": 25,
              "width": 80
          },
          "user": {
              "uid": 1,
              "gid": 1,
              "umask": 63,
              "additionalGids": [5, 6]
          },
          "env": [
              "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
              "TERM=xterm"
          ],
          "cwd": "/root",
          "args": [
              "sh"
          ],
          "apparmorProfile": "acme_secure_profile",
          "selinuxLabel": "system_u:system_r:svirt_lxc_net_t:s0:c124,c675",
          "noNewPrivileges": true,
          "capabilities": {
              "bounding": [
                  "CAP_AUDIT_WRITE",
                  "CAP_KILL",
                  "CAP_NET_BIND_SERVICE"
              ],
             "permitted": [
                  "CAP_AUDIT_WRITE",
                  "CAP_KILL",
                  "CAP_NET_BIND_SERVICE"
              ],
             "inheritable": [
                  "CAP_AUDIT_WRITE",
                  "CAP_KILL",
                  "CAP_NET_BIND_SERVICE"
              ],
              "effective": [
                  "CAP_AUDIT_WRITE",
                  "CAP_KILL"
              ],
              "ambient": [
                  "CAP_NET_BIND_SERVICE"
              ]
          },
          "rlimits": [
              {
                  "type": "RLIMIT_NOFILE",
                  "hard": 1024,
                  "soft": 1024
              }
          ]
      }
    

3.6 主机名(Hostname)

  • hostname(string,OPTIONAL):指定运行在容器内的进程可见的主机名(在Linux系统上,通过改变container UTS namespace来实现)
  •   "hostname": "mrsdalloway"
    

3.7 平台信息配置(Platform-specific Configuration)

  • 用于为对应的平台设置相关的配置
  • Linux(object, OPTIONAL)参考这里
  • windows(object, OPTIONAL)参考这里
  • solaris(object, OPTIONAL)参考这里
  • vm(object, OPTIONAL)参考这里
  • zos(object, OPTIONAL)参考这里
  •   {
          "linux": {
              "namespaces": [
                  {
                      "type": "pid"
                  }
              ]
          }
      }
    

3.8 POSIX平台钩子(POSIX-platform Hooks)

  • 在POSIX平台上,允许对容器生命周期的行为进行自定义的配置(hooks)
  • hooks(object,OPTIONAL)可能含有任意以下属性
    • prestart(array of objects,OPTIONAL,DEPRECATED):是一个关于prestart操作的hooks列表
    • createRuntime(array of objects,OPTIONAL):是一个关于createRuntime操作的hooks列表
    • createContainer(array of objects,OPTIONAL):是一个关于createContainer操作hooks的列表
    • startContainer(array of objects, OPTIONAL):是一个关于startContainer操作hooks的列表
    • poststart(array of objects, OPTIONAL):是一个关于poststart操作hooks的列表
    • poststop(array of objects, OPTIONAL)是一个关于poststop操作hooks的列表
  • hook总结
  •   "hooks": {
          "prestart": [
              {
                  "path": "/usr/bin/fix-mounts",
                  "args": ["fix-mounts", "arg1", "arg2"],
                  "env":  [ "key1=value1"]
              },
              {
                  "path": "/usr/bin/setup-network"
              }
          ],
          "createRuntime": [
              {
                  "path": "/usr/bin/fix-mounts",
                  "args": ["fix-mounts", "arg1", "arg2"],
                  "env":  [ "key1=value1"]
              },
              {
                  "path": "/usr/bin/setup-network"
              }
          ],
          "createContainer": [
              {
                  "path": "/usr/bin/mount-hook",
                  "args": ["-mount", "arg1", "arg2"],
                  "env":  [ "key1=value1"]
              }
          ],
          "startContainer": [
              {
                  "path": "/usr/bin/refresh-ldcache"
              }
          ],
          "poststart": [
              {
                  "path": "/usr/bin/notify-start",
                  "timeout": 5
              }
          ],
          "poststop": [
              {
                  "path": "/usr/sbin/cleanup.sh",
                  "args": ["cleanup.sh", "-f"]
              }
          ]
      }
    

3.9 注释(Annotation)

  • annotations(objects, OPTIONAL):包含有任意需要传递给容器的元数据;键值对形式;可以没有该部分

3.10 扩展性(Extensibility)

  • 即对于spec中没有指定的属性,即使config.json中出现了,runtime也不应该报错而是应该忽略它们

3.11 有效值(Valid Values)

  • 即如果config.json中出现了非法值,runtime应该能够检测出来并且报错

3.12 一个完整示例(Json格式)——来自这里

	{
	    "ociVersion": "1.0.1",
	    "process": {
	        "terminal": true,
	        "user": {
	            "uid": 1,
	            "gid": 1,
	            "additionalGids": [
	                5,
	                6
	            ]
	        },
	        "args": [
	            "sh"
	        ],
	        "env": [
	            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
	            "TERM=xterm"
	        ],
	        "cwd": "/",
	        "capabilities": {
	            "bounding": [
	                "CAP_AUDIT_WRITE",
	                "CAP_KILL",
	                "CAP_NET_BIND_SERVICE"
	            ],
	            "permitted": [
	                "CAP_AUDIT_WRITE",
	                "CAP_KILL",
	                "CAP_NET_BIND_SERVICE"
	            ],
	            "inheritable": [
	                "CAP_AUDIT_WRITE",
	                "CAP_KILL",
	                "CAP_NET_BIND_SERVICE"
	            ],
	            "effective": [
	                "CAP_AUDIT_WRITE",
	                "CAP_KILL"
	            ],
	            "ambient": [
	                "CAP_NET_BIND_SERVICE"
	            ]
	        },
	        "rlimits": [
	            {
	                "type": "RLIMIT_CORE",
	                "hard": 1024,
	                "soft": 1024
	            },
	            {
	                "type": "RLIMIT_NOFILE",
	                "hard": 1024,
	                "soft": 1024
	            }
	        ],
	        "apparmorProfile": "acme_secure_profile",
	        "oomScoreAdj": 100,
	        "selinuxLabel": "system_u:system_r:svirt_lxc_net_t:s0:c124,c675",
	        "noNewPrivileges": true
	    },
	    "root": {
	        "path": "rootfs",
	        "readonly": true
	    },
	    "hostname": "slartibartfast",
	    "mounts": [
	        {
	            "destination": "/proc",
	            "type": "proc",
	            "source": "proc"
	        },
	        {
	            "destination": "/dev",
	            "type": "tmpfs",
	            "source": "tmpfs",
	            "options": [
	                "nosuid",
	                "strictatime",
	                "mode=755",
	                "size=65536k"
	            ]
	        },
	        {
	            "destination": "/dev/pts",
	            "type": "devpts",
	            "source": "devpts",
	            "options": [
	                "nosuid",
	                "noexec",
	                "newinstance",
	                "ptmxmode=0666",
	                "mode=0620",
	                "gid=5"
	            ]
	        },
	        {
	            "destination": "/dev/shm",
	            "type": "tmpfs",
	            "source": "shm",
	            "options": [
	                "nosuid",
	                "noexec",
	                "nodev",
	                "mode=1777",
	                "size=65536k"
	            ]
	        },
	        {
	            "destination": "/dev/mqueue",
	            "type": "mqueue",
	            "source": "mqueue",
	            "options": [
	                "nosuid",
	                "noexec",
	                "nodev"
	            ]
	        },
	        {
	            "destination": "/sys",
	            "type": "sysfs",
	            "source": "sysfs",
	            "options": [
	                "nosuid",
	                "noexec",
	                "nodev"
	            ]
	        },
	        {
	            "destination": "/sys/fs/cgroup",
	            "type": "cgroup",
	            "source": "cgroup",
	            "options": [
	                "nosuid",
	                "noexec",
	                "nodev",
	                "relatime",
	                "ro"
	            ]
	        }
	    ],
	    "hooks": {
	        "prestart": [
	            {
	                "path": "/usr/bin/fix-mounts",
	                "args": [
	                    "fix-mounts",
	                    "arg1",
	                    "arg2"
	                ],
	                "env": [
	                    "key1=value1"
	                ]
	            },
	            {
	                "path": "/usr/bin/setup-network"
	            }
	        ],
	        "poststart": [
	            {
	                "path": "/usr/bin/notify-start",
	                "timeout": 5
	            }
	        ],
	        "poststop": [
	            {
	                "path": "/usr/sbin/cleanup.sh",
	                "args": [
	                    "cleanup.sh",
	                    "-f"
	                ]
	            }
	        ]
	    },
	    "linux": {
	        "devices": [
	            {
	                "path": "/dev/fuse",
	                "type": "c",
	                "major": 10,
	                "minor": 229,
	                "fileMode": 438,
	                "uid": 0,
	                "gid": 0
	            },
	            {
	                "path": "/dev/sda",
	                "type": "b",
	                "major": 8,
	                "minor": 0,
	                "fileMode": 432,
	                "uid": 0,
	                "gid": 0
	            }
	        ],
	        "uidMappings": [
	            {
	                "containerID": 0,
	                "hostID": 1000,
	                "size": 32000
	            }
	        ],
	        "gidMappings": [
	            {
	                "containerID": 0,
	                "hostID": 1000,
	                "size": 32000
	            }
	        ],
	        "sysctl": {
	            "net.ipv4.ip_forward": "1",
	            "net.core.somaxconn": "256"
	        },
	        "cgroupsPath": "/myRuntime/myContainer",
	        "resources": {
	            "network": {
	                "classID": 1048577,
	                "priorities": [
	                    {
	                        "name": "eth0",
	                        "priority": 500
	                    },
	                    {
	                        "name": "eth1",
	                        "priority": 1000
	                    }
	                ]
	            },
	            "pids": {
	                "limit": 32771
	            },
	            "hugepageLimits": [
	                {
	                    "pageSize": "2MB",
	                    "limit": 9223372036854772000
	                },
	                {
	                    "pageSize": "64KB",
	                    "limit": 1000000
	                }
	            ],
	            "memory": {
	                "limit": 536870912,
	                "reservation": 536870912,
	                "swap": 536870912,
	                "kernel": -1,
	                "kernelTCP": -1,
	                "swappiness": 0,
	                "disableOOMKiller": false
	            },
	            "cpu": {
	                "shares": 1024,
	                "quota": 1000000,
	                "period": 500000,
	                "realtimeRuntime": 950000,
	                "realtimePeriod": 1000000,
	                "cpus": "2-3",
	                "mems": "0-7"
	            },
	            "devices": [
	                {
	                    "allow": false,
	                    "access": "rwm"
	                },
	                {
	                    "allow": true,
	                    "type": "c",
	                    "major": 10,
	                    "minor": 229,
	                    "access": "rw"
	                },
	                {
	                    "allow": true,
	                    "type": "b",
	                    "major": 8,
	                    "minor": 0,
	                    "access": "r"
	                }
	            ],
	            "blockIO": {
	                "weight": 10,
	                "leafWeight": 10,
	                "weightDevice": [
	                    {
	                        "major": 8,
	                        "minor": 0,
	                        "weight": 500,
	                        "leafWeight": 300
	                    },
	                    {
	                        "major": 8,
	                        "minor": 16,
	                        "weight": 500
	                    }
	                ],
	                "throttleReadBpsDevice": [
	                    {
	                        "major": 8,
	                        "minor": 0,
	                        "rate": 600
	                    }
	                ],
	                "throttleWriteIOPSDevice": [
	                    {
	                        "major": 8,
	                        "minor": 16,
	                        "rate": 300
	                    }
	                ]
	            }
	        },
	        "rootfsPropagation": "slave",
	        "seccomp": {
	            "defaultAction": "SCMP_ACT_ALLOW",
	            "architectures": [
	                "SCMP_ARCH_X86",
	                "SCMP_ARCH_X32"
	            ],
	            "syscalls": [
	                {
	                    "names": [
	                        "getcwd",
	                        "chmod"
	                    ],
	                    "action": "SCMP_ACT_ERRNO"
	                }
	            ]
	        },
	        "namespaces": [
	            {
	                "type": "pid"
	            },
	            {
	                "type": "network"
	            },
	            {
	                "type": "ipc"
	            },
	            {
	                "type": "uts"
	            },
	            {
	                "type": "mount"
	            },
	            {
	                "type": "user"
	            },
	            {
	                "type": "cgroup"
	            }
	        ],
	        "maskedPaths": [
	            "/proc/kcore",
	            "/proc/latency_stats",
	            "/proc/timer_stats",
	            "/proc/sched_debug"
	        ],
	        "readonlyPaths": [
	            "/proc/asound",
	            "/proc/bus",
	            "/proc/fs",
	            "/proc/irq",
	            "/proc/sys",
	            "/proc/sysrq-trigger"
	        ],
	        "mountLabel": "system_u:object_r:svirt_sandbox_file_t:s0:c715,c811"
	    },
	    "annotations": {
	        "com.example.key1": "value1",
	        "com.example.key2": "value2"
	    }
	}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"tasks.json" 文件是用于配置 Visual Studio Code 中任务的文件。它可以配置多种任务,如编译、运行、测试等。 任务配置由 "version"、"label"、"command"、"args"、"problemMatcher" 等字段组成。 - "version" 字段用于指定 tasks.json 的版本。 - "label" 字段用于指定任务的标签。 - "command" 字段用于指定运行任务的命令。 - "args" 字段用于指定传递给命令的参数。 - "problemMatcher" 字段用于指定在执行任务时用于匹配错误和警告的正则表达式。 可以通过快捷键 ctrl + shift + b 或者在命令面板中选择 "Tasks: Run Task" 来运行配置好的任务。 示例: ``` { "version": "2.0.0", "tasks": [ { "label": "compile", "command": "gcc", "args": [ "-g", "main.c", "-o", "main" ], "problemMatcher": { "owner": "c", "fileLocation": ["relative", "${workspaceFolder}"], "pattern": { "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", "file": 1, "line": 2, "column": 3, "severity": 4, "message": 5 } } } ] } ``` 这个配置文件中有一个 "compile" 的任务,运行 "gcc -g main.c -o main" 命令来编译 main.c 文件并将输出重定向到 main 文件,同时使用正则表达式来匹配编译时的错误和警告信息。可以通过快捷键 ctrl + shift + b 或者在命令面板中选择 "Tasks: Run Task" 来运行这个任务。该任务的标签是 "compile"。可以通过修改 "command"、"args"、"problemMatcher" 等字段来配置不同的任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值