last
我使用如下命令获取特定用户的最后一次会话的时间:
last -aiF -n 1 fakeuser
该命令的输出类似于:
fakeuser pts/0 2018年11月27日星期二11:03:19 - 2018年11月27日星期二11:14:57 (00:11) 999.999.99.999
我的问题是关于会话时间((00:11)
在示例中)。有什么办法可以让这个时间以秒为单位吗?
我知道我可以根据登录和注销时间来计算它,但我正在直接在命令中寻找一些解决方案last
,因为我在man
该命令的入口中也没有在网络中找到任何内容。
仅供参考,我正在使用 Debian 9.5,但我相信它的某些解决方案应该适用于任何发行版。
完美答案的附带问题(我在此处第一个答案后确定了它):如何确定持续时间不到一分钟的会话?
答案1
如果我没记错的话,您感兴趣的字段通常采用格式Days+HH:MM
,为了将其转换为秒,我们可以这样做:
last -aiF -n 1 fakeuser | \
awk '{gsub(/\(|\)/, "", $14); print $14}' | \
awk -F'[:+]' 'length($0) != 0 {if(length($3) == 0) {$3=$2; $2=$1; $1=0} {print ($1 * 86400) + ($2 * 3600) + ($3 * 60)}}'
第一行是您的last
命令。
在第二行中,我们将您想要的字段从命令输出中分离出来,该字段似乎是字段 14。
第三行包含所有动作。设置分隔符 ( -F
) 以在加号 ( +
) 和冒号 ( :
) 上分割字段。然后我们进行测试以确保该行不为空 ( length($0) != 0
)。下一位 ( if(length($3) == 0) {$3=$2; $2=$1; $1=0}
) 是一个快速技巧,可将任意行标准化为三个字段:天、小时和分钟。剩下的 ( {print ($1 * 86400) + ($2 * 3600) + ($3 * 60)}
) 只是转换为秒(一天 86400 秒,一小时 3600 秒,一分钟 60 秒)。
可能有一种更简单的方法,但这是我在午餐时搞乱这个问题时想到的。
答案2
GracefulRestart 对这个问题的 awk 解决方案非常出色;正如您在对他的回答的评论中指出的那样,该last
命令不够精细。但是,假设auth.log
debian 上的情况与我在 Ubuntu 上看到的足够相似,您可以根据那里的数据进行一些数学计算。
我很感激这不是答案,但它仍然可能对您有用。
我从 中过滤了一堆行/var/log/auth.log
,它们既涉及本地登录又涉及 ssh 登录。
cat auth.log
2018-12-06T07:28:00.487714+13:00 server systemd-logind[944]: New session 2597 of user tink.
2018-12-06T08:34:16.360766+13:00 server login[29537]: pam_unix(login:session): session opened for user tink by LOGIN(uid=0)
2018-12-06T08:34:16.372714+13:00 server systemd-logind[944]: New session c4 of user tink.
2018-12-06T08:34:20.960596+13:00 server login[29537]: pam_unix(login:session): session closed for user tink
2018-12-06T08:36:01.197712+13:00 server systemd-logind[944]: Removed session 2597.
这是一个(复杂的)awk 脚本..
cat session.awk
{
if( $0 ~ /systemd-logind.+New session/ && $0~user ){
start[$6]=$1
}
if( $0 ~ /systemd-logind.+ Removed session/ && start[gensub(/([0-9]+).*/, "\\1", "1", $6)] != "" ){
tmp = start[gensub(/([0-9]+).*/, "\\1", "1", $6)]
cmd = "date +%s -d ";
cmd $1 | getline outa;
cmd " " tmp | getline ina;
close( cmd )
printf "%s was logged in for %s seconds\n", user, outa-ina
}
if( $0 ~ /login.+ session opened/ && $0~user ){
start[gensub(/[^0-9]+([0-9]+).*/,"\\1","1",$3)]=$1
}
if( $0 ~ /login.* session closed/ ){
tmp = start[gensub(/[^0-9]+([0-9]+).*/,"\\1","1",$3)]
cmd = "date +%s -d ";
cmd $1 | getline outa;
cmd " " tmp | getline ina;
close( cmd )
printf "%s was logged in for %s seconds\n", user, outa-ina
}
}
针对上面的代码片段运行该代码:
awk -v user=tink -f session.awk sessions
tink was logged in for 4 seconds
tink was logged in for 4081 seconds