https://google.github.io/styleguide/shell.xml
建议的bash风格,不可不学
DevOps
https://google.github.io/styleguide/shell.xml
建议的bash风格,不可不学
1 2 3 4 5 6 7 8 |
function Usage() { cat <<eof Usage: --help: show this help eof } |
注意,这个脚本里面的cat,这里很容易写作echo的,因为php中就是用的echo; 我们很容易将这种语法视为写复杂字符串的一种方法,而在shell中,这不是一个复杂的字符串,而是把这些内容作为命令的标准输入提供给命令的,而不是命令的参数:
1 2 3 4 5 6 7 8 9 10 |
# strace -e read,write cat <<eof aaa eof read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@\34\2\0\0\0\0\0"..., 832) = 832 read(0, "aaa\n", 65536) = 4 write(1, "aaa\n", 4aaa ) = 4 read(0, "", 65536) = 0 +++ exited with 0 +++ |
知道了原理之后,就再也不用担心写错了
上胡不法先王之法,非不贤也,为其不可得而法。先王之法,经乎上世而来者也,人或益之,人或损之,胡可得而法?虽人弗损益,犹若不可得而法。
凡先王之法,有要於时也,时不与法俱至。法虽今而至,犹若不可法。故释先王之成法,而法其所以为法。先王之所以为法者何也?先王之所以为法者人也。而己亦人也,故察己则可以知人,察今则可以知古,古今一也,人与我同耳。有道之士,贵以近知远,以今知古,以益所见,知所不见。故审堂下之阴,而知日月之行、阴阳之变;见瓶水之冰,而知天下之寒、鱼鳖之藏也;尝一脟肉,而知一镬之味、一鼎之调。
列出所有安全组:
1 |
openstack security group list |
列出所有名叫default的安全组的ID:
1 |
openstack security group list -fjson|jq -r '.[]|select(.Name == "default")|.ID' |
列出指定安全组下的所有规则: (–long 显示每条规则的方向,默认不显示方向)
1 |
openstack security group rule list --long bc462cd9-1957-4a33-ac22-d3941e5113b5 |
可以通过–ingress –egress 只显示指定方向上的规则; 通过 –protocol 显示指定协议相关的规则
实际应用:
检查是否所有的“default” 安全组都设置了允许所有tcp、udp都可以主动外出的规则:
1 2 3 4 5 |
openstack security group list -fjson|jq -r '.[]|select(.Name == "default")|.ID'| while read id; do echo $id; openstack security group rule list --long $id -f json |jq -r '.[]|select((.["IP Protocol"] == "tcp" or .["IP Protocol"] == "udp") and .["IP Range"] == "0.0.0.0/0" and .["Direction"] == "egress" and .["Port Range"] == "1:65535" and .["Ethertype"] == "IPv4") |.["IP Protocol"]' echo done |
结果输出:
1 2 3 |
1bfd33d7-6278-4718-9680-fd6f3328561d tcp udp |
如果输出了tcp和udp就意味着是正确的
添加安全组规则:
允许所有tcp主动外出访问:
1 |
openstack security group rule create --protocol tcp --remote-ip 0.0.0.0/0 --dst-port "1:65535" --egress --ethertype IPv4 --description "allow all tcp active request" eb9dd2e8-129d-4135-bee8-f92744f5fbdd |
问题: 如题。
现场情况:
问题原因:
如下图: 虚拟机管理器和计算主机中显示的主机的名字不同,为什么呢?
说明:
虚拟机管理器说的是hypervisor,具体来讲就是libvirtd
主机说的是虚拟机管理器所在的宿主机,就是我们所谓的计算节点
二者的信息都是记录在nova.compute_nodes 表中的,二者都没有唯一约束;
当然,host是不会重复的;特殊情况下hypervisor_hostname 重复是有可能的; 从dashboard来看,节点资源是hypervisor的,而不是host的。
而且也可以存在一个host上有多个虚拟机管理器的情况,一个nova-compute接到任务后,可以通过不同的虚拟机管理器来创建虚拟机
分析:
不同计算节点上使用相同hypervisor_hostname时,hypervisor将拥有了多个机器的资源,那么虚拟机调度时参考hypervisor_hostname的资源的话,虚拟机分配的任务最终会被分配到哪个host上呢?毕竟不同host上都有nova-compute进程的; 另,上报资源时使用的是node的uuid还是host还是hypervisor_hostname?
node的uuid又是如何生成的呢?
hypervisor_hostname 是如何获取到的呢?hypervisor_hostname是不是第一次注册的时候写入后来就不再修改了呢?
主机资源是记录在 nova_api.resource_providers 表中的:
当然,只有nova.compute_nodes 表中记录的uuid才是有效的resource_providers,才会被dashboard显示
为什么node节点的hostname已经修改了,虚拟机管理器中显示的还是以前的名字?
nova-compute.log 中会有错误信息:
1 |
2018-05-07 14:53:44.561 3257 ERROR nova.virt.libvirt.host [req-4cf04c1b-8b6f-4ce9-8832-185720825fbc - - - - -] Hostname has changed from compute-5.i.beebank.com to compute-5. A restart is required to take effect. |
问题: 谁和谁不一致?重启谁?
解决办法:
比较: hostname 和virsh hostname的结果:
二者是不同的,前者的信息是从libvirtd中获取到的,也就是说,libvirtd中显示的主机名和当前的主机名不一致,需要重启libvirtd, 相关逻辑:
问题:
总结:
注意:
代码功能:
同时执行多条命令,花费时间接近于最长那条命令的时间,而不是每条命令执行的时间和。
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 34 35 36 37 38 39 40 41 42 43 44 45 |
<?php function multi_cmd($arr) { $arrResult = array(); $arrFp = array(); foreach($arr as $k => $cmd) { $arrFp[$k] = popen($cmd, "r"); if(!$arrFp[$k]) { $arrResult[$k] = array("stdout" => null, "meta"=>array("elapse"=>0)); unset($arrFp[$k]); continue; } stream_set_blocking($arrFp[$k], false); } $start = microtime(1); $write = null; $expect = null; while(count($arrFp) > 0) { $arrRead = array_values($arrFp); $ret = stream_select($arrRead, $write, $expect, 0, 200000); if($ret === false) break; if($ret === 0) continue; foreach($arrFp as $k=>$fp) { if (!in_array($fp, $arrRead)) continue; while(!feof($fp)) { $r = fread($fp, 1024); if ($r !== "" && $r !== false) $arrResult[$k]["stdout"] .= $r; if (feof($fp) || $r === false) { unset($arrFp[$k]); $arrResult[$k]["meta"]["elapse"] = microtime(1) - $start; break; } if ($r === "") break; } } } return $arrResult; } $arr = array( "cmd1" => "sleep 1; eacho 1", "cmd2" => "sleep 2; echo 2", "cmd3" => "sleep 3; echo 3", ); $arrResult = multi_cmd($arr); print_r($arrResult); |
在配置了ansible的机器上启用了ControlPath配置: (这样效率会高一些)
1 2 3 4 5 6 7 8 |
# cat ~/.ssh/config Host * Compression yes ServerAliveInterval 60 ServerAliveCountMax 5 ControlMaster auto ControlPath ~/.ansible/cp/ansible-ssh-%h-%p-%r ControlPersist 8h |
然而,我还想在这个机器上使用ssh协议的git,这样不用每次都输入密码,然而,我不想使用默认的ssh key,于是在 ~/.ssh/config 中添加如下配置:
1 2 3 |
Host gitlab IdentityFile ~/.ssh/id_rsa.gitlab User git |
问题来了,如果没有Host * 的配置,git是好使的,有了Host * 的配置就不好使了,测试发现,是因为git不喜欢ControlPath, 然而,我google了一大圈,找不到unset掉ControlPath的方法,只好采用如下方式:
1 2 3 4 5 6 7 |
Host *,!gitlab Compression yes ServerAliveInterval 60 ServerAliveCountMax 5 ControlMaster auto ControlPath ~/.ansible/cp/ansible-ssh-%h-%p-%r ControlPersist 8h |
参考:
自从使用了docker容器,在容器中yum安装的软件就怎么着也man不了,man的时候就提示:
1 |
No manual entry for man |
通过rpm查看软件包中是否包含man文件,确实包含; 使用rpm -V 也检查不到rpm包损坏; 实际上,man文件是不存在的。
1 |
tsflags=nodocs |
注: 上述情况是把docker容器当虚拟机使用的,并不太在乎镜像的大小
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中去。
解决办法:
参考资料:
https://searchservervirtualization.techtarget.com/tip/Memory-swap-strategies-for-KVM