Search code examples
bashcopy-pastebash-trap

How to disable ctrl-c in a non-interactive bash script and its git subprograms


I am calling git clone from a non-interactive bash shell. It is non-interactive because it is launched from a Windows Explorer contect menu. I am running git version 2.20.1.windows.1 on Windows 10 64-bit.

I am running Git/usr/bin/bash -l -e 'myscript' in a Git/usr/bin/mintty window launched from the context menu.

I want to block the user from interrupting the git clone with ctrl-c.

I tried:

set -m
trap '' SIGINT SIGTERM (2 single quotes)
git clone ... &
wait -n
echo $?

The ctrl-c passes through to the git clone which exits. I assume it has a signal handler that exits on SIGINT. I would like to know why this does not work.

I tried:

saved=$(stty -g)
stty -isig
git clone ...
stty "$saved"

The stty fails with "stty: standard input: Inappropriate ioctl for device" because there is no tty for a non-interactive bash shell. So how is the ctrl-c getting to the git clone if there is no tty?

I am testing with git clone, but want to deploy this for git pull and git push. Our developers have caused their local repos to be inconsistent by interrupting a long git pull with ctrl-c.

Any help would be appreciated.


Solution

  • Processes that handle signals themselves (examples seem to be git, ping and scp) prevent the parent trap from being called.

    So this simple example won't fit these purposes:

    #!/bin/bash
    trap '' SIGINT SIGTERM
    sleep 10
    

    This answer suggests using set -m (processes run in separate process group) in a subshell which does not send SIGINT to the the process:

    #!/bin/bash
    trap '' SIGINT SIGTERM
    uninterruptableCommand="git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/"
    ( set -m; $uninterruptableCommand & wait )
    

    WARNING: the example is a really long-running command. You can still send signals to the process directly (e.g. pkill git).