5

I have written this menu that calls forth several scripts. One of this script is

dbus-monitor --system

so it displays live traffic over dbus.

but when I want to exit this I normally do Ctrl+C, but that also exits my menu and I would like to just return to my menu.

is there a code that I can put after the dbus-moniter, when an exit is detected it starts my menu again? my menu is just another .sh script

or ....

---------------- clarify ---------------

i am not that advanced "yet" ;) in scripting. this is the menu where i call my dbus script

select opt in "dbus Live Traffic" "option 2" "Main menu" "Quit"
    do
        case $opt in
            "dbus Live Traffic")
                curl -s -u lalala:hihihi ftp://ftp.somewhere.com/folder/dbuslivetraffic.sh | bash ;;   
            "option 2")
                do_something ;;   
            "Main menu")
                main_menu;;
            "Quit")
                quit_menu;;
        esac
        if [[ $opt != "Main menu" ]] || [[ $opt != "Quit" ]] ;
        then
            main_menu
        fi
    done

and this is the content of my dbuslivetraffic.sh

dbus-monitor --system

for now just this single line, but maybe in the near future more code will be added to this script.

i don't really understand where i need to put the TRAP function like suggested by @RoVo

0

3 Answers 3

7

You can run the command in a subshell and trap on SIGINT running kill 0 to kill the process group of the subshell only.

select opt in a b; do
    case $REPLY in
      1)
        (
          trap "kill -SIGINT 0" SIGINT
          sleep 10
        )
        ;;
      2)
        sleep 10
        ;;
    esac
done
  • Selecting (1) will let you use Ctrl+c without killing the menu.
  • Selecting (2) and pressing Ctrl+c will kill the menu, too.
0
4

Graphical desktop environment

You can run the command in another terminal window (if you have a graphical desktop environment).

The following shellscript uses xterm, which can be installed with

sudo apt update
sudo apt install xterm

but you can use other terminal window emulators too, for example gnome-terminal or lxterminal.

Shellscript:

#!/bin/bash

select opt in "dbus-monitor --system" htop exit; do
    case $REPLY in
      1)
        xterm -e dbus-monitor --system 2>/dev/null
        ;;
      2)
        htop
        ;;
      3)
        exit
        ;;
    esac
done

Text screen (this method works also in a graphical desktop)

You can use the trap method in @RoVo's answer.

The important thing is to run the trap command before you run the command, that you must interrupt with ctrl+c.

  • So if you want it in the whole menu script, put it in the beginning.

  • If you want it only when it is absolutely necessary, run a subshell and put the trap command inside the subshell as illustrated by @RoVo, alternatively with

    bash -c 'trap "kill -SIGINT 0" SIGINT; dbus-monitor --system';;
    

Shellscript:

#!/bin/bash

echo "Press the Enter key to print out the menu again"

trap "kill -SIGINT 0" SIGINT

select opt in "dbus-monitor --system" "option 2" "Quit"
do
    case $opt in
        "dbus-monitor --system")
            dbus-monitor --system;;   
        "option 2")
            echo "Hello World";;   
        "Quit")
            exit;;
    esac
done

Comment

Your curl command line did not work for me, so I invoke my local dbus-monitor to test that the shellscript works when using ctrl+c.

7
  • i dont have a graphical desktop environment. and i cant install other shells so i am limited in my actions
    – WingZero
    Dec 21, 2018 at 10:00
  • @WingZero, in that case you cannot use the method in this answer. Is RoVo's method with a trap working for you?
    – sudodus
    Dec 21, 2018 at 10:03
  • hey, i just update my initial question, because the comment section was to small
    – WingZero
    Dec 21, 2018 at 10:07
  • problem is i am a novice in shell scripting, so i don't know where the trap method from @RoVo needs to fit in
    – WingZero
    Dec 21, 2018 at 10:08
  • @WingZero, I added an alternative with the trap method to my answer. Try that shellscript and edit it to make it do what you want.
    – sudodus
    Dec 21, 2018 at 10:46
0

To add to @pLumo's excellent answer, you may define a function like this, to shorten the amount of code needed in each case:

run_in_subshell () {
    command="$@"
    (
        trap "kill -INT 0" INT
        $command
    )
}

Then in the case:

select opt in a b; do
    case $REPLY in
      1) run_in_subshell sleep 10 ;;
      2) sleep 10 ;;
    esac
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .