知道上周有多少用户连接到我的计算机,以及每个用户连接了多少时间

时间:2013-04-02 09:33:01

标签: linux bash shell

我需要一个脚本,其中显示了上周内哪些用户连接到我的计算机的摘要以及频率。

我知道我可以使用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

2 个答案:

答案 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输出看起来与我的不同,不支持-FDate::Parse无法解析您的last命令打印的格式,它也会爆炸。还有很大的改进空间,但这应该可以让你开始。

备注

    {li> -F需要last打印完整日期(我们需要这个来获取年份,否则我们无法从其输出中确定正确的时间戳)
  • -i告诉最后输出IP地址,这使得输出更容易解析
  • 它不解析会话持续时间列,而是解析登录/注销日期,将它们转换为纪元时间并计算差异以获得会话持续时间。除了使用Date::Parse之外,解析日期没有其他魔法,这意味着它必须排除所有没有正确登录/注销日期的会话(即,他们仍然登录或他们的会话由于重启,崩溃等原因而终止,因此这些会话不会成为计算输出的一部分!
  • 默认为7天,但您可以使用-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)

试试这个

步骤

  1. last > login.txt

  2. last | awk '{print $3}' | sort -u > names.txt

  3. 迭代names.txt中的每一行并应用grep "line1" login.txt | wc -l

  4. 您将获得每个用户的计数(每个用户都是names.txt中的每一行)