I have a bash script which is supposed to run a command every X seconds, until the operator interrupts it. Like this:
test.sh
#!/bin/bash
while true; do
echo Doing a thing...
sleep 3 & wait
done
This, for the most part, works as expected. However, on one particular user account (which is of course the account I want this to run under) the CTRL-C key combination doesn't seem to be sending an interrupt signal to the script, which means it runs forever until I kill it in another terminal.
Suboptimal.
The first thing I checked was whether the .profile for this account had somehow undefined stty intr, but that is not the case (and explicitly adding the line
stty intr "^c"
to my script didn't help, neither did setting the escape code to something different). The .profile
also does not appear to be trapping any signals anywhere. This problem occurs whether I sudo into the account or log in directly. CTRL-C seems to work as expected when I run other commands (e.g. ping) from the command line.
CTRL-C interrupts the script as expected if I run it as root, or if I run it while logged in under a different unprivileged account. Creating an entirely new unprivileged account with a default .profile, it doesn't work. This is all using the same terminal installation and settings (PuTTY), so it doesn't appear to be a case of the terminal itself somehow intercepting or mangling the signals.
The only thing I can think of is that this is some profile setting affecting the behaviour, but I can't see anything in .profile, and outside of stty
and possibly $TERM
(which is the same in all accounts) I can't think of anything else that could be affecting it like this.
(I'm not including my .profile(s) right now because, quite frankly, they're a mess and it will take a while for me to sanitize. I'm less concerned with finding out what's wrong with my .profile per se, especially since the default .profile on a new account also has this issue, and more about where even I should be looking at for a solution.)
Just in case they're relevant, my stty -a settings (they're the same in the working and the non-working accounts):
speed 38400 baud;
rows = 25; columns = 80; ypixels = 0; xpixels = 0;
intr = ^c; quit = <undef>; erase = ^h; kill = ^x;
eof = ^d; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^q; stop = ^s; susp = ^z; dsusp = <undef>;
rprnt = ^r; flush = ^o; werase = ^w; lnext = ^v;
-parenb -parodd -parext cs8 -cstopb hupcl cread -clocal -loblk
-ignbrk brkint -inpck -ignpar -parmrk -istrip -inlcr -igncr icrnl -iuclc
ixon -ixany ixoff -imaxbel
opost -olcuc onlcr -ocrnl -onocr -onlret -ofill -ofdel tab3
isig icanon -xcase echo echoe echok -echonl -noflsh
-tostop -echoctl -echoprt -echoke -defecho -flusho -pendin -iexten
-isscancode -xscancode
What am I missing? If it matters, I am running GNU bash 3.2.17(1)-release on SCO OpenServer 6.0.0 MP4.
Other things tried (recording here to get them out of comment threads)
Running the following command from another terminal while the script is running:
kill -INT <process>
didn't accomplish anything, even while running the kill command as root. Running
kill -HUP <process>
terminated the script as expected.
I attempted to trap the signal by adding the following lines to my script:
trap "echo hi" SIGINT trap "echo lo" SIGHUP
Hitting CTRL-C or running
kill -INT <process>
as above showed no reaction. Runningkill -HUP <process>
as above did echo "lo" as expected.I have tried running the script in the following ways
/bin/sh /path/to/test.sh /bin/bash /path/to/test.sh /path/to/test.sh cd /path/to; test.sh
No difference.
As suggested by @mosvy in the comments, I tried running it through perl as follows:
perl -e '$SIG{INT}="DEFAULT"; exec @ARGV or die "exec: $!"' /path/to/test.sh
This, for some reason, did work.
kill -INT <process>
work? – Arkadiusz Drabczyk Mar 24 '20 at 01:45trap 'echo hi' SIGINT
to check if script receives SIGINT at all in the first place. – Arkadiusz Drabczyk Mar 24 '20 at 01:47/proc/<pid>/status
https://unix.stackexchange.com/questions/85364/how-can-i-check-what-signals-a-process-is-listening-to – Arkadiusz Drabczyk Mar 24 '20 at 01:55/bin/sh
(eg. as/bin/sh /path/to/script
)? Or explicitly by bash (eg. as/bin/bash /path/to/script
)? Or if you run it viaperl -e '$SIG{INT}="DEFAULT"; exec @ARGV or die "exec: $!"' /path/to/script
? – Mar 24 '20 at 02:14/bin/sh /path/to/test.sh
,/bin/bash /path/to/test.sh
and as just/path/to/test.sh
with +x set, no difference. – goldPseudo Mar 24 '20 at 02:19INT
signal ignored upon starting. – Mar 24 '20 at 02:23trap - INT
(in the shell you're calling your script from, NOT in the script). FWIW, the reason why it won't work inside the script is: "Signals that were ignored on entry to a non-interactive shell [ie a script] cannot be trapped or reset, although no error need be reported when attempting to do so." Reference – Mar 24 '20 at 02:33trap
commands in all your initialization scripts (Does bash also uses the/etc/profile.d
madness on OpenServer too?). A signal can be accidentally ignored by a command liketrap "$cmd" INT
whencmd
is an empty or undefined variable. – Mar 24 '20 at 02:43