1

凭借我生疏的 bash 技能,我正在尝试执行以下操作:

  1. 查找所有 UID > 500 的用户
  2. 打印用户列表,包括他们的用户名、评论、shell 等
  3. 将上次登录日期附加到这些用户中的每一个

到目前为止,我有这个:

[user1@test2 ~]$ sudo awk -F: '{if ($3 > 500) {system("lastlog -u" $1)} }' /etc/passwd | grep -iv username

    oracle                                     **Never logged in**
    user1      pts/0    hostname Tue Mar 31 16:18:42 +1300 2015
    user2                                    **Never logged in**

和这个:

[user1@test2 ~]$ sudo awk -F: '{if ($3 > 500) {print $1 "," $3 "," $5}}' /etc/passwd

nfsnobody,65534,Anonymous NFS User
oracle,54321,
user1,54324,Test user1

我希望像这样把所有东西都放在一行中:

oracle,54321,,**Never logged in**
user1,54324,Test user1,pts/0    hostname Tue Mar 31 16:18:42 +1300 2015

不知道如何加入两者,并用逗号替换空格。

有人可以建议吗?谢谢!

4

2 回答 2

1

尝试这个:

awk -F':' '$3 > 500 {("lastlog -u" $1 | getline a); print $1,$3,$5,a}' OFS=',' /etc/passwd 

解释:

  • $3 > 500确保 UID(第 3 列)大于 500
  • ("lastlog -u" $1 | getline a)将输出保存到变量“a”。这个输出应该等同于你的system("lastlog -u" $1)——我实际上没有这个功能,但我会假设它有效
  • print $1,$3,$5,a将打印您想要的任何列(这里我有第 1、3、5 列以及之前保存的“lastlog”输出)
  • OFS=','将使用输出字段分隔符作为逗号
于 2015-03-31T05:01:15.093 回答
1

这里不需要 awk;bash 可以内置所需的一切。(对于此处的示例,请确保您的脚本以#!/bin/bash、 not开头#!/bin/sh,或者您使用bash scriptname而不是调用它们sh scriptname)。

while IFS=: read -r username _ uid gid name homedir shell; do
  ((uid >= 500)) || continue
  { read; read; } < <(lastlog -u "$username")
  if [[ $REPLY = *"Never logged in"* ]]; then
    port=; from=; latest=
  else
    read _ port from latest <<<"$REPLY"
  fi
  echo "$username,$uid,$name,$homedir,$shell,$port,$from,$latest"
done < <(getent passwd)

顺便说一句,说join“不起作用”肯定是错误的——只加入一次lastlog调用的输出比lastlog每个用户调用一次效率要高得多,可以这样做:

join -t, \
    <(getent passwd | tr : , | sort -t, -k1,1) \
    <(lastlog | sed -r -e 's/[*][*]Never logged in[*][*]//' \
                       -e 's@[[:space:]]+@,@g' | tail -n +2 | sort -t, -k1,1) \
  | awk -F, '$3 >= 500'
于 2015-03-31T15:20:16.447 回答