3

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. Running kill -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.

  • How do you kill this process in another terminal? Does kill -INT <process> work? – Arkadiusz Drabczyk Mar 24 '20 at 01:45
  • And maybe add a signal trap like this trap 'echo hi' SIGINT to check if script receives SIGINT at all in the first place. – Arkadiusz Drabczyk Mar 24 '20 at 01:47
  • @ArkadiuszDrabczyk kill -INT doesn't work, even if i'm logged in as root to do it. kill -HUP works as expected to stop the script. – goldPseudo Mar 24 '20 at 01:50
  • @ArkadiuszDrabczyk Trapping SIGINT does nothing when i CTRL-C in script, or kill -INT from another terminal. – goldPseudo Mar 24 '20 at 01:53
  • ok, maybe check signals status in /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
  • Or wait, is it Linux system? – Arkadiusz Drabczyk Mar 24 '20 at 02:05
  • @ArkadiuszDrabczyk It's SCO OpenServer, not linux. I'm not sure how to get the relevant information in here (the instructions on that link don't help) but i'm digging into it right now. – goldPseudo Mar 24 '20 at 02:08
  • How are you running that script? Does it change anything if you're running it with your system's /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 via perl -e '$SIG{INT}="DEFAULT"; exec @ARGV or die "exec: $!"' /path/to/script? –  Mar 24 '20 at 02:14
  • @mosvy I have tried running it and as /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:19
  • Try the perl command if you have perl on that system. –  Mar 24 '20 at 02:21
  • @mosvy The perl line, however, did work. – goldPseudo Mar 24 '20 at 02:21
  • That means that the interactive shell you run that from had the INT signal ignored upon starting. –  Mar 24 '20 at 02:23
  • 3
    Try trap - 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:33
  • @mosvy It didn't work, but adding the line to my .profile and logging back in did. – goldPseudo Mar 24 '20 at 02:40
  • 1
    Better look for trap 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 like trap "$cmd" INT when cmd is an empty or undefined variable. –  Mar 24 '20 at 02:43
  • @mosvy If you can write up a proper answer, I think I've got a checkmark waiting for you. – goldPseudo Mar 24 '20 at 02:44

0 Answers0