Скрипт разницы во времени
Я пытаюсь создать 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)