15

I have gnome-terminal and Guake installed. I want to give different startup messages to be displayed on these terminal emulators as they start. What code should I write in .bashrc so that this is achieved?

10

This function should do the job:

container() {
    pid=$$
    while true; do
        pid=$(ps -h -o ppid -p $pid 2>/dev/null)
        case $(ps -h -o comm -p $pid 2>/dev/null) in
        (gnome-terminal) echo "Running in gnome terminal";return;;
        (xterm) echo "Running in xterm";return;;
        (rxvt) echo "Running in rxvt";return;;
        (python) if [ ! -z "$(ps -h -o args -p $pid 2>/dev/null | grep guake)" ]; then echo "Running in Guake"; return; fi ;;
        esac
        [[ $(echo $pid) == 1 ]] && break
    done
}
container
  • Nice answer! Don't forget to actually call the function with container after the definition. – rosch Oct 31 '12 at 18:43
  • I expected this to be obvious but you are right, answer updated accordingly. – jlliagre Oct 31 '12 at 21:51
  • @jlliagre I tried the code. It works smoothly on gnome-terminal but it has a problem on Guake. It doesn't give any output. Instead it kind of freezes as if in deadlock. I have to Ctrl+C it to use it. Didn't really understand the code so don't know where it is going wrong. – VedVals Nov 1 '12 at 11:59
  • Code fixed. I missed guake is run by python and had a bug preventing the function to exit. Thanks for the feed-back. – jlliagre Nov 1 '12 at 16:40
  • Sorry dude, still not quite working. Gives error bash: [: too many arguments. Got bash v4.2.24, python v2.7.3 if it helps. – VedVals Nov 3 '12 at 11:29
10

Try this:

echo $TERM

This is more authoritative, but could be messed up by your programs. However on mine, it says xterm and on ttys it says linux, which I think stands for Linux Console.

  • 2
    $TERM is a variable which refers to the specification as self-reported by the terminal emulator you are using, not to the actual emulator itself. For example, on my system, echo $TERM returns xterm even though I am actually running lxterminal. What is happening is lxterminal self-reports xterm compliance. lxterminal is not actually fully xterm compliant, so you have to watch out. The spec files are usually located in /usr/share/terminfo. – stazher Dec 31 '16 at 22:44
7

You can get the terminal emulator name, by grepping the parents process name. Therefore it works with every terminal emulator.

In bash, zsh, etc.:

basename "/"$(ps -f -p $(cat /proc/$(echo $$)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')

With fish-shell:

basename "/"(ps -f -p (cat /proc/(echo %self)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')
  • Do note however, that this will catch program arguments when the terminal emulator is launched with them. – Robobenklein Jun 16 '17 at 13:53
  • Does this work if I'm connected using SSH? – user3731622 Mar 21 '18 at 17:38
  • @user3731622 it won't! You'll have to forward it from the client. – Enrico Jul 6 '18 at 3:51
2

On many linux system echo $TERM return xterm see stazher post above.

To get actual terminal in use, do this:

1: Close every terminal instance currently running.

2: Open new terminal using your usual method.

3: Enter command as follows:

ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)

4: Return should be something like such:

lxterminal --geometry=135x20

Here is breakdown:

So: ps is "process status"

ps option -o is Display information associated with the space or comma separated list of keywords specified. Sounds complicated, but is not really. (space or comma) separated (list of keywords) specified.

So, (list of keywords) is 'cmd=' Only one keyword in list. So, just asking to display command to open terminal.

ps option -p is "by process id" Wow this is very nice option for ps. Problem is, you must pass to ps this process id. So, how to get process id? We unwrap expression $(ps -o 'ppid=' -p $$)

Here we must start to think a little deeper. I wish I invented this bash one-liner, but I did not. I think I stole it from https://wiki.archlinux.org/ somewhere, I could not find again. Those guys are awesome, but many times I cannot understand what they say to do until after much study. What we can do, is to understand it now, because I will explain.

so we know $ is expansion operator in bash. I like to think "un-wrap". So, $(foo -opt bar) will unwrap, or expand, "foo -opt bar". But in bash, single round brace (...) opens subshell.

So, $(foo -opt bar) expands "foo -opt bar" as run in daughter shell. Very weird and difficult to understand.

OK, so now we are running almost identical command again, ps -o 'ppid=' -p $$ but this time ps, process status, shows us what he can see from within daughter shell instance.

-o list of keywords, only one keyword as before, but ppid= this is asking directly for process id of parent shell!! From WITHIN DAUGHTER SHELL! Very clever, yes? I am so excited when I can understand this!

-p again, "by process id" and in bash $$ is the process id.

If you call ps -o 'ppid=' -p $$ , or any other command asking for $$ directly from the first shell, he might say pid=1, or the pid from xWindow, or from your desktop program, or you maybe get actual pid of shell. If you ask many times, you maybe get different answer each time!

But, if you invoke a daughter and ask her "Who's your Daddy" she will tell you! Very clever. I wish I could be such genius to invent this method.

  • OK so AU will not allow proper breakdown within one post. Sorry, not willing to fight with blog system and make multiple posts. Maybe you can get idea. – stazher Dec 31 '16 at 23:45
  • Your other answer seems to be a sophisticated and informative comment on this answer rather than an answer to the question... It would be great if you could combine your two answers into one and delete one of them, and add to it so that it fully answers the question. Use ---- to draw a line in the middle? There is a button also. – Zanna Jan 1 '17 at 1:01
  • I think I have answered OP question exactly, and in detail.You jumped on me before I had a chance understand blog edit system and to finish. Bring on the down votes, I am used to it. – stazher Jan 1 '17 at 7:43
  • 1
    I don't think I jumped on you, I was just doing review... thanks for making your post more complete – Zanna Jan 1 '17 at 7:57
  • Thank you for your response. I am sorry, maybe I jumped on you. I apologise very much. – stazher Jan 1 '17 at 8:02
1

Using pstree and awk is the easyest way:

pstree -sA $$ | awk -F "---" '{ print $2 }'

Explaining

  1. Display a tree of processes with pstree of $$ (the atual process).
  2. The pstree arguments:

    • -s: display the parents of a process
    • -A: display output in pure ASCII.
  3. The awk tool scan a pattern and -F argument is used to split the processes.

  4. Finally '{ print $2 }'tells to awk to output only the 2nd match pattern (in this case, the terminal emulator name).
  • Are you sure about $2? In my case, what is piped in into awk is actually systemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree... – Enrico Maria De Angelis Jun 19 '18 at 9:44
  • @EnricoMariaDeAngelis Ya. Thank you for your observation. In my case the terminal emulator initializes directly in systemd service. I check again the code and edit it with a correction. – silvadev Jun 20 '18 at 11:35
  • This doesn't work when I use a keyboard shortcut to launch the emulator. On XFCE, I get xfsettingsd instead of the terminal I'm using. – Michael Hoffmann Sep 22 '18 at 5:26
  • Works better if you start from the end: pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }' – lleaff Dec 20 '18 at 23:33
0

You are correct, I only made answer for headline question, not question in body. So here you go, and Bob's yer Uncle.

I am not sure what the case switch was about, in one answer shown above. Such case switch is not needed. My ~/.bashrc script is actually only one simple line, all the echo commands are just for fun. How to explain...

Any term when starting reads ~/.bashrc , and executes whatever commands he will see in .bashrc. So, no matter which term is called, he will read .bashrc and execute the commands, so only structure needed in .bashrc would be to modify the behavior of or exclude one term or another. Desired behavior is for every term to execute same command, so case switch not needed. Terminal himself will tell you how he was called, so there is no need to differentiate.

Note (1) I did not test for guake, but works for all others mentioned in first answer by jlliagre.

Note (2) Due to formatting in markdown for wiki, you can not cut and paste as shown. You must delete each backtick, including to delete the underline characters, and add actual backtick, with no space before the ps or after the -p $$).

script for ~/.bashrc

# show welcome message for actual terminal in use
echo "Welcome.  You are attempting to use"
echo ""
echo _backtick_ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)_backtick_
echo ""
echo "Good Luck and God Speed."

This was much fun. I have added this to my own ~/.bashrc.

  • per Note(1), have tested on Tilda, works fine. Guake is similar to Tilda, but is written in python, so still do not know about Guake. – stazher Jan 1 '17 at 20:38
0

if you are using bash , I thing this command will help you :

which $(ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$))

0

If you were using ZSH, there is a better (faster) solution, which only uses ZSH builtins and manipulates /proc/$pid/{stat,cmdline} directly.

get-terminal-emulator() {
    if [[ $TTY = "/dev/tty"* ]]; then
        echo "linux-console"
        return
    fi
    local pid=$$ name=''
    while true; do
        proc_stat=(${(@f)$(</proc/${pid}/stat)})
        name=${proc_stat[2]//[()]/}
        case "${name}" in
            gnome-terminal|konsole|rxvt|xterm)
                echo "${name}"; return ;;
            python*)
                local cmdline=(${(@f)$(</proc/${pid}/cmdline)})
                if [[ "$cmdline" =~ "\\bguake.main\\b" ]]; then
                    echo "guake"; return
                fi
                ;;
        esac
        if test "$pid" = "1" -o "$pid" = ""; then
            echo "unknown"
            return
        fi
        pid=${proc_stat[4]}       
    done
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.