Posts RSS Comments RSS 48 Posts and 155 Comments till now

Getting user login data from Macs using AppleScript

A lab we work with recently upgraded to 10.5 and found that the program they were running to get the user login data for their billing wouldn’t work in 10.5 and wasn’t going to be upgrading. In looking at the data it was grabbing it was clear the same data could be gotten using the last command in Terminal. You can see more about last at my post here. However, these folks were not computer-savvy and needed the information in a comma-delimited file. So, I came up with this script.

When you run the script it asks you which month you want the data for in a list. Select the month and it will generate a file on the desktop with that months data. You can save it out as an application, run it from Script Editor or run it as a launchd/cron job. You can customize the output by changing the line that begins with “write”. For example, replace the “,” with tab and create a tab-delimited file instead.

If you run this script logged in as a regular user you will only get the login information for that user. If you run it as an administrator you’ll get the login information for every account on the machine.

Click here to download the script file:
Monthly Login accounting

[codesyntax lang=”applescript” lines=”no”]
set the_months to {}
set the_total to 0
set the_time to “”
set the_computer to (computer name of (system info))

--get the raw login log information
set the_login to (do shell script “last”) as text

set the_count to the count of paragraphs of the_login

--get the list of all the months login data is available for
repeat with x from 1 to the_count
if paragraph x of the_login contains “console” then
set month_check to (word 4 of paragraph x of the_login) as text
if the_months does not contain month_check then
set end of the_months to month_check
end if
end if
end repeat
set selected_month to choose from list the_months with prompt “Select the month:”

--create the file to write data to
if selected_month is not false then
tell application “Finder”
set file_name to (the_computer & “-” & selected_month & “-” & (year of (current date)) & ” login stats.txt”)
if not (exists file (((path to desktop from user domain as text) & file_name))) then
set login_file to make file with properties {name:file_name, file type:”TEXT”} at (path to desktop from user domain)
else
display dialog “This stats file already exists. Do you want to overwrite it?” buttons {“Yes”, “No”} default button 2
set the_answer to the button returned of the result
if the_answer is “Yes” then
delete file ((path to desktop from user domain as text) & file_name)
set login_file to make file with properties {name:file_name, file type:”TEXT”} at (path to desktop from user domain)
end if
end if
end tell
set login_file to ((path to desktop from user domain) & file_name) as text
end if

--loop through the data and pull out the logins for the selected month
repeat with x from 1 to the_count
if paragraph x of the_login contains selected_month then
if paragraph x of the_login contains “console” then
set the_user to (word 1 of paragraph x of the_login)
set the_month to (word 4 of paragraph x of the_login) as text
set the_logmonth to MonthNumber(the_month)
set the_day to (word 5 of paragraph x of the_login) as text
if (the (count of characters of the_day) is less than 2) then
set the_day to (“0” & the_day)
end if
set the_year to yearCheck(selected_month, the_months)
set log_date to (the_logmonth & “/” & the_day & “/” & the_year)
set login_time to (word 6 of paragraph x of the_login & “:” & word 7 of paragraph x of the_login)
set logout_time to (word 8 of paragraph x of the_login & “:” & word 9 of paragraph x of the_login)

set old_delims to AppleScript’s text item delimiters
set AppleScript’s text item delimiters to “(”
try
set the_time1 to text item 2 of paragraph x of the_login
set AppleScript’s text item delimiters to old_delims
set the_time to (characters 1 through 5 of the_time1) as text
on error
set AppleScript’s text item delimiters to old_delims
end try

–write all the date to the file
write (the_user & “,” & the_computer & “,” & log_date & “,” & login_time & “,” & log_date & “,” & logout_time & “,” & the_time & return) to file login_file starting at eof
end if
end if
end repeat

--if the list contains January see if the selected month comes before or after January. Adjust the year accordingly.
on yearCheck(selected_month, the_months)
if the_months contains “Jan” then
repeat with x from 1 to count of the_months
if item x of the_list contains selected_month then
set the_num to x
else
if item x of the_list contains “Jan” then
set jan_num to x
end if
end if
end repeat
set year_check to (the_num – jan_num)
if year_check is greater than 0 then
set the_year to ((year of (current date)) – 1)
else
set the_year to (year of (current date))
end if
else
set the_year to (year of (current date))
end if
return the_year
end yearCheck

on MonthNumber(the_month)
if the_month = “Jan” then
set the_month to “01”
else
if the_month = “Feb” then
set the_month to “02”
else
if the_month = “Mar” then
set the_month to “03”
else
if the_month = “Apr” then
set the_month to “04”
else
if the_month = “May” then
set the_month to “05”
else
if the_month = “Jun” then
set the_month to “06”
else
if the_month = “Jul” then
set the_month to “07”
else
if the_month = “Aug” then
set the_month to “08”
else
if the_month = “Sep” then
set the_month to “09”
else
if the_month = “Oct” then
set the_month to “10”
else
if the_month = “Nov” then
set the_month to “11”
else
if the_month = “Dec” then
set the_month to “12”
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
return the_month as string
end MonthNumber
[/codesyntax]

2 Responses to “Getting user login data from Macs using AppleScript”

  1. on 18 Apr 2010 at 2:30 ammohawke

    What’s wrong with Python?

    #!/usr/bin/python
    import subprocess, time
    # OS X 10.6+ -Mohawke 2010

    def get_user_logons(get_month, report=’/Users/mohawke/Desktop/logons.csv’):
    data=[]; clean=[]
    fields = ‘user,type,from,to,dur(mins)\n’
    # Won’t worry about year considering the user picks a month…
    year = time.strftime(‘%Y’, time.localtime(time.time()))
    months={‘Jan’:1,’Feb’:2,’Mar’:3,’Apr’:4,
    ‘May’:5,’Jun’:6,’Jul’:7,’Aug’:8,’Sep’:9,
    ‘Oct’:10,’Nov’:11,’Dec’:12}

    # get the data via the last command.
    process = subprocess.Popen(‘last’, shell=False, stdout=subprocess.PIPE)
    data = process.communicate()
    logins = data[0].split(‘\n’)
    data = [entry.split() for entry in logins if entry]

    # get data based on users input, format, and write out the data.
    f=open(report,’w’)
    f.write(fields)

    for item in data:
    if ‘in’ in item[-1]: continue
    if ‘wtmp’ in item[0]:
    logstart = ‘ ‘.join(item)
    print logstart
    continue
    user = item[0]
    type = item[1]
    end_time = item[-2]
    start_time = item[-4]
    day = item[-5]
    month = item[-6]

    if months[month] == get_month:
    # conv. time in secs… Nice for storing…
    date_frm = ‘%s/%s/%s %s’ %(months[month], day, year, start_time)
    date_to = ‘%s/%s/%s %s’ %(months[month], day, year, end_time)
    tt_to = time.strptime(date_to, ‘%m/%d/%Y %H:%M’)
    tt_frm = time.strptime(date_frm, ‘%m/%d/%Y %H:%M’)
    secs_frm = time.mktime(tt_frm)
    secs_to = time.mktime(tt_to)
    dur = (secs_to – secs_frm) / 60
    clean.append([user,type,secs_frm,secs_to,dur]) # in case you want to save it.
    f.write(user+’,’+type+’,’+time.ctime(secs_frm)+’,’+time.ctime(secs_to)+’,’+str(dur)+’\n’)
    f.close()
    return clean

    try:
    print get_user_logons(4)
    except Exception, error:
    print error

  2. on 02 Jan 2013 at 12:24 pmBen

    I have used this script for several months to track usage on a couple of Macs. However, now that it is a new year I am getting some errors. I am a complete newbie to scripting. The error I’m getting is “the variable the_list” is not defined.” number -2753 from “the_list”. I don’t get errors when the list doesn’t contain Jan on some computer, only when the computers do.

    I believe a minor tweak needs to occur in the “year check” section and you need to define “the_list or change it to something else. I’ve tried several things, but i’m a complete newbie and I”m out of ideas. I’ve pasted the code below so you can see the section i’m talking about.

    Any help would be fabulous.

    –if the list contains January see if the selected month comes before or after January. Adjust the year accordingly.
    on yearCheck(selected_month, the_months)
    if the_months contains “Jan” then
    repeat with x from 1 to count of the_months
    if item x of the_list contains selected_month then
    set the_num to x
    else
    if item x of the_list contains “Jan” then
    set jan_num to x
    end if
    end if
    end repeat
    set year_check to (the_num – jan_num)
    if year_check is greater than 0 then
    set the_year to ((year of (current date)) – 1)
    else
    set the_year to (year of (current date))
    end if
    else