我可以递归打印所有当前的远程 shell 吗?

Ste*_*ger 5 ssh trace

有没有办法递归地打印出我当前所在的所有本地和远程 shell?

例如,在我的本地机器上,我将 ssh 连接到另一台机器。从那里,我可以切换用户(打开另一个外壳)。然后我再次 ssh 到我的本地机器,等等。更复杂的是,我通常会有多个 shell 选项卡(甚至窗口),所以我通常无法记住我对每个选项卡的跟踪。

我想要的是按照我所在的位置打印出每个会话。或者至少如果我exit是当前的 shell,我会被踢回哪个shell。

在打开多个外壳几天或几周后,我不知道如果我输入exit. 我的 shell 窗口会关闭吗(因为我在“根”shell 中)?我会被踢回另一台服务器吗?

换句话说,我想要我的 SSH 跃点的踪迹。

Bra*_*ley 2

您可以编写一个脚本,沿着进程树向上走,打印出唯一的用户名/pid/可执行文件/任何在列表中向上移动的内容,并在它最终离开终端时停止。sshd 通常在对用户执行 setuid() 后开始侦听 TTY,因此连接到 TTY 的最早进程将以您登录的用户身份运行。

这是该概念的 Linux 特定 Bash 脚本版本。

脚本输出:

简单的 sudo 到 root:

[root@ditirlns04 ~]# ./test.sh
Current User: 0
Previous UID: 504
Run Code Online (Sandbox Code Playgroud)

UID 504 是我登录盒子的方式,因此它可以工作:

[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)
Run Code Online (Sandbox Code Playgroud)

与上面相同,仅通过中间用户(即:登录 504,sudo 到 root,sudo 到常规 UID 501,然后返回 root):

[root@ditirlns04 ~]# ./test.sh
Current User: 0
Previous UID: 501
Previous UID: 0
Previous UID: 504
[root@ditirlns04 ~]#
Run Code Online (Sandbox Code Playgroud)

因此,每个 UID 转换都会按照其发生的相反顺序进行捕获。如果您需要以相同的顺序进行转换,只需将脚本放入一个函数中即可获取输出:

[root@ditirlns04 ~]# ./test.sh | tac
Previous UID: 504
Previous UID: 0
Previous UID: 501
Current User: 0
[root@ditirlns04 ~]#
Run Code Online (Sandbox Code Playgroud)

脚本主体:

#!/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
Run Code Online (Sandbox Code Playgroud)

基本上,它只是利用每个 pidstatstatus文件。您可以制作更多独立于平台的版本来包装ps输出,但当数据以要解析的格式随时可用时,我不信任解析命令输出,因此我选择了 procfs 路线。

基本上,每当它找到新的 UID 时,它都会将其打印出来。它们保证与用户 sudo 的顺序相同,因此它应该有效地覆盖您在该计算机上的整个登录会话。如果您愿意,您应该能够轻松修改上述内容以打印 PID 或命令名称,但通常在这方面思考的人更关心他们将作为谁运行,而不是将运行的 shell 程序。