Как мы можем узнать псевдоперминальный мастер и раб друг от друга?

С GNU sed :

sed -i 's/\s//g;s/\(|[^|]*\)|\([^|]*\)|/\1\2/;s/.*/\L&/' Results.txt
1
09.10.2019, 07:37
3 ответа

В Linux при использовании devptsнет главного файла устройства. Процесс на главной стороне использует дескриптор файла, который он получает, открывая ptmx, но соответствующий узел устройства отсутствует.

Подробнее см. на справочной странице ptmx.

(В стиле BSD -ptyв Linux существуют совпадающие пары устройств, такие как /dev/ptyp1и /dev/ttyp1, соответственно на ведущей и подчиненной стороне.)

6
27.01.2020, 23:11

Это то, что сложнее, чем должно быть.

В более новых ядрах 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;
}
10
27.01.2020, 23:11

Похоже, что lsof +Eдает вам информацию об обоих концах FD, включая точки и точки.

0
09.12.2020, 06:41

Теги

Похожие вопросы