我需要一个脚本,其中显示了上周内哪些用户连接到我的计算机的摘要以及频率。
我知道我可以使用last
并使用awk
过滤时间列,但是如何?
我必须在上周连接每个用户,并计算连接数加上所有连接的总时间。
这是我到目前为止所提出的:
for USER in `last | awk '{print $1}' | sort -u`; do
echo "Conexiones de $USER:"
last | grep $USER | wc -l
# BUT I NEED T COUNT ONLY LAST WEEK AND PRINT TOTAL TIME
done
答案 0 :(得分:1)
我强烈建议不要解析last
的输出,因为它的输出可能因实现而异,并且解析登录/注销日期很容易出错。此外,似乎几乎所有的实现都不支持-F
或类似的,没有你完全没有运气,因为你需要年份信息。从理论上讲,你可以检查一个月到另一个月是否有一个跳跃,这个跳跃在两个连续的行上是最近的(例如Jan-> Dec表示一年的变化),但是这种启发式方法存在缺陷 - 你无法猜出正确的年份正确。例如,采取一年中没有人登录的罕见情况。
如果您绝对必须/想要以任何方式解析其输出,请不要只使用bash / awk / cut / ...出于上述原因。要获得会话持续时间,您必须自己解析漂亮的登录/注销日期或已经计算的持续时间,这也是精心打印的,并且可能因实现而异(例如,不仅仅是小时和分钟。如何获得日期/列/年代表该列?)。 使用bash / awk执行此操作将是一场噩梦,甚至比我下面的脚本更容易破损 - 请不要这样做。
最好和最少hacky的解决方案是编写一个直接对wtmp
数据进行操作的小型C程序或脚本(man wtmp
),但是你必须自己计算会话持续时间登录/注销对(你不是免费获得;登录是一个记录,登出是第二个记录)。有关如何阅读其内容的参考,请参阅busybox' last
implementation。如果你想以正确的方式去做,这就是你要走的路。
话虽如此,我想出了下面的quick'n'dirty(perl)解决方案。它不运行last
命令,你必须自己输入正确的输入,否则它会爆炸。如果您的last
输出看起来与我的不同,不支持-F
或Date::Parse
无法解析您的last
命令打印的格式,它也会爆炸。还有很大的改进空间,但这应该可以让你开始。
-F
需要last
打印完整日期(我们需要这个来获取年份,否则我们无法从其输出中确定正确的时间戳)
-i
告诉最后输出IP地址,这使得输出更容易解析Date::Parse
之外,解析日期没有其他魔法,这意味着它必须排除所有没有正确登录/注销日期的会话(即,他们仍然登录或他们的会话由于重启,崩溃等原因而终止,因此这些会话不会成为计算输出的一部分! -d
开关#!/usr/bin/perl
use strict;
use warnings;
use Date::Parse;
use Getopt::Std;
our $opt_d;
getopt('d');
my $days = $opt_d || 7;
my $since = time() - (60 * 60 * 24 * $days);
my %data;
while (<>)
{
chomp;
next if /ssh|reboot|down|crash|still logged in/;
# last -Fi gives this on my box
# username line ip Mon Apr 1 18:17:49 2013 - Tue Apr 2 01:00:45 2013 (06:42)
my ($user, undef, undef, $date_from, $date_to) = /^(\S+)\s+(\S+)\s+([0-9.]+)\s+([[:alnum:]:\s]+)\s+-\s+([[:alnum:]:\s]+[^\s])\s+\(.+\)/;
my $time_from = str2time($date_from);
last if $time_from < $since;
my $time_to = str2time($date_to);
$data{$user}{"count"}++;
$data{$user}{"duration"} += $time_to - $time_from;
# print "$user|$line|$ip|$date_from|$date_to\n";
}
print "login history for the last $days day(s):\n\n";
if (keys %data > 0)
{
foreach my $user (keys %data)
{
my $duration = $data{$user}{"duration"};
printf "%s was logged in %d time(s) for a total of %d day(s), %d hour(s) and %d minute(s)\n",
$user,
$data{$user}{"count"},
($duration / (24 * 60 * 60)),
($duration / (60 * 60 )) % 24,
($duration / 60 ) % 60,
}
}
else
{
print "no logins during the specified time period\n";
}
$ last -Fi | ./last_parse.pl -d 700
login history for the last 700 day(s):
root was logged in 25 time(s) for a total of 36 day(s), 12 hour(s) and 35 minute(s)
foobar was logged in 362 time(s) for a total of 146 day(s), 17 hour(s) and 17 minute(s)
quux was logged in 3 time(s) for a total of 0 day(s), 0 hour(s) and 4 minute(s)
$
答案 1 :(得分:0)
试试这个
步骤
last > login.txt
last | awk '{print $3}' | sort -u > names.txt
迭代names.txt中的每一行并应用grep "line1" login.txt | wc -l
您将获得每个用户的计数(每个用户都是names.txt中的每一行)