using sed and pstree to display the type of terminal being used

前端 未结 4 1305
慢半拍i
慢半拍i 2021-01-28 14:02

I\'ve been trying to display the type of terminal being used as the name only. For instance if I was using konsole it would display konsole. So far I\'ve been using this command

相关标签:
4条回答
  • 2021-01-28 14:21

    I don't know how to isolate the terminal name on your system, but as a parsing exercise, and assuming the terminal is directly running your bash you could pipe the pstree output through:

     awk -F"---bash---" ' NF == 2 { count = split( $1, arr, "---" ); print arr [count]; }'
    

    This will find the word prior to the "---bash---" which in your examples is

    konsole
    terminator
    lxterminal
    

    If you want different shell types, you could expand the field separator to include them like:

    awk -F"---(bash|csh)---" ' NF == 2 { count = split( $1, arr, "---" ); print arr[count]; }'
    

    Considering an imaginary line like:

    systemd---imaginary---monkey---csh---pstree
    

    the awk would find "monkey" as the terminal name as well as anything from your test set.

    0 讨论(0)
  • 2021-01-28 14:23

    You could use

    ps -p "$PPID" -o comm=
    

    Or

    ps -p "$PPID" -o fname=
    

    If your shell does not have PPID variable set you could get it with

    ps -p "$(ps -p "$$" -o ppid= | sed 's|\s\+||')" -o fname=
    

    Another theory is that the parent process of the current shell that doesn't belong to the same tty as the shell could actually be the one that produces the virtual terminal, so we could find it like this as well:

    #!/bin/bash
    
    shopt -s extglob
    
    SHELLTTY=$(exec ps -p "$$" -o tty=)
    P=$$
    
    while read P < <(exec ps -p "$P" -o ppid=) && [[ $P == +([[:digit:]]) ]]; do
        if read T < <(exec ps -p "$P" -o tty=) && [[ $T != "$SHELLTTY" ]]; then
            ps -p "$P" -o comm=
            break
        fi
    done
    
    0 讨论(0)
  • 2021-01-28 14:30
    curTerm=$(update-alternatives --query x-terminal-emulator | grep '^Best:')
    curTerm=${curTerm##*/}
    
    printf "%s\n" "$curTerm"
    

    And the result is

    terminator
    

    Of course it can be different.
    Now you can use $curTerm variable in your sed command.

    But I am not sure if this is going to work properly with symlinks.

    0 讨论(0)
  • 2021-01-28 14:38

    No guarantees here, but I think this will work most of the time, on linux:

    ps -ocomm= $(lsof -tl /proc/$$/fd/0 | grep -Fxf <(lsof -t /dev/ptmx))
    

    A little explanation is probably in order, but see man ps, man lsof and (especially) man pts for information.

    /dev/ptmx is a pseudo-tty master (on modern linux systems, and some other unix(-like) systems). A program will have one of these open if it is a terminal emulator, a telnet/ssh daemon, or some other program which needs a captive terminal (screen, for example). The emulator writes to the pseudo-tty master what it wants to "type", and reads the result from the pseudo-tty slave.

    /proc/$$/fd/0 is stdin of process $$ (i.e. the shell in which the command is executed). If stdin has not been redirected, this will be a symlink to some slave pseudotty, /dev/pts/#. That is the other side of the /dev/ptmx device, and consequently all of the programs listed above which have /dev/ptmx open will also have some /dev/pts/# slave open as well. (You might think that you could use /dev/stdin or /dev/fd/0 instead of /proc/$$/fd/0, but those would be opened by lsof itself, and consequently would be its stdin; because of the way lsof is implemented, that won't work.) The -l option to lsof causes it to follow symlinks, so that will cause it to show the process which have the same pts open as the current shell.

    The -t option to lsof causes it to produce "terse" output, consisting only of pids, one per line. The -Fx options to grep cause it to match strings, rather than regex, and to force a full line match; the -f FILE option causes it to accept the strings to match from FILE (which in this case is a process substitution), one per line.

    Finally, ps -ocomm= prints out the "command" (chopped, by default, to 8 characters) corresponding to a pid.

    In short, the command finds a list of terminal emulators and other master similar programs which have a master pseudo-tty, and a list of processes which use the pseudo-tty slave; finds the intersection between the two, and then looks up the command name for whatever results.

    0 讨论(0)
提交回复
热议问题