Скрипт разницы во времени

Я пытаюсь создать 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 ответа

Решение

Это основано на предположении, что вы хотите указать имя пользователя, а не 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)

Я использую l1, потому что последний оставляет последний зарегистрированный, но для согласованности я просто беру последний ряд. 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"

Ваш скрипт, кажется, содержит ряд ошибок.

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

Это соответствует /etc/passwd файл в начале (^) для uid, AFAIK, файл passwd всегда начинается с имени пользователя, а не uid.
Возможно, вы не понимаете, что означает идентификатор пользователя; в UNIX идентификатор пользователя всегда ссылается на числовой идентификатор каждого пользователя; имя пользователя относится к имени пользователя, которое вы вводите при входе в систему.

В любом случае, используя getent это более надежный метод; мы могли бы найти :$uid:, но это может сломаться, если идентификатор группы совпадает с идентификатором пользователя (среди других сценариев). getent также будет работать как с идентификатором пользователя, так и с именем пользователя.

Кроме того, используя /bin/grep почти всегда плохая идея; поиски в $PATH почти всегда лучше (так что просто используйте grep).

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

last ожидает имя пользователя, а не идентификатор пользователя; возможно есть аромат, который также принимает 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 потребовала немного больше работы (создание сценариев оболочки часто трудно сделать переносимым)

Пример вывода:

[~]% 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)
Другие вопросы по тегам