时差bash脚本

时间:2014-11-30 03:35:05

标签: linux bash date-formatting

我正在尝试制作一个bash脚本,用于计算用户首次登录与用户最近登录之间的时差。任何帮助表示赞赏:)

这是我到目前为止所做的:

read -p "Enter a user ID: " ID
echo "You entered the following ID(s): $ID"

#/bin/egrep -i "^$ID" /etc/passwd

echo -n "The users real name is: "
/bin/grep "^$ID" /etc/passwd | cut -f5 -d :

echo -n "$ID's first login time is: "
l1=`last "$ID" | tail -n 1`


echo -n "$ID's last login time is: "
l2=`last "$ID" | head -n 1`

echo $l1
echo $l2

echo -n "The time difference is $(l1-l2) "

2 个答案:

答案 0 :(得分:1)

您的脚本似乎包含许多错误。

  

/ bin / grep“^ $ ID”/ etc / passwd | cut -f5 -d:

这与uid,AFAIK开头的/etc/passwd文件匹配(^),passwd文件始终以用户名开头,而不是uid。
也许你对用户ID的含义感到困惑;在UNIX中,用户ID始终引用每个用户拥有的数字ID;用户名是指您登录时键入的登录名。

无论如何,使用getent是一种更可靠的方法;我们可以grep :$uid:,但如果组ID与用户ID(在其他方案中)相同,则可能会中断。 getent也可以使用 用户ID和用户名。

此外,使用/bin/grep几乎总是一个坏主意; $PATH中的查找几乎总是更好(所以只需使用grep)。

l1=`last "$ID" | tail -n 1`

last需要用户名,而不是用户ID;也许有一种味道也接受了一个uid(?);无论如何,使用用户名更可靠。

  

echo -n“时差为$(l1-l2)”

last的日期采用字符串格式(Sat Nov 1 00:39);你不能只将它们减去整数,首先需要用date解析它们。

以下是工作版本的样子;我还做了一些对你有用的其他(次要)改进:

#!/bin/sh

# Keep asking for the uid until *something* is entered
while :; do
    read -p "Enter a user ID: " uid
    [ -n "$uid" ] && break
done

# Get line from /etc/passwd
passwd=$(getent passwd "$uid")

# Exit code was non-zero; the uid is unknown
if [ $? -ne 0 ]; then
    echo "User id '$uid' is unknown"
    exit 1
fi

# Get data from passwd
username=$(echo "$passwd" | cut -d: -f1)
realname=$(echo "$passwd" | cut -d: -f5)


# Get info from last, strip last 2 lines since they're not useful for us. Use
# ISO format so that date can parse them
lastlog=$(last --time-format iso "$username" | head -n-2)

# Get first & last line; we only need the date
last_login=$(echo "$lastlog" | head -n1 | tr -s ' ' | cut -d ' ' -f 4)
first_login=$(echo "$lastlog" | tail -n1 | tr -s ' ' | cut -d ' ' -f 4)

# Parse dates with date, output time in seconds since 1-1-1970 ('epoch')
diff=$(( $(date --date "$last_login" +%s) - $(date --date "$first_login" +%s) ))

# Format the date
diff_fmt=$(date --date @$diff +'%d days %H hours %M minutes %S seconds')

# Output info
echo "Found user $username ($realname) for userid $uid"
echo "First recorded login: $first_login"
echo "Last recorded login: $last_login"
echo "Difference: $diff_fmt (total of $diff seconds)"

不幸的是,这只适用于Linux系统;在所有 UNIX风格上工作需要更多的工作(shell脚本通常很难做到便携)

示例输出:

[~]% sh test.sh
Enter a user ID: 1001
Found user martin (Martin Tournoij) for userid 1001
First recorded login: 2014-11-01T00:13:28+0100
Last recorded login: 2014-11-30T06:08:54+0100
Difference: 30 days 06 hours 55 minutes 26 seconds (total of 2526926 seconds)

答案 1 :(得分:1)

这是基于您想要提供用户名而不是ID的假设。

首先,您要正确执行捕获

l1=$(last "$ID" | tail -n 1)
l2=$(last "$ID" | head -n 1)
在我的实例中

离开了

l1="wtmp begins Sun Nov  9 07:32:12 2014"
l2="graham   pts/11       :0               Sat Nov 29 22:13   still logged in"  

这不好,因为我们只需要 日期

所以让我们解决这个问题。这里有一些hacky解析只能获得时间:

l1=$(last -RF | grep $ID | tail -n 1 | tr -s ' ' | cut -d ' ' -f 3,4,5,6)
l2=$(last -RF "$ID" | head -n 1 | tr -s ' ' | cut -d ' ' -f 3,4,5,6)

我为l1 grep因为最后一次登录,但为了保持一致性,我抓住了最后一行。 last -RF删除主机(-R),因为我们不感兴趣并且时间更短(-F)。 tr修剪所有其他空格并剪切,用空格分隔,抓住日期。

我们想要计算两者之间的时间,所以让我们改变日期时间字符串并减去:

a=$(date -ud "$l2" +"%s") 
b=$(date -ud "$l1" +"%s")

d=$(( a-b ))

最后让我们打印

echo "$ID's last login time is: $l1"
echo "$ID's first login time is: $l2"
echo "The time difference is $d seconds"