Reputation: 943
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
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
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
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