С GNU sed
:
sed -i 's/\s//g;s/\(|[^|]*\)|\([^|]*\)|/\1\2/;s/.*/\L&/' Results.txt
В Linux при использовании devpts
нет главного файла устройства. Процесс на главной стороне использует дескриптор файла, который он получает, открывая ptmx
, но соответствующий узел устройства отсутствует.
Подробнее см. на справочной странице ptmx
.
(В стиле BSD -pty
в Linux существуют совпадающие пары устройств, такие как /dev/ptyp1
и /dev/ttyp1
, соответственно на ведущей и подчиненной стороне.)
Это то, что сложнее, чем должно быть.
В более новых ядрах Linux индекс ведомого pty, связанного с ведущим, можно получить из записи tty-index
из /proc/PID/fdinfo/FD
. См. commit .
В более старых ядрах единственный способ добиться этого — подключиться с помощью отладчика к процессу, содержащему главный pty, и вызватьptsname(3)
(или напрямуюioctl(TIOCGPTN)
)в файловом дескрипторе.
[но оба метода вызовут проблемы в системах, использующих несколько монтирований devpts, см. ниже]
Используя эту информацию, вы можете составить список пар -ведущее/ведомое устройство, что также позволит вам найти ведущее устройство, начиная с подчиненного устройства.
Вот дурацкий скрипт, который должен это делать; сначала он попробует tty-index
способ, и если это не сработает, он вернется к gdb
. В последнем случае требуется работающий gdb
(, а не gdb-minimal
или другой наполовину -сломанный gdb
большинство дистрибутивов с ), и из-за использования gdb
он будет очень медленно .
Для каждой пары pty будет напечатано что-то вроде:
/dev/pts/1
1227 3 t/ct_test
1228 +* t/ct_test
1230 + t/ct_test
/dev/pts/3
975 9 'sshd: root [priv]' '' '' '' '' '' '' '' ''
978 14,18,19 'sshd: root@pts/3' '' '' '' '' '' '' ''
979 -*0,1,2,255 -bash
1222 1 tiocsti
1393 -0,1,2 sleep 3600
1231 +0,2 perl ptys.pl
1232 +1,2 cut -b1-60
два sshd
процесса (pids 975 и 978 )имеют открытые дескрипторы на главную сторону (один как 9 fd, а другой как 14, 18 и 19 fds ). sleep
и -bash
имеют открытые рукоятки к ведомой стороне в стандартной комплектации (0,1 и 2 )fds. Лидер сеанса(bash
)также отмечен *
, процессы на переднем плане(perl
иcut
)— +
, а фоновые(less
и-bash
)— -
..
Процессы t/ct_test
используют pty в качестве своего управляющего терминала, не имея открытых для него файлов fd. tiocsti
имеет открытый дескриптор, но не является управляющим терминалом.
Протестировано на Debian 9 и Fedora 28. Информацию об используемых им магических числах можно найти вprocfs(5)
иDocumentation/admin-guide/devices.txt
в исходниках ядра linux.
Это приведет к сбою в любой системе, использующей chroot или контейнеры пространства имен; это невозможно исправить без некоторых изменений в ядре, поскольку нет надежного способа сопоставить поле tty
из /proc/PID/stat
с pty, а fd, открытый через /dev/ptmx
, с соответствующим монтированием /dev/pts
. См. здесь для разглагольствования по этому поводу.
Это также не будет ссылаться ни на один fd, открытый через /dev/tty
; реальный tty может быть обработан путем присоединения к процессу и вызова ioctl(fd, TIOCGDEV, &dev)
, но это будет означать еще одно грязное интенсивное использование gdb, и оно столкнется с теми же проблемами, что и выше, с основным, второстепенным числа неоднозначны для псевдо-tty-ведомых устройств.
ptys.pl:
my (%pty, %ctty);
for(</proc/*[0-9]*/{fd/*,stat}>){
if(my ($pid, $fd) = m{/proc/(\d+)/fd/(\d+)}){
next unless -c $_;
my $rdev = (stat)[6]; my $maj = $rdev >> 8 & 0xfff;
if($rdev == 0x502){ # /dev/ptmx or /dev/pts/ptmx
$pty{ptsname($pid, $fd, readlink $_)}{m}{$pid}{$fd} = 1;
}elsif($maj >= 136 && $maj <= 143){ # /dev/pts/N
$pty{readlink $_}{s}{$pid}{$fd} = 1;
}
}else{
my @s = readfile($_) =~ /(?<=\().*(?=\))|[^\s()]+/gs;
$ctty{$s[6]}{$s[0]} = # ctty{tty}{pid} =
($s[4] == $s[7] ? '+' : '-'). # pgrp == tpgid
($s[0] == $s[5] ? '*' : ''); # pid == sid
}
}
for(sort {length($a)<=>length($b) or $a cmp $b} keys %pty){
print "$_\n";
pproc(4, $pty{$_}{m}); pproc(8, $pty{$_}{s}, $ctty{(stat)[6]});
}
sub readfile { local $/; my $h; open $h, '<', shift and <$h> }
sub cmdline {
join ' ', map { s/'/'\\''/g, $_ = "'$_'" if m{^$|[^\w./+=-]}; $_ }
readfile("/proc/$_[0]/cmdline") =~ /([^\0]*)\0/g;
}
sub pproc {
my ($px, $h, $sinfo) = @_;
exists $$h{$_} or $$h{$_} = {''} for keys %$sinfo;
return printf "%*s???\n", $px, "" unless $h;
for my $pid (sort {$a<=>$b} keys %$h){
printf "%*s%-5d %s%-3s %s\n", $px, "", $pid, $$sinfo{$pid},
join(',', sort {$a<=>$b} keys %{$$h{$pid}}),
cmdline $pid;
}
}
sub ptsname {
my ($pid, $fd, $ptmx) = @_;
return '???' unless defined(my $ptn = getptn($pid, $fd));
$ptmx =~ m{(.*)(?:/pts)?/ptmx$} ? "$1/pts/$ptn" : "$ptmx..?? pts/$ptn"
}
sub getptn {
my ($pid, $fd) = @_;
return $1 if
readfile("/proc/$pid/fdinfo/$fd") =~ /^tty-index:\s*(\d+)$/m;
return gdb_ioctl($pid, $fd, 0x80045430); # TIOCGPTN
}
sub gdb_ioctl {
my ($pid, $fd, $ioctl) = @_;
my $cmd = qq{p (int)ioctl($fd, $ioctl, &errno) ? -1 : errno};
qx{exec 3>&1; gdb -batch -p $pid -ex '$cmd' 2>&1 >&3 |
grep -v '/sysdeps/.*No such file or directory' >&2}
=~ /^\$1 *= *(\d+)$/m ? $1 : undef;
}
Похоже, что lsof +E
дает вам информацию об обоих концах FD, включая точки и точки.