时隔多年,趁着这次折腾 Golang 开发环境的机会,把 N 多年没有更新的 vim 配置文件重新改了一版。好久没使用,发现很多东西都记不清楚了,再加上这几年 vim 的插件管理也变化挺大,花了点时间学习,不过总是越来越方便了。
下面是我的 vim 配置文件(Github 地址),主要针对 go 语言的开发环境。
合格的运维工程师必须是一名出色的系统管理员,工欲善其事,必先利其器,本博客会介绍一些系统管理相关的技巧。
有时候删除文件里的重复行是一个很常见的需求,这个用 shell 命令有很多处理方法。
第一种方案是用 sort 命令的 -u 参数:
$ sort -u input.txt > output.txt
第二种方案是用 awk 命令,它的关键在于用一个字典来保存记录:
$ awk '!seen[$0]++' input.txt > output.txt
这和第一种方案的区别在于,即使文件中重复行不连续,依然可以删除。
第三种方案是用 sed 命令,但是其实不大推荐,它相比第一种方案复杂多,而且很容易写错:
$ sort -n input.txt | sed '$!N;/^\(.*\)\n\1$/!P;D' > output.txt
某次项目发布过程中,当我们把 rpm 包下发到每台 nc 之后,发现过了一会儿文件就被删除了,当时百思不得其解,第二天亲自试了下,果然能够稳定复现。
试了几次发现,放在 /tmp 目录下的文件,只要文件权限是当前的帐号(假设 abc),并且最近修改时间比较久(大概是分钟级别),就会被自动清理。所以第一个线索:自动清理的脚本应该是 abc 权限运行的,而且根据修改时间去删除文件。
当时第一反应是 tmpwatch 搞得鬼,但是 tmpwatch 印象中是按天执行的,而且是删除 10 天内未修改的文件(ctime/mtime/atime),所以应该可以排除。当然不排除有人擅自修改了配置文件,看了下确实不是:
flags=-umc /usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \ -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix \ -X '/tmp/hsperfdata_*' 240 /tmp /usr/sbin/tmpwatch "$flags" 720 /var/tmp for d in /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?}; do if [ -d "$d" ]; then /usr/sbin/tmpwatch "$flags" -f 720 "$d" fi done
当确认不是 tmpwatch 的问题之后,我就想找个工具去监控“删除”这个行为,google 找到 inotify-tools 工具,尝试运行采集了一把:
$inotifywatch -v -t 60 -r /tmp/b.rpm.bak Establishing watches... Setting up watch(es) on /tmp/b.rpm.bak OK, /tmp/b.rpm.bak is now being watched. Total of 1 watches. Finished establishing watches, now collecting statistics. Will listen for events for 60 seconds. total attrib delete_self filename 3 1 1 /tmp/b.rpm.bak
但是很遗憾,这个工具无法知道是哪个进程操作的,只能确定确实发生了“删除”的行为。
前段时间发现某些机器磁盘空间报警,使用 du 命令(慎重使用)查询后发现部分日志文件非常大,例如 secure 日志,差不多有 10G 左右。
$ ls -lh /var/log/secure -rw-r----- 1 root adm 9.7G Mar 24 20:44 /var/log/secure
我们发现 secure 日志已经超过一周没有滚动了,按照 logrotate 的配置,secure 日志应该按周滚动一次,最多滚动 4 次:
$cat /etc/logrotate.d/syslog-ng /var/log/messages /var/log/secure /var/log/maillog /var/log/spooler /var/log/boot.log /var/log/cron { sharedscripts postrotate /etc/rc.d/init.d/syslog-ng reload 2>/dev/null || true endscript } $cat /etc/logrotate.conf # see "man logrotate" for details # rotate log files weekly weekly # keep 4 weeks worth of backlogs rotate 4 # create new (empty) log files after rotating old ones create # uncomment this if you want your log files compressed compress # RPM packages drop log rotation information into this directory include /etc/logrotate.d # system-specific logs may be also be configured here.
看起来应该是日志滚动过程出现了问题,然后通过 logroate debug 了一把,发现中间出错:
$ logrotate -dv /etc/logrotate.conf reading config file /etc/logrotate.conf including /etc/logrotate.d reading config file acpid reading config info for /var/log/acpid reading config file balloond reading config info for /var/log/xen/balloond.log reading config file conman error: error accessing /var/log/conman: No such file or directory error: conman:5 glob failed for /var/log/conman/*
看最后两行 error,因为 /var/log/conman
目录找不到,导致滚动过程出错,所以就没有触发 secure 日志滚动处理。
那么最直接的解决方法是,手工创建 /var/log/conman
目录,这个问题就可以跳过了。但是,这种方法毕竟不完美,如果哪天另外一个目录不存在,仍然会出现这个问题。而且,logrotate 对这种场景的处理本来就不合理,然后去翻了下它的 changelog,发现这个 bug 已经在 3.7.4-12 以后的版本中 fixed:
* Thu Mar 31 2011 Jan Kaluza <jkaluza@redhat.com> - 3.7.4-12 - fix #540119 - fixed missingok problem with globs
所以,根本的解决方法是更新 logrotate 包。
ZooKeeper 运维相关资料汇总,如有帮助,转给有需要的同学。
ZooKeeper 机器数量要求是 2xF+1 台,其中 F 表示可以容忍的机器故障台数,比如 3 台机器可以容忍 1 个 Failure,5 台机器容忍 2 个 Failure,… 一般最少选择 3 台机器(开发测试环境除外)。
确定好数量之后,要合理的部署 ZooKeeper 机器,理论上有条件的话,应该将 ZooKeeper 机器部署到不同的机房,做到跨机房容灾。例如,3 台 ZooKeeper 机器放到 3 个机房,这样可以最大程度降低故障概率。如果条件不允许,请把 Zookeeper 部署在不同的交换机下,或者至少不同的机柜下。
ZooKeeper 会把每个事务都写到磁盘文件中,然后定期汇总一份快照文件。为了最大限度的提高性能,建议把 transaction log 写到独立的磁盘中,避免受到其他应用程序的干扰(有没有试过写到 /dev/shm 内存?),而且 dataDir 和 dataLogDir 不要配置到同一快磁盘。
默认情况下,ZooKeeper 不会对历史的日志文件进行清理,这一点需要自己去做。从 3.4.0+ 版本开始,ZooKeeper 有提供内置的解决方案,通过参数可以配置清理策略。对于 3.3.x 版本,还是只能通过定时任务的方式清理。
ZooKeeper 写的 transaction log 和 snapshot log 文件不是直接给人看的,如果你想查看日志的内容,可以通过一些工具来实现。比如,使用 LogFormatter 查看 transaction log 文件,SnapshotFormatter 看 snapshot log 文件。
3.3.5 版本下,LogFomatter 看到的信息有限,SnapshotFormatter 不存在,应该是 3.4.0+ 版本才支持,下面是一个例子:
# /opt/taobao/java/bin/java -cp /opt/taobao/zookeeper/zookeeper-3.3.5.jar:/opt/taobao/zookeeper/lib/log4j-1.2.15.jar org.apache.zookeeper.server.LogFormatter /disk2/zkDataLog/version-2/log.900000001
ZooKeeper 有提供一些四个字母的命令,具体看前面提到的管理指南,使用这些命令可以很好的观察系统的运行状况。
现在是懒人的天下,为了迎合用户的需求,很多开源软件或者包提供的安装步骤都非常简单,大家应该看到不少类似一键安装的命令。下面是几个典型的例子:
# homebrew 安装 $ ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)" # nvm 安装, 两种方法 $ curl https://raw.githubusercontent.com/creationix/nvm/v0.8.0/install.sh | sh $ wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.8.0/install.sh | sh # rvm 安装 $ \curl -sSL https://get.rvm.io | bash -s stable
简单粗暴,CMD + C
再加 CMD + V
,随手一个 Enter
,就搞定了。
那么这上面的原理是什么样子的呢?其实很简单。
首先通过 curl 或者 wget 将安装脚本下载下来,将内容输出到标准输出。这一步对应上面的 curl -ssL
或者 wget -qO-
,一定要注意将错误或者异常输出过滤掉,保证标准输出的内容就是脚本的内容。
然后通过管道传递给 shell,shell 在没有指定脚本文件的时候,支持从标准输入读取脚本内容并解释执行。这样将"下载 - 保存 - 安装"这几步操作合到一个命令中完成。
对于 rvm 的安装又有点特殊,安装脚本需要指定执行参数,bash -s stable
中 -s
之后的部分就是透传给安装脚本的参数,翻译下可以理解的形式是:
$ \curl -sSL https://get.rvm.io > /tmp/rvm_install.sh $ bash /tmp/rvm_install.sh stable $ rm -f /tmp/rvm_install.sh
PS: \curl
的用法,我在 终端下肉眼看不见的东西 曾经提到过。
不过,建议执行类似一键安装的命令之前,一定要先大致看下安装脚本,避免里面有不安全的代码。
iftop 是 Linux 下的流量监控工具,可以用来观察实时的网络连接和网络流量情况。网上有很多介绍使用的相关文章,但是我发现很难找到原文,有些文章对它的使用的解释很生硬。所以,我今天将自己理解的用法整理出来,分享给需要的同学。如有不对之处,还请各位不吝指出。
在命令行中执行之后,会显示抓取的网络连接列表,以及对应的网络流量统计。每个连接显示结果类似:
foo.example.com => bar.example.com 1Kb 500b 100b <= 2Mb 2Mb 2Mb
两行分别表示不同的数据传输方向,对于第一行而言,第一列是源地址,第二列是目的地址,最后三列分别是最近 2 秒、10 秒、40 秒发送的平均网络流量。默认情况下,是按十秒内的平均网络流量排序的。
底部会显示一些全局的统计数据,peek 是指峰值情况,cumm 是从运行至今的累计情况,而 rates 表示最近 2 秒、10 秒、40 秒内总共接收或者发送的平均网络流量。
TX: cumm: 143MB peak: 10.5Mb rates: 1.03Mb 1.54Mb 2.10Mb RX: 12.7GB 228Mb 189Mb 191Mb 183Mb TOTAL: 12.9GB 229Mb 190Mb 193Mb 185MbW
这是 Bash One-Liners Explained 系列的第五篇文章。在这一部分,我会教你如何快速在 Bash 命令行中使用 Emacs 风格的键盘导航快捷键。
Bash 使用 GNU readline 库来提供行编辑特性。readline 库同时支持 Emacs 风格和 Vi 风格的快捷键绑定,也支持用户去做自定义绑定。默认情况下,readline 会使用 Emacs 风格的键绑定,不过你可以很方便的切换到 Vi 风格,或者自定义设置。
执行set -o emacs
命令切换到 Emacs 风格,set -o vi
则会切换到 Vi 风格。
除此之外,你仍可以通过~/.inputrc
或者bind
命令来自定义快捷键绑定。例如,bind '"\C-f": "ls\n"'
将CTRL+F
绑定为执行ls
命令。你可以通过查阅 Bash 手册中的 readline 一节来更多地了解 readline 的快捷键绑定语法。
CTRL + a
CTRL + e
ESC + b
或者 ALT + b
ESC + f
或者 ALT + f
CTRL + w