如何在Unix中关闭tty

33
这是 finger 命令的结果(今天(星期一)我(Vidya)登录时)。
sekic1083 [6:14am] [/home/vidya] -> finger
Name        Tty       Idle   Login Time    Where
Felix   pts/0        -       Thu 10:06  sekic2594.rnd.ki.sw.
john        pts/1       2d       Fri 15:43
john        *pts/2      2d       Fri 15:43
john      *pts/3       4     Fri 15:44
john      *pts/7       -         Thu 16:25
Vidya      pts/0       -         Mon 06:14
Vidya     *pts/5       -         Mon 06:14
Vidya     *pts/6       -         Tue 10:13
Vidya     *pts/9       -         Wed 05:39
Vidya     *pts/10      -         Wed 10:23

在列下,Tty pts/0和pts/5是当前活动的终端。
除了这两个之外,pts/6pts/9pts/10也存在,我上周登录过这些终端。但是它们的空闲时间显示为“-”(非空闲)。
我怎样才能关闭这些6、9和10号终端?
10个回答

42

你可以运行:

ps -ft pts/6 -t pts/9 -t pts/10

这将产生类似于以下输出:
UID        PID  PPID  C STIME TTY          TIME CMD
Vidya      772  2701  0 15:26 pts/6    00:00:00 bash
Vidya      773  2701  0 16:26 pts/9    00:00:00 bash
Vidya      774  2701  0 17:26 pts/10   00:00:00 bash

从结果中获取PID
使用PIDs杀死进程:
kill <PID1> <PID2> <PID3> ...

对于上面的例子:
kill 772 773 774

如果进程没有正常终止,那么最后的选择是通过发送 SIGKILL 强制结束。

kill -9 <PID>

ps -ft 可以用于 pts/5,但无法用于终止 pts/6、pts/9 或 pts/10。对于 tty 6、9、10 抛出错误:ERROR: 找不到 TTY。 - Vidya Sagar
你能获取到pts 6、9和10的进程ID吗?kill命令报告了什么错误?同时,在ps输出中是否列出了同一pts的多个进程? - Tuxdude
当我执行 ps -ft pts/6 时出现错误。错误:找不到TTY。 - Vidya Sagar
ps -ef | grep pts,当我执行此命令时,tty的6、9和10未列出。这3个tty仅在“finger”命令中出现。 - Vidya Sagar
2
fingerwhow和其他类似的工具从/var/run/utmp中获取信息,但看起来在关闭这些会话时可能没有正确更新。由于您确认这些会话未列在ps的输出中,因此这些会话已关闭。 - Tuxdude
当默认的“TERM”信号无法工作时,“kill -HUP <PID>”通常就足够了。我建议小心使用“-9”,因为它不会给任何子进程清理的机会。 - TheDudeAbides

30

我和你有同样的问题,但我想退出当前的gnome终端。我阅读了“who”命令的手册,发现您可以使用“-a”选项列出登录到计算机上的所有会话,然后使用“-l”选项打印系统登录过程。

who -la

谁给了我这个东西 你应该得到类似这样的东西。然后你只需要用“kill”命令杀掉进程。

kill <PID>

当n大于1时,将向进程组n中的所有进程发送信号。如果给出形式为“-n”的参数,并且它是用来表示进程组的,则必须首先指定信号,或者该参数必须在“--”选项之前,否则它将被视为要发送的信号。--- http://linux.die.net/man/1/kill - Jacob Bryan
注意:-a开关也会打印出已经停止的进程...所以如果你试图找出谁在使用所有那些tty...他们不是。 - Timothy L.J. Stewart
kill $(who -la | grep old | awk -F' +' '{print $7}') 对我来说有效-不确定是否安全 :) - urban

27
例如,执行命令 kill pts/0。
pkill -9 -t pts/0

4
在尝试使用pkill -9kill -9之前,请尝试使用pkill -HUP。这通常已足以终止tty/pty进程,而且HUP("挂断")仍然会给终端的子进程一个机会在结束进程之前进行清理工作——例如清理临时文件。 - TheDudeAbides

11

试试这个:

skill -KILL -v pts/6

skill -KILL -v pts/9

skill -KILL -v pts/10

甚至只需使用skill -t pts/6命令。 - digitaltoast
2
从man页:这些工具可能已经过时且不可移植。命令语法定义不清楚。考虑改用killall、pkill和pgrep命令。 - andreee

2
最简单的方法是使用pkill命令。 在您的情况下:
pkill -9 -t pts/6
pkill -9 -t pts/9
pkill -9 -t pts/10

关于tty会话,下面的命令总是有用的:

w - 显示活动终端会话

tty - 显示您当前的终端会话(以防意外关闭)

last | grep logged - 显示当前登录用户

有时,我们想关闭空闲用户的所有会话(即当连接突然丢失时)。

pkill -u username - 杀死“username”用户的所有会话。

有时候,当我们想要关闭除当前会话之外的所有自己的会话时,我制作了一个脚本。该脚本包含一些美化和一些交互功能(以避免意外运行脚本)。

#!/bin/bash
MYUSER=`whoami`
MYSESSION=`tty | cut -d"/" -f3-`
OTHERSESSIONS=`w $MYUSER | grep "^$MYUSER" | grep -v "$MYSESSION" | cut -d" " -f2`
printf "\e[33mCurrent session\e[0m: $MYUSER[$MYSESSION]\n"

if [[ ! -z $OTHERSESSIONS ]]; then
  printf "\e[33mOther sessions:\e[0m\n"
  w $MYUSER | egrep "LOGIN@|^$MYUSER" | grep -v "$MYSESSION" | column -t
  echo ----------
  read -p "Do you want to force close all your other sessions? [Y]Yes/[N]No: " answer
  answer=`echo $answer | tr A-Z a-z`
  confirm=("y" "yes")

  if [[ "${confirm[@]}" =~ "$answer" ]]; then
  for SESSION in $OTHERSESSIONS
    do
         pkill -9 -t $SESSION
         echo Session $SESSION closed.
    done
  fi
else
        echo "There are no other sessions for the user '$MYUSER'".
fi

1
今天我遇到了同样的问题。 我没有剩余的进程,但是用户“xxx”的剩余指针条目阻止我使用“userdel xxx”删除该用户。 错误消息为:userdel:帐户“xxx”当前正在使用中。 看起来像是一个崩溃的终端会话。所以我重新启动了计算机,但问题仍然存在。
last xxx
xxx      pts/5        10.1.2.3     Fri Feb  7 10:25 - crash  (01:27)

因此,我删除了/var/run/utmp文件:

mv /var/run/utmp /var/run/utmp.save ; touch /var/run/utmp

这将清除所有手指输入。不幸的是,即使当前正在运行的会话也将被清除。如果这对您有影响,则必须重新启动,在(重新)移除utmp文件后进行。

然而,在我的情况下,这是解决方案。之后,我能够成功地使用"userdel xxx"删除用户。


1

你不需要知道pts号码,只需输入以下命令:

ps all | grep bash

然后输入:

kill pid1 pid2 pid3 ...


0
如果您想关闭特定用户的所有进程的 tty,上述命令是最简单的。您可以使用:
killall -u user_name

0

你也可以使用killall命令。

-o,--older-than 仅匹配早于指定时间(启动前)的进程。 时间以浮点数和单位指定。 单位为秒,分钟,小时,天,周,月,年,表示为s,m,h,d,w,M,y。

-e,--exact 要求非常长的名称必须完全匹配。

-r,--regexp 将进程名称模式解释为扩展正则表达式。

这个工作起来非常好。


-2
除了 AIXroot 的回答之外,还有一个登出功能可以用于编写 utmp 登出记录。因此,如果您没有任何用户xxxx的进程,但是userdel说“userdel: account xxxx is currently in use”,则可以手动添加一个登出记录。创建一个名为logout.c的文件,类似于以下内容:
#include <stdio.h>
#include <utmp.h>

int main(int argc, char *argv[])
{
  if (argc == 2) {
    return logout(argv[1]);
  }
  else {
    fprintf(stderr, "Usage: logout device\n");
    return 1;
  }
}

编译它:

gcc -lutil -o logout logout.c

然后运行它,将finger的“On since”行的输出作为参数。
# finger xxxx
Login: xxxx                             Name:
Directory: /home/xxxx                   Shell: /bin/bash
On since Sun Feb 26 11:06 (GMT) on 127.0.0.1:6 (messages off) from 127.0.0.1
On since Fri Feb 24 16:53 (GMT) on pts/6, idle 3 days 17:16, from 127.0.0.1
Last login Mon Feb 10 14:45 (GMT) on pts/11 from somehost.example.com
Mail last read Sun Feb 27 08:44 2014 (GMT)
No Plan.

# userdel xxxx
userdel: account `xxxx' is currently in use.
# ./logout 127.0.0.1:6
# ./logout pts/6
# userdel xxxx
no crontab for xxxx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接