5

Is there a way to print out all of the local and remote shells I am currently in, recursively?

For example, on my local machine, I will ssh into another machine. From there, I may switch users (opening another shell). Then I ssh to my local machine again, etc. And to complicate matters, I'll generally have multiple tabs (and even windows) of shells, so I can't usually remember my trail for each one.

What I would like is to have each of those sessions print out in order where I am. Or at least what shell I will be kicked back into if I exit the current shell.

After a few days or weeks of having multiple shells open, I have no idea where I will be sent if I type in exit. Will my shell window close (because I'm at the 'root' shell)? Will I be kicked back to another server?

In other words, I'd like a trace of my SSH hops.

  • 2
    And you want to receive electro shocks when a ssh-loop is detected? – ott-- Jul 5 '13 at 16:07
2

You could write a script that just walks up the process tree printing out unique usernames/pids/executables/whatever as it went up the list, stopping when it finally left the terminal. sshd usually starts listening on a TTY after it has already done the setuid() to the user so the earliest process connected to the TTY will be running as the user you logged in with.

Here's a Linux-specific Bash script version of the concept.

script output:

Simple sudo to root:

[root@ditirlns04 ~]# ./test.sh
Current User: 0
Previous UID: 504

UID 504 is how I logged into the box so it worked:

[root@ditirlns04 ~]# logname
jadavis6
[root@ditirlns04 ~]# id jadavis6
uid=504(jadavis6) gid=504(jadavis6) groups=504(jadavis6),16777216(enterprise admins),16777217(ncatsys),16777218(sms admins),16777219(domain admins),16777220(aggieanywhere),16777221(group policy creator owners),16777222(tlh-test),16777223(dba admins),16777224(domain controllers),16777225(cupsadmin),16777226(linuxusers),16777227(da admins),16777228(webdev),16777229(schema admins),16777230,16777231(changeauditor operators - ncat),16777232(configmgr remote control users),16777233(changeauditor administrators - ncat),16777234(telnetclients),16777235(denied rodc password replication group)

Same as above, only going through an intermediary user (i.e: logged in 504, sudo'd to root, sudo'd to regular UID of 501, then back to root):

[root@ditirlns04 ~]# ./test.sh
Current User: 0
Previous UID: 501
Previous UID: 0
Previous UID: 504
[root@ditirlns04 ~]#

So each UID transition is caught in reverse order that it happened in. If you need it in the same order, just put the script into a function where you tac the output:

[root@ditirlns04 ~]# ./test.sh | tac
Previous UID: 504
Previous UID: 0
Previous UID: 501
Current User: 0
[root@ditirlns04 ~]#

script body:

#!/bin/bash

currentPID=$$
currentUser=$(id -u)
currentTTY=$(awk '{print $7}' /proc/$$/stat)

echo "Current User: $currentUser"

while /bin/true; do

  parentPID=$(awk '{print $4}' /proc/$currentPID/stat)
  parentTTY=$(awk '{print $7}' /proc/$currentPID/stat)

  if [ $parentTTY -ne $currentTTY ]; then
     break
  fi

  parentUser=$(awk '/^Uid:/ {print $2}' /proc/$currentPID/status)

  if [[ "x$parentUser" != "x$currentUser" ]]; then
     echo "Previous UID: $parentUser"
  fi

  currentPID=$parentPID
  currentUser=$parentUser

done

Basically, it just makes use of the per-pid stat and status files. You could make more platform independent versions wrapping around ps output, but I don't trust parsing command output when the datum is readily available in a format meant to be parsed, so I went the procfs route.

Basically, any time it finds a new UID it prints it out. They're guaranteed to be in the same order the user sudo'd so it should effectively cover your entire login session on that machine. You should be able to easily modify the above to print PID's or command names instead if you want that, but usually people thinking in this area are more concerned with who they'll be running as rather than the shell program that will be running.

1

A shell started from sshd can identify this by the presence of the $SSH_CLIENT variable. Another variable, $SHLVL, can indicate a shell started from another shell on the same host. If you need to trace further, choose a variable and allow sshd to accept it from remote ssh clients.

1

You can see your shells using the following ps command. It isn't perfect but does a pretty good job of showing the hierarchy of the shells in a nice tree format:

$ ps auxw --forest | grep -E "gnome-terminal|\_ bash|-bash|sshd|login "

Also you can find out which shell you're in by simply looking at the current shell's PID using $$:

$ echo $$

Example

$ ps auxw --forest | grep -E "gnome-terminal|\_ bash|-bash|sshd|login "
root      1751  0.0  0.0  67824   820 ?        Ss   Jun24   0:00 login -- root     
root       989  0.0  0.0 114116   928 tty2     Ss+  Jun30   0:00  \_ -bash
saml      6018  0.0  0.1 553356 13296 ?        Sl   Jun24   3:42 gnome-terminal
saml      8182  0.0  0.0 115104   992 pts/2    Ss+  Jun24   0:00  \_ bash
saml      3483  0.0  0.0 115156   936 pts/62   Ss   Jun27   0:02  \_ bash
saml      3742  0.0  0.0 114972  1712 pts/64   Ss+  Jun28   0:00  \_ bash
saml      7368  0.0  0.0 122544  4608 pts/65   Ss   Jun28   0:05  \_ bash
saml     32256  0.0  0.0 114980  6320 pts/65   S    20:54   0:00  |   \_ bash
saml      3753  0.0  0.0 115036  1960 pts/81   Ss+  Jul03   0:01  \_ bash
saml     12843  0.0  0.0 115076  5204 pts/82   Ss+  Jul03   0:01  \_ bash
saml     14702  0.0  0.0 114972  6392 pts/87   Ss   16:04   0:00  \_ bash
root     26084  0.0  0.0  75096  1152 ?        Ss   09:40   0:00 /usr/sbin/sshd
root     32345  0.0  0.0 106716  3840 ?        Ss   20:55   0:00  \_ sshd: saml [priv]
saml     32349  0.0  0.0 106716  1800 ?        S    20:55   0:00      \_ sshd: saml@pts/88
saml     32352  0.0  0.0 114908  6304 pts/88   Ss   20:55   0:00          \_ -bash
saml     32764  0.0  0.0 103380   820 pts/88   S+   21:02   0:00              \_ grep --color=auto -E gnome-terminal|\_ bash|-bash|sshd|login 

What's my PID?

$ echo $$
32352
So I'm here:

saml 32352 0.0 0.0 114908 6304 pts/88 Ss 20:55 0:00 _ -bash

 # Now if I exit
 $ exit

  # I'm in this shell now
 $ echo $$
 32256
Now I'm here:

saml 32256 0.0 0.0 114980 6320 pts/65 S 20:54 0:00 | _ bash

 # Another exit
 $ exit

 # I'm now here
 $ echo $$
 7368
Finally I'm here:

saml 7368 0.0 0.0 122544 4608 pts/65 Ss Jun28 0:05 _ bash

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.