PHP 并发执行命令之multi_cmd

代码功能:

同时执行多条命令,花费时间接近于最长那条命令的时间,而不是每条命令执行的时间和。

 

当 git 遇上 ansible

在配置了ansible的机器上启用了ControlPath配置: (这样效率会高一些)

 

然而,我还想在这个机器上使用ssh协议的git,这样不用每次都输入密码,然而,我不想使用默认的ssh key,于是在 ~/.ssh/config 中添加如下配置:

问题来了,如果没有Host * 的配置,git是好使的,有了Host * 的配置就不好使了,测试发现,是因为git不喜欢ControlPath, 然而,我google了一大圈,找不到unset掉ControlPath的方法,只好采用如下方式:

 

参考:

https://deepzz.com/post/how-to-setup-ssh-config.html

Docker容器中 man 提示 ‘No manual entry for man’

现象:

自从使用了docker容器,在容器中yum安装的软件就怎么着也man不了,man的时候就提示:

通过rpm查看软件包中是否包含man文件,确实包含; 使用rpm -V 也检查不到rpm包损坏; 实际上,man文件是不存在的。

原因:

  1. 我们使用的docker镜像已经被官方精简过了,把所有已安装软件的man页都删除了,这样镜像可以更小
  2. docker镜像中的/etc/yum.conf 也被刻意处理了一下,里面有个tsflags的选项,配置了nodocs,这样的话,新安装的软件也会被自动剔掉man文件(估计rpm知道man文件是被故意删掉的,所以也不报错)

解决办法:

  • /etc/yum.conf 中注释掉:
  • 卸载掉相关软件,重新yum安装

 

注: 上述情况是把docker容器当虚拟机使用的,并不太在乎镜像的大小

 

qemu-kvm 问题

guest内部显示内存充裕:

 

宿主机内存也充裕:

 

guest 对应的qemu-kvm进程在不停地将内存中的数据交换到swap中:

 

还有相同问题的另一个实例:

宿主机有足够的内存,qemu-kvm占用5.3G的swap,只使用566MB的内存,为什么?

guest内部的内存使用情况如下:

 

分析:

我们可能看见guest中看到的已用内存小于kvm进程的rss, 因为kvm进程的内存不仅包含提供给guest使用的内存,也包含自身其他需要的内存。

我们也可能看见guest中看到的已用内存大于kvm进程的rss,因为guest看到的内存未必是真正的内存,很可能早已被宿主机给交换到swap中去了,这就是我们上面看到的情况;guest刚刚起来的时候,并没有直接分配自己可以使用的最大内存,但是,可能某一个时刻一下子占用了90%的内存,当内存下降到10%的时候,80%的内存并没有还给宿主机,而是闲着,但是,宿主机永远不知道这80%的内存是在闲着的,唯一知道的就是好长时间没有访问了,于是,宿主机可能就会将这部分(不活跃的)内存交换到swap中去;等到guest想用内存的时候,其实访问的并不是内存,而是宿主机上的swap; 疑问: 随着guest中这80%的内存的频繁使用,会使得guest的真实内存变多而swap变少吗?应该会的

 

场景1: 大内存的kvm(16GB),里面只有一个使用很少内存(200MB)的小程序,不断地从外部下载文件,写入到磁盘中,结果就是: 下载过的文件都会被尽量缓存到内存中,16GB的内存大部分用于cache了,而且下载过的文件基本不会再被使用,于是,这部分内存就是in-active的了,于是,表现在宿主机上,这部分内存就会被尽力swap到磁盘上,当宿主机的swap被用尽时,其他进程想swap却很为难:

guest:

宿主机上:

宿主机上的kvm进程的RES远大于guest中内存的used,因为宿主机上的swap已用尽,如果添加更多的swap的话,会继续有更多的RES迁移到swap中去。

 

解决办法:

  1. guest本没必要使用16GB内存,给2GB就可以了; (尽管如此,也会有不必要的cache存在)
  2. guest中可以定期地drop cache,避免cache占用太大; 理论上来讲,一旦guest有大量的cache占用了内存,即使drop cache了,宿主机上也不会释放这部分内存(或swap),因为宿主机根本不知道这部分内存是不再使用了的;(当然,可以通过别的方式真正意义上回收这部分内存),如下:

    guest中drop cache后,buff/cache使用1.2G,宿主机上的RES、swap依然保持不变; 其实,不仅drop cache不能影响宿主机分配给guest的内存大小,reboot guest都不会影响宿主机分配给guest的内存大小的,因为reboot guest是热引导,kvm进程还是原来的进程,宿主机也不知道里面发生了重启的动作,所以,分配给kvm进程的资源也不会有变化

 

参考资料:

https://searchservervirtualization.techtarget.com/tip/Memory-swap-strategies-for-KVM

http 之 非常规部分响应

 

当在chrome上测试video标签的流媒体播放mp4时,发现确实不会完全下载完再播放,关键是使用range http头时从来只指定开始位置,不指定结束位置,为什么呢?

chrome video标签加载mp4的大概逻辑是:

  1. 先查看一下资源大小,一般来讲,head方法可以查看资源大小,但是chrome没有使用head方法(怀疑是考虑到很多服务器管理员并不专业,仅仅允许GET、POST方法),而是使用了GET + range ( range: 0- )头的方法; 但是,这样web服务器会比较规矩地返回整个文档内容,并且告知文档的总大小,显然,浏览器并不想要全部的内容(而仅仅想看看资源最后的64KB),怎么办呢?于是,读取到自己想要的信息(http头中包含的资源总大小)就把连接close掉,如此一来,client再收到后续的数据包的时候,就自然会reset了
  2. 知道了资源总大小后,再次发送一个GET请求,这次只请求资源的最后64KB(瞎猜,最后64KB估计是包含一些元信息吧),这次就可以正常结束请求,而不需要使用鲁棒的reset
  3. 后续的按需加载,不过,也并没有使用严格的range来指定想要的大小:

    也是client想读多少就读多少,最后reset掉,或许和mp4格式有关系,毕竟mp4不是流媒体格式,client应该真的不知道要确切读多少才行

 

 

 

 

EMC设备参观

产品: unity500

 

实物拍照:

前面板:

上面是一个扩展柜,下面是一个主机,都是2u的设备

后面板:

从后面来看,扩展柜比主机要短一截

(话说,这布线也够烂的)

其它:

  • unity500就是最多支持500块儿盘,unity400就是最多支持400块儿盘
  • 从前面板可以看到,每个扩展柜(或主机)支持2.5英寸盘25个,(具介绍,如果是3.5英寸盘类型的盘柜的话,可以插15个)
  • unity的web管理界面常用到的功能是池子的创建、lun的创建等;
  • 不满意的地方: 每个磁盘只能属于一个池子

Docker 源码build rpm包

官方文档:

https://github.com/docker/docker-ce-packaging/tree/master/rpm

 

环境搭建:

安装并启动docker就行:

 

命令很简单:

 

打包原理:

从make命令说起,通过docker容器对engine  cli分别进行打包,通过git获取版本号信息,通过docker-ce-packaging/rpm/Dockerfile.x86_64 构建一个基于centos:7 的容器镜像,镜像中安装编译环境(golang),容器挂载外部的一些目录,即,输入来自于外部目录,编译结果输出到外部目录;容器镜像直接启动rpmbuild命令进行构建,构建的详细步骤都在rpm的spec文件中,构建过程中还需要下载有些其他的源码

 

部分细节:

rpmbuild 命令:

 

容器挂载的外部目录:

 

问题记录:

  1. git 版本需要支持 -C 选项
  2. engine 的路径不小心写错了,导致engine的源码文件没有打进去,修改后OK

 

构建优化:

  1. 将github.com 解析到自己的代理服务器,加速下载构建中依赖的代码
  2. 将Dockerfile.x86_64中golang安装包下载地址修改为国内地址,只需将golang.org 修改为golang.google.cn 即可,加速下载golang安装包,当然,更快的办法是改为本地的地址
  3. 更快的办法是,自己build一个自己的环境,用完也不要销毁,每次自己直接执行rpmbuild -ba docker-ce.spec 就行了,不过注意:
    1. 构建过程中需要git clone一些代码,如果目录已经存在,就报错的,所以,可以做一个假的git,使得目录已存在就不再clone,这样还快些

 

owncloud 配置openstack对象存储作为外部存储

本人使用的owncloud版本号: 8.2.8

第一步:

使用admin账号在“管理”部分开启外部存储配置:

第二步:

在任意账号(也可以是管理员账号)配置外部存储:

 

注意:

  • 这里支持的keystone协议版本号只能是v2.0 的,不可配置,所以Identity URI 类似于: http://openstack-controller:5000/v2.0/
  • 其中的swift就是对象存储服务的名字,可以通过openstack endpoint list查到
  • 其中的test(bucket)就是openstack中对象存储部分创建的一个容器的名字,当然,如果没有预先创建的话,会自动创建的,所以,你可以随便写

 

问题:

  • 只要openstack对象存储中的容器被owncloud挂载过,容器根目录就会出现一个名字为 “.” 的文件,该文件在owncloud中看不见的,在openstack-dashboard中可以看见,但是删除总失败,而且,如果不删除该文件的话,容器也是删除不了的; 测试发现,openstack-dashboard中是创建不了一个名字叫做”.” 的目录的,相关issue: https://github.com/owncloud/core/issues/7191
    • 解决办法:
      • 通过openstack命令删除 “.” 文件:
      • end
    • 总结:这里似乎暴露了两个问题:
      • owncloud为什么要创建一个 “.” 文件,真的有必要吗?而且,就算是把 “.” 文件删除掉了,只要owncloud一访问,该文件就又出现了,暂且不太影响,pass
      • openstack-dashboard为什么就删除不了 “.” 文件,应该是个bug吧

 

owncloud + openstack 对象存储的好处:

  • 给owncloud找了一个可靠的存储
  • 给openstack对象存储找了一个比较好的前端
    • 可以通过浏览器直接访问
    • 也可以通过webdav的方式直接mount到各种操作系统和终端(windows、linux、手机端等)
      • linux 上mount,eg:

参考:

ceph 之 choose 和 chooseleaf

语法说明

即: 选择 $n 个不同的bucket, 其中, $n = 0 意味着需要多少个副本就选择多少个bucket, $n = -1 意味着还需要选择多少副本就选择多少副本,返回结果是bucket,如果bucket 是osd自然就是叶子节点

 

即: 选择 $n 个不同的bucket,然后,再从每个bucket中任意选择一个osd,相当于:

 

这种情况下,显然chooseleaf比choose简单许多,表达的意思都是以bucket为故障域,在里面选择$n 个osd, 这也是比较常见的情况

 

情况二:

那么,如果我有多个row,但是期望将3份数据都存放在同一个row下,并且选择3个不同的rack存放呢?表达如下:

等价于:

 

情况三:

假如我有5个row,但是仅仅希望存储的两个副本分别存放在row1和row2(我们知道,每个bucket都是有名字的),而不是随意选择两个,然后以rack为故障域来选择osd,该如何写呢?

这时候,仅仅使用choose和chooseleaf就搞不定了,还记得take语法吧,如下:

 

 

参考: