mar_sanbas
mar_sanbas

Reputation: 943

BASH - using trap ctrl+c

I'm trying to execute commands inside a script using read, and when the user uses Ctrl+C, I want to stop the execution of the command, but not exit the script. Something like this:

#!/bin/bash

input=$1
while [ "$input" != finish ]
do
    read -t 10 input
    trap 'continue' 2
    bash -c "$input"
done
unset input

When the user uses Ctrl+C, I want it to continue reading the input and executing other commands. The problem is that when I use a command like:

while (true) do echo "Hello!"; done;

It doesn't work after I type Ctrl+C one time, but it works once I type it several times.

Upvotes: 60

Views: 68072

Answers (3)

Doctor
Doctor

Reputation: 7996

For bash :

#!/bin/bash

trap ctrl_c INT

function ctrl_c() {
        echo "Ctrl + C happened"
}

For sh:

#!/bin/sh

trap ctrl_c INT

ctrl_c () {
    echo "Ctrl + C happened"
}

Upvotes: 26

Gilles Quénot
Gilles Quénot

Reputation: 185730

Use the following code :

#!/bin/bash
# type "finish" to exit

stty -echoctl # hide ^C

# function called by trap
other_commands() {
    tput setaf 1
    printf "\rSIGINT caught      "
    tput sgr0
    sleep 1
    printf "\rType a command >>> "
}

trap 'other_commands' SIGINT

input="$@"

while true; do
    printf "\rType a command >>> "
    read input
    [[ $input == finish ]] && break
    bash -c "$input"
done

Upvotes: 52

cdarke
cdarke

Reputation: 44424

You need to run the command in a different process group, and the easiest way of doing that is to use job control:

#!/bin/bash 

# Enable job control
set -m

while :
do
    read -t 10 -p "input> " input
    [[ $input == finish ]] && break

    # set SIGINT to default action
    trap - SIGINT

    # Run the command in background
    bash -c "$input" &

    # Set our signal mask to ignore SIGINT
    trap "" SIGINT

    # Move the command back-into foreground
    fg %-

done 

Upvotes: 17

Related Questions