系统管理 类目

合格的运维工程师必须是一名出色的系统管理员,工欲善其事,必先利其器,本博客会介绍一些系统管理相关的技巧与出色的工具。

tmp 目录文件被自动清理问题的调查

某次项目发布过程中,当我们把 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

但是很遗憾,这个工具无法知道是哪个进程操作的,只能确定确实发生了“删除”的行为。

既然工具不行,就开始想找找系统日志,Linux 有日志审计(audit)的功能,只不过服务器上不一定开启,开启看看是否可以抓到问题:

$sudo /etc/init.d/auditd start
$sudo /sbin/auditctl -w /tmp/test.rpm

运行一会后,可以使用 ausearch 命令查找审计日志:

$sudo ausearch -f /tmp/test.rpm
----
time->Thu Nov 20 16:23:15 2014
type=PATH msg=audit(1416471795.984:3893): item=1 name="/tmp/b.rpm.bak" inode=8304 dev=08:02 mode=0100664 ouid=505 ogid=505 rdev=00:00
type=PATH msg=audit(1416471795.984:3893): item=0 name="/tmp/" inode=8193 dev=08:02 mode=041777 ouid=0 ogid=0 rdev=00:00
type=CWD msg=audit(1416471795.984:3893):  cwd="/"
type=SYSCALL msg=audit(1416471795.984:3893): arch=c000003e syscall=87 success=yes exit=0 a0=7ffffd607bb5 a1=7ffffd607bb5 a2=2 a3=1 items=2 ppid=16473 pid=16475 auid=0 uid=505 gid=505 euid=505 suid=505 fsuid=505 egid=505 sgid=505 fsgid=505 tty=(none) ses=154149 comm="rm" exe="/bin/rm" key=(null)

审计日志中可以看到第二个线索:删除是通过 rm 命令操作的,而且发现了进程的 pid 和 ppid。但是很遗憾,对应的进程通过 ps 命令已经找不到了,说明不是常驻进程搞得鬼。得出第三个最宝贵的线索:是一个定时执行的脚本清理了 /tmp 目录下的文件

查看全文

logrotate 没有滚动日志

前段时间发现某些机器磁盘空间报警,使用 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 包。

Shell 一键安装命令

现在是懒人的天下,为了迎合用户的需求,很多开源软件或者包提供的安装步骤都非常简单,大家应该看到不少类似一键安装的命令。下面是几个典型的例子:

# 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 下的流量监控工具

iftop 是 Linux 下的流量监控工具,可以用来观察实时的网络连接和网络流量情况。网上有很多介绍 iftop 使用的相关文章,但是我发现很难找到原文,有些文章对它的使用的解释很生硬。所以,我今天将自己理解的 iftop 用法整理出来,分享给需要的同学。如有不对之处,还请各位不吝指出。

显示结果

在命令行中执行 iftop 之后,会显示抓取的网络连接列表,以及对应的网络流量统计。每个连接显示结果类似:

foo.example.com  =>  bar.example.com      1Kb  500b   100b
                 <=                       2Mb  2Mb    2Mb 

两行分别表示不同的数据传输方向,对于第一行而言,第一列是源地址,第二列是目的地址,最后三列分别是最近 2 秒、10 秒、40 秒发送的平均网络流量。默认情况下,是按十秒内的平均网络流量排序的。

底部会显示一些全局的统计数据,peek 是指峰值情况,cumm 是从 iftop 运行至今的累计情况,而 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

查看全文

rsync 同步文件重复拷贝问题

newrsynclogo

rsync 是同步文件的利器,一般用于多个机器之间的文件同步与备份,同时也支持在本地的不同目录之间互相同步文件。在这种场景下,rsync 远比 cp 命令更加合适,它只会同步需要更新的文件,默认情况下,rsync 通过比较文件的最后修改时间(mtime)和文件的大小(size)来确认哪些文件需要被同步过去。

最近刚好有一个需求,需要将文件从一个目录同步到另外一个目录去,我就首先试了下下面的命令:

# mkdir src dest
# echo hello > src/one.txt
# rsync --stats src/1.txt dest

这里加上 --stats 的目的是为了显示文件传输的详细信息。执行完成后文件已经同步到目标目录,非常简单,但是如果再执行一次,我们会非常尴尬地发现文件被再次同步过去:

# rsync --stats src/one.txt dest

Number of files: 1
Number of files transferred: 1
Total file size: 6 bytes
Total transferred file size: 6 bytes
Literal data: 6 bytes
Matched data: 0 bytes
File list size: 21
File list generation time: 0.001 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 77
Total bytes received: 31

sent 77 bytes  received 31 bytes  216.00 bytes/sec
total size is 6  speedup is 0.06

查看全文

mark-directory: 快速目录切换工具

今天早上看到@程序员的那些事转的一条微博《使用命令行快速操控文件系统》,文中作者介绍了他提升工作效率的一个命令行小工具,可以快速切换工作目录,我觉得蛮有意思的,小小研究了下。在原工具的基础上,我在 Github fork了一个改进的版本 —— mark-directory,具体可以看文章最后。

工作原理

这个小工具的工作原理非常简单,相信大家扫过一遍原文就可以明白,它创建了一个隐藏目录(例如~/.marks),目录里面存放的文件都是常用目录的软链接。我们可以将这个软链接看作一个书签,通过访问这个书签我们可以方便地跳转到相应的目录。

具体实现

这个小工具也提供了相应的命令来管理这些软链接文件,当前支持的是jump, mark, unmark和marks。

以上4个操作命令的实现代码如下所示,非常简单:

export MARKPATH=$HOME/.marks
function jump { 
    cd -P "$MARKPATH/$1" 2>/dev/null || echo "No such mark: $1"
}
function mark { 
    mkdir -p "$MARKPATH"; ln -s "$(pwd)" "$MARKPATH/$1"
}
function unmark { 
    rm -i "$MARKPATH/$1"
}
function marks {
    ls -l "$MARKPATH" | sed 's/  / /g' | cut -d' ' -f9- | sed 's/ -/\t-/g' && echo
}

将这段代码放到~/.bashrc 文件中。接下来我们来尝试使用这个小工具。

查看全文

CPU Topology

如果你也是对/proc/cpuinfo文件里面的内容不甚了解,请跟我一起来学习下CPU的拓扑结构 (CPU Topology)。我们先从一些简单的概念开始。

NUNA与SMP

NUMA(Non-Uniform Memory Access,非一致性内存访问)和SMP(Symmetric Multi-Processor,对称多处理器系统)是两种不同的CPU硬件体系架构。

SMP的主要特征是共享,所有的CPU共享使用全部资源,例如内存、总线和I/O,多个CPU对称工作,彼此之间没有主次之分,平等地访问共享的资源,这样势必引入资源的竞争问题,从而导致它的扩展内力非常有限。

NUMA技术将CPU划分成不同的组(Node),每个Node由多个CPU组成,并且有独立的本地内存、I/O等资源。Node之间通过互联模块连接和沟通,因此除了本地内存外,每个CPU仍可以访问远端Node的内存,只不过效率会比访问本地内存差一些,我们用Node之间的距离(Distance,抽象的概念)来定义各个Node之间互访资源的开销。

查看全文

学习 Linux 命令(三)

本文是学习Linux命令 (Learn linux command)系列文章的第三篇,在这里会介绍一些让大家平时都会经常用到的命令。注意,命令出现的顺序与重要程度无关。

1. ls - list directory contents

ls命令是用得比较多的一个命令,它用于列出某个目录下面的文件或者子目录及它们的属性(大小、创建时间、所属用户等信息)。

ls命令的参数比较多,这里只介绍一些实用的。

a. 通过-a选项列出目录下面的隐藏文件(即以.号开头的文件),例如:

# ls -a ~
.  ..  .bash_history  .bash_logout  .bash_profile  .bashrc  .cshrc .tcshrc  .viminfo

其中.和..表示当前目录与上一级目录,如果不想显示可以使用-A选项。

# ls -A ~
.bash_history  .bash_logout  .bash_profile  .bashrc .cshrc .tcshrc  .viminfo

查看全文

1 2 3 4