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.