8.13 找出系统中用户的活动时段
考虑一个使用共享主机(shared hosting)的Web服务器。每天都会有很多用户登录和注销。用户活动都被记入服务器的系统日志。这则攻略是一项实践任务:利用系统日志找出每个用户在服务器上停留了多久,并根据用户的使用时间对他们进行分级,最后生成一份包含等级、用户名、首次登录时间、末次登录时间、登录次数以及总时长等细节信息的报告。让我们看看如何解决这个问题。
8.13.1 新手上路
last
命令用来列出一个系统中有关用户登录会话的细节。这些会话数据被存储在/var/log/wtmp文件中。通过分别累计各用户的会话时间,我们就能得出各用户的总使用时间。
8.13.2 实战演练
研究一下这个用来找出活跃用户并生成报告的脚本:
#!/bin/bash
#用户名: active_users.sh
#用途:查找活跃用户
log=/var/log/wtmp
if [[ -n $1 ]];
then
log=$1
fi
printf "%-4s %-10s %-10s %-6s %-8s\n" "Rank" "User" "Start" "Logins"
"Usage hours"
last -f $log | head -n -2 > /tmp/ulog.$$
cat /tmp/ulog.$$ | cut -d' ' -f1 | sort | uniq> /tmp/users.$$
(
while read user;
do
grep ^$user /tmp/ulog.$$ > /tmp/user.$$
seconds=0
while read t
do
s=$(date -d $t +%s 2> /dev/null)
let seconds=seconds+s
done< <(cat /tmp/user.$$ | awk '{ print $NF }' | tr -d ')(')
firstlog=$(tail -n 1 /tmp/user.$$ | awk '{ print $5,$6 }')
nlogins=$(cat /tmp/user.$$ | wc -l)
hours=$(echo "$seconds / 60.0" | bc)
printf "%-10s %-10s %-6s %-8s\n" $user "$firstlog" $nlogins $hours
done< /tmp/users.$$
) | sort -nrk 4 | awk '{ printf("%-4s %s\n", NR, $0) }'
rm /tmp/users.$$ /tmp/user.$$ /tmp/ulog.$$
样例输出如下:
- $ ./active_users.sh
- Rank User Start Logins Usage hours
- 1 easyibaa Dec 11 531 11437311943
- 2 demoproj Dec 10 350 7538718253
- 3 kjayaram Dec 9 213 4587849555
- 4 cinenews Dec 11 85 1830831769
- 5 thebenga Dec 10 54 1163118745
- 6 gateway2 Dec 11 52 1120038550
- 7 soft132 Dec 12 49 1055420578
- 8 sarathla Nov 1 45 969268728
- 9 gtsminis Dec 11 41 883107030
- 10 agentcde Dec 13 39 840029414
8.13.3 工作原理
在脚本active_users.sh中,我们要提供日志文件wtmp作为命令行参数,也可以使用日志文件defaulwtmp。命令last-f
用来打印日志文件的内容。日志文件的第一列是用户名。我们用cut
从中提取第一列,然后用sort
和uniq
找出不重复的用户。对每一位用户,用grep
找出其对应登录会话的日志行并写入一个临时文件。日志的最后一列是用户登录会话的时长。为了找出用户总的使用时间,需要累加所有的会话时长。使用时间的格式是(小时:秒),因此还需要用date
命令将其转换成秒。
要提取用户的会话时长,得使用awk
命令。要移除括号,得使用tr -d
。用<( COMMANDS )
操作符将用户使用时长字符串列表作为标准输入传递给while
循环。它的作用就像是文件输入。利用date
命令将每一个时长字符串转换成秒数,并累加到变量seconds
中。将出现在最后一行的用户的首次登录时间提取出来。登录次数就是日志的行数。要根据总的使用时间来计算每位用户的等级,数据记录需要将总使用时间作为键,进行降序排列。用sort
命令的-nr
选项指定按照数值逆序排列。-k4
指定键的列号(即使用时间)。最后,sort
的输出被传递给awk
。awk
命令为每一行添加上行号,这个行号就是每一位用户的等级。