Специфікація POSIX дійсно хеджує свої ставки, що стосуються терміналу керування , і який він визначає таким чином:
- Управління терміналом
- Питання про те, який із можливих кількох спеціальних файлів, що посилаються на термінал, не розглядається в POSIX.1. Ім'я шляху
/dev/tty
- синонім керуючого терміналу, пов'язаного з процесом.
Це в списку визначень - і це все, що там є. Але в загальному термінальному інтерфейсі говориться ще про щось:
Термінал може належати процесу як його контрольний термінал. Кожен процес сеансу, який має контрольний термінал, має той самий термінал керування. Термінал може бути керуючим терміналом не більше одного сеансу. Керуючий термінал для сеансу розподіляється керівником сесії у визначеному реалізацією порядку. Якщо у лідера сеансу немає керуючого терміналу і відкриває файл термінального пристрою, який вже не асоційований із сеансом без використання параметра O_NOCTTY (див. Open ()), він визначається реалізацією, чи стає термінал контрольним терміналом сеансу. лідер.
Термінал управління успадковується дочірнім процесом під час виклику функції fork (). Процес відмовляється від свого керуючого терміналу, коли він створює новий сеанс зsetsid()
функція; інші процеси, що залишилися в старій сесії, які мали цей термінал як свій керуючий термінал, продовжують мати його. Після закриття останнього дескриптора файлів у системі (незалежно від того, чи є він у поточному сеансі), пов'язаного з керуючим терміналом, не визначено, чи всі процеси, які мали цей термінал як свій контрольний термінал, перестають мати будь-який керуючий термінал. Не визначається, чи може і як керівник сеансу знову придбати контрольний термінал після того, як контрольний термінал відмовлено таким чином. Процес не відмовляється від свого керуючого терміналу, просто закривши всі його дескриптори файлів, пов'язані з керуючим терміналом, якщо інші процеси продовжують його відкривати.
Там багато що залишилося не визначеним - і чесно кажучи, я думаю, що це має сенс. Незважаючи на те, що термінал є ключовим інтерфейсом користувача, у деяких випадках він також є всілякі інші речі, як-от фактичне обладнання або навіть певний принтер, але у багатьох випадках це практично нічого - як, наприклад, xterm
емулятор . Важко конкретизуватись там - і я не думаю, що це все одно зацікавило б Unix, адже термінали роблять набагато більше, ніж Unix.
У будь-якому випадку, POSIX також досить неприємний щодо того, як ps
слід вести себе, якщо йдеться про ctty.
Там -a
вимикач:
- Запишіть інформацію про всі процеси, пов'язані з терміналами. Впровадження може не опустити лідерів сесій із цього списку.
Чудово. Керівники сесії можуть бути опущені. Це не дуже корисно.
І -t
:
- Запишіть інформацію для процесів, пов'язаних з терміналами, наведеними у списку термінів. Додаток повинен гарантувати, що список термінів є єдиним аргументом у вигляді списку,
<blank>
розділеного комами, або. Ідентифікатори терміналів надаються у форматі, визначеному реалізацією .
... що є черговим піднесенням. Але це продовжує говорити про системи XSI:
- У системах, сумісних з XSI, вони мають бути вказані в одній з двох форм: ім'я файлу пристрою (наприклад,
tty04
) або, якщо ім'я файлу пристрою починається з tty
, просто ідентифікатор, що слідує за символами tty
(наприклад, 04
) .
Це трохи краще, але це не шлях. Також у системах XSI є -d
перемикач:
- Пишіть інформацію для всіх процесів, крім керівників сеансів.
... що принаймні зрозуміло. Ви можете вказати -o
вимикач виводу, а також tty
рядок формату, але, як ви зазначили, його вихідний формат визначається реалізацією. Все-таки я думаю, що це так добре, як виходить. Я думаю, що - при багато роботи - перераховані вище перемикачі в поєднанні з деякими іншими комунальними програмами можуть отримати вам досить хороший бал-парк. Якщо чесно кажучи, я не знаю, коли / як це порушується для вас - і я не міг уявити собі ситуацію, в якій це було б. Але, я думаю, ймовірно, якщо ми додамо fuser
і find
зможемо перевірити шлях.
exec 2<>/dev/null
ctty=$(sh -c 'ps -p "$$" -o tty=' <&2)
sid=$(sh -c 'ps -Ao pid= -o tty=|
grep '"$ctty$"' |
grep -Fv "$(ps -do pid=)"' <&2)
find / -type c -name "*${ctty##*/}*" \
-exec fuser -uv {} \; 2>&1 |
grep ".*$ctty.*${sid%%"$ctty"*}"
Цей /dev/null
матеріал полягав лише в тому, щоб показати, що він може працювати, коли жодна з пошукових підрозділів не мала 0,1,2, пов'язаного з ctty. У будь-якому випадку, це друкує:
/dev/pts/3: mikeserv 3342 F.... (mikeserv)zsh
Тепер вищесказаний отримує повний шлях на моїй машині, і я думаю, це було б для більшості людей у більшості випадків. Я також можу уявити, що це може провалитися. Це просто груба евристика.
Це, можливо, не вдасться з багатьох інших причин, але якщо ви працюєте в системі, яка дозволяє лідеру сесії відмовитись від усіх дескрипторів до ctty і при цьому залишатись sid, як дозволяє специфікація, то це, безумовно, не допоможе. Зважаючи на це, я думаю, що це може отримати досить хорошу оцінку в більшості випадків.
Звичайно, простіше за все, що потрібно робити , якщо у вас є якісь - дескриптори , підключених до CT просто ...
tty <&2
... або подібне.
ps
рішення охоплює більшість систем (іwho
не допомагає більшеps
), можливо, трохи більше коду для обробки ідентифікатора поодинці (наприклад, "04"). Мені було цікаво, чи є ще більш портативне рішення.