Duncan posted on Wed, 09 Jan 2013 11:55:17 +0000 as excerpted:

>>> My suspend/hibernate solution is something I scripted myself,
>> 
>> I may be interested in that, if it's little trouble.
> 
> I'll followup with an explanation and attach it.

Keep in mind that I wrote this for me, then generalized it a bit, set
it up to use a config file, etc.  However, I've only run it here so
I've not actually tested the generalization beyond my own two machines
(netbook and workstation), and in any case, it is still designed with
gentoo in mind, so assumes things like self-compiled kernels that have
the suspend-to partition already set (and no initrd), that gentoo's
openrc is the init system in use (in particular, it's NOT systemd
ready, tho that bit can be simply ignored, as it's an option that
doesn't have to be enabled), etc.

That said, as the script is much shorter than the general suspend
script many distros package (and that's available from
suspend.sourceforge.net ) and is reasonably well commented, it should
be a reasonable start, easier to modify than to start from scratch, for
someone looking to write their own script, or useful for those simply
wanting to have something to compare against the big long general
purpose script in the above package, and possibly use as a pattern for
their own, learning from both.

As I mentioned in the above post, the idea is to put the script itself 
somewhere on your main partition, where it'll be accessible regardless
of what optional partitions you might have mounted.  However, it does
NOT need to be in your path, altho the access/execute (and possibly
SUID/SGID if you intend to run it directly as non-root, owner root, of
course) permissions should be set as appropriate.  Then, create
symlinks to it called s2standby, s2ram, s2disk, s2both, as desired, and
stick THEM in your path.  

Up near the top of the script, set the suspend.conf path to point to 
wherever you put that.  I'll attach my suspend.conf as well, but while 
it's commented, it's NOT generalized.  You'll need to change many of
the suspend.conf settings to something appropriate for your system.

If you set SUSP_VT to anything other than 0 (thus enabling that
feature), there are two arguably semi-exotic executables that the
script calls, fgconsole and chvt, at least here on gentoo, both part of
the kbd package.  The clear executable, from ncurses, is also used, but
ncurses is a pretty basic package so likely installed.  If these aren't 
available, you may need to install their package, or simply disable
(set to 0) that feature.  The in-script default is 0/disabled, but it
may be set in the config file.

The script also uses the "logger" executable, but that's part of the 
standard util-linux package, so chances are you have it installed.

Other than that, bash (the script specifically uses bashisms like [[ ]] 
tests, so a non-bash shell will likely have trouble with it, but it 
shebangs /bin/bash so...), and the swapon and swapoff commands (util-
linux), are used, but these are pretty standard so unlikely to be an 
issue.

One other possibly unusual bit to note:  The config file is actually 
simply sourced into the main script, so standard shell features may be 
used for a "dynamic" config.  As you'll not reading it, I've taken 
advantage of that here, to be able to use the same config file for both 
my (HOSTTYPE=x86_64) workstation, and my (32-bit-only-atom-based 
HOSTTYPE=i686) netbook, with slightly different settings for each and 
detection using the bash HOSTTYPE variable.  If you wanted, you could
do similar, keying if you wish on some other var, as long as it's set
in the environment that the script and thus the config file inherit.

Other than that, the script is pretty much just bash logic, with output 
to the appropriate /sys/power/* files to tell the kernel what to
suspend to, the size of the suspend image if it's written to disk, and
to trigger the actual suspend when it's time.  The /sys/power/* files
are all documented in the the various files in the kernel's
Documentation/power/ subdir, if you'd like to read them for yourself.
That's what I did, first writing a tiny script, that gradually grew,
but it's still way shorter and easier to hack on than the huge suspend
script at the link above, especially since I already had a working
script and basic understanding of how it worked, before I even looked
at the above (tho I did take a couple hints from it once I did look at
it, I think that's where I got the idea for the vt switch and
suspend/resume hooks, for instance).

OK, now to do the attachment dance and send...

-- 
Duncan - List replies preferred.   No HTML msgs.
"Every nonfree program has a lord, a master --
and if you use the program, he is your master."  Richard Stallman
# suspend.conf
# shell-script fragment so feel free to use shell syntax...

################################################################################
# general suspend settings

# number of VT to use for suspend script messages, 0 to disable switching
SUSP_VT=11

# Type of suspend/hibernate (of three: standby, ram, disk).
# See /sys/power/state and $KERNELDOC/power/states.txt. If set here this will
# overrule the default type which is based on how the script was called.
# SUSP_MASTER_TYPE=disk

################################################################################
# hibernate (suspend to disk) settings

# type of disk hibernate (platform test testproc shutdown reboot, 
/sys/power/disk)
# If set here this will overrule the default type which is based
# on how the script was called.
# SUSP_DISK_TYPE=shutdown

# hibernate/resume partition, leave unset to use the kernel default
# this only tells the script for swap management, etc
# the resume kernel still uses what's on its command line.
SUSP_DISK_PART=/dev/sda3
[[ $HOSTTYPE = i686 ]] && SUSP_DISK_PART=/dev/sda4

# size of hibernate image (500 MB default, /sys/power/image_size)
# see /proc/swaps for max size (also in KB)
# if SUSP_DISK_PART is set, you may set this 0 to use the max from /proc/swaps,
# but note that swsusp can only use <= half of physical memory, due to how it 
works
SUSP_DISK_SIZE_KB=0

################################################################################
# service suspend settings

# init_dir location
SUSP_INITDIR="/etc/init.d"

# services to suspend and restart (only if running at suspend time)
# ordered, space separated list, name only
# append "_nd" if to be stopped without stopping dependencies
# _nd is recommended, as stopped dependencies won't restart!
# (Add them specifically instead, if necessary.)
# default/example: SUSP_SERVICES="hwclock_nd"
SUSP_SERVICES="hwclock_nd ntp-client_nd ntpd_nd"

################################################################################
# RUN_AT_SUSPEND/RUN_AT_RESUME executables
# RUN_AT_SUSPEND[x] are run before service suspension,
# RUN_AT_RESUME[x] after service resume.
# The script checks for null entries but won't work as
# expected with skipped entries (1,3,8) and ignores [0].

#RUN_AT_SUSPEND[1]=
#RUN_AT_SUSPEND[2]=

#RUN_AT_RESUME[1]=
[[ $HOSTTYPE = i686 ]] && RUN_AT_RESUME[1]='laptop_mode auto'
#!/bin/bash

################################################################################
# Author John Duncan, 2013.0109 version, based on the kernel docs,
# with hints from the suspend script found at suspend.sourceforge.net
#
# Calls chvt and fgconsole, from the kbd package, clear, from ncurses,
# and swapon, swapoff, and logger, from util-linux.
# SUSP_SERVICES are designed for openrc, but should work without too
# much modification with any sysv-init style init, with runnable service
# scripts in /etc/init.d/
#
# Note that to look right on wakeup, echoes to the VT
# before the suspend need the -e switch and a terminating \r added

# setup our default values. these can be overridden in the conf file
# (exept for the conf file location itself, naturally)

#SUSPEND_CONF="/usr/local/etc/suspend.conf"
SUSPEND_CONF="/l/etc/suspend.conf"

SUSP_INITDIR="/etc/init.d"
SUSP_VT=0 # 0=disabled

calledas="${0##*/}"

# SUSP_MASTER_TYPE default should be based on what we were called as
case $calledas in
        s2both)         SUSP_MASTER_TYPE=disk ;;
        s2disk)         SUSP_MASTER_TYPE=disk ;;
        s2ram)          SUSP_MASTER_TYPE=mem ;;
        s2standby)      SUSP_MASTER_TYPE=standby ;;
        *)              logger "suspend: Called incorrectly as $calledas. 
Exiting."; exit 1;;
esac
grep -q "$SUSP_MASTER_TYPE" /sys/power/state || {
        logger "Suspend type $SUSP_MASTER_TYPE not registered in 
/sys/power/state. Exiting."
        exit 2
}

# Default to shutdown for suspend to disk...
SUSP_DISK_TYPE=shutdown
# ... but be suspend to both aware, too.
[[ $calledas = s2both ]] && SUSP_DISK_TYPE=suspend

#SUSP_DISK_PART= # keep unset to use kernel default; this lets us manage the 
swap end,
#                # but the kernel uses its command line or kconfig setting.
SUSP_DISK_SIZE_KB=$((500*1024)) # kernel default 500*1024, set 0 to use full 
partition size. \
                                # NOTE, swsusp only used <= 1/2 physical memory 
due to how it works!

# SUSP_SERVICES don't suspend/resume unless SUSP_MASTER_TYPE=disk

SUSP_SERVICES="hwclock_nd" # _nd appended for no-deps

# RUN_AT_* commands always run.
#RUN_AT_SUSPEND[1]='echo susp1'
#RUN_AT_SUSPEND[2]='echo susp2'
#RUN_AT_RESUME[1]='echo resu1'

# source suspend.conf if it exists
[[ -e  $SUSPEND_CONF ]] && . "$SUSPEND_CONF"


################################################################################
# switch to suspend VT if feature is enabled
if [[ $SUSP_VT -ne 0 && -c /dev/tty$SUSP_VT ]] ; then
                orig_vt=$(/usr/bin/fgconsole)
        [[ $orig_vt -ne $SUSP_VT ]] && /usr/bin/chvt $SUSP_VT && exec &> 
/dev/tty$SUSP_VT
        /usr/bin/clear
        echo
        echo -e "*** Switched to suspend VT $SUSP_VT from VT $orig_vt\r"
else
        echo -e "*** SUSP_VT is set to VT $SUSP_VT which is not valid!\r"
        SUSP_VT=0
fi

# run the RUN_AT_SUSPEND entries
num=1
until [[ $num -gt ${#RUN_AT_SUSPEND[*]} ]] ; do
        [[ ${RUN_AT_SUSPEND[$num]} ]] && ${RUN_AT_SUSPEND[$num]}
        num=$(( $num + 1 ))
done

# Only bother with this if we're suspending to disk.
[[ $SUSP_MASTER_TYPE = disk ]] && {
        # If we're actually suspending to both, don't stop services
        [[ $SUSP_DISK_TYPE = suspend ]] || {
                echo
                echo -e "*** Stopping necessary services\r"
                svc_restart=
                # split out space separated services
                while [[ $SUSP_SERVICES ]] ; do

                        # first, delete any spaces at the beginning
                        until [[ $SUSP_SERVICES = ${SUSP_SERVICES# } ]]; do
                                SUSP_SERVICES=${SUSP_SERVICES# }
                        done
                        # if there's nothing left, exit loop
                        [[ $SUSP_SERVICES ]] || break
                        # set $svc to first service, remove it from 
$SUSP_SERVICES
                        svc=${SUSP_SERVICES%% *}
                        SUSP_SERVICES=${SUSP_SERVICES#$svc}

                        ### OK, we have our service, now process it
                        nodeps=
                        # parse for _nd, remove and set nodeps if there
                        [[ ! $svc = ${svc%_nd} ]] && nodeps="--nodeps" 
svc=${svc%_nd}
                        svc_cmd="$SUSP_INITDIR/$svc"

                        # if svc is executable and running, stop and add to 
restart list
                        if [[ -x $svc_cmd ]]; then
                                if "$svc_cmd" --quiet status; then
                                        $svc_cmd $nodeps stop
                                        svc_restart="$svc_restart $svc"
                                else
                                        echo -e "$svc is not running, 
skipping\r"
                                fi
                        else
                                echo -e "$svc is not a valid service in 
$SUSP_INITDIR\r"
                        fi
                done
                # sleep to give services time to stop
                sleep 2
        }

        echo
        echo -e "*** Managing swap\r"
        swapoff -a; swapon -a

        echo -e "*** Setting suspend parameters\r"
        # swapon $SUSP_DISK_PART if necessary
        flag_swap_act=0
        [[ $SUSP_DISK_PART && $SUSP_MASTER_TYPE = disk ]] && {
                swapsline="$(grep -s $SUSP_DISK_PART /proc/swaps)" || {
                        echo -e "Activating $SUSP_DISK_PART for suspend\r"
                        swapon -p 0 "$SUSP_DISK_PART" || {
                                echo -e "Failed activation, exiting (services 
may be stopped)\r"
                                echo
                                exit 100
                        }
                        flag_swap_act=1
                        swapsline="$(grep -s $SUSP_DISK_PART /proc/swaps)"
                }
                [[ $SUSP_DISK_SIZE_KB = 0 ]] && {
                        SUSP_DISK_SIZE_KB=$(echo $swapsline | awk '{ print $3 
}')
                        # apparently there's a bit of overhead that needs 
figured in... say 4 MB
                        SUSP_DISK_SIZE_KB=$(( $SUSP_DISK_SIZE_KB - 4*1024 ))
                }
        }
        [[ $SUSP_DISK_SIZE_KB = 0 ]] && SUSP_DISK_SIZE_KB=$((500*1024))
        echo -e "Suspend image size: $((${SUSP_DISK_SIZE_KB}*1024))\r"
        echo $((${SUSP_DISK_SIZE_KB}*1024)) >> /sys/power/image_size
        echo $SUSP_DISK_TYPE >> /sys/power/disk
}

echo
echo -e "*** Syncing disk\r"
sync; sync; sync

################################################################################
############                      Suspend now                       ############
################################################################################
echo -e "*** Suspending....\r"
sleep 3
# type of suspend, setting this triggers it!
echo $SUSP_MASTER_TYPE >> /sys/power/state

################################################################################
############                       Wakeup now                       ############
################################################################################

echo
echo 
"*******************************************************************************"
echo "********************************** WAKING UP 
**********************************"
echo 
"*******************************************************************************"
echo

#echo "*** Resetting console font"
#resetres

# only bother with this if we're resuming from disk
[[ $SUSP_MASTER_TYPE = disk ]] && {
        [[ $flag_swap_act = 1 ]] && {
                echo "Deactivating $SUSP_DISK_PART for resume"
                swapoff "$SUSP_DISK_PART"
        }

        echo "*** Managing swap"
        swapoff -a; swapon -a

        # if we suspended to both, we didn't stop services, otherwise...
        [[ $SUSP_DISK_TYPE = suspend ]] || {
                echo "*** Restarting services stopped for suspend"
                while [[ $svc_restart ]] ; do
                        # first, delete any spaces at the beginning
                        until [[ $svc_restart = ${svc_restart# } ]]; do
                                svc_restart=${svc_restart# }
                        done
                        # if there's nothing left, exit loop
                        [[ $svc_restart ]] || break
                        # set $svc to first service, remove it from $svc_restart
                        svc=${svc_restart%% *}
                        svc_restart=${svc_restart#$svc}
                        ### OK, we have our service, start it
                        "$SUSP_INITDIR/$svc" start
                done
        }
}

# run the RUN_AT_RESUME entries
num=1
until [[ $num -gt ${#RUN_AT_RESUME[*]} ]] ; do
        [[ ${RUN_AT_RESUME[$num]} ]] && ${RUN_AT_RESUME[$num]}
        num=$(( $num + 1 ))
done

echo
[[ $SUSP_VT -ne 0 ]] && {
        echo "*** Switching back to VT $orig_vt"
        [[ $orig_vt -ne $SUSP_VT ]] && sleep 1 && /usr/bin/chvt $orig_vt
}
___________________________________________________
This message is from the kde mailing list.
Account management:  https://mail.kde.org/mailman/listinfo/kde.
Archives: http://lists.kde.org/.
More info: http://www.kde.org/faq.html.

Reply via email to