제어 터미널의 실제 이름(있는 경우, 그렇지 않으면 오류 발생)을 경로 이름으로 어떻게 얻습니까?
"실명"이란 /dev/tty
다른 임의의 프로세스가 이를 사용하여 동일한 터미널을 참조할 수 있다는 의미가 아닙니다. 가능하다면 간단한 쉘 코드(아래 예와 같은)로 답변을 선호하고, 그렇지 않으면 C 함수로 답변하는 것을 선호합니다.
이는 표준 입력이 리디렉션되더라도 작동해야 하므로 tty
유틸리티를 사용할 수 없습니다. 이 경우 표준 입력에 연결된 터미널의 파일 이름만 인쇄되기 not a tty
때문에 오류가 나타납니다 .tty
Linux에서는 다음을 사용할 수 있습니다.
echo "/dev/`ps -p $$ -o tty | tail -n 1`"
그러나 POSIX에 따르면 이것은 이식성이 없습니다.터미널 이름의 형식이 지정되지 않았습니다..
C 함수의 경우 ctermid (NULL)
return 을 사용합니다 /dev/tty
. 여기서는 유용하지 않습니다.
노트:zsh
문서 에 따르면 다음을 수행할 수 있어야 합니다.
zsh -c 'echo $TTY'
그러나 현재(버전 5.0.7) stdin과 stdout이 모두 리디렉션되면 실패합니다.
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null
/dev/pts/9
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null > /dev/null
/dev/tty
답변1
"제어 터미널"이라고도 합니다. ctty는 "와 다릅니다.이것프로세스가 상호작용하는 터미널입니다."
ctty 경로를 얻는 표준 방법은 ctermid(3)입니다. 이 명령을 호출한 후, 버전 10부터 freebsd에서는 실제 경로를 조회합니다.[1], 이전 freebsd 및glibc 구현[2] 무조건 "/dev/tty"를 반환합니다.
Linux procps 3.2.8 패키지의 ps(1),/proc/*/stat의 숫자 항목 읽기[3] 그럼경로명 공제 부분적으로는 추측으로[4, 5] 인해시스템 지원 부족[6].
그러나 ctty에만 관심이 없고 대신 stdio와 관련된 터미널에 관심이 있는 경우 tty(1)는 ttyname(fileno(stdin))
c와 동일한 stdin에 연결된 터미널 경로를 인쇄하고 대안은 입니다 readlink /proc/self/fd/0
.
무조건적인 "/dev/tty"의 동작에 대한 덜 중요한 생각: 사양에서는 단순히 "현재 경로"가 아닌 "경로 이름으로 사용될 때 현재 제어 터미널을 참조"하는 ctermid에 의해 반환된 문자열이 있다고 말합니다. 이름은 "control 터미널"입니다. "/dev/tty"는 제어 터미널이 아니라 동일한 프로세스가 열릴 때만 제어 터미널을 참조하는 것으로 해석될 수 있으므로(3) 위반이 없습니다. "터미널은 최대 하나의 세션에 대한 CTY일 수 있습니다." 규칙[7].
또 다른 결과는 제어 터미널이 없어도 ctermid가 실패하지 않는다는 것입니다.사양에서는 이러한 오류를 허용합니다.[8] -- 그래서 나는 후속 open(3)이 실패할 때까지 ctty'less라는 것을 깨닫지 못합니다. 이는 또한 사양에 open(3) 호출이 성공이 보장되지 않는다고 나와 있기 때문에 괜찮습니다.
답변2
POSIX 사양은 실제로 베팅을 헤지합니다.제어 터미널관련성이 있으며 다음과 같이 정의됩니다.
- 제어 터미널
- 터미널에 대한 여러 특수 파일 중 어떤 파일이 관련될 수 있는지에 대한 질문은 POSIX.1에서 해결되지 않았습니다. 경로 이름은
/dev/tty
프로세스와 연관된 제어 터미널의 동의어입니다.
- 터미널에 대한 여러 특수 파일 중 어떤 파일이 관련될 수 있는지에 대한 질문은 POSIX.1에서 해결되지 않았습니다. 경로 이름은
이것은 정의 목록에 있습니다. 그게 전부입니다. 하지만범용 터미널 인터페이스, 그리고 다음과 같은 말이 있습니다.
터미널은 제어 터미널로서 프로세스에 속할 수 있습니다. 제어 터미널과의 세션의 각 프로세스는 동일한 제어 터미널을 갖습니다. 터미널은 최대 하나의 세션을 제어하는 터미널이 될 수 있습니다. 세션의 제어 끝점은 구현 정의 방식으로 세션 리더에 의해 할당됩니다. 세션 리더에 제어 터미널이 없고 세션과 아직 연결되지 않은 터미널 장치 파일이 O_NOCTTY 옵션(open() 참조)을 사용하지 않고 열리는 경우 해당 터미널이 세션의 제어 터미널이 될지 여부는 구현입니다. 정의된 리더.
fork() 함수 호출 중에 제어 터미널은 하위 프로세스에 의해 상속됩니다. 프로세스가 이 기능을 사용하여 새 세션을 생성하면 제어 터미널이
setsid()
계속 터미널을 가지므로 터미널을 유지했던 이전 세션의 다른 프로세스를 포기합니다. 시스템의 제어 터미널과 연관된 마지막 파일 설명자가(현재 세션에 있는지 여부에 관계없이) 닫히면 해당 터미널을 제어 터미널로 사용하는 모든 프로세스가 더 이상 제어 터미널을 소유하지 않는지 여부가 지정되지 않습니다. 세션 리더가 이러한 방식으로 제어 터미널을 포기한 후 제어 터미널을 다시 획득하는지 여부와 방법은 지정되지 않습니다. 다른 프로세스가 해당 프로세스를 계속 열면 프로세스는 단순히 제어 터미널과 관련된 모든 파일 설명자를 닫음으로써 제어 터미널을 포기하지 않습니다.
아직 많이 남았어명시되지 않은-솔직히 그 말이 맞는 것 같아요. 터미널은 주요 사용자 인터페이스이지만 경우에 따라 실제 하드웨어나 프린터 유형과 같은 다양한 다른 요소이기도 하지만 대부분의 경우 실제로는 아무것도 아닙니다. 마치 xterm
에뮬레이터일 뿐입니다. 이것을 지정하는 것은 어렵습니다. 그리고 터미널이 Unix보다 더 많은 일을 하기 때문에 어쨌든 Unix에 많은 이점이 있을 것이라고 생각하지 않습니다.
ps
그럼에도 불구하고 POSIX는 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
것들은 검색 하위 쉘에 ctty에 연결된 0, 1, 2가 없을 때 작동한다는 것을 보여주기 위한 것입니다. 어쨌든 출력되는 내용은 다음과 같습니다.
/dev/pts/3: mikeserv 3342 F.... (mikeserv)zsh
이제 위의 내용은 내 컴퓨터의 전체 경로를 가져오며 대부분의 경우 대부분의 사람들에게 작동할 것이라고 생각합니다. 실패할 수도 있다고 상상해 봅니다. 이것은 단지 대략적인 경험적 방법일 뿐입니다.
이는 다른 여러 가지 이유로 실패할 수 있지만, 세션 리더가 ctty에 대한 모든 설명자를 포기할 수 있지만 사양에서 허용하는 sid는 여전히 유지하는 시스템을 사용하는 경우에는 확실히 도움이 되지 않습니다. 즉, 나는 이것이 대부분의 경우 꽤 좋은 추정치를 제공한다고 생각합니다.
틀림없이가장 단순한할 일이 있다면어느ctty에 첨부된 설명자는 다음과 같습니다.
tty <&2
...또는 유사합니다.