[SOLVED] VM Hook Script Won't Run In Background

JohnMC

Active Member
Oct 12, 2017
10
6
43
38
I have a simple hook script and on post-start I need to run a shell script in the background (which will take a while to run).

The core of the issue is that the VM is locked until the hook script exits. Since I don't care about any return from my shell script, i'd like to just have it run in the background and have the hook script return so the the vm can unlock.

I would expect something like this to work and it does from a shell but it doesn't when run by the hook script:
Code:
system("./background.sh &");

I tried messing with using fork and exec, it didn't seem to help but I don't have enough of a grasp on perl to know.

I also tried attaching a shell script directly to the vm and then tried using ./background.sh & again with no luck. It seemed like this example would have worked but this time it doesn't run at all when executed by the hook script:

Code:
(sleep 5s; echo test >> /root/test.log) > /dev/null 2>&1 &

The interesting part about that example is it led me to discover that redirecting stderr could be a clue as redirecting it seems to be what causes the subshell commands to not run at all... not redirecting stderr causes the the hook script to wait for the subshell commands to complete just like before.

I must have a fundamental misunderstanding of something going on here and I can't help but wonder if it has something to do with the way perl executes system commands, it would be really nice to be pointed in the right direction.
 
to go into the background, the hookscript has to close stdout,stderr and stdin
 
Thanks, that gave me a lot of things to read about and try but I seem to still be missing something, this is my current simplified example of a hook script, it returns immidiatly but whatever is started seems to terminate at the same time as the hook script. I was also playing with nohup to see if that would help but no luck, in this example nohup (or sleep alone) returns a pid but doesn't run for any noticeable length and i'm not sure how to get more information about why.

Code:
#!/bin/bash
echo parameters: $1 $2 [$0]

if [ $2 = "post-start" ]; then
  echo post-start start >> /root/test.log
  exec 0>&-
  exec 1>&-
  exec 2>&-
  nohup sleep 6s &
  # bash -c "sleep 6s; echo success? >> /root/test.log" &
  echo $! >> /root/test.log
  echo post-start end >> /root/test.log
fi
exit 0

Edit: also, if i run my sleep command (or anything) before closing the streams, the command works and the script continues but it seems to still wait at the end before returning and unlocking the vm.
 
Last edited:
I've been continuing to research this, It seemed like it might not be proxmox specific so I tried a couple other forums but didn't have any luck. Taking one more stab here, this is my latest non working simplified example where I have the hook script and a second script that I want to run in the background:

hook.sh
Code:
#!/bin/bash
echo hook parameters: $1 $2 [$0]

if [ $2 = "post-start" ]; then
  echo [post-start] start
  /var/lib/vz/snippets/background.sh &
  sleep 5s
  echo [post-start] end
fi
exit 0

background.sh
Code:
#!/bin/bash
exec 0>&-
exec 1>&-
exec 2>&-
sleep 10s

The idea in this example is that the sleep commands replace the work I want to do and they help with testing. The result in the example is that when the VM starts, I can see both the sleep 5s and sleep 10s running on the host but when sleep 5s is done, sleep 10s terminates early. I tried experimenting with disown and nohup too but didn't get anywhere.
 
The problem is the parent-child relation between the two scripts. When parent dies children are killed too. Child needs to detach from parent process group, like a daemon does. One easy way to do this is to start the child with ''nohup''.

nohup /var/lib/vz/snippets/background &

Read the man page. It also handles the file descriptor issue.
 
The problem is the parent-child relation between the two scripts. When parent dies children are killed too. Child needs to detach from parent process group, like a daemon does. One easy way to do this is to start the child with ''nohup''.

nohup /var/lib/vz/snippets/background &

Read the man page. It also handles the file descriptor issue.
Thanks for the reply, I've used nohup the way you described before but I tried again, hook script looks like this:

Code:
#!/bin/bash
echo parameters: $1 $2 [$0]

if [ $2 = "post-start" ]; then
echo [post-start] start
nohup /var/lib/vz/snippets/background.sh &
sleep 5s
echo [post-start] end
fi
exit 0

I get the exact same behavior where background.sh / sleep 10s terminate early, i've also tried "nohup sleep 10s" in background.sh just for kicks but that didn't help. The man page doesn't seem to offer any more options or clues, I thought disown might help but i'm not sure i'm using it correctly yet or that it's even remotely the answer.

I should also point out that running the script directly works like a charm (nohup or not) where the script drops me back to terminal input after the "sleep 5s" and I can see that "sleep 10s" is still running in the background, even if I exit the terminal.

Code:
/var/lib/vz/snippets/hook.sh 123 post-start
 
I can't say I understand the solution yet but I finally found something that worked.

Code:
setsid command &

For 99% of situations this appears to work the same as nohup and since so much information suggests nohup was the solution (but it didn't work) I never thought to pursue it deeper. I don't know why setsid will successfully send my command/script to the background (without terminating along with the parent) and nohup won't but maybe i'll figure it out eventually.

So just to be clear, this example is currently working for me, the hook script will exit and the VM will unlock while the background script is still running:

hook.sh
Code:
#!/bin/bash
echo hook parameters: $1 $2 [$0]

if [ $2 = "post-start" ]; then
  echo [post-start] start
  setsid /var/lib/vz/snippets/background.sh &
  sleep 5s
  echo [post-start] end
fi
exit 0

background.sh
Code:
#!/bin/bash
exec 0>&-
exec 1>&-
exec 2>&-
sleep 10s
 
Last edited:
  • Like
Reactions: yayuuu
Interesting. Two possibilities come to mind. Most shells have a built-in version of nohup, maybe there is some difference with the one in /use/bin. The other is that setsid may do an extra fork() that nohup doesn't do.
 

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!