使用awk获取给定用户的最长登录时间
Get the longest logon time of a given user using awk
我的任务是编写一个 bash 脚本,使用 awk 来查找给定用户的最长登录时间(“仍然登录”不算在内),并打印 month
day
IP
logon time in minutes
.
示例输入:./scriptname.sh username1
last username1
内容:
username1 pts/ IP Apr 2 .. .. .. .. (00.03)
username1 pts/ IP Apr 3 .. .. .. .. (00.13)
username1 pts/ IP Apr 5 .. .. .. .. (12.00)
username1 pts/ IP Apr 9 .. .. .. .. (12.11)
示例输出:
Apr
9
IP
731
(expl: 12小时11分钟共计731分钟)
我写了这个脚本,但是弹出一堆错误,我真的很困惑:
#!/bin/bash
usr=
last $usr | grep -v "still logged in" | awk 'BEGIN {max=-1;}
{
h=substr(,2,2);
min=substr(,5,2) + h/60;
}
(max < min){
max = min;
}
END{
maxh=max/60;
maxmin=max-maxh;
($maxh == 0 && $maxmin >=10){
last $usr | grep "00:$maxmin" | awk '{print ," ",," ", ," ",$maxmin}'
exit 1
}
($maxh == 0 $$ $maxmin < 10){
last $usr | grep "00:0$maxmin" | awk '{print ," ",," ",," ",$maxmin}'
exit 1
}
($maxh < 10 && $maxmin == 0){
last $usr | grep "0$maxh:00" | awk '{print ," ",," ",," ",$maxmin}'
exit 1
}
($maxh < 10 && $maxmin < 10){
last $usr | grep "0$maxh:0$maxmin" | awk '{print ," ",," ",," ",$maxmin}'
exit 1
}
($maxh >= 10 && $maxmin < 10){
last $usr | grep "$maxh:0$maxmin" | awk '{print ," ",," ",," ",$maxmin}'
exit 1
}
($maxh >=10 && $maxmin >= 10){
last $usr | grep "$maxh:$maxmin" | awk '{print ," ",," ",," ",$maxmin}'
exit 1
}
}'
所以稍微解释一下我想象中的效果:
初始化后,我想找到last $usr
命令的(hh:mm)
列,保存每一行的h
和min
,找到最大的数(以分钟为单位,意味着它是最长的登录时间)。
找到最长登录时间后(以分钟为单位,存储在变量 max
中),然后我必须将唯一的分钟格式重新格式化为 hh:mm
才能使用 grep,再次使用上一个命令,但现在只搜索包含 max
登录时间的行,并在 month
day
[=14= 中打印所有需要的信息] logon time in minutes
格式,使用另一种awk
.
我在 运行 这段代码 时得到的错误:当我尝试在原始代码中使用 grep
和 awk
时出现一堆语法错误awk
.
如果 gnu-awk
可用,您可以对最后一个字段中的数字使用包含 2 个捕获组的模式。在 END 块中打印您想要的格式。
如果在此示例中,file
包含示例内容,并且最后一列包含登录:
awk '
match ($(NF), /\(([0-9]+)\.([0-9]+)\)/, a) {
hm = (a[1] * 60) + a[2]
if(hm > max) {max = hm; line = [=10=];}
}
END {
n = split(line,a,/[[:space:]]+/)
print a[3], a[4], a[5], max
}
' file
输出
IP Apr 9 731
awk 不是 shell。您不能直接从 awk
调用 last
、grep
和 awk
之类的工具,就像您不能直接从 C
程序调用它们一样。
在每个 Unix 机器上的任何 shell 中使用任何 awk 并假设多行是否有您想要打印所有这些的最大时间,如果没有找到带时间戳的行,您需要类似 No matching records
打印(如果没有,可以轻松调整,只需告诉我们您对这些情况的要求,并将它们包含在您问题的示例中):
last username1 |
awk '
/still logged in/ {
next
}
{
split($NF,t,/[().]/)
cur = (t[2] * 60) + t[3]
}
cur >= max {
out = ( cur > max ? "" : out ORS ) OFS OFS OFS cur
max = cur
}
END {
print (out ? out : "No matching records")
}
'
Apr 9 IP 731
正在我的机器上测试 last
命令:
使用红帽 Linux 7.8
得到以下输出:
user0022 pts/1 10.164.240.158 Sat Apr 25 19:32 - 19:47 (00:14)
user0022 pts/1 10.164.243.80 Sat Apr 18 22:31 - 23:31 (1+01:00)
user0022 pts/1 10.164.243.164 Sat Apr 18 19:21 - 22:05 (02:43)
user0011 pts/0 10.70.187.1 Thu Nov 21 15:26 - 18:37 (03:10)
user0011 pts/0 10.70.187.1 Thu Nov 7 16:21 - 16:59 (00:38)
astukals pts/0 10.70.187.1 Mon Oct 7 19:10 - 19:13 (00:03)
reboot system boot 3.10.0-957.10.1. Mon Oct 7 22:09 - 14:30 (156+17:21)
astukals pts/0 10.70.187.1 Mon Oct 7 18:56 - 19:08 (00:12)
reboot system boot 3.10.0-957.10.1. Mon Oct 7 21:53 - 19:08 (-2:-44)
IT pts/0 10.70.187.1 Mon Oct 7 18:50 - 18:53 (00:03)
IT tty1 Mon Oct 7 18:48 - 18:49 (00:00)
user0022 pts/1 30.30.30.168 Thu Apr 16 09:43 - 14:54 (05:11)
user0022 pts/1 30.30.30.59 Wed Apr 15 11:48 - 04:59 (17:11)
user0022 pts/1 30.30.30.44 Tue Apr 14 19:03 - 04:14 (09:11)
发现时间格式为 DD+HH:MM
仅当 DD
不为零时出现。
发现还有其他技术用户:IT
、system
、reboot
需要过滤。
建议解决方案:
last | awk 'BEGIN {FS="[ ()+:]*"}
/reboot|system|still/{next}
{ print OFS OFS OFS $(NF-1) + ($(NF-2) * 60) + ($(NF-3) * 60 * 24)}
' |sort -nk 4| head -1
结果:
Apr 15 30.30.30.59 85991
我的任务是编写一个 bash 脚本,使用 awk 来查找给定用户的最长登录时间(“仍然登录”不算在内),并打印 month
day
IP
logon time in minutes
.
示例输入:./scriptname.sh username1
last username1
内容:
username1 pts/ IP Apr 2 .. .. .. .. (00.03)
username1 pts/ IP Apr 3 .. .. .. .. (00.13)
username1 pts/ IP Apr 5 .. .. .. .. (12.00)
username1 pts/ IP Apr 9 .. .. .. .. (12.11)
示例输出:
Apr
9
IP
731
(expl: 12小时11分钟共计731分钟)
我写了这个脚本,但是弹出一堆错误,我真的很困惑:
#!/bin/bash
usr=
last $usr | grep -v "still logged in" | awk 'BEGIN {max=-1;}
{
h=substr(,2,2);
min=substr(,5,2) + h/60;
}
(max < min){
max = min;
}
END{
maxh=max/60;
maxmin=max-maxh;
($maxh == 0 && $maxmin >=10){
last $usr | grep "00:$maxmin" | awk '{print ," ",," ", ," ",$maxmin}'
exit 1
}
($maxh == 0 $$ $maxmin < 10){
last $usr | grep "00:0$maxmin" | awk '{print ," ",," ",," ",$maxmin}'
exit 1
}
($maxh < 10 && $maxmin == 0){
last $usr | grep "0$maxh:00" | awk '{print ," ",," ",," ",$maxmin}'
exit 1
}
($maxh < 10 && $maxmin < 10){
last $usr | grep "0$maxh:0$maxmin" | awk '{print ," ",," ",," ",$maxmin}'
exit 1
}
($maxh >= 10 && $maxmin < 10){
last $usr | grep "$maxh:0$maxmin" | awk '{print ," ",," ",," ",$maxmin}'
exit 1
}
($maxh >=10 && $maxmin >= 10){
last $usr | grep "$maxh:$maxmin" | awk '{print ," ",," ",," ",$maxmin}'
exit 1
}
}'
所以稍微解释一下我想象中的效果:
初始化后,我想找到last $usr
命令的(hh:mm)
列,保存每一行的h
和min
,找到最大的数(以分钟为单位,意味着它是最长的登录时间)。
找到最长登录时间后(以分钟为单位,存储在变量 max
中),然后我必须将唯一的分钟格式重新格式化为 hh:mm
才能使用 grep,再次使用上一个命令,但现在只搜索包含 max
登录时间的行,并在 month
day
[=14= 中打印所有需要的信息] logon time in minutes
格式,使用另一种awk
.
我在 运行 这段代码 时得到的错误:当我尝试在原始代码中使用 grep
和 awk
时出现一堆语法错误awk
.
如果 gnu-awk
可用,您可以对最后一个字段中的数字使用包含 2 个捕获组的模式。在 END 块中打印您想要的格式。
如果在此示例中,file
包含示例内容,并且最后一列包含登录:
awk '
match ($(NF), /\(([0-9]+)\.([0-9]+)\)/, a) {
hm = (a[1] * 60) + a[2]
if(hm > max) {max = hm; line = [=10=];}
}
END {
n = split(line,a,/[[:space:]]+/)
print a[3], a[4], a[5], max
}
' file
输出
IP Apr 9 731
awk 不是 shell。您不能直接从 awk
调用 last
、grep
和 awk
之类的工具,就像您不能直接从 C
程序调用它们一样。
在每个 Unix 机器上的任何 shell 中使用任何 awk 并假设多行是否有您想要打印所有这些的最大时间,如果没有找到带时间戳的行,您需要类似 No matching records
打印(如果没有,可以轻松调整,只需告诉我们您对这些情况的要求,并将它们包含在您问题的示例中):
last username1 |
awk '
/still logged in/ {
next
}
{
split($NF,t,/[().]/)
cur = (t[2] * 60) + t[3]
}
cur >= max {
out = ( cur > max ? "" : out ORS ) OFS OFS OFS cur
max = cur
}
END {
print (out ? out : "No matching records")
}
'
Apr 9 IP 731
正在我的机器上测试 last
命令:
使用红帽 Linux 7.8 得到以下输出:
user0022 pts/1 10.164.240.158 Sat Apr 25 19:32 - 19:47 (00:14)
user0022 pts/1 10.164.243.80 Sat Apr 18 22:31 - 23:31 (1+01:00)
user0022 pts/1 10.164.243.164 Sat Apr 18 19:21 - 22:05 (02:43)
user0011 pts/0 10.70.187.1 Thu Nov 21 15:26 - 18:37 (03:10)
user0011 pts/0 10.70.187.1 Thu Nov 7 16:21 - 16:59 (00:38)
astukals pts/0 10.70.187.1 Mon Oct 7 19:10 - 19:13 (00:03)
reboot system boot 3.10.0-957.10.1. Mon Oct 7 22:09 - 14:30 (156+17:21)
astukals pts/0 10.70.187.1 Mon Oct 7 18:56 - 19:08 (00:12)
reboot system boot 3.10.0-957.10.1. Mon Oct 7 21:53 - 19:08 (-2:-44)
IT pts/0 10.70.187.1 Mon Oct 7 18:50 - 18:53 (00:03)
IT tty1 Mon Oct 7 18:48 - 18:49 (00:00)
user0022 pts/1 30.30.30.168 Thu Apr 16 09:43 - 14:54 (05:11)
user0022 pts/1 30.30.30.59 Wed Apr 15 11:48 - 04:59 (17:11)
user0022 pts/1 30.30.30.44 Tue Apr 14 19:03 - 04:14 (09:11)
发现时间格式为 DD+HH:MM
仅当 DD
不为零时出现。
发现还有其他技术用户:IT
、system
、reboot
需要过滤。
建议解决方案:
last | awk 'BEGIN {FS="[ ()+:]*"}
/reboot|system|still/{next}
{ print OFS OFS OFS $(NF-1) + ($(NF-2) * 60) + ($(NF-3) * 60 * 24)}
' |sort -nk 4| head -1
结果:
Apr 15 30.30.30.59 85991