1

I've written a bash function that accepts a command as an argument, runs it in the background, and allows the user to kill the command by pressing any key. This part works fine.

However, when I pipe it to a whiptail dialog gauge, the whiptail runs as expected, but after it returns, the terminal will no longer display keypresses. I can still run commands, I just don't see what I'm typing printed to the screen. The output is also formatted weirdly, where stdout appears after $.

I'm pretty sure the read command is responsible for this behavior, but I don't understand why. Can anyone offer any insight?

#!/bin/bash
function killOnKeypress() {
    local runcommand="${1}"
    local args=(${@:2})

    # Run the command in the background
    "${runcommand}" ${args[@]} &

    # Get the process id of $runcommand
    local pid=$!

    # Monitor $runcommand and listen for keypress in foreground
    while kill -0 "${pid}" >/dev/null 2>&1; do
        # If key pressed, kill $runcommand and return with code 1
        read -sr -n 1 -t 1 && kill "${pid}" && return 1
    done

    # Set $? to return code of $runcommand
    wait $pid

    # Return $runcommand's exit code
    return $?
}

function count100() {
    for ((i = 0; i < 100; i++)); do
        echo $i
        sleep .02
    done
}

killOnKeypress "count100" | whiptail \
    --gauge "Counting to 100" \
    16 56 \
    0

enter image description here

ridgek
  • 25
  • 4

2 Answers2

2

While this doesn't answer OP question, it can be useful for someone else landed here, looking for the fix/workaround.

As NickD in his comment pointed out, whiptail sets -echo (in my environment not just echo).

To fix your script you can put

stty echo

at the end of it.

What your script (whiptail) changes you can see with 'stty -a' before and after your script is run.
Of course you can save the outputs to files and make it easier to spot the differences:

stty -a > good_terminal

run your script - your terminal is messed, reset it with 'reset' or 'tset' or 'stty sane' and run again 'stty' command, and diff after it:

stty -a > bad_terminal
diff good_terminal bad_terminal
Damir
  • 491
  • 2
  • 4
  • 1
    Thank you, this completely answers my question! I was not aware of `stty`, so I didn't know how to check to see what had changed or how to debug it. – ridgek Oct 19 '21 at 07:19
0

It may be that whiptail leaves the terminal in a weird state. Try stty sane as the command (you'll have to type it blind, so be careful). If that fixes the terminal, then that's probably the problem.

NickD
  • 2,866
  • 1
  • 10
  • 21
  • Thanks, I wasn't aware of `stty`. I forgot to mention `reset` also works, I just wish I knew what was wrong in the first place! – ridgek Oct 18 '21 at 04:48
  • 1
    As I said, apparently `whiptail` sets `-echo` and does not reset it on exit (at least in some cases). Try eliminating `whiptail` from the pipeline: does the resulting script leave the terminal in a funny state? In my experiment, it does not: the terminal works properly afterwards. Add a `stty sane` at the end of your script: again the terminal works properly afterwards. That is enough to convince me that `whiptail` has a bug. – NickD Oct 18 '21 at 05:17
  • Thank you! I didn't see any comment about `whiptail` setting `-echo`, did u delete it? Per the answer below, this seems to be exactly what I wanted to know. – ridgek Oct 19 '21 at 07:18