25

I know how to start a Konsole with one executable running in it, and leave the Konsole open after the program ends. I can do this using a .desktop file and change some options in it.

But I would like one step further, to launch a KDE konsole with multiple tabs open, each running a particular program, and that when the program finishes it stays open and give you a prompt.

There's no man page for Konsole so I don't even know what options it can take. Or some d-bus calls? Thanks

Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
dargaud
  • 2,431
  • 2
  • 26
  • 39
  • you can do it through `qdbus`: e.g. `qdbus org.kde.konsole /Konsole newSession` – gengisdave Sep 25 '15 at 10:42
  • $ qdbus org.kde.konsole Service 'org.kde.konsole' does not exist. But adding -PID works. But also the doc (https://docs.kde.org/trunk5/en/applications/konsole/scripting.html) says not to use /Konsole... – dargaud Sep 25 '15 at 12:18

4 Answers4

17

Who ever sees beauty in the accepted solution is hopefully not in software development : ) This must be a one liner or a bug report must be submitted. Every other common terminal has this option. I did some research and the "almost one liner solution" is this:

  1. Create a file configuring your tabulators like so and name it let's say "tabs":
   title: %n;; command: /usr/bin/htop
   title: %n;; command: /usr/bin/ncmpcpp

(The full documentation is at https://docs.kde.org/stable5/en/konsole/konsole/command-line-options.html. The called command binaries are examples. The "%n" will name the tab exactly like the command)

  1. Execute it like so:

    konsole --tabs-from-file path_to_tabs_file/tabs

Result: A new konsole window with 3 tabs, running defined binaries and one empty prompt. I couldn't get a bash script to run. But I did just a few minutes of testing.

skierpage
  • 2,514
  • 21
  • 19
CaptainCrunch
  • 1,230
  • 14
  • 15
  • 1
    I marked yours as the new solution as it is much simpler than my script. I'd searched for those options without success... Thanks – dargaud Feb 14 '18 at 11:07
  • How does one use aliased commands from their .my_cshrc file. It gives "Warning: Could not find 'alias-command', starting '/bin/tcsh' instead." and yet it appears to run the alias command anyways. It would also be useful to know how to put multiple commands in the tab config file. Typically I would string multiple commands together delimited by ';' but this is causing those tabs to not open at all. – Matt Apr 16 '18 at 17:26
  • I tried your answer and it worked, instantly. It is also much shorter than the shell-script variant below. – shevy Nov 07 '18 at 10:31
  • Captain Crunch! The roof of my mouth hurts just writing it! – Tom Russell Feb 17 '21 at 21:18
  • Nice, but seems to work inconsistently. Sometimes the window is spawned and immediately exits, thankfully leaving no orphans to hunt down and kill. – Tom Russell Feb 17 '21 at 21:30
  • works like a charm. My shell script is also running. TabFile entry like this: .. title: radio;; command sh /home/manoca/radio.sh .. – roediGERhard May 14 '21 at 13:14
14

I did some more digging and found and even more "subjectively" beautiful answer. Goal: start empty shell, music player and screen session running irssi in 3 different tabs in konsole:

  1. Create a simple, executable script file with:

#!/bin/bash konsole --hold --new-tab & konsole --hold --new-tab -e $SHELL -c "/usr/bin/screen -DRS irssi-in-screen irssi" & konsole --hold --new-tab -e $SHELL -c "/usr/bin/ncmpcpp" &

The clue is not to execute the the command directly but to call a shell, that can take in all arguments passed. $SHELL is set to /bin/bash. This "issue" is documented here:

Quote: " Konsole treats arguments after the -e option as one command and runs it directly, instead of parsing it and possibly dividing it into sub-commands for execution. This is different from xterm.

konsole -e "command1 ; command2" does not work

konsole -e $SHELL -c "command1 ; command2" works
skierpage
  • 2,514
  • 21
  • 19
CaptainCrunch
  • 1,230
  • 14
  • 15
  • Thanks for this answer! When I use it to run commands though, they seem to be running in a different 'environment' (wrong term?) than when I open a terminal directly; i.e. aliases defined in my .bashrc don't work, and it uses a different version of Node than I have setup with nvm. Any idea how this could be made to work, but have the commands run in the 'same way' as when I run them directly in a standard terminal? – J23 Jun 14 '21 at 03:17
  • BTW when using this solution you can also specify --layout path/to/layout.json which would open a new tab with spit views how you like – Michael Butler Dec 03 '21 at 15:30
5

This is a solution using qdbus, see D-Bus documentation. The Konsole docs doesn't say much about the interfaces used, so some experimenting is necessary. I've left comments in the code about the things I attempted but that didn't work.

This works in KDE 5.

#! /bin/bash
# Multi command start in various konsole tabs

# List of commands to run, with parameters, in quotes, space-separated; do not use quotes inside (see bash arrays)
COMMANDS=("/my/prog1 param" "/my/prog2 param2" "/my/prog3 param1 param2 param3")

# KDS=$KONSOLE_DBUS_SERVICE # This is a ref to current Konsole and only works in Konsole
# KDS=$(org.kde.konsole)    # This is found in some examples but is incomplete

qdbus >/tmp/q0              # Get the current list of konsoles
/usr/bin/konsole            # Launch a new konsole
# PID=$!                    # And get its PID - But for some reason this is off by a few
sleep 1
qdbus >/tmp/q1              # Get the new list of konsoles
# KDS=org.kde.konsole-$PID      
# KDS=org.kde.konsole       # Sometimes
KDS=$(diff /tmp/q{0,1} | grep konsole)  # Let's hope there's only one
#echo $KDS
KDS=${KDS:3}
echo $KDS

echo $KDS >/tmp/KDS
echo >>/tmp/KDS

qdbus $KDS >>/tmp/KDS || exit
echo >>/tmp/KDS

# See note https://docs.kde.org/trunk5/en/applications/konsole/scripting.html about using /Konsole
qdbus $KDS /Konsole >>/tmp/KDS
echo >>/tmp/KDS

FirstTime=1

for i in "${COMMANDS[@]}"
do 
    echo "Starting: $i"
    echo >>/tmp/KDS
    if [ $FirstTime -eq 1 ]
    then
        session=$(qdbus $KDS /Konsole currentSession)
        FirstTime=0
    else
        session=$(qdbus $KDS /Konsole newSession)
    fi
    echo $session >>/tmp/KDS

    # Test: Display possible actions
    qdbus $KDS /Sessions/${session} >>/tmp/KDS

    # Doesn't work well, maybe use setTabTitleFormat 0/1 instead
    # Title "0" appears to be the initial title, title "1" is the title used after commands are executed. 
    #qdbus $KDS /Sessions/${session} setTitle 0 $i
    #qdbus $KDS /Sessions/${session} setTitle 1 $i

    # The line break is necessary to commit the command. \n doesn't work
    qdbus $KDS /Sessions/${session} sendText "${i}
"

    # Optional: will ping when there's no more output in the window
    qdbus $KDS /Sessions/${session} setMonitorSilence true
done

Update 2016: the structure of qdbus has changed again. Here's an update of the above script (I left out the original since depending on your KDE version you may need one or the other):

#! /bin/bash
# Multi command start in various konsole tabs

# List of commands to run, with parameters, in quotes, space-separated; do not use quotes inside (see bash arrays)
COMMANDS=("echo 1" "echo 2" "echo 3")

# KDS=$KONSOLE_DBUS_SERVICE # This is the ref of the current konsole and only works in a konsole
# KDS=$(org.kde.konsole)    # This is found in some examples but is incomplete

qdbus >/tmp/q0              # Get the current list of konsoles
/usr/bin/konsole            # Launch a new konsole
sleep 1
qdbus >/tmp/q1              # Get the new list of konsoles
KDS=$(diff /tmp/q{0,1} | grep konsole)  # Let's hope there's only one
KDS=${KDS:3}
echo $KDS

echo $KDS >/tmp/KDS
echo >>/tmp/KDS

qdbus $KDS >>/tmp/KDS || exit
echo >>/tmp/KDS

# See note https://docs.kde.org/trunk5/en/applications/konsole/scripting.html about using /Konsole
qdbus $KDS /konsole >>/tmp/KDS
echo >>/tmp/KDS

FirstTime=1

for i in "${COMMANDS[@]}"
do 
    echo "Starting: $i"
    echo >>/tmp/KDS
    if [ $FirstTime -eq 1 ]
    then
        session=$(qdbus $KDS /Windows/1 currentSession)
        FirstTime=0
    else
        session=$(qdbus $KDS /Windows/1 newSession)
    fi
    echo $session >>/tmp/KDS

    # Test: Display possible actions
    qdbus $KDS /Sessions/${session} >>/tmp/KDS

    # The line break is necessary to commit the command. \n doesn't work
    qdbus $KDS /Sessions/${session} sendText "${i}
"

    # Optional: will ping when there's no more output in the window
    qdbus $KDS /Sessions/${session} setMonitorSilence true
done
Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
dargaud
  • 2,431
  • 2
  • 26
  • 39
  • This looks lovely, but I don't know enough to modify it. How could I get it to start a new instance of konsole with 5 tabs open in different directories, but not running anything? I'm using KDE 5.18.0 on Ubuntu 16.04. If this is too involved, I can ask it as a separate question. – Joe Oct 21 '16 at 23:27
  • Simply comment out the line with sendText and sendMonitorSilence. But this script does not work anymore, they changed the structure of the calls, again. I'll update it. – dargaud Oct 25 '16 at 08:11
  • +1 Thanks. That works great! If I could trouble you for one last thing: After I start three sessions in the loop, how do I get it to make the first session the active one instead of the last one which was created? I saved its session number in a variable, but don't know how to use it. I didn't see a method that looked like it would do that. – Joe Oct 27 '16 at 04:12
  • I tried playing with qdbus $KDS but did not find anything resembling an activate function for a tab and/or session. – dargaud Oct 27 '16 at 14:02
  • Thanks for looking. – Joe Oct 31 '16 at 21:20
  • 1
    There is also `runCommand` which is a bit more appropriate than `sendText`. – Ondra Žižka Jan 02 '17 at 00:19
  • The sad thing is that this is extremely verbose. It should really just be a one-liner without too many commands - though that may only be my own opinion, but see also the answer above. – shevy Nov 07 '18 at 10:22
-1

qdbus solution above didn't work for me because blockable call /usr/bin/konsole, so I upgrade it a little. I'm using ZSH so change shebang on yours.

#! /bin/zsh
# Multi command start in various konsole tabs

# List of commands to run, with parameters, in quotes, space-separated; do not use quotes inside (see bash arrays)
COMMANDS=("vi" "nano")
# Geting length of the COMMANDS array
len_arr=${#COMMANDS[@]}

# Simple /usr/bin/konsole block this script, no work for me. So use qdbus to run konsole
qdbus org.kde.klauncher5 /KLauncher exec_blind "/usr/bin/konsole" "/home/$USER"
# Wait until konsole was run up completely. 1s for me
sleep 1s
# get the last added konsole and save it in $KDS variable
qdbus | grep konsole | tail -1 | { read KDS }
# loop the array with commands . 
for (( i=1; i<=$len_arr; i++ ))
do
 if [ $i -gt 1 ]
 then
     # for all commands beside first getting the number of the new konsole tab
     session=$(qdbus $KDS /Windows/1 newSession)
     
 else
     # get the number of the current console tab
     session=$(qdbus $KDS /Windows/1 currentSession)
 fi
 # run current command in tab
 qdbus $KDS /Sessions/${session} runCommand "${COMMANDS[$i]}"
 
 # Silence if you need. I'm not using it.
 # Optional: will ping when there's no more output in the window
 # qdbus $KDS /Sessions/${session} setMonitorSilence true
done