I've got a script that is executed in order to have suspending/resuming working in my laptop. Then I have another series of xinput,xkbset and xmodmap commands that are executed when I initiate a session to have two-finger scrolling and keyboard shortcuts set up. When I resume from suspend, two-finger scrolling and my keyboard shortcuts won't work. I need to manually execute the commands in the second file again. How can I add those to the suspend/resume script to have this done automatically? See below:

suspend/resume script

/etc/pm/sleep.d/20_custom-ehci_hcd

#!/bin/sh
#inspired by http://art.ubuntuforums.org/showpost.php?p=9744970&postcount=19
#...and http://thecodecentral.com/2011/01/18/fix-ubuntu-10-10-suspendhibernate-not-working-bug    
# tidied by tqzzaa :)

VERSION=1.1
DEV_LIST=/tmp/usb-dev-list
DRIVERS_DIR=/sys/bus/pci/drivers
DRIVERS="ehci xhci" # ehci_hcd, xhci_hcd
HEX="[[:xdigit:]]"
MAX_BIND_ATTEMPTS=2
BIND_WAIT=0.1

unbindDev() {
  echo -n > $DEV_LIST 2>/dev/null
  for driver in $DRIVERS; do
    DDIR=$DRIVERS_DIR/${driver}_hcd
    for dev in `ls $DDIR 2>/dev/null | egrep "^$HEX+:$HEX+:$HEX"`; do
      echo -n "$dev" > $DDIR/unbind
      echo "$driver $dev" >> $DEV_LIST
    done
  done
}

bindDev() {
  if [ -s $DEV_LIST ]; then
    while read driver dev; do
      DDIR=$DRIVERS_DIR/${driver}_hcd
      while [ $((MAX_BIND_ATTEMPTS)) -gt 0 ]; do
          echo -n "$dev" > $DDIR/bind
          if [ ! -L "$DDIR/$dev" ]; then
            sleep $BIND_WAIT
          else
            break
          fi
          MAX_BIND_ATTEMPTS=$((MAX_BIND_ATTEMPTS-1))
      done  
    done < $DEV_LIST
  fi
  rm $DEV_LIST 2>/dev/null
}

case "$1" in
  hibernate|suspend) unbindDev;;
  resume|thaw)       bindDev;;
esac

touchpad two-finger scrolling and keyboard shortcuts script

xinput set-int-prop "SynPS/2 Synaptics TouchPad" "Two-Finger Scrolling" 8 1
xinput set-int-prop "SynPS/2 Synaptics TouchPad" "Synaptics Two-Finger Scrolling" 8 1 1
xinput set-int-prop "SynPS/2 Synaptics TouchPad" "Synaptics Two-Finger Pressure" 32 10
xinput set-int-prop "SynPS/2 Synaptics TouchPad" "Synaptics Two-Finger Width" 32 8
setxkbmap -layout gb
xkbset m
xkbset exp =m
xmodmap -e "keycode 135 = Pointer_Button2"
up vote 38 down vote accepted

You can place your scripts in the /etc/pm/sleep.d directory to have them run after suspend. You will need to add a conditional to make your script run only during resume and not during the suspend process as well. For example, your touchpad script would look like:

case "${1}" in
    resume|thaw)
        DISPLAY=:0.0 ; export DISPLAY
        xinput set-int-prop "SynPS/2 Synaptics TouchPad" "Two-Finger Scrolling" 8 1
        xinput set-int-prop "SynPS/2 Synaptics TouchPad" "Synaptics Two-Finger Scrolling" 8 1 1
        xinput set-int-prop "SynPS/2 Synaptics TouchPad" "Synaptics Two-Finger Pressure" 32 10
        xinput set-int-prop "SynPS/2 Synaptics TouchPad" "Synaptics Two-Finger Width" 32 8
        setxkbmap -layout gb
        xkbset m
        xkbset exp =m
        su $USER -c "sleep 3; /usr/bin/xmodmap -e "keycode 135 = Pointer_Button2"" &
;;
esac

Be sure your script is marked globally executable and change $USER to the corresponding username.

You can find more detailed information in the pm-suspend manpage (man pm-suspend) or by looking at the documentation in /usr/share/doc/pm-utils (particularly /usr/share/doc/pm-utils/HOWTO.hooks.gz).

  • 2
    It can be called whatever you like. It's a good idea to start it with a number between 00-49, per the pm-suspend manpage: "00 - 49 User and most package supplied hooks. If a hook assumes that all of the usual services and userspace infrastructure is still running, it should be here." – fader Jan 3 '12 at 13:28
  • 3
    Another (now deleted) answer had this: 'please note the following bug report: launchpad.net/ubuntu/+source/pm-utils/+bug/1455097 after upgrading to vivid scripts need to be put into /lib/systemd/system-sleep/' – Wilf Aug 15 '15 at 9:43
  • 8
    On Ubuntu 15.10, the script has to be in /lib/systemd/system-sleep/ instead of /etc/pm/sleep. – Marc Belmont Jan 25 '16 at 14:00
  • 6
    On Ubuntu 16.04 the arguments given to the script are pre before entering suspend and post after resume instead of suspend and resume – Germar Jul 22 '16 at 0:34
  • 3
    Tried the last two comments here on yakkety (16.10), and it didn't work. How to troubleshoot? – Gringo Suave Oct 18 '16 at 18:53

On Ubuntu 16.04 I had to create service this way:

  1. create file

    sudo gedit /etc/systemd/system/somename.service
    
  2. put inside

    [Unit]
    Description=Some description
    Before=sleep.target
    StopWhenUnneeded=yes
    
    [Service]
    Type=oneshot
    RemainAfterExit=yes
    ExecStop=-/path/to/your/script.sh
    
    [Install]
    WantedBy=sleep.target
    
  3. enable service

    sudo systemctl enable somename
    
  4. (optional) if not working after resume from suspend > check for errors with

    journalctl -u somename.service
    
  • This also seems to work on Ubuntu 18.04, thanks! – kelunik Jun 18 at 7:02
  • Why does Ubuntu leave /etc/pm/sleep.d lying around if it doesn't use it? It is confusing and misleading. – Jonathan Neufeld Sep 23 at 3:42

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.