2014-11-30 5 views
2

사용자의 첫 번째 로그온과 가장 최근에 로그온 한 사용자 간의 시간차를 계산하는 bash 스크립트를 만들려고합니다. 어떤 도움에 감사드립니다 :)시차 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) " 

답변

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" 

왼쪽 그것을 고쳐라. 마지막으로 마지막 로그인 잎 때문에

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

스크립트 오류의 수를 포함 할 것으로 보인다.

/bin/grep "^ $ ID"/ etc/passwd | -f5 -d를 잘라 :

이이 UID의 시작 (^)에서 /etc/passwd 파일과 일치, AFAIK, passwd 파일은 항상 사용자 이름이 아닌 UID로 시작합니다.
아마도 사용자 ID가 무엇을 의미하는지 혼란 스러울 것입니다. UNIX에서 사용자 ID는 항상 모든 사용자가 가지고있는 숫자 ID를 참조합니다. 사용자 이름은 로그인 할 때 입력 한 로그인 이름을 나타냅니다.

어쨌든 getent을 사용하는 것이 더 신뢰할 수있는 방법입니다. 우리는 :$uid:에 대해 grep 할 수 있지만 그룹 id가 (다른 시나리오들 중에서) 사용자 ID와 동일하면 그 값이 깨질 수 있습니다. getent 사용자 ID와 사용자 이름도 사용할 수 있습니다.

또한 /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)" 

이는 리눅스 시스템에서 작동됩니다; 조금 더 많은 작업이 모든 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' 명령은 리눅스에서만 사용됩니다 (예를 들어, Mac OS X에서는 사용할 수 없습니다). 'last-time-iso' 옵션은 GNU의'last'에서만 사용할 수 있습니다 (예를 들어, Mac OS X에서는 사용할 수 없습니다). GNU의'date' 명령을 제외하고 여러분이 사용하고있는 주요'date' 옵션은 모두 직접 사용할 수 없습니다. 유닉스 계열 시스템에 GNU 코드를 설치할 수 있지만 대부분의 비 리눅스 시스템에서는 코드가 제대로 작동하지 않습니다. –