Suspend to ram/standby/(disk): Here's my flexible, adjustable 'suspend2' script.
Linux - DesktopThis forum is for the discussion of all Linux Software used in a desktop context.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
When I enter the alias and the laptop is still open I can only press the "Fn" key to resume (no spacebar etc.) BUT if I close the screen, it will resume automatically when I open it again.
Quote:
However that said, there is also on some systems a "standby" state, which I think is somewhere between s2ram and s2disk, and which apparently doesn't work on your system if I'm reading between the lines correctly from your post.
I didn't know about that state, thanks for telling me. For me s2ram is all i need.
I picked 'standby' for the alias name because there already a 'suspend' command (I haven't tried it though).
BTW i am going through your script and seeing how it works out on my laptop. I congratulate you on the effort put into that script.
If you read my script, you can see that it reads /sys/power/state, and determines from that, what suspend methods are possible on your machine. You can do the same:
shell# cat /sys/power/state
and see if "standby" is an option for you (just FYI), and/or what other options may be there.
Also, another FYI: Maybe somewhere like /etc/acpi on your system, you will find a script called something like "acpi_handler.sh" or something like that (That's a Slackware-ish name perhaps-- I am not sure if it would have the same name on your system) and examine that script and any other files in the location with that file (maybe there's a folder called "events"), to learn what your machine is doing when it detects such ACPI events as the lid closing and opening, or when the power button is pressed. While there's more than one way to deal with such events, the ACPI handler script(s) are a common method.
Kind regards,
Sasha
Last edited by GrapefruiTgirl; 10-13-2009 at 02:01 AM..
Been busy with other stuff all day so just bouncing this back before bed ...
Quote:
Originally Posted by GrapefruiTgirl
if you have 4 Gib of RAM installed, I would use a 4096Kib swap space to suspend to.
You know a way to mark swap space for suspend as opposed to general swap?
Quote:
Originally Posted by GrapefruiTgirl
Here's some input about the console messages:
The above is normal; just an INFO type message about the running suspend process. You could comment it out if you don't like it.
No, that's cool but may be useful to identify messages as "information" or "error"?
Quote:
Originally Posted by GrapefruiTgirl
The above is because your kernel log file has a different name than mine, because I tend to rename/change all my log files to <something>.log rather than just <something> which was particularly relevant on my Slack11 system where I mostly developed the script. The log file names are defined in the script-- just change the name of yours to the default (probably just "kernel").
Regards this and other parts of your reply, it seems there are unavoidably some values used by suspend2 that are system specific. Would you be OK with me offering a script snippet to read a configuration file?
Quote:
Originally Posted by GrapefruiTgirl
Hmm.. The above, about the sensors/fans thing, I don't have a suggestion at this time, except to perhaps kill/re-execute the fancontrol program after resume.
I am going to venture a guess that since the fancontrol thing likely uses BIOS calls/info to read/write to the PWM system that controls fan speeds, then **possibly** a BIOS call would be required to either save the state of the fans, and/or restore them later. I don't think this can be done from bash, which is perhaps one of the reasons SuSE has created the s2ram binary in C, although to my recollection, there are no fan-control hacks in their s2ram tool; they have mainly video corruption prevention hacks. EDIT:I just realized after some time, that you said "script" when you referred to the fancontrol tool you use; therefore I think I'm wrong about the BIOS stuff, and perhaps instead your script uses the /sys interface and/or /proc file system to deal with the PWM control for the fans. If this is the case, do let me know; in fact, a link to the fan-control script would be great, so I can have a look at it.[/EDIT]
fancontrol writes to files in /sys/class/hwmon or /sys/bus/i2c/devices. It traps SIGQUIT and SIGTERM, resetting the fans to full speed on receiving them Sane and safe. Re-starting the script on resume (ideally only if it was running when the system was suspended) would be a perfect solution. Don't have a link to the fancontrol script so here it is FYI (in slightly modified form so as not to generate trivial messages at boot time):
Code:
#!/bin/bash
#
# Simple script implementing a temperature dependent fan speed control
# Supported Linux kernel versions: 2.6.5 and later
#
# Version 0.68
#
# 7oct9 Charles. Redirected all abnormal messages to stderr.
#
# Usage: fancontrol [CONFIGFILE]
#
# Dependencies:
# bash, egrep, sed, cut, sleep, lm_sensors :)
#
# Please send any questions, comments or success stories to
# marius.reiner@hdev.de
# Thanks!
#
# For configuration instructions and warnings please see fancontrol.txt, which
# can be found in the doc/ directory or at the website mentioned above.
#
#
# Copyright 2003 Marius Reiner <marius.reiner@hdev.de>
# Copyright (C) 2007-2009 Jean Delvare <khali@linux-fr.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
#
#
PIDFILE="/var/run/fancontrol.pid"
#DEBUG=1
MAX=255
declare -i pwmval
function LoadConfig {
echo "Loading configuration from $1 ..."
if [ ! -r "$1" ]
then
echo "Error: Can't read configuration file" >&2
exit 1
fi
# grep configuration from file
INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'`
FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'`
MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'`
MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'`
MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'`
MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'`
# optional settings:
FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'`
MINPWM=`egrep '^MINPWM=.*$' $1 | sed -e 's/MINPWM=//g'`
MAXPWM=`egrep '^MAXPWM=.*$' $1 | sed -e 's/MAXPWM=//g'`
# Check whether all mandatory settings are set
if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]]
then
echo "Some mandatory settings missing, please check your config file!" >&2
exit 1
fi
if [ "$INTERVAL" -le 0 ]
then
echo "Error in configuration file:" >&2
echo "INTERVAL must be at least 1" >&2
exit 1
fi
# write settings to arrays for easier use and print them
echo
echo "Common settings:"
echo " INTERVAL=$INTERVAL"
let fcvcount=0
for fcv in $FCTEMPS
do
if ! echo $fcv | egrep -q '='
then
echo "Error in configuration file:" >&2
echo "FCTEMPS value is improperly formatted" >&2
exit 1
fi
AFCPWM[$fcvcount]=`echo $fcv |cut -d'=' -f1`
AFCTEMP[$fcvcount]=`echo $fcv |cut -d'=' -f2`
AFCFAN[$fcvcount]=`echo $FCFANS |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`
AFCMINTEMP[$fcvcount]=`echo $MINTEMP |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`
AFCMAXTEMP[$fcvcount]=`echo $MAXTEMP |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`
AFCMINSTART[$fcvcount]=`echo $MINSTART |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`
AFCMINSTOP[$fcvcount]=`echo $MINSTOP |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`
AFCMINPWM[$fcvcount]=`echo $MINPWM |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`
[ -z "${AFCMINPWM[$fcvcount]}" ] && AFCMINPWM[$fcvcount]=0
AFCMAXPWM[$fcvcount]=`echo $MAXPWM |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`
[ -z "${AFCMAXPWM[$fcvcount]}" ] && AFCMAXPWM[$fcvcount]=255
# verify the validity of the settings
if [ "${AFCMINTEMP[$fcvcount]}" -ge "${AFCMAXTEMP[$fcvcount]}" ]
then
echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2
echo "MINTEMP must be less than MAXTEMP" >&2
exit 1
fi
if [ "${AFCMAXPWM[$fcvcount]}" -gt 255 ]
then
echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2
echo "MAXPWM must be at most 255" >&2
exit 1
fi
if [ "${AFCMINSTOP[$fcvcount]}" -ge "${AFCMAXPWM[$fcvcount]}" ]
then
echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2
echo "MINSTOP must be less than MAXPWM" >&2
exit 1
fi
if [ "${AFCMINSTOP[$fcvcount]}" -lt "${AFCMINPWM[$fcvcount]}" ]
then
echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2
echo "MINSTOP must be greater than or equal to MINPWM" >&2
exit 1
fi
if [ "${AFCMINPWM[$fcvcount]}" -lt 0 ]
then
echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2
echo "MINPWM must be at least 0" >&2
exit 1
fi
echo
echo "Settings for ${AFCPWM[$fcvcount]}:"
echo " Depends on ${AFCTEMP[$fcvcount]}"
echo " Controls ${AFCFAN[$fcvcount]}"
echo " MINTEMP=${AFCMINTEMP[$fcvcount]}"
echo " MAXTEMP=${AFCMAXTEMP[$fcvcount]}"
echo " MINSTART=${AFCMINSTART[$fcvcount]}"
echo " MINSTOP=${AFCMINSTOP[$fcvcount]}"
echo " MINPWM=${AFCMINPWM[$fcvcount]}"
echo " MAXPWM=${AFCMAXPWM[$fcvcount]}"
let fcvcount=fcvcount+1
done
echo
}
if [ -f "$1" ]
then
LoadConfig $1
else
LoadConfig /etc/fancontrol
fi
# Detect path to sensors
if echo "${AFCPWM[0]}" | egrep -q '^/'
then
DIR=/
elif echo "${AFCPWM[0]}" | egrep -q '^hwmon[0-9]'
then
DIR=/sys/class/hwmon
else
DIR=/sys/bus/i2c/devices
fi
if [ ! -d $DIR ]
then
echo $0: 'No sensors found! (did you load the necessary modules?)' >&2
exit 1
fi
cd $DIR
if [ -f "$PIDFILE" ]
then
echo "File $PIDFILE exists, is fancontrol already running?" >&2
exit 1
fi
echo $$ > "$PIDFILE"
# $1 = pwm file name
function pwmdisable()
{
ENABLE=${1}_enable
# No enable file? Just set to max
if [ ! -f $ENABLE ]
then
echo $MAX > $1
return 0
fi
# Try pwmN_enable=0
echo 0 > $ENABLE 2> /dev/null
if [ `cat $ENABLE` -eq 0 ]
then
# Success
return 0
fi
# It didn't work, try pwmN_enable=1 pwmN=255
echo 1 > $ENABLE 2> /dev/null
echo $MAX > $1
if [ `cat $ENABLE` -eq 1 -a `cat $1` -ge 190 ]
then
# Success
return 0
fi
# Nothing worked
echo "$ENABLE stuck to" `cat $ENABLE` >&2
return 1
}
# $1 = pwm file name
function pwmenable()
{
ENABLE=${1}_enable
if [ -f $ENABLE ]
then
echo 1 > $ENABLE 2> /dev/null
if [ $? -ne 0 ]
then
return 1
fi
fi
echo $MAX > $1
}
function restorefans()
{
local status=$1
echo 'Aborting, restoring fans...' >&2
let fcvcount=0
while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs
do
pwmo=${AFCPWM[$fcvcount]}
pwmdisable $pwmo
let fcvcount=$fcvcount+1
done
echo 'Verify fans have returned to full speed' >&2
rm -f "$PIDFILE"
exit $status
}
trap 'restorefans 0' SIGQUIT SIGTERM
trap 'restorefans 1' SIGHUP SIGINT
# main function
function UpdateFanSpeeds {
let fcvcount=0
while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs
do
#hopefully shorter vars will improve readability:
pwmo=${AFCPWM[$fcvcount]}
tsens=${AFCTEMP[$fcvcount]}
fan=${AFCFAN[$fcvcount]}
let mint="${AFCMINTEMP[$fcvcount]}*1000"
let maxt="${AFCMAXTEMP[$fcvcount]}*1000"
minsa=${AFCMINSTART[$fcvcount]}
minso=${AFCMINSTOP[$fcvcount]}
minpwm=${AFCMINPWM[$fcvcount]}
maxpwm=${AFCMAXPWM[$fcvcount]}
read tval < ${tsens}
if [ $? -ne 0 ]
then
echo "Error reading temperature from $DIR/$tsens" >&2
restorefans 1
fi
read pwmpval < ${pwmo}
if [ $? -ne 0 ]
then
echo "Error reading PWM value from $DIR/$pwmo" >&2
restorefans 1
fi
# If fanspeed-sensor output shall be used, do it
if [[ -n ${fan} ]]
then
read fanval < ${fan}
if [ $? -ne 0 ]
then
echo "Error reading Fan value from $DIR/$fan" >&2
restorefans 1
fi
else
fanval=1 # set it to a non zero value, so the rest of the script still works
fi
# debug info
if [ "$DEBUG" != "" ]
then
echo "pwmo=$pwmo"
echo "tsens=$tsens"
echo "fan=$fan"
echo "mint=$mint"
echo "maxt=$maxt"
echo "minsa=$minsa"
echo "minso=$minso"
echo "minpwm=$minpwm"
echo "maxpwm=$maxpwm"
echo "tval=$tval"
echo "pwmpval=$pwmpval"
echo "fanval=$fanval"
fi
if (( $tval <= $mint ))
then pwmval=$minpwm # below min temp, use defined min pwm
elif (( $tval >= $maxt ))
then pwmval=$maxpwm # over max temp, use defined max pwm
else
# calculate the new value from temperature and settings
pwmval="(${tval}-${mint})*(${maxpwm}-${minso})/(${maxt}-${mint})+${minso}"
if [ $pwmpval -eq 0 -o $fanval -eq 0 ]
then # if fan was stopped start it using a safe value
echo $minsa > $pwmo
# Sleep while still handling signals
sleep 1 &
wait $!
fi
fi
echo $pwmval > $pwmo # write new value to pwm output
if [ $? -ne 0 ]
then
echo "Error writing PWM value to $DIR/$pwmo" >&2
restorefans 1
fi
if [ "$DEBUG" != "" ]
then
echo "new pwmval=$pwmval"
fi
let fcvcount=$fcvcount+1
done
}
echo 'Enabling PWM on fans...'
let fcvcount=0
while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs
do
pwmo=${AFCPWM[$fcvcount]}
pwmenable $pwmo
if [ $? -ne 0 ]
then
echo "Error enabling PWM on $DIR/$pwmo" >&2
restorefans 1
fi
let fcvcount=$fcvcount+1
done
echo 'Starting automatic fan control...'
# main loop calling the main function at specified intervals
while true
do
UpdateFanSpeeds
# Sleep while still handling signals
sleep $INTERVAL &
wait $!
done
Quote:
Originally Posted by GrapefruiTgirl
And, if you find that killing/re-starting your fancontrol program before/after suspend+resume fixes the problem, then perhaps I should add a stub (supporting code) for where users can add such scripts to the suspend process, if other machines have the same problem with fancontrol or other things? Again, let me know.
Maybe make scripts to run on resume a configurable item?
You know a way to mark swap space for suspend as opposed to general swap?
(based on the 'swapon' manpage) Usually, swap spaces for swapping, are activated for the OS by grabbing those swap spaces that are configured in /etc/fstab file. This is done by "swapon -a" in an init script (in Slack, it's in rc.S). According to the manpage, this is pretty standard for most distros. The exception is if the "noauto" option is given with a swap space in fstab. Thus, your space you want to use for suspending, would be an fstab entry with the "noauto" option.
\Besides this, of course as you found, set the "resume=" option in your LILO or GRUB config.
Quote:
No, that's cool but may be useful to identify messages as "information" or "error"?
Good plan. I'll do that, as well as a sanity check for the log file(s) such as kernel.log to make sure they exist.
Quote:
Regards this and other parts of your reply, it seems there are unavoidably some values used by suspend2 that are system specific. Would you be OK with me offering a script snippet to read a configuration file?
Of course -- I'd be happy to examine and consider any offerings of code and improvements. I't would be the best for everyone if it is configurable for the widest possible variety of machines/OS's/situations.
Quote:
fancontrol... Re-starting the script on resume (ideally only if it was running when the system was suspended) would be a perfect solution....
Maybe make scripts to run on resume a configurable item?
Yes, again that would be something ideally placed into a configuration file. I'll add this into the list of pending upgrades, but as I'm not in a panic, I will wait to see if you have any ideas for implementing this. I've done a similar functionality with my firewall script, which used a large config file, so implementing the file itself and parsing the options is no trouble; but suggestions for particular items that should BE IN this config file, will be especially appreciated.
Thanks for your input!
Sasha
PS - Thank you for posting the fancontrol script -- I may look into using that myself, at least for testing it with the suspend script. But for general usage myself, I actually use the temperature-controlled BIOS features of my board, for controlling my fan(s) (It might only be the CPU fan that is BIOS controlled-- I'd hafta double check). I have them set to run at 25% of full-blast, until certain temperature checkpoint, at which point the fan speed starts to increase until the temp levels off or goes back down.
I might like to use the script for the other fans though, if the BIOS doesn't control those ones, as 3 of 4 fans I run are speed-controllable.
Last edited by GrapefruiTgirl; 10-13-2009 at 05:24 PM..
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.