2014-11-30 4 views
2

Я пытаюсь создать сценарий bash, который рассчитает разницу во времени между первым входом пользователя и последним входом в систему пользователей. Любая помощь приветствуется :)Time bash script

Это то, что я до сих пор:

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) " 

ответ

1

Это базируется на предположении, который вы хотите указать имя пользователя и а не идентификатор.

Во-первых, вы хотите, чтобы выполнить ваши захваты правильно

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, поскольку последний оставляет последний вход в системе, но для последовательности, я просто захватить последнюю строку. 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" 
1

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

/bin/grep "^ $ ID"/etc/passwd | вырезать -f5 -d:

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

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

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

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

last ожидает имя пользователя, а не идентификатор пользователя; возможно, есть вкус, который также принимает uid (?); в любом случае использование имени пользователя является более надежным.

эхо -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) 
+0

Гораздо более полным, чем у меня. Я не уверен, почему я только сейчас вижу это, хотя вы разместили передо мной. –

+1

@ DylanMadisetti Спасибо :-) Я отправил его ~ 40 минут назад, но думал, что это может быть лучше/более всеобъемлющим, поэтому я удалил свой пост. Я сделал свои улучшения и восстановил его сразу после того, как вы отправили свой ответ :-) – Carpetsmoker

+0

Прошу прощения, чтобы разбить вам новость, но ваш код будет работать только в Linux - он не удаленно переносится. Команда 'getent' специфична для Linux (например, недоступна для Mac OS X). Опция 'last -time-iso' доступна только с последней версией GNU (например, недоступной для Mac OS X). Все основные параметры «даты», которые вы используете, недоступны напрямую, кроме как с помощью команды «date» от GNU. Хотя код GNU может быть установлен в любой Unix-подобной системе, код не будет работать из коробки на большинстве систем, отличных от Linux. –