How do you run a script before suspending?

I’d like to run a script before my system suspends. Suspend works pretty great on my system and I set up a systemd unit to run a script on suspend: /etc/systemd/system/suspend@.service contains:

[Unit]
Description=Resume actions for user %I
Before=suspend.target

[Service]
User=%i
Type=simple
ExecStart=/home/jt/bin/nopath/presuspend.sh

[Install]
WantedBy=suspend.target

From my debugging, I can tell that the script is being run when I suspend the system. The problem is that it is not run before the system suspends. This means that either half the script runs before suspending and the other half after resuming, or the script runs after my network goes down so I can’t move files to a network share.

Welcome! :rocket:


Sounds like something up @BluishHumility alley…

Me?!

Try changing it from Type=simple to Type=oneshot so it will wait for the script to finish.

1 Like

I’ll experiment with this and report back, thanks!

I have had 3 tabs open to properly learn Systemd for a month because my server died when I started to learn it :frowning:

That didn’t seem to work. I can see that it ran:

$ journalctl -b -u systemd-suspend.service
Sep 08 22:01:15 mybox systemd[1]: Starting System Suspend...
Sep 08 22:01:15 mybox systemd-sleep[175470]: presuspend system-sleep hook argv: pre suspend
Sep 08 22:01:15 mybox systemd-sleep[175471]: vmware system-sleep hook argv: pre suspend
Sep 08 22:01:15 mybox systemd-sleep[175471]: Number of running VMs: 0
Sep 08 22:02:45 mybox systemd-sleep[175467]: Entering sleep state 'suspend'...
Sep 09 11:11:47 mybox systemd-sleep[175781]: vmware system-sleep hook argv: post suspend
Sep 09 11:11:47 mybox systemd-sleep[175777]: presuspend system-sleep hook argv: post suspend
Sep 09 11:11:47 mybox systemd-sleep[175781]: Nothing to do
Sep 09 11:11:47 mybox systemd-sleep[175777]: Nothing to do
Sep 09 11:11:47 mybox systemd[1]: systemd-suspend.service: Deactivated successfully.
Sep 09 11:11:47 mybox systemd[1]: Finished System Suspend.

The script is just moving some files out of my downloads to a share, and I actually saw mv crash in dmesg:

[47357.788979] Freezing user space processes
[47377.794949] Freezing user space processes failed after 20.005 seconds (1 tasks refusing to freeze, wq_busy=0):
[47377.795087] task:mv              state:D stack:0     pid:176959 ppid:1      flags:0x00000006
[47377.795093] Call Trace:
[47377.795094]  <TASK>
[47377.795098]  __schedule+0xca9/0x1960
[47377.795104]  ? srso_alias_return_thunk+0x5/0x7f
[47377.795107]  ? __kmem_cache_alloc_node+0x198/0x330
[47377.795111]  ? __d_alloc+0x170/0x230
[47377.795115]  schedule+0x5e/0xd0
[47377.795117]  d_alloc_parallel+0x392/0x460
[47377.795121]  ? __pfx_default_wake_function+0x10/0x10
[47377.795124]  __lookup_slow+0x5d/0x130
[47377.795128]  path_lookupat+0x2b3/0x3e0
[47377.795131]  filename_lookup+0xe8/0x1f0
[47377.795137]  ? getname_flags.part.0+0x4b/0x200
[47377.795140]  __x64_sys_newfstatat+0xb2/0x1b0
[47377.795147]  do_syscall_64+0x5d/0x90
[47377.795151]  ? srso_alias_return_thunk+0x5/0x7f
[47377.795153]  ? syscall_exit_to_user_mode+0x2b/0x40
[47377.795155]  ? srso_alias_return_thunk+0x5/0x7f
[47377.795157]  ? do_syscall_64+0x6c/0x90
[47377.795159]  ? srso_alias_return_thunk+0x5/0x7f
[47377.795161]  ? exc_page_fault+0x7f/0x180
[47377.795164]  entry_SYSCALL_64_after_hwframe+0x72/0xdc
[47377.795167] RIP: 0033:0x7fcc506ffd2e
[47377.795196] RSP: 002b:00007fff3a278d68 EFLAGS: 00000202 ORIG_RAX: 0000000000000106
[47377.795199] RAX: ffffffffffffffda RBX: 00007fff3a278f10 RCX: 00007fcc506ffd2e
[47377.795200] RDX: 00007fff3a278f10 RSI: 0000560320eb7cc8 RDI: 0000000000000003
[47377.795201] RBP: 00007fff3a279190 R08: 0000000000008000 R09: 00000000ffffff01
[47377.795203] R10: 0000000000000100 R11: 0000000000000202 R12: 00007fff3a2791ea
[47377.795204] R13: 0000000000000012 R14: 0000000000000001 R15: 0000000000000001
[47377.795209]  </TASK>
[47377.795497] OOM killer enabled.
[47377.795498] Restarting tasks ... done.
[47377.800629] random: crng reseeded on system resumption
[47377.800635] PM: suspend exit
[47377.800677] PM: suspend entry (s2idle)
[47377.816047] Filesystems sync: 0.015 seconds
[47377.816426] Freezing user space processes
[47397.824585] Freezing user space processes failed after 20.007 seconds (1 tasks refusing to freeze, wq_busy=0):
[47397.824723] task:mv              state:D stack:0     pid:176959 ppid:1      flags:0x00000006
[47397.824729] Call Trace:
[47397.824730]  <TASK>
[47397.824734]  __schedule+0xca9/0x1960
[47397.824740]  ? srso_alias_return_thunk+0x5/0x7f
[47397.824743]  ? __kmem_cache_alloc_node+0x198/0x330
[47397.824747]  ? __d_alloc+0x170/0x230
[47397.824751]  schedule+0x5e/0xd0
[47397.824754]  d_alloc_parallel+0x392/0x460
[47397.824757]  ? __pfx_default_wake_function+0x10/0x10
[47397.824761]  __lookup_slow+0x5d/0x130
[47397.824764]  path_lookupat+0x2b3/0x3e0
[47397.824768]  filename_lookup+0xe8/0x1f0
[47397.824774]  ? getname_flags.part.0+0x4b/0x200
[47397.824777]  __x64_sys_newfstatat+0xb2/0x1b0
[47397.824784]  do_syscall_64+0x5d/0x90
[47397.824788]  ? srso_alias_return_thunk+0x5/0x7f
[47397.824790]  ? syscall_exit_to_user_mode+0x2b/0x40
[47397.824792]  ? srso_alias_return_thunk+0x5/0x7f
[47397.824795]  ? do_syscall_64+0x6c/0x90
[47397.824797]  ? srso_alias_return_thunk+0x5/0x7f
[47397.824799]  ? exc_page_fault+0x7f/0x180
[47397.824801]  entry_SYSCALL_64_after_hwframe+0x72/0xdc
[47397.824804] RIP: 0033:0x7fcc506ffd2e
[47397.824833] RSP: 002b:00007fff3a278d68 EFLAGS: 00000202 ORIG_RAX: 0000000000000106
[47397.824835] RAX: ffffffffffffffda RBX: 00007fff3a278f10 RCX: 00007fcc506ffd2e
[47397.824837] RDX: 00007fff3a278f10 RSI: 0000560320eb7cc8 RDI: 0000000000000003
[47397.824838] RBP: 00007fff3a279190 R08: 0000000000008000 R09: 00000000ffffff01
[47397.824840] R10: 0000000000000100 R11: 0000000000000202 R12: 00007fff3a2791ea
[47397.824841] R13: 0000000000000012 R14: 0000000000000001 R15: 0000000000000001
[47397.824846]  </TASK>
[47397.825144] OOM killer enabled.
[47397.825146] Restarting tasks ... done.
[47397.829920] random: crng reseeded on system resumption
[47397.829925] PM: suspend exit
[47433.785503] INFO: task mv:176959 blocked for more than 122 seconds.
[47433.785509]       Tainted: G           OE      6.4.12-zen1-1-zen #1
[47433.785511] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[47433.785513] task:mv              state:D stack:0     pid:176959 ppid:1      flags:0x00000006
[47433.785517] Call Trace:
[47433.785519]  <TASK>
[47433.785521]  __schedule+0xca9/0x1960
[47433.785527]  ? srso_alias_return_thunk+0x5/0x7f
[47433.785530]  ? __kmem_cache_alloc_node+0x198/0x330
[47433.785534]  ? __d_alloc+0x170/0x230
[47433.785538]  schedule+0x5e/0xd0
[47433.785540]  d_alloc_parallel+0x392/0x460
[47433.785544]  ? __pfx_default_wake_function+0x10/0x10
[47433.785548]  __lookup_slow+0x5d/0x130
[47433.785551]  path_lookupat+0x2b3/0x3e0
[47433.785554]  filename_lookup+0xe8/0x1f0
[47433.785561]  ? getname_flags.part.0+0x4b/0x200
[47433.785564]  __x64_sys_newfstatat+0xb2/0x1b0
[47433.785570]  do_syscall_64+0x5d/0x90
[47433.785574]  ? srso_alias_return_thunk+0x5/0x7f
[47433.785576]  ? syscall_exit_to_user_mode+0x2b/0x40
[47433.785579]  ? srso_alias_return_thunk+0x5/0x7f
[47433.785581]  ? do_syscall_64+0x6c/0x90
[47433.785583]  ? srso_alias_return_thunk+0x5/0x7f
[47433.785585]  ? exc_page_fault+0x7f/0x180
[47433.785588]  entry_SYSCALL_64_after_hwframe+0x72/0xdc
[47433.785591] RIP: 0033:0x7fcc506ffd2e
[47433.785615] RSP: 002b:00007fff3a278d68 EFLAGS: 00000202 ORIG_RAX: 0000000000000106
[47433.785618] RAX: ffffffffffffffda RBX: 00007fff3a278f10 RCX: 00007fcc506ffd2e
[47433.785619] RDX: 00007fff3a278f10 RSI: 0000560320eb7cc8 RDI: 0000000000000003
[47433.785621] RBP: 00007fff3a279190 R08: 0000000000008000 R09: 00000000ffffff01
[47433.785622] R10: 0000000000000100 R11: 0000000000000202 R12: 00007fff3a2791ea
[47433.785623] R13: 0000000000000012 R14: 0000000000000001 R15: 0000000000000001
[47433.785628]  </TASK>
[47453.756549] CIFS: VFS: \\KRONDOR has not responded in 180 seconds. Reconnecting...
[47464.039674] RTL8226B_RTL8221B 2.5Gbps PHY r8169-0-900:00: attached PHY driver (mii_bus:phy_addr=r8169-0-900:00, irq=MAC)
[47464.206780] r8169 0000:09:00.0 enp9s0: Link is Down
[47465.880523] r8169 0000:09:00.0 enp9s0: Link is Up - 100Mbps/Full - flow control rx/tx
[47465.880540] IPv6: ADDRCONF(NETDEV_CHANGE): enp9s0: link becomes ready
[47466.080683] userif-2: sent link up event.
[47466.520653] userif-2: sent link up event.

During this test my system didn’t even actually suspend, I just saw the screen lock and then the network went down. I see that the script really did run since I had it write a timestamp.

Did the suspend@.service exit? If not, then that would be the expected behavior.

Have you confirmed the script works outside the context of the system going to suspend? Run systemctl start suspend@.service and see if it succeeds.

It may be necessary to move the script out of /home; systemd doesn’t like running stuff out of user directories.

I think you’re onto something! The script is failing to start from systemd every time:

Sep 09 12:27:06 mybox systemd[1]: Failed to start suspend actions for user service.
░░ Subject: A start job for unit suspend@service.service has failed
░░ Defined-By: systemd
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
░░ 
░░ A start job for unit suspend@service.service has finished with a failure.
░░ 
░░ The job identifier is 2960 and the job result is failed.

This log doesn’t really tell me much. I moved it out of my home anyway. Do you think it’s failing because

Running the script itself seems fine:

$ bash -x /usr/local/bin/mvtorrents.sh 
+ date
+ mv -v /home/jt/Downloads/fake.torrent /media/krondor/incoming/
+ date
+ touch /media/krondor/incoming/mvtorrents-ran
+ exit 0

Do you think systemd is not running the script as my user so it runs into permission problems or something? Thanks again for your help! :slight_smile:

I do. I am not super familiar with using a User=%i line, but I have been reading a little bit and from what I understand it looks like your service is running as the user service:

I think when you start an instance of this service, you provide a value for %i as an argument after the @ and before the .service. (source)

systemctl start suspend@john.service

Here, %i is replaced with “john,” and the service will run with the user account “john”.

I believe I was mistaken about this; if you are running it as your user it should be fine for it to be in /home/user.

This makes sense, now that I think about it the script must be running as me because it makes other files as me as part of debugging, and that was running before. So what else should I try other than oneshot?

So running sudo systemctl start suspend@jt.service does seem run the script properly. It makes my debugging files, it moves the files out of my downloads properly. I guess the problem is really getting it to run before suspending still.

What part is not working?

When I actually suspend my system it doesn’t work right. It runs as the network is going down so it either crashes while a move is in process or fails because the server is unreachable. In the past I observed it running half the script before suspend and half after. I just did a suspend to tell you exactly what happened and my machine didn’t wake back up so I had no evidence of it running at all. A test file or debugging file didn’t make it to my server.

I’m starting to think that even if I get this working properly, it’s still going to suck if my machine just doesn’t wake up from suspend sometimes. It’ll mean lost data on the ramdisk which means I can’t rely on this anyway. Maybe I should just stop trying :confused:

Do you have these issues with suspending outside of the new systemd service? In other words, if you disable this new service altogether, does your machine ever have issues not waking properly? It seems like a separate issue.

It might be actually. It might only be freezing when there’s actually something to move. The main issue is still that I need this script to run and complete before the other suspend stuff happens.

Have you considered doing all commands simply in a script?
Then the order would be trivially correct…
For example

command1 && command2 && command3

and so on.

Then the script can be run in various ways, like a key sequence, mouse click, terminal command, …

Edit: read your post again, this isn’t enough… need to do all in systemd before network stops.