问题描述:

一个人要穿越沙漠,路程需要20天才能走完,但他只能携带2天的补给,可以把补给放在途中的任意地方作为补给点,可以返回出发点免费得到补给。问他最少需要多少天才能走出沙漠

解答思路:

要走完全程,必须在路途的中间不断来回设立补给站。这样思考比较有难度。我把它等效转换成另一个问题:

这个人可以携带多个助手,同样可以携带2天的补给,并且要确保助手能安全地返回。

可以把这个助手想象成分身。只要把每一个助手的工作都交给这个人,就回到原来的问题了。
现在我们规定每一个人都有2天的水去完成任务,在路上用别人的水。

对于主角而言,他需要在前18天喝别人的水,最后2天用自留水。
如果这个主角带一个小弟,那么他要把2天的水给主角和自己喝,自己还要回到原来的地方。
需要到达终点的主角
那么这个小弟的移动距离为: 2/3天
更一般地如果上面有n个人要养,有t个送水的。那么这批人只能移动
$$ \frac{2 t}{n+2 t} $$
然而t的取值似乎是个难题,那就设ti吧。那么总的移动距离为
$$ S=\sum_{i=1}^x \frac{2 t_i}{\sum_{j=1}^i t_j+2 t_i} $$
既要 S>18 ,同时要
$$ \sum_{j=1}^i $$ 最小

发布程序

1.创建节点

erlang总是以节点为单位组织的。
使用rebar create-node nodeid=xxx可以生成files,reltool.config。里面包含了各种节点信息。

  • reltool.config
    下面列举几个比较常用的参数:
    mod_cond:

    1. all: 将会包含所有引用的模块。即在搜索路径下存在ebin的模块都会被包含。
    2. ebin: 只包含本模块。
    3. app: 包含本模块和相关模块。
    4. derived : 包含相关模块。

    lib_dir: 模块搜索目录。
    excl_sys_filters:将包含在系统目录下匹配的文件。
    profile: 影响ncl_sys_filters, excl_sys_filters, incl_app_filters and excl_app_filters.的作用

    1. development
    2. embedded
    3. standalone

    excl_lib:实验中,勿使用

    • otp_root :不包含erlang运行环境ert

    app_file: 拷贝app file的程度

    1. keep
    2. strip
    3. all

2.升级

Application.appup 文件描述了如何热升级代码
使用如下语法:

1
2
3
{Vsn,
[{UpFromVsn, Instructions}, ...],
[{DownToVsn, Instructions}, ...]}.

Instructions 由以下内容构成:

{update, Mod}
{update, Mod, supervisor}
{update, Mod, Change}
{update, Mod, DepMods}
{update, Mod, Change, DepMods}
{update, Mod, Change, PrePurge, PostPurge, DepMods}
{update, Mod, Timeout, Change, PrePurge, PostPurge, DepMods}
{update, Mod, ModType, Timeout, Change, PrePurge, PostPurge, DepMods}
  Mod = atom()
  ModType = static | dynamic
  Timeout = int()>0 | default | infinity
  Change = soft | {advanced,Extra}
    Extra = term()
  PrePurge = PostPurge = soft_purge | brutal_purge
  DepMods = [Mod]

升级过程可以参见:Release Handling

  1. 按照Release中所述的方法创建版本。

  2. 将释放转移到目标环境并安装在目标环境中。有关如何安装第一个目标系统的信息,请参阅系统原理。

  3. 对开发环境中的代码进行修改,例如错误更正。

  4. 在某些时候,需要制作新版本。相关的.app文件被更新,并写入一个新的.rel文件。

  5. 对于每个修改的应用程序,创建应用程序升级文件.appup。在此文件中,描述了如何在旧版本和新版本的应用程序之间进行升级和/或降级。

  6. 基于.appup文件,创建一个名为relup的版本升级文件。该文件描述如何在整个版本的旧版本和新版本之间升级和/或降级。

  7. 创建新的发行包并将其传输到目标系统。

  8. 使用发布处理程序解压缩新的发行包。

  9. 安装新版本,也使用发布处理程序。这是通过评估relup中的指令来完成的。可以添加,删除或重新加载模块,应用程序可以启动,停止或重新启动,等等。在某些情况下,甚至需要重启整个仿真器。

不同功能的模块的升级办法

基本概念

  1. 镜像 :是一个只读的模板,包含了系统 运行程序,相当于一份虚拟机的磁盘文件。

  2. 容器 :当镜像启动后就转化为容器,即运行状态。在容器内的修改不会影响镜像,程序的写入操作都保存在容器中。

  3. 仓库 : 集中存放镜像文件的场所 。

镜像的基本操作

  1. ##本地镜像
    保存:docker save -o file image ,载入:docker load file

    从容器里获得镜像:docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

  2. ##网络镜像
    类似于git使用docker pull [OPTIONS] NAME[:TAG|@DIGEST]docker push [OPTIONS] NAME[:TAG]

  3. Dockerfile :自动构建镜像

    用法:docker build

    Dockerfile 的写法

    1. 使用#来注释
    2. FROM :指令告诉 Docker 使用哪个镜像(下载镜像)
    3. RUN :下载镜像后执行的命令结果会写入到镜像 中,比如安装一个软件包。
    4. ADD :src destination,将本地文件写入镜像。
    5. CMD : command param1 param2 , 提供了容器默认的执行命令。 Dockerfile 只允许使用一次 CMD 指令
    6. EXPOSE : port, 指定容器在运行时监听的端口。
    7. ENTRYPOINT:配置给容器一个可执行的命令,这意味着在每次使用镜像创建容器时一个特定的应用程序可以被设置为默认程序
    8. WORKDIR :path, 指定RUN、CMD与ENTRYPOINT命令的工作目录。
    9. VOLUME :[path], 授权访问从容器内到主机上的目录
      10 . ENV ; USER

容器的基本操作

  1. ##run:docker run [OPTIONS] IMAGE [COMMAND] [ARG...] 从镜像中创建容器
    • -d :后台运行
    • -i :保持容器活动
    • -t :进行交互
    • -p [主机:port:port]:端口映射
    • -P :随机端口映射
    • -v:绑定外部存储空间
    • 其他重要的:–name:容器命名,–link,–ip, –rm
  2. ##start,stop :docker start [OPTIONS] CONTAINER [CONTAINER...]

    当使用run创建出新的容器后,使用这2个命令来控制容器的运行状态。

  3. ##查看容器:docker ps -a

    不带参数则为当前运行状态的容器

  4. ##进入容器

    1. docker attach [OPTIONS] CONTAINER :把后台容器调到前端。

    2. docker exec [OPTIONS] CONTAINER COMMAND [ARG...]:在容器内新建一个命令。

      docker exec -it CONTAINER bash

    3. 使用 nsenter 等软件。

  5. ##连接容器

    docker run --link name:alias CONTAINER:将新建主机和被连接的主机组成一个局域网。

    name 是指被连接的容器,alias是在这个互联网络内name的主机名称。在新建的容器内使用alias进行访问(ping alias)