我想了解当月每天有多少用户登录我的服务器。从每个月的第一天开始。我最好使用 awk 来做到这一点。
我的输出应该是这样的:
Apr 1: numOfLogins
Apr 2: numOfLogins
...
current day: numOfLogins
答案1
您可以像下面这样使用它:
last <user> | awk -v dt="$(date +%b)" '$5==dt{ k[$5$6]+=1; a[$5$6]=$5"-"$6"-"$7 } END { for ( i in k ) { split(a[i],s,"-");print s[1]" "s[2]": "k[i]" No of Logins" } }' | sort -n -k2
对于非特定用户:
last | grep -ve reboot -ve wtmp | awk -v dt="$(date +%b)" '$5==dt{ k[$5$6]+=1; a[$5$6]=$5"-"$6"-"$7 } END { for ( i in k ) { split(a[i],s,"-");print s[1]" "s[2]": "k[i]" No of Logins" } }' | sort -n -k2
或者
按用户列出:
last | grep -ve reboot -ve wtmp | awk -v dt="$(date +%b)" '$5==dt{ k[$1$5$6]+=1; a[$1$5$6]=$1"-"$5"-"$6"-"$7 } END { for ( i in k ) { split(a[i],s,"-");print s[1]" "s[2]" "s[3]": "k[i]" No of Logins" } }' | sort -n -k3
答案2
如果您last
支持该--since
选项,您可以通过以下方式限制为当前月份:
last --since "$(date +'%Y-%m-01')"
该命令date +'%Y-%m-01'
打印本月第一天的日期。例如,如果我今天(2020 年 4 月 26 日)运行它,我会得到:
$ date +'%Y-%m-01'
2020-04-01
所以last
命令变成了last --since 2020-04-01
。
这意味着我们在 awk 中需要做的就是排除以 开头的行reboot
、以 开头的行wmtp
以及任何空行,然后进行计数:
last --since "$(date +'%Y-%m-01')" | awk '!/^reboot/&&!/^wtmp /&&/./{date=$5" "$6; a[date]++}END{for(date in a){printf "%s: %d\n",date,a[date]}}' | sort -nk2
或者,更容易阅读:
last --since "$(date +'%Y-%m-01')" |
awk '!/^reboot/ && !/^wtmp / && /./{
date=$5" "$6;
a[date]++
}
END{
for(date in a){
printf "%s: %d\n",date,a[date]
}
}' | sort -nk2
在我的笔记本电脑上,返回:
$ last --since "$(date +'%Y-%m-01')" | awk '!/^reboot/&&!/^wtmp / && /./{date=$5" "$6; a[date]++}END{for(date in a){printf "%s: %d\n",date,a[date]}}' | sort -nk2
Apr 3: 1
Apr 5: 1
Apr 20: 1
~/.bashrc
如果这是您经常使用的东西,您可以通过将这些行添加到您的(或等效的,如果您不使用 bash)中,将其变成 shell 函数:
monthLogins(){
last --since "$(date +'%Y-%m-01')" |
awk '!/^reboot/ && !/^wtmp / && /./{
date=$5" "$6;
a[date]++
}
END{
for(date in a){
printf "%s: %d\n",date,a[date]
}
}' | sort -nk2
}
然后您可以运行monthLogins
并获得所需的输出。
或者,您可以使用以下命令仅过滤现有用户名(假设您的 shell 支持该构造),而不是过滤掉reboot
和:wtmp
<()
monthLogins(){
last --since "$(date +'%Y-%m-01')" |
grep -f <(cut -d: -f1 /etc/passwd)
awk '/./{
date=$5" "$6;
a[date]++
}
END{
for(date in a){
printf "%s: %d\n",date,a[date]
}
}' | sort -nk2
}
答案3
非常感谢斯大林·维涅什·库马尔的回答。此代码将仅显示由系统月份确定的当前月份(日期+%b),过滤掉reboot用户,显示在最后的每当系统启动时命令的输出,并显示全部用户的登录。如果我能弄清楚如何在适当变量的输出中添加前导零,我将更新我的答案:
#!/bin/bash
last | grep `date +%b` | grep -v -e "reboot" | awk ' { k[$5$6]+=1; a[$5$6]=$5"-"$6"-"$7 } END { for ( i in k ) { split(a[i]"\n",s,"-");print s[1]" "s[2]": "k[i]" logins" } }' | sort -n -k2