Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

trap not working in shell script?

I'm in the process of writing a script on OS X that needs to trap SIGTERM in order to kill some child processes before exiting. For the sake of this question I've boiled it down to the following minimal example that, for some reason, isn't working as I'd expect it to:

#!/bin/sh

function shutdown()
{
  touch foo.txt
  exit 0
}

trap shutdown TERM
su -l myusername -c "sleep 9999"

I run this script in one terminal window, then switch to another and "ps -aef" yields this:

  502   857   645   0 11:38PM ttys001    0:00.00 /bin/sh ./foo.sh
    0   858   857   0 11:38PM ttys001    0:00.02 su -l myusername -c sleep 9999
  502   859   858   0 11:38PM ttys001    0:00.00 sleep 9999

From that second window I then issue "kill -15 857", but the trap is never triggered. The script remains blocked on the "su" command.

Any idea why? I get the feeling it's something simple.

like image 868
jph Avatar asked Nov 11 '14 05:11

jph


People also ask

What does trap do in shell?

Trap allows you to catch signals and execute code when they occur. Signals are asynchronous notifications that are sent to your script when certain events occur. Most of these notifications are for events that you hope never happen, such as an invalid memory access or a bad system call.

How do I run a shell script from a yaml file?

How do you call a shell script in YAML? To run the inputs as a shell command on a Linux or Unix system, the “eval” command must be used. The “eval” command takes the parse_yaml function with the Person. yaml file.


1 Answers

The bash manual states that:

If bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes.

As gniourf_gniourf says, this is a POSIX spec relative to signals in shells.

You can check it by trapping for instance SIGUSR1 in place of SIGTERM; you'll see that kill -TERM will kill again the process.

A solution is to run the command in background, then wait for its termination. In this case the trap will work. Try this:

#! /bin/bash

shutdown()
{
    touch foo.txt
    exit 0
}

trap shutdown TERM
su -l myusername -c "sleep 9999" &    # On Ubuntu: sudo su
wait

You will get two problems: su won't be able to ask password in foreground; you will have to manually kill su.

like image 58
Edouard Thiel Avatar answered Oct 05 '22 07:10

Edouard Thiel