6

I need a list of the periods of times I used my MacBook throughout the last 30 days.

It would be sufficient to have a list of all lid-open and lid-close datetimes (because I close the lid whenever I don't use the MacBook). A chronological list of all sleep / wakeup / poweroff / poweron (and maybe login) datetimes would help as well.

What didn't help:

  • Googling
  • The last command
  • Filtering /var/log/system.log (which btw only contains one day)
  • Filtering the console app (but maybe there's a way...)
1
  • system.log gets rotated every so often and you can see the previous logs if you look in console for system.log.0.gz, system.log.1.gz etc. I don't know if even these will go back 30 days however.
    – Fyrefly
    Oct 29, 2014 at 21:09

4 Answers 4

10

If it is sufficient to have a list of all sleep/wake cycles (lid-open, lid-close), you can run:

pmset -g log | grep ' Wake '

or

pmset -g log | grep ' sleep '

Play around with the string passed to grep to get the information that you need.

3
  • Wow, thanks for this fast answer. This looks promising! Any chance to output more than 14 days using pmset? (I need at least 30 days)
    – Joshua
    Sep 30, 2014 at 19:39
  • 3
    This didn't work for me on OSX. It gave me incorrect date times. But this worked like a charm: pmset -g log | grep 'Display is turned on'. May 6, 2015 at 7:20
  • Nice! You can get a better timeline if you use just one command: pmset -g log | grep -E 'Wake from|Entering Sleep'
    – hdiogenes
    Dec 12, 2019 at 1:11
1

I looked at this a bit and it seems doable, but you'll need to look at your behaviour with the system over time to determine exactly what messages in the logs to grep. I did the following set of steps to analyze the full history of sleep/wake cycles for this MacBook and it goes back all the way to Aug 12.

Preconditions: Writing to non-root user into ~/Downloads. Change paths and output filenames as desired.


#!/bin/bash
#
# Read system wake/sleep cycles from kernel logs from oldest to newest.
#
# First, read the archived kernel logs for wakes.
for file in $(ls -r /var/log/kernel.log.*) ; do   bunzip2 -c $file | grep 'Wake reason:' >> ~/Downloads/wakeup.txt; done
#
# Read current kernel.log for wakes.
grep 'Wake reason:' /var/log/kernel.log >> ~/Downloads/wakeup.txt
#
# Read archived kernel logs for sleeps.
for file in $(ls -r /var/log/kernel.log.*) ; do   bunzip2 -c $file | grep ': sleep' >> ~/Downloads/wakeup.txt; done
#
# Read current kernel.log for sleeps.
grep ': sleep' /var/log/kernel.log >> ~/Downloads/wakeup.txt
#
# Sort raw output from greps for chronological picture.
sort -o ~/Downloads/sortedwake.txt ~/Downloads/wakeup.txt

That should give you a decent jump on arriving at a more complete picture. You can examine the kernel logs to let you know when the system was rebooted, etc. Once you know what to filter on, you'll be able to expand on this quite a bit. Have fun with it.

Oh, one final note: If you're examining a system that visits many networks, you'll see your system name changing in the logs according to what the DNS server associates with your IP address. It looks a little odd, but it's quite normal behaviour.

3
  • Thanks for your detailed answer! I played a little bit with your script and had to modify the following things - files are named system.log instead of kernel.log on my MacBook - instead of bunzip2 I need to use gunzip - remove old files at the beginning rm ~/Downloads/wakeup.txt rm ~/Downloads/sortedwake.txt Then your script works well BUT it unfortunately contains only 9 days of history (the oldest log file is system.log.9.gz). Are there any older hidden backups anywhere?
    – Joshua
    Oct 28, 2014 at 17:16
  • All right, from reading apple.stackexchange.com/questions/77373/… I found out that the system.log files will be rotated automatically and pruned after some days. I will try to change /etc/newsyslog.conf as follows: /var/log/system.log 640 40 * @T00 J This will in future hopefully preserve my system.log files for 40 days. (Sorry for the ugly formatting, mini-Markdown is broken at the moment)
    – Joshua
    Oct 28, 2014 at 17:41
  • @Joshua, good luck with it. Oct 29, 2014 at 6:40
1

I finally wrapped it up in a oneliner which extracts system sleep and wake events from several log files:

(pmset -g log|grep -e " Sleep " -e " Wake "; syslog | grep -e "System Sleep" -e " Wake reason:") | more

If your system already uses log instead of syslog use the following command instead:

(pmset -g log|grep -e " Sleep " -e " Wake "; log show | grep -e "System Sleep" -e " Wake reason:") | more

  • Hint 1: pmset is limited to 14 days
  • Hint 2: The syslog command automatically searches archived system.log entries as well. By default there are 10 daily system.log backups. To save 30 days of system.log backups for future reference add the following line to /var/log/newsystemlog.conf: (still evaluating how well this works)


    /var/log/system.log                     640  30     *    @T00  J
    

@trane-francks @aglasser Thanks for your contributions! They helped to track the problem down.

0

I made myself a shell script that lists the Boot, Shutdown, Sleep and Wake events, in chronological order since the last full battery charge. I'm sharing this now to see if it's useful for someone else.

(change the variable last_timestamp to any datetime so that the script calculates from there, for example last_timestamp="2023-05-31 12:00:00").

As a bonus, the script calculates the real uptime, how long the machine was actually awake and how long it can last with the battery.

An example output:

2023-06-24 22:07:09 Full Charge
2023-06-24 22:07:09 Wake
2023-06-25 00:01:37 Sleep
------------------- 6868 sec
2023-06-25 00:08:01 Wake
2023-06-25 01:54:56 Shutdown
------------------- 13283 sec
2023-06-25 17:30:56 Boot
2023-06-25 19:10:16 Sleep
------------------- 19243 sec
2023-06-25 22:15:39 Wake
2023-06-26 00:20:56 Now
------------------- 26760 sec
Real uptime: 7.43 hours
Battery level: 47 %
Remaining time on battery: 6.58 hours
Estimated total time on battery: 14.01 hours

Usage:

  1. Save to realuptime.sh
  2. chmod +x realuptime.sh
  3. ./realuptime.sh

Tested on macOS Ventura 13.4

#!/bin/bash

# Find the first log entry that logs the most recent full charge
fullcharge_date=$(pmset -g log | grep -e "Using BATT (Charge:100%)" -e "Charge: 100" | tail -n 1 | cut -d ' ' -f1)
fullcharge_earliest_datetime=$(pmset -g log | grep -e "Using BATT (Charge:100%)" -e "Charge: 100" | grep $fullcharge_date | head -n 1 | cut -d ' ' -f1,2)
echo "$fullcharge_earliest_datetime Full Charge"

# Timestamp from which we monitor the Boot, Sleep, Wake and Shutdown events
last_timestamp=$(date -j -f "%Y-%m-%d %H:%M:%S" "$fullcharge_earliest_datetime" "+%s")

(         # Start a subshell
IFS=$'\n' # Set the Internal Field Separator temporarily

# The "events" variable is an array, where we collect every Boot, Sleep, Wake and Shutdown events in "Y-m-d H:M:S Eventname" format.

# sleep and wake events excluding DarkWakes
events=( $(pmset -g log | grep -e "Entering Sleep state" -e "Wake from" | grep -v -e "DarkWake" -e "Sleep Service Back to Sleep" -e "Maintenance Sleep" | cut -d' ' -f1,2,4 | awk -v start="$fullcharge_earliest_datetime" '$0 >= start') )

# shutdown events
events+=( $(last | grep -e "shutdown" | awk '{print $4" "$5" "$6}' | LC_TIME=C xargs -I {} date -j -f "%b %d %H:%M" {} "+%Y-%m-%d %H:%M:%S Shutdown" | awk -v start="$fullcharge_earliest_datetime" '$0 >= start') )

sleep 1 # wait 1 sec after querying the boot events to get bigger second counters for correct order

# boot events
events+=( $(last | grep -e "reboot" | awk '{print $4" "$5" "$6}' | LC_TIME=C xargs -I {} date -j -f "%b %d %H:%M" {} "+%Y-%m-%d %H:%M:%S Boot" | awk -v start="$fullcharge_earliest_datetime" '$0 >= start') )

# current time
events+=(  $(date +"%Y-%m-%d %H:%M:%S Now") )

# Sort in ascending order
sorted_events=($(printf '%s\n' "${events[@]}"|sort))

# Here we collect the number of seconds when the computer is awake
sum=0

# Loop through events array
for line in "${sorted_events[@]}"
do
    echo $line

    date=$(echo $line | cut -d' ' -f1,2)
    timestamp=$(date -j -f "%Y-%m-%d %H:%M:%S" "$date" "+%s")

    # If this is a Boot or Wake event, we note its time (timestamp)
    if [[ $line == *"Boot"* || $line == *"Wake"* ]]
    then
        last_timestamp=$timestamp
    fi

    # If it is a Shutdown or Sleep event when wakefulness ends, 
    # then we calculate the seconds that have passed since the previous recorded time.
    # We also add the time that has passed until the current moment.
    if [[ $last_timestamp -ne 0 && ($line == *"Sleep"* || $line == *"Shutdown"* || $line == *"Now"*) ]]
    then
        count=$(expr $timestamp - $last_timestamp)
        sum=$(expr $sum + $count)
        last_timestamp=0
        echo -e "------------------- $count sec \t(Total: $sum sec)"
    fi
done

hours=$(echo "scale=2; $sum / 3600" | bc -l)
echo "Real uptime: $hours hours"

batterylevel=$(pmset -g batt | grep -Eo "\d+%" | cut -d% -f1)
onepercent_time=$(echo "$hours / (100 - $batterylevel + 0.0001)" | bc -l)
remaining_time=$(echo "scale=2; ($onepercent_time * $batterylevel)/1" | bc -l)
full_time=$(echo "scale=2; ($onepercent_time * 100)/1" | bc -l)

echo "Battery level $batterylevel %"
echo "Remaining time on battery: $remaining_time hours"
echo "Estimated total time on battery: $full_time hours"
)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .