Linux 时差bash脚本

Linux 时差bash脚本,linux,bash,date-formatting,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 -

我正在尝试制作一个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) "

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

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

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

无论如何,使用
getent
是一种更可靠的方法;我们可以搜索
:$uid:
,但如果组id与用户id相同(在其他场景中),则可能会中断搜索
getent
还将使用用户id和用户名

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

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

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

上次的日期为字符串格式(
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)

这是基于您希望提供用户名而不是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"  
这不好,因为我们只需要日期

让我们来解决这个问题。下面是一些只获取时间的黑客解析:

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)
我grep为l1,因为last离开最后一个登录,但为了一致性,我只抓取最后一行
last-RF
删除主机(
-R
),因为我们对它不感兴趣,而且会让时间变得更好(
-F
tr
修剪所有额外的空格并剪切(以空格分隔)以获取日期

我们要计算时间间隔,所以我们将两者更改为datetime字符串并减去:

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"

比我的要全面得多。我不知道为什么我现在才看到这个,尽管你在我之前发布了。@DylanMadisetti谢谢:-)我在大约40分钟前发布了它,但认为它可以更好/更全面,所以我删除了我的帖子。我做了改进,并在您发布答案后取消了删除:-)很抱歉告诉您这个消息,但您的代码只能在Linux上工作-它不能远程移植。
getent
命令特定于Linux(例如,在Mac OS X上不可用)。
last--time iso
选项仅适用于GNU的
last
(例如,在Mac OS X上不可用)。除GNU的
date
命令外,您使用的所有主要
date
选项都不能直接使用。虽然GNU代码可以安装在任何类似Unix的系统上,但在大多数非Linux系统上,该代码都无法开箱即用。@JonathanLeffler,谢谢;做这种特定于平台的事情很难做到干净;例如,FreeBSD有自己的
date
扩展来实现这一点,它与GNU
date
不兼容,而且
getent
不是特定于Linux的,我知道至少FreeBSD、NetBSD和Solaris有它,但显然不是OSX。。。无论如何,我认为这个问题是关于Linux的。。。(我调整了兼容性备注)。
echo "$ID's last login time is: $l1"
echo "$ID's first login time is: $l2"
echo "The time difference is $d seconds"