1 |
# diff <(cd /data1/weedfs/volume4.2; find . -type f -printf "%p %s\n" ) <(cd /mnt/weedfs/volume4.2; find . -type f -printf "%p %s\n" ) |
DevOps
1 |
# diff <(cd /data1/weedfs/volume4.2; find . -type f -printf "%p %s\n" ) <(cd /mnt/weedfs/volume4.2; find . -type f -printf "%p %s\n" ) |
diff 可以比较两个文件,那么能否比较两个字符串呢(主要是懒得创建文件),其实是可以的,如:
不仅仅diff可以这么玩, vimdiff也能这么玩,如:
1 |
#vimdiff <(echo 0) <(echo 1) |
那么,比较的两部分算是什么呢?
其实也是两个文件,如下:
这是两个什么文件呢?其实是两个pipe,如下:
这里vimdiff还为这两个pipe创建了两个交换文件.
知识点:
bash中 “<(list)” 是一种语法结构,叫做Process Substitution :
Process substitution allows a process’s input or output to be referred to using a filename. It takes the form of
1 |
<(list) |
or
1 |
>(list) |
The process list is run asynchronously, and its input or output appears as a filename. This filename is passed as an argument to the current command as the result of the expansion. If the >(list)
form is used, writing to the file will provide input for list. If the <(list)
form is used, the file passed as an argument should be read to obtain the output of list. Note that no space may appear between the <
or >
and the left parenthesis, otherwise the construct would be interpreted as a redirection. Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files.
When available, process substitution is performed simultaneously with parameter and variable expansion, command substitution, and arithmetic expansion.
该语法结构在zsh中记作: =(list)
注意1:
这里产生的文件是管道,是管道,是管道,只能读一次,不能到做普通文件使用,如:
这里cat了两次,只输出一次hello
为什么写个简单的测试还要放在function里面?拿出来不好使
脚本:
1 2 3 4 5 6 7 |
#!/bin/bash function hello() { f=<(echo hello) cat $f cat $f } hello |
注意2:
进程替换只对于bash生效,对于sh不生效; sh 不理解进程替换,至少对于4.2.46版本的bash来讲,如果把bash mv成为 sh,就不再理解进程替换了; 更有甚者,如果 sh 软连接到bash,然后使用sh执行上面脚本就得出现错误
参考:
https://unix.stackexchange.com/questions/62140/filesize-difference-of-same-name-folders
http://tiswww.case.edu/php/chet/bash/bashref.html#Process-Substitution
ceph osd down $id: 将osd $id 标记为down(mark down),达到不再访问的效果,并不真正停止进程,(仍然参与hash?),ceph osd tree 查看的时候,依然可能是up的状态
ceph osd out $id: 将weight 设置为0(零), 达到不再访问的效果,(不参与hash?)
ceph osd lost $id: 删除该osd上的所有数据,该操作比较危险,需要明确指定 –yes-i-really-mean-it, 如:
ceph osd rm $id: 从集群中彻底删除该osd;如果要删除某osd,必须先停止进程,仅仅标记为down(ceph osd down $id) 是不够的,如:
1 2 |
# /bin/ceph osd rm 3 Error EBUSY: osd.3 is still up; must be down before removal. |
停止指定osd进程:
仅仅rm掉osd还是可以在ceph osd tree中看到,如下:
需要从crush中移除:
然而,依然删除的不够干净,如 auth中还有相关信息:
删除:
查看所有osd:
关于cgroupdriver:
docker 默认的cgroupdriver为cgroupfs,也可以手动指定(通过环境变量、命令行参数、daemon.json)systemd,有些docker的rpm包会在 /usr/lib/systemd/system/docker.service 中通过命令行的方式指定cgroupdriver为systemd, 当前支持的cgroupdriver有: cgroupfs、systemd; 命令行设置方式:
1 |
--exec-opt native.cgroupdriver=systemd |
虽然创建容器时没有指定cgroupdriver的选项,但是通过修改cgroupdriver重启daemon,可以使得同一个daemon下的容器使用不同的cgroupdriver的(仅仅是出于理解技术实现的思考,实践中似乎没有任何必要)
至于容器使用的native.cgroupdrive 是cgroupfs 还是 systemd 不是配置在容器上的,而是取决于dockerd启动时的配置,如果dockerd配置的是cgroupfs,则容器启动的时候就是使用的cgroupfs,如果dockerd在配置为cgroupfs时已经启动了几个容器,然后修改配置为systemd,则现在启动的容器就是systemd的了,这时候,两种类型的cgroupdriver的容器是并存的,切换cgroupdriver只需要修改dockerd配置后重启容器即可
曾经有文章中疑惑,有的docker容器的cgroup都是在相同的docker目录下的,有的却是docker-xxxx.scope; 原因就在于前者是通过cgroupfs来实现的,后者是通过systemd来实现的; 另外 docker daemon也可以通过选项–cgroup-parent 来指定一个父cgroup(cgroup是有层级结构的),默认为docker,根据cgroupdriver的不同,该cgroup-parent的表现形式也不同,cgroupfs中表现为父目录,systemd中表现为前缀(参考: https://docs.docker.com/engine/reference/commandline/dockerd/#default-cgroup-parent );每个容器都可以有自己的–cgroup-parent,这个对于不同容器进行分组时似乎是不错的。
关于runc:
默认runc为 docker-runc,其实runc表现为一个可执行的二进制文件,docker info中显示的只是一个配置时指定的名字,至于该名字对应哪个二进制文件,是在配置的时候指定的,也就是说,你可以在不修改配置的情况下,直接修改对应的二进制文件来修改runc,重启容器就会生效; 另外,创建容器的时候,可以指定runc,指定的是配置daemon时使用的名字,每个容器可以有不同的runc
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 46 47 48 49 50 51 52 |
# docker info Containers: 162 Running: 56 Paused: 0 Stopped: 106 Images: 161 Server Version: 1.12.5 Storage Driver: devicemapper Pool Name: data-docker_thinpool Pool Blocksize: 524.3 kB Base Device Size: 32.21 GB Backing Filesystem: xfs Data file: Metadata file: Data Space Used: 469.4 GB Data Space Total: 644.2 GB Data Space Available: 174.9 GB Metadata Space Used: 73.79 MB Metadata Space Total: 16.98 GB Metadata Space Available: 16.9 GB Thin Pool Minimum Free Space: 64.42 GB Udev Sync Supported: true Deferred Removal Enabled: true Deferred Deletion Enabled: false Deferred Deleted Device Count: 0 Library Version: 1.02.135-RHEL7 (2016-11-16) Logging Driver: journald Cgroup Driver: systemd Plugins: Volume: local Network: null overlay host bridge Swarm: inactive Runtimes: runc docker-runc Default Runtime: docker-runc Security Options: seccomp Kernel Version: 3.10.0-514.6.1.el7.x86_64 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 Number of Docker Hooks: 2 CPUs: 40 Total Memory: 94.14 GiB Name: VM-2-10-12 ID: NYBE:NZML:4KQQ:PF2J:RXCB:IPPI:Y3BI:CY7E:RVAC:WVWV:VDM2:3EEK Docker Root Dir: /data1/docker Debug Mode (client): false Debug Mode (server): false Registry: https://index.docker.io/v1/ Insecure Registries: docker-registry.i.bbtfax.com:5000 127.0.0.0/8 Registries: docker.io (secure) |
参考: http://blog.csdn.net/theorytree/article/details/6259104
说明: 显示所有支持的调度策略, 方框内的是当前启用的调度策略
查看当前系统支持的调度算法:
1 2 3 4 |
# dmesg | grep -i scheduler [ 0.605910] io scheduler noop registered [ 0.605916] io scheduler deadline registered (default) [ 0.605974] io scheduler cfq registered |
难道调度算法和设备本身也有关系?从下面来看,阿里云的云盘不支持任何调度策略:
1 2 |
# cat /sys/block/xvda/queue/scheduler none |
但是:
值得一提的是,Anticipatory算法从Linux 2.6.33版本后,就被移除了,因为CFQ通过配置也能达到Anticipatory算法的效果。
查资料发现, 调度策略为 ‘none’ 的现象和阿里云虚拟机没关系,和阿里云云盘没关系,和操作系统版本也没有(直接)关系,仅仅和内核版本有关系, linux内核从3.13开始引入 blk-mq 队列机制,并在3.16得以全部实现,上面看到的非‘none’的情况,内核版本都在3.10之前,为‘none’的情况是被我手动升级内核到4.4.61 的
如何验证是否启用了blk-mq机制?可以通过查看是否存在mq目录,如下:
目录不存在,说明没有启用该机制
存在mq目录,说明使用的是blk-mq机制
参考: https://www.thomas-krenn.com/en/wiki/Linux_Multi-Queue_Block_IO_Queueing_Mechanism_(blk-mq)
centos中有rpm包util-linux,包含 blockdev命令(其实很多常用的命令都在这里),常见功能如下:
查看预读大小:(单位为扇区)
1 2 |
# blockdev --getra /dev/xvda 256 |
设置预读大小:
1 |
# blockdev --setra 2048 /dev/xvda |
查询是否为只读:( 1 为只读 )
1 2 |
# blockdev --getro /dev/xvda 0 |
设置设备为只读:
1 |
# blockdev --setro /dev/xvda |
设置设备为读写:
1 |
# blockdev --setrw /dev/xvda |
查看扇区大小: (一般都是512)
1 2 |
# blockdev --getss /dev/xvda 512 |
查看设备容量: (单位为 扇区 )
1 2 |
# blockdev --getsz /dev/xvda 83886080 |
查看块儿大小: (单位为字节)
1 2 |
# blockdev --getbsz /dev/xvda 4096 |
查看块儿设备综合信息:
1 2 3 |
# blockdev --report /dev/xvda RO RA SSZ BSZ StartSec Size Device rw 256 512 4096 0 42949672960 /dev/xvda |
其中:
RO: 是否只读
RA(read ahead):预读扇区数
SSZ(sector size): 扇区大小
BSZ(block size): 块儿大小
注意: 这里关于设备的设置在设备重新挂载后会失效,需要重新设置
根据java core文件打印java堆栈信息:
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 |
# jstack /usr/bin/java ../core.java Attaching to core ../core.java from executable /usr/bin/java, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.45-b02 Deadlock Detection: No deadlocks found. Thread 21928: (state = BLOCKED) Thread 21927: (state = BLOCKED) - java.lang.Object.wait(long) @bci=0 (Interpreted frame) - java.lang.ref.ReferenceQueue.remove(long) @bci=59, line=143 (Interpreted frame) - java.lang.ref.ReferenceQueue.remove() @bci=2, line=164 (Interpreted frame) - java.lang.ref.Finalizer$FinalizerThread.run() @bci=36, line=209 (Interpreted frame) Thread 21926: (state = BLOCKED) - java.lang.Object.wait(long) @bci=0 (Interpreted frame) - java.lang.Object.wait() @bci=2, line=502 (Interpreted frame) - java.lang.ref.Reference$ReferenceHandler.run() @bci=36, line=157 (Interpreted frame) Thread 21896: (state = BLOCKED) - java.lang.Thread.sleep(long) @bci=0 (Interpreted frame) - Hello.main(java.lang.String[]) @bci=11, line=4 (Interpreted frame) |
java 都用了N长时间了,突然,意外地发现有一个依赖的so文件从来没找见过
1 2 3 4 5 6 7 |
# ldd /usr/bin/java linux-vdso.so.1 => (0x00007fffba769000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00000038c4000000) libjli.so => not found libdl.so.2 => /lib64/libdl.so.2 (0x0000003da7c00000) libc.so.6 => /lib64/libc.so.6 (0x0000003da7400000) /lib64/ld-linux-x86-64.so.2 (0x0000003da6c00000) |
其实这个so文件在java的安装包中是有的,只是没有添加了ld_path 里面,解决办法:
1 2 3 |
# rpm -ql jdk1.8.0_45|grep libjli /usr/java/jdk1.8.0_45/jre/lib/amd64/jli/libjli.so /usr/java/jdk1.8.0_45/lib/amd64/jli/libjli.so |
然后,将/usr/java/jdk1.8.0_45/jre/lib/amd64/jli/ 或 /usr/java/jdk1.8.0_45/lib/amd64/jli/ 添加到文件: /etc/ld.so.conf 中,然后执行ldconfig 即可
最后,libjli.so 是个啥玩意儿,为啥从来没找见过,却也从来没报错过?