gpakosz / .tmux

🇫🇷 Oh my tmux! My self-contained, pretty & versatile tmux configuration made with ❤️
MIT License
22.02k stars 3.37k forks source link

Status bar to display hostname on ssh #208

Closed bserrao closed 2 years ago

bserrao commented 5 years ago

Hi, The issue i'm facing is the following: 1- I connect over ssh to a jump machine where i have tmux 2- Attach to existing tmux session or open a new one. (Here everything works as supposed i'm able to see username and host correctly)

image

3- ssh to another machine. Here i would like to have the username and host of the machine i've connected but i get the following

image

It's possible to show the hostname i'm connected to?

Thanks

gpakosz commented 5 years ago

Hello @bserrao 👋

I find it strange that /usr/bin/ssh ends up being shown as hostname 🤔

I understand that your situation is the following:

Is that correct?

bserrao commented 5 years ago

yep, that's correct.

gpakosz commented 5 years ago

Alright, can you please give me the following details?

Thank you

bserrao commented 5 years ago

OS: Centos Release 6.7 Tmux 2.6 (Installed as user, no root previleges) OpenSSH_5.3p1

gpakosz commented 5 years ago

Alright, I'll need a bit of help.

Debugging is tricky but feasible, please follow the following steps.

  1. from s4gesin2, open a new tmux window
  2. and run the following command tmux display -p '#{pane_tty}' → let's pretend the output is /dev/ttys050
  3. from that same pane, ssh into host3
  4. now from s4gesin2, split the window to have a second pane
  5. from that second pane, run cut -c3- ~/.tmux.conf | sh -sx _hostname /dev/ttys050 ← this is important to use the tty from which you initiated the ssh connection to host3

And please paste the output of cut -c3- ~/.tmux.conf | sh -sx _hostname /dev/ttys050 in a code block here.

bserrao commented 5 years ago

First of all thank you for your help and fast response. The debug you asked me to do, helped me remember something.... on s4gesin2 the ssh command is a symlink to other executable (responsible to save some audit logs) that calls the original ssh command in the end... I've tried to run the original ssh command and the hostname shows, but username is blank.

Here goes the output:


+ set -e
+ export LC_NUMERIC=C
+ LC_NUMERIC=C
+ __newline='
'
+ _hostname /dev/pts/3
+ tty=/dev/pts/3
+ ssh_only=
+ '[' xlinux-gnu = xcygwin ']'
++ ps -t /dev/pts/3 -o command=
++ awk '/ssh/ && !/vagrant ssh/ && !/autossh/ && !/-W/ { $1=""; print $0; exit }'
+ ssh_parameters=' /usr/bin/ssh c4caredb2'
+ '[' -n ' /usr/bin/ssh c4caredb2' ']'
++ ssh -G /usr/bin/ssh c4caredb2
++ awk 'NR > 2 { exit } ; /^hostname / { print $2 }'
+ hostname=
+ '[' -z '' ']'
++ ssh -T -o ControlPath=none -o 'ProxyCommand=sh -c '\''echo %%hostname%% %h >&2'\''' /usr/bin/ssh c4caredb2
++ awk '/^%hostname% / { print $2; exit }'
+ hostname=/usr/bin/ssh
++ echo /usr/bin/ssh
++ awk '\
    { \
      if ($1~/^[0-9.:]+$/) \
        print $1; \
      else \
        split($1, a, ".") ; print a[1] \
    }'
+ hostname=/usr/bin/ssh
+ echo /usr/bin/ssh
/usr/bin/ssh
gpakosz commented 5 years ago

Ah that's interesting.

It seems my conf is confused by your script. In the debug output, we can see ssh_parameters=' /usr/bin/ssh c4caredb2' and ssh -G /usr/bin/ssh c4caredb2 and this is the culprit.

$ ssh -G FOOBARBAZ | grep hostname
hostname FOOBARBAZ
canonicalizehostname false

explains why ssh -G /usr/bin/ssh whatever | grep hostname answers /usr/bin/ssh and that's what you end up seeing displayed.

Can you please paste the output of ps -t /dev/pts/3 -o command=? Where /dev/pts/3 is the TTY from which the ssh command is issued.

bserrao commented 5 years ago

sure, here goes


-bash
/bin/bash /usr/bin/ssh c4caredb2
/usr/bin/ssh_orig c4caredb2
sudo tee -a /var/log/audit_users/tm504391/tm504391-pts3.ssh.log
tee -a /var/log/audit_users/tm504391/tm504391-pts3.ssh.log
gpakosz commented 5 years ago

Thank you.

For now, I'm not sure how to solve this in the general case. And I'm inclined to categorize this issue as enhancement rather than bug.

bserrao commented 5 years ago

Okay, thanks for you time. I understand this isn't the usual behaviour (probably it's only me), so it might not make sense to make changes. If you remember something i can try to change on my side only, to make it work let me know.

I'll also have look at my script to see if i can make any changes that work.

gpakosz commented 3 years ago

Hello @bserrao 👋

It's been a while! I don't know if you're still using the same setup but I just pushed the gh-208 that I believe makes it work in your case.

Can you please give it a try?

bserrao commented 3 years ago

Hey there, I haven't updated in a while... but i've just tried the new version image

This is on the bastion host (jump machine), no uptime, user or hostname shown. The older version i was using displays like this: image

gpakosz commented 3 years ago

You need to reload the configuration with <prefix> + r after pulling changes 🙂

bserrao commented 3 years ago

It's not that... :) maybe i'm missing some dependency. I've closed tmux and open a new one, also reloaded like you said... same behavior. As soon as i put the "old" tmux conf and reload it works again, like the screens above

gpakosz commented 3 years ago

Does the master branch work?

gpakosz commented 3 years ago

I double checked, %0 being displayed instead of hostname happens when .tmux.conf has been updated but the configuration not reloaded

bserrao commented 3 years ago

I was making a video to show you the behavior and noticed this: <'cut -c3- ~/.tmux.conf | sh -s _username 7378 false %0' not ready> <'cut -c3- ~/.tmux.conf | sh -s _hostname 7378 false false gesin2 %0' not ready>

Does this makes sense to you? Right now i don't have much time to debug this... Thanks BTW

https://user-images.githubusercontent.com/8951686/138435504-9d75f274-f158-436b-8965-6fdc676b9062.mp4

:)

gpakosz commented 3 years ago

I can't manage to play the video 😐

bserrao commented 3 years ago

neither do i 😄

https://user-images.githubusercontent.com/8951686/138467573-9ab2df51-2517-4f06-a3e8-b6bf44a8a3f3.mp4

I think it's working now.

gpakosz commented 3 years ago

I used Windows Terminal and Debian but can't reproduce it 🤔

Can you please double check

Then can you please launch the following command from a pane:

$ cut -c3- ~/.tmux.conf | sh -sx _hostname $(tmux display -p '#{pane_pid} #{pane_tty} false true #h')

Because at that point I have no idea of what's going on 😢

bserrao commented 3 years ago

The tmux version is 2.6 I've just copied both files (.tmux.conf and .tmux.conf.local) inside my home

Here goes the output:

+ :                                                                                                                                                                                                                            [2/3]+ set -e                                                                                                                                                                                                                            + unset GREP_OPTIONS                                                                                                                                                                                                                + export LC_NUMERIC=C
+ LC_NUMERIC=C
+ printf ''
+ sed -E s///
++ uname -s
+ _uname_s=Linux
++ tmux -V
++ awk '{gsub(/[^0-9.]/, "", $2); print ($2+0) * 100}'
+ _tmux_version=260
+ command -v pkill
+ _hostname 16792 /dev/pts/13 false true gesin2
+ pane_pid=16792
+ tty=/dev/pts/13
+ ssh_only=false
+ full=true
+ h_or_H=gesin2
++ _pane_info 16792 /dev/pts/13
++ pane_pid=16792
++ tty=pts/13
++ case "$_uname_s" in
++ command -v lsof
++ lsof -awPROnX -d0 -S2 -- /dev/pts/13
++ awk -v pane_pid=16792 '
          NR > 1 {
            user[$2] = $4; parent[$2] = $3; child[$3] = $2; pid=$2;
          }
          END {
            pid = pane_pid
            while (child[pid])
              pid = child[pid]

            "ps -p " pid " -o command=" | getline command
            print pid":"user[pid]":"command
          }
        '
+ pane_info=16792:tm504391:-bash
+ command=tm504391:-bash
+ command=-bash
++ _ssh_or_mosh_args -bash
++ case "$1" in
++ printf %s ''
+ ssh_or_mosh_args=
+ '[' -n '' ']'
+ _is_enabled false
+ '[' xfalse = xtrue ']'
+ '[' xfalse = xyes ']'
+ '[' xfalse = xenabled ']'
+ '[' xfalse = x1 ']'
+ hostname=gesin2
+ printf '%s\n' gesin2
gesin2

The version i was using before still works... Now both master and this gh-208 have this behaviour. Also tried command prompt instead of windows terminal and the result is the same.

gpakosz commented 3 years ago

What I don't understand then is that the command you ran correctly prints gesin2 so I don't explain the %0 in your video 🤷‍♂️

bserrao commented 3 years ago

Hello, I've compiled and updated ncurses, libevent and tmux (3.2a) and the user and hostname are showing again :) About showing the hostname i SSH into, it still doesn't update... but it's better now. Now it keeps showing my username and previous host.

image

On the master branch also shows gesin2 as the host, but shows username like root whenever i ssh into another machine. Anyway i appreciate your effort but don't mind to much... i belive my use case is rare or unique 😄

bserrao commented 3 years ago

Here's some debug:

cut -c3- ~/.tmux.conf | sh -sx _hostname /dev/pts/18                                                                                                                                                                                                                                   [75/520]+ :
+ set -e
+ unset GREP_OPTIONS
+ export LC_NUMERIC=C
+ LC_NUMERIC=C
+ sed -E s///
+ printf ''
++ uname -s
+ _uname_s=Linux
++ tmux -V
++ awk '{gsub(/[^0-9.]/, "", $2); print ($2+0) * 100}'
+ _tmux_version=320
+ command -v pkill
+ _hostname /dev/pts/18
+ pane_pid=/dev/pts/18
++ tmux display -p '#{s,/dev/,,:pane_tty}'
+ tty=pts/24
+ ssh_only=
+ full=
+ h_or_H=
++ _pane_info /dev/pts/18 pts/24
++ pane_pid=/dev/pts/18
++ tty=pts/24
++ case "$_uname_s" in
++ command -v lsof
++ lsof -awPROnX -d0 -S2 -- /dev/pts/24
++ awk -v pane_pid=/dev/pts/18 '
          NR > 1 {
            user[$2] = $4; parent[$2] = $3; child[$3] = $2; pid=$2;
          }
          END {
            pid = pane_pid
            while (child[pid])
              pid = child[pid]

            "ps -p " pid " -o command=" | getline command
            print pid":"user[pid]":"command
          }
        '
ERROR: Process ID list syntax error.
********* simple selection *********  ********* selection by list *********
-A all processes                      -C by command name
-N negate selection                   -G by real group ID (supports names)
-a all w/ tty except session leaders  -U by real user ID (supports names)
-d all except session leaders         -g by session OR by effective group name
-e all processes                      -p by process ID
                                      -q by process ID (unsorted & quick)
T  all processes on this terminal     -s processes in the sessions given
a  all w/ tty, including other users  -t by tty
g  OBSOLETE -- DO NOT USE             -u by effective user ID (supports names)
r  only running processes             U  processes for specified users
x  processes w/o controlling ttys     t  by tty
*********** output format **********  *********** long options ***********
-o,o user-defined  -f full            --Group --User --pid --cols --ppid
-j,j job control   s  signal          --group --user --sid --rows --info
-O,O preloaded -o  v  virtual memory  --cumulative --format --deselect
-l,l long          u  user-oriented   --sort --tty --forest --version
-F   extra full    X  registers       --heading --no-heading --context
                                      --quick-pid
                    ********* misc options *********
-V,V  show version      L  list format codes  f  ASCII art forest
-m,m,-L,-T,H  threads   S  children in sum    -y change -l format
-M,Z  security data     c  true command name  -c scheduling class
-w,w  wide output       n  numeric WCHAN,UID  -H process hierarchy
+ pane_info=/dev/pts/18::
+ command=:
+ command=
++ _ssh_or_mosh_args ''
++ case "$1" in
++ printf %s ''
+ ssh_or_mosh_args=
++ case "$1" in
++ printf %s ''
+ ssh_or_mosh_args=
+ '[' -n '' ']'
+ _is_enabled ''
+ '[' x = xtrue ']'
+ '[' x = xyes ']'
+ '[' x = xenabled ']'
+ '[' x = x1 ']'
+ hostname=
+ printf '%s\n' ''
gpakosz commented 3 years ago

You should use

$ cut -c3- ~/.tmux.conf | sh -sx _hostname $(tmux display -p '#{pane_pid} #{pane_tty} false true #h')

As the parameters of _hostname() have recently changed.

Also I force pushed the gh-208 branch as using lsof was a dead end

gpakosz commented 3 years ago

BTW can you share again the ssh script you use to replace the ssh command?

bserrao commented 3 years ago

Sure,

user=`who am i|awk '{print $1}'
sess=`tty|awk -F '/' '{print $3$4}'

/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 "$@"|sudo tee -a /var/log/audit_users/$user/$user-$sess.ssh.lo
gpakosz commented 3 years ago

image

👆 In the screenshot above, I did

As you can see, username and hostname are properly detected

bserrao commented 3 years ago

Hum.... 😄 I think we are close here!

First pane

[tm504391@gesin2 ~]$ tmux display -p '#{pid} #{client_pid} #{pane_pid} #{pane_tty}'
2114 2078 6316 /dev/pts/2
[tm504391@gesin2 ~]$ ssh inapps

Second pane

[tm504391@gesin2 ~]$ cut -c3- ~/.tmux.conf | sh -s _pane_info 6316 /dev/pts/2
16438:tm504391:/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps
cut -c3- ~/.tmux.conf | sh -sx _hostname $(tmux display -p '6316 /dev/pts/2 false true #h')
+ :
+ set -e
+ unset GREP_OPTIONS
+ export LC_NUMERIC=C
+ LC_NUMERIC=C
+ printf ''
+ sed -E s///
++ uname -s
+ _uname_s=Linux
++ tmux -V
++ awk '{gsub(/[^0-9.]/, "", $2); print ($2+0) * 100}'
+ _tmux_version=320
+ command -v pkill
+ _hostname 6316 /dev/pts/2 false true gesin2
+ pane_pid=6316
+ pane_tty=/dev/pts/2
+ ssh_only=false
+ full=true
+ h_or_H=gesin2
++ _pane_info 6316 /dev/pts/2
++ pane_pid=6316
++ pane_tty=pts/2
++ case "$_uname_s" in
++ awk -v pane_pid=6316 '
        ((/ssh/ && !/-W/) || !/ssh/) && !/tee/ {
          user[$2] = $1; if (!child[$3]) child[$3] = $2; pid=$2; $1 = $2 = $3 = ""; command[pid] = substr($0,4)
        }
        END {
          pid = pane_pid
          while (child[pid])
            pid = child[pid]

          print pid":"user[pid]":"command[pid]
        }
      '
++ ps -t pts/2 --sort=lstart -o user=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -o pid= -o ppid= -o command=
+ pane_info='16438:tm504391:/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
+ command='tm504391:/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
+ command='/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
++ _ssh_or_mosh_args '/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
++ case "$1" in
+++ printf %s '/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
+++ perl -n -e 'print if s/(.*?)\bssh\b\s+(.*)/\2/'
++ args=
++ printf %s ''
+ ssh_or_mosh_args=
+ '[' -n '' ']'
+ _is_enabled false
+ '[' xfalse = xtrue ']'
+ '[' xfalse = xyes ']'
+ '[' xfalse = xenabled ']'
+ '[' xfalse = x1 ']'
+ hostname=gesin2
+ printf '%s\n' gesin2
gesin2
gpakosz commented 3 years ago

Ah thanks for the feedback!

I pushed a commit to the gh-208 branch that should wrap it up!

In _ssh_or_mosh_args(), the regex I was using didn't match ssh_orig. The command had to match ssh and nothing else: perl -n -e 'print if s/(.*?)\bssh\b\s+(.*)/\2/'

I rewrote it to support sshxxxx as well as dbclient which is the name of the Dropbear SSH client

bserrao commented 3 years ago

No, thank you for putting so much effort into this :) I confirm the hostname now shows correctly which is a huge improvement for me 🎉 , but now the user isn't showing up. I believe it's something minor with the regex also... but don't bother if it's something more awkward.

Dunno if this helps... Tried with ssh hostname and ssh user@hostname, same behavior

+ pane_info='15268:tm504391:/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
+ command='tm504391:/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
+ command='/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
++ _ssh_or_mosh_args '/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
++ case "$1" in
+++ printf %s '/usr/bin/ssh_orig -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
+++ perl -n -e 'print if s/.*?\b(ssh|dbclient).*?\b\s+(.*)/\2/'
++ args='-o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
++ printf %s '-o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
+ ssh_or_mosh_args='-o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps'
+ '[' -n '-o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps' ']'
++ awk '/^user / { print $2; exit }'
++ ssh -G -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps
+ username=
+ '[' -z '' ']'
++ ssh -T -o ControlPath=none -o 'ProxyCommand=sh -c '\''echo %%username%% %r >&2'\''' -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps
++ awk '/^%username% / { print $2; exit }'
+ username=
+ printf '%s\n' ''
gpakosz commented 3 years ago

This is your ssh script interfering again 😅

Can you please run

$ ssh -G -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps

and

$ ssh -T -o ControlPath=none -o 'ProxyCommand=sh -c '\''echo %%username%% %r >&2'\''' -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps

?

bserrao commented 3 years ago

Hello,

The second ssh shows this error: percent_expand: unknown key %

gpakosz commented 3 years ago

And what does the first one say?

$ ssh -G -o ServerAliveInterval=300 -o ServerAliveCountMax=3 inapps

This should print out all the values the ssh client will use to connect to the remote server.

gpakosz commented 3 years ago

Also can you please try

$ ssh -T -o ControlPath=none -o ProxyCommand="sh -c 'echo %%username%% %r >&2'" inapps
bserrao commented 3 years ago

Hey there, sorry for the late feedback but work had been crazy this days...

The ssh version in this machine doesn't have the -G option, and the error is the same using ". (unknown key %r) But like i said before... it's perfect like this :)

Cheers

gpakosz commented 3 years ago

Can you please share the version of your ssh client? Is this OpenSSH Client?

bserrao commented 2 years ago

OpenSSH_5.3p1

gpakosz commented 2 years ago

That's indeed an old version but it should support %r.

My understanding is that your client understands %h

$ ./ssh -T -o ControlPath=none -o ProxyCommand="sh -c 'echo %h >&2'" inapps

But not %r

$ ./ssh -T -o ControlPath=none -o ProxyCommand="sh -c 'echo %r >&2'" inapps

I have a last question please. Does your man ssh_config have a section about TOKENS that mentions tokens accepted by ProxyCommand? image

gpakosz commented 2 years ago

Hey @bserrao 👋

I installed rhel6 with Vagrant and played with this old version of OpenSSH client.

I forced pushed the gh-208 branch and I believe this should improve things and display the username when connecting to a remote server

bserrao commented 2 years ago

Hey @gpakosz Sorry for the delay... the man on ssh_config doesn't have the TOKENS section. Also the last update still doesn't display the username 😢, but for me the host is the most important and it's there... 😃 Thanks a lot for your work

Cheers

gpakosz commented 2 years ago

Alright! I'm tenacious 😅

I forced pushed again. What I pushed had a typo 😢

I believe I'm very close to your setup. While I understand username it's not so important to you, now that I understood that you have a script that replaces the original ssh command and that you're running OpenSSH_5.3p1 I see no blocker beside my own bugs and displaying the username should work.

Can you please try again when you have some more spare minutes? 🙏

bserrao commented 2 years ago

YAY !!! 🎉 I can confirm it's all working now!!!

Good work 😄 , thank you.

gpakosz commented 2 years ago

Thanks @bserrao for your patience 👍

I'll merge the branch soon and move on to other features 🎉