I Am Joe’s Blog:

August 7, 2007 • 2:14 PM

Safe Sleep addendum

My article in last week’s issue of TidBITS, Stewing Over Safe Sleep, generated an awful lot of feedback. Most of it was of the “Yeah, that was really stupid of Apple” or “Thanks; now I know how to solve an annoying problem” varieties. Some of it was along the lines of “How could anyone not love safe sleep?” or “I’m not seeing 49-second delays on MY machine” or “It probably doesn’t really matter if you move your computer while the RAM is being cached to disk” or the simple and elegant “You’re an idiot.” Well, thanks one and all for sharing your thoughts, constructive and otherwise.

Two particular threads of discussion, though, are worth a more detailed look.

Hibernating Only When Necessary First, Greg Nicholson sent me a clever script he wrote (to replace the one I showed in TidBITS) that’s significantly smarter. Greg pointed out that there are certain situations, such as a long flight to China, in which one might be much more likely to want the default Safe Sleep behavior. So his script, which he runs every 10 minutes with cron, checks the battery life. If it’s over 50%, it turns off hibernatemode (as my script does). But if the charge is less than 30%, it turns hibernatemode back on. Very spiffy, and I wish Apple would have built something like this right into Mac OS X. You can, of course, tweak the percentages and so on to your liking. Here’s (my slightly modified version of) Greg’s script:

#!/bin/sh
MODE=`/usr/bin/pmset -g | grep hibernatemode | awk '{ print $2 }'`
LEFT=`/usr/bin/pmset -g batt | grep Internal | awk '{ print $2 }' | awk -F % '{ print $1 }'`

if [ $LEFT -lt 30 ] && [ $MODE != 3 ] ; then
  {
     echo "Less than 30% remains" >> /var/log/system.log
     echo "setting Hibernate mode 3" >> /var/log/system.log
     `/usr/bin/pmset -a hibernatemode 3`
  }
elif  [ $LEFT -gt 50 ] && [ $MODE != 0 ]; then
  {
     echo "Greater than 50% remains" >> /var/log/system.log
     echo "Setting Hibernate mode 0" >> /var/log/system.log
     `/usr/bin/pmset -a hibernatemode 0`
     `rm /var/vm/sleepimage`
  }
fi

Greg noted that since the script requires root privileges, you need to add the following to your sudoers file:

ALL ALL=(ALL) NOPASSWD: /usr/bin/pmset -a hibernatemode 3
ALL ALL=(ALL) NOPASSWD: /usr/bin/pmset -a hibernatemode 0

An easier way to achieve that effect would be to put the cron job in your system crontab, if you feel comfortable doing that.

Dealing with an Unencrypted “sleepimage” file Correction (08-Aug-2007): I see I munged some of my facts here earlier, so I’ve rewritten this paragraph to reflect what I currently believe to be the truth.

Second, the issue of encryption came up. It turns out that using hibernatemode values of 5 or 7 (the prescribed values for those using Secure Virtual Memory) don’t actually result in your sleepimage file being encrypted—in fact, it’s just the opposite. If you have Secure VM turned on and use 5 or 7, your encrypted RAM is apparently decrypted while being written to the sleepimage file. So if you’re using Secure VM and want your sleepimage file, too, to be encrypted (which you should), stick with values of 1 or 3 (3 being the default).

Now, in the real world, this fact probably makes little practical difference for most people, most of the time. Even if you don’t encrypt your VM, it’s not a given that any particular password (or other sensitive data) will actually be in RAM when it comes time for your computer to sleep—it might be, or it might not, depending on a long list of details about how particular programs do things, how recently you logged in, what applications you have running, and so on. And also, the risk is certainly greater for power users who enter an administrative password multiple times per hour than people for whom that is a rare occurrence. Even then, the contents of your RAM is cached to that unencrypted disk image only when your computer goes to sleep and only when the hibernatemode setting is at its default (3) or “always hibernate” (1). And even then, the fact that potentially sensitive stuff is sitting on your hard disk in a readily readable format only causes problems if someone gets access to your computer and knows how to find this data. So, like I say, not a problem for most people, most of the time.

If you’re concerned about this, though, DO follow my advice to turn of Safe Sleep. But go a step further. Instead of using

sudo rm /var/vm/sleepimage

to delete the RAM cache, use the secure version of rm, srm, and use the -m flag for a 7x overwrite rather than the default 35x overwrite:

sudo srm -m /var/vm/sleepimage

The command will take a long time to run, but the disk image holding your RAM contents will be safely overwritten. Note that you only have to do this the first time. If you’ve set up a script (as discussed previously) to check regularly to see that hibernatemode hasn’t turned itself back on, having a simple rm in that script will do the trick. The reason? When hibernatemode turns back on, Mac OS X recreates the sleepimage file immediately. But initially, it’s blank. It doesn’t fill up with the contents of your RAM until your machine tries to go to sleep. If your script runs and deletes the (blank) image before then, nothing incriminating will have been in that file.

I truly hope this all gets sorted out in Leopard.

Comments

  1. Stephen Weil
    August 21st, 2007 | 6:37 pm

    So, I felt comfortable enough with my rudimentary terminal skills to implement the script to turn off safe sleep. And I’ve been loving how quickly my MacBook Pro 2.33 Core2Duo goes to sleep and awakens. But I now see that there’s some benefit to having the option to automate this process for the ultimate in control and comfort.

    Only problem is, you lost me after the writing of Greg’s script. Other than creating the script and giving it a name, there’s no way that I feel comfortable implementing the remainder of the instructions and knowing that I got them right. Any chance someone woulds like to walk this novice through the process?

  2. Stephen Weil
    August 21st, 2007 | 8:37 pm

    So, I felt comfortable enough with my rudimentary terminal skills to implement the script to turn off safe sleep. And I’ve been loving how quickly my MacBook Pro 2.33 Core2Duo goes to sleep and awakens. But I now see that there’s some benefit to having the option to automate this process for the ultimate in control and comfort.

    Only problem is, you lost me after the writing of Greg’s script. Other than creating the script and giving it a name, there’s no way that I feel comfortable implementing the remainder of the instructions and knowing that I got them right. Any chance someone woulds like to walk this novice through the process?

  3. August 21st, 2007 | 6:45 pm

    Stephen:

    I followed up this follow-up in yet another TidBITS article: http://db.tidbits.com/article/9115. Take a look and see if that answers your question; if not, drop me a note.

  4. August 21st, 2007 | 8:45 pm

    Stephen:

    I followed up this follow-up in yet another TidBITS article: http://db.tidbits.com/article/9115. Take a look and see if that answers your question; if not, drop me a note.

  5. Stephen Weil
    August 21st, 2007 | 8:38 pm

    Joe:

    That’s the article that actually brought me to your blog for what I hoped would be a more complete description of how to implement the script. Any help explaining how to set it up in terminal (even something as simple as making my way around the directory structure) would be greately appreciated.

    Stephen

  6. Stephen Weil
    August 21st, 2007 | 10:38 pm

    Joe:

    That’s the article that actually brought me to your blog for what I hoped would be a more complete description of how to implement the script. Any help explaining how to set it up in terminal (even something as simple as making my way around the directory structure) would be greately appreciated.

    Stephen

  7. August 21st, 2007 | 10:59 pm

    Stephen:

    I mean no disrespect, but if your knowledge of the command line is that limited, you need more assistance than I have the time to provide. So sorry!

    Joe

  8. August 22nd, 2007 | 12:59 am

    Stephen:

    I mean no disrespect, but if your knowledge of the command line is that limited, you need more assistance than I have the time to provide. So sorry!

    Joe

  9. Stephen Weil
    August 22nd, 2007 | 5:25 am

    No problem. I’m going to bookmark Greg’s script and study up. At some point in the future I’ll come far enough that I’ll be able to get it up and running.

  10. Stephen Weil
    August 22nd, 2007 | 3:25 am

    No problem. I’m going to bookmark Greg’s script and study up. At some point in the future I’ll come far enough that I’ll be able to get it up and running.

  11. September 3rd, 2007 | 8:55 pm

    I enjoyed the article, and have followed the TidBITS Talk discussion. I was glad to see your mention of summarizing and correcting the important points in your blog. So, here I am at the blog, and the only two comments posted so far each ask for more information on implementing your proposed script. There were two similar requests in the TidBITS Talk thread, and two or three answers given.

    I recognize that you can’t provide a Terminal tutorial here, but I think it would make this blog entry vastly more useful to many more people, if you added a little more information. Adding the implementation instructions that have already appeared in TibBITS Talk would make your blog entry a complete resource for most readers interested in this subject.

    Please consider revising your blog entry once more, to include information on implementing the script via the system chrontab, and perhaps via Greg’s approach, and other variations already detailed in TidBITS Talk. Make this blog entry a complete resource for understanding and responding to the issues that your TidBITS article raised.

    Thanks,

    Derek Rof

  12. September 3rd, 2007 | 10:55 pm

    I enjoyed the article, and have followed the TidBITS Talk discussion. I was glad to see your mention of summarizing and correcting the important points in your blog. So, here I am at the blog, and the only two comments posted so far each ask for more information on implementing your proposed script. There were two similar requests in the TidBITS Talk thread, and two or three answers given.

    I recognize that you can’t provide a Terminal tutorial here, but I think it would make this blog entry vastly more useful to many more people, if you added a little more information. Adding the implementation instructions that have already appeared in TibBITS Talk would make your blog entry a complete resource for most readers interested in this subject.

    Please consider revising your blog entry once more, to include information on implementing the script via the system chrontab, and perhaps via Greg’s approach, and other variations already detailed in TidBITS Talk. Make this blog entry a complete resource for understanding and responding to the issues that your TidBITS article raised.

    Thanks,

    Derek Rof

  13. September 3rd, 2007 | 9:09 pm

    Derek (and others): Have you read my second TidBITS article on this topic? That article, rather than this blog post, was intended to be the last word on this subject, and it goes into more detail than I can here.

    I wish I had the time to spell out every step of the process for getting this working in Terminal, but I’m afraid I don’t. Luckily, though, there are lots of resources out there on the Web already that do a fine job of explaining things like scheduling cron jobs, and I’m sure a few Google searches will provide the necessary info.

    But I do want to emphasize that all of this is really only intended for computer geeks, not ordinary, nontechnical folk. This really is highly technical stuff, and I can’t recommend it for people who aren’t already familiar with Unix. That was really the point of my first article: not how to do this, but a lament that this is the only way it can be done, and thus available only to propellerheads!

  14. September 3rd, 2007 | 11:09 pm

    Derek (and others): Have you read my second TidBITS article on this topic? That article, rather than this blog post, was intended to be the last word on this subject, and it goes into more detail than I can here.

    I wish I had the time to spell out every step of the process for getting this working in Terminal, but I’m afraid I don’t. Luckily, though, there are lots of resources out there on the Web already that do a fine job of explaining things like scheduling cron jobs, and I’m sure a few Google searches will provide the necessary info.

    But I do want to emphasize that all of this is really only intended for computer geeks, not ordinary, nontechnical folk. This really is highly technical stuff, and I can’t recommend it for people who aren’t already familiar with Unix. That was really the point of my first article: not how to do this, but a lament that this is the only way it can be done, and thus available only to propellerheads!

  15. John McKeown
    October 4th, 2007 | 8:53 am

    My macbook swutched from safesleep to ‘sleep’ always shutting down, and when powered on then restoring memory. I set hibernatemode=0 and now it sleeps and wakes fast, but still takes 30 seconds to go into sleep. Weird?

  16. John McKeown
    October 4th, 2007 | 10:53 am

    My macbook swutched from safesleep to ‘sleep’ always shutting down, and when powered on then restoring memory. I set hibernatemode=0 and now it sleeps and wakes fast, but still takes 30 seconds to go into sleep. Weird?

  17. October 4th, 2007 | 11:30 am

    John: That is weird, and offhand I have no explanation. Did you also delete the sleepimage file?

  18. October 4th, 2007 | 1:30 pm

    John: That is weird, and offhand I have no explanation. Did you also delete the sleepimage file?

  19. October 21st, 2007 | 9:11 am

    Stephen,

    Here is an Apple article on scripting that may be of help:

    http://developer.apple.com/internet/opensource/opensourcescripting.html

    Doug

  20. October 21st, 2007 | 11:11 am

    Stephen,

    Here is an Apple article on scripting that may be of help:

    http://developer.apple.com/internet/opensource/opensourcescripting.html

    Doug

  21. Michael
    October 25th, 2007 | 5:35 pm

    Thanks! This is great. I’ve produced a launchd plist which will run the script every 10 minutes. Put the (root executable) script in /usr/local/sbin/hibcontrol and the following in /Library/LaunchDaemons/localhost.hibcontrol.plist and do

    sudo launchctl load /Library/LaunchDaemons/localhost.hibcontrol.plist

    no need for cron file.

    Michael

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>localhost.hibcontrol</string>
        <key>LowPriorityIO</key >
        <true/>
        <key>Nice</key>
        <integer>1</integer>
        <key>Program</key>
        <string>/usr/local/sbin/hibcontrol</string>
        <key>ServiceDescription</key>
        <string>Control the hibernate state based on battery level (http://db.tidbits.com/article/9115)</string>
        <key>StartInterval</key>
        <integer>600</integer>
    </dict>
    </plist>
    

  22. Michael
    October 25th, 2007 | 7:35 pm

    Thanks! This is great. I’ve produced a launchd plist which will run the script every 10 minutes. Put the (root executable) script in /usr/local/sbin/hibcontrol and the following in /Library/LaunchDaemons/localhost.hibcontrol.plist and do

    sudo launchctl load /Library/LaunchDaemons/localhost.hibcontrol.plist

    no need for cron file.

    Michael

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>localhost.hibcontrol</string>
        <key>LowPriorityIO</key >
        <true/>
        <key>Nice</key>
        <integer>1</integer>
        <key>Program</key>
        <string>/usr/local/sbin/hibcontrol</string>
        <key>ServiceDescription</key>
        <string>Control the hibernate state based on battery level (http://db.tidbits.com/article/9115)</string>
        <key>StartInterval</key>
        <integer>600</integer>
    </dict>
    </plist>
    

  23. March 12th, 2008 | 1:33 pm

    Thanks for the Script and the launchd plist file. I think the reason while Apple has not implement the feature that only at the end on the battery source the suspend to RAM will be enabled is the battery replacement.

    Thanks

  24. March 12th, 2008 | 3:33 pm

    Thanks for the Script and the launchd plist file. I think the reason while Apple has not implement the feature that only at the end on the battery source the suspend to RAM will be enabled is the battery replacement.

    Thanks

  25. October 31st, 2008 | 10:40 pm

    […] found in this website http://alt.cc/jk/2007/08/07/safe-sleep-addendum/ this nice script that handles when to FastSleep or when to […]

Leave a reply