제어 터미널의 실제 이름을 얻는 방법?


13

제어 터미널의 실제 이름 (있는 경우 오류가있는 경우)을 경로 이름으로 얻는 방법은 무엇입니까?

"실명" /dev/tty은 다른 터미널에서 동일한 터미널을 참조하는 데 사용할 수없는 not을 의미합니다. 가능한 경우 간단한 쉘 코드 (아래 예와 같은), 그렇지 않으면 C 함수로 대답을 선호합니다.

tty유틸리티를 사용할 수 없도록 표준 입력이 재 지정된 경우에도 작동해야합니다 . 표준 입력에 연결된 터미널의 파일 이름 만 인쇄하기 not a tty때문에 이러한 경우 오류가 발생 tty합니다.

Linux에서는 다음을 사용할 수 있습니다.

echo "/dev/`ps -p $$ -o tty | tail -n 1`"

POSIX에 따르면 터미널 이름의 형식이 지정되어 있지 않으므로 이식성이 없습니다 .

C 함수에 관해서 는 여기서을 ctermid (NULL)반환합니다 /dev/tty.

참고 :zsh 문서 에 따르면 할 수 있어야합니다

zsh -c 'echo $TTY'

그러나 표준 입력과 표준 출력이 모두 리디렉션되면 현재 (버전 5.0.7)에 실패합니다.

$ zsh -c 'echo $TTY > /dev/tty' < /dev/null
/dev/pts/9
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null > /dev/null
/dev/tty

@mikeserv 내가 생각 ps솔루션 커버 대부분의 시스템은 (그리고 who더 이상 도움이되지 않습니다 ps가능성 ( "04"와 같은) 혼자 식별자를 처리하기 위해 좀 더 코드). 더 휴대용 솔루션이 있는지 궁금합니다.
vinc17

사전 페어링 된 세트-이전 bsd 스타일 pty 쌍과 관련이있을 수도 있습니다. 모든 pty가 UNIX 98 유형 인 것은 아닙니다. 어쨌든, from man xterm: -Sccn 이 옵션을 사용 xterm하면 기존 프로그램의 I / O 채널로 사용할 수 있습니다 ... 옵션 값은 슬레이브 모드에서 사용할 pty 이름의 몇 글자와 상속 된 fd 번호입니다. 옵션에 "/"문자가 포함되어 있으면 fd에서 pty 이름을 구분합니다.
mikeserv

@mikeserv이 솔루션은 GNU / Linux에서도 busybox (Android, BTW에서 사용) ps에서 작동하지 않습니다 . " 처리 할 수 ​​있습니다 " 는 무슨 뜻 입니까? xterm04
vinc17

busyboxPOSIX 호환이 아닙니다. toybox그러나 매우 잘합니다.
mikeserv

답변:


8

"제어 터미널"일명. 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)은 stdin에 연결된 터미널 경로를 인쇄합니다. 이는 ttyname(fileno(stdin))c와 동일 하며 대안은 readlink /proc/self/fd/0입니다.


무조건적인 "/ dev / tty"동작에 관한 덜 중요한 생각 : 스펙은 단지 ctermid에 의해 리턴 된 문자열을 말합니다. 제어 터미널 ". "/ dev / tty"는 제어 터미널이 아니라 해석 프로세스가 동일한 경우에만 제어 터미널을 참조하는 것으로 해석 될 수 있습니다 (3). 따라서 "터미널은 최대 하나의 세션에 대해 ctty"규칙을 위반하지 않습니다 [7].

또 다른 결과는 제어 터미널이 없어도 ctermid가 실패하지 않는 것입니다. 그러한 실패는 사양에 의해 허용됩니다 [8]. 사양에 따르면 open (3)을 호출해도 성공 보장되지 않기 때문에 괜찮습니다.


ps모든 OS에 /proc파일 시스템 이있는 것은 아니기 때문에이 질문에 대답 한 것보다 이식성이 떨어집니다 . 주의 ps자체에 readlink를 사용합니다 /proc/self/fd/2(심지어 작동하는 표준 오류 리디렉션)입니다.
vinc17

1
편집했습니다. / proc / * / fd / 2의 ps readlink는 ctty를 찾지 않고 숫자 터미널을 경로에 매핑하기위한 추가 정보를 찾으려면 link [4] [5]를 참조하십시오.
把 友情 留 在 无 盐

1
훌륭한 편집. ctty에 대하여; 나는 vinc17을 말할 수는 없지만 항상 어딘가에 쓸 수는 있지만 프로세스 그룹을 유지하기 위해 열려 있어야하는 파일은 하나뿐입니다.
mikeserv

1
@ vinc17-ctty에 열려 있는 파일 디스크립터가 있으면를 사용하여 읽을 수 있습니다 tty. stderr오픈 r / w로 지정되어 있기 때문에 아마도 가장 좋습니다. 그래서 tty <&2.
mikeserv

1
주어진 터미널이 최대 하나의 세션에 대해 ctty가 될 수 있다고해서 glibc가 ctermid()항상 돌아 오는 것에 대해 부적합하지는 않습니다 "/dev/tty". 이 이름은 항상 프로세스에 액세스하는 프로세스 의 제어 터미널 나타내며 세션에 따라 다릅니다. 터미널은 세션마다 다르지만 액세스하는 이름은 필요하지 않습니다.
PellMel

5

POSIX 사양은 실제로 제어 터미널 과 관련 하여 베팅 을 방지합니다.

  • 터미널 제어
    • POSIX.1에서는 터미널을 참조하는 여러 특수 파일 중 어떤 것이 가능한지에 대한 질문은 다루지 않습니다. 경로 이름 /dev/tty은 프로세스와 연관된 제어 터미널의 동의어입니다.

그것은 정의 목록에 있으며, 그게 전부입니다. 그러나 일반 터미널 인터페이스 에서는 다음과 같은 내용이 더 있습니다.

  • 단말기는 제어 단말기로서 프로세스에 속할 수있다. 제어 터미널이있는 세션의 각 프로세스에는 동일한 제어 터미널이 있습니다. 단말기는 최대 하나의 세션 동안 제어 단말기 일 수있다. 세션에 대한 제어 단말기는 구현 정의 방식으로 세션 리더에 의해 할당된다. 세션 리더에 제어 터미널이없고 O_NOCTTY 옵션을 사용하지 않고 세션과 아직 연결되지 않은 터미널 장치 파일을 여는 경우 (open () 참조), 터미널이 세션의 제어 터미널이되는지 여부는 구현 정의됩니다. 리더.

  • 제어 터미널은 fork () 함수 호출 중에 하위 프로세스에 의해 상속됩니다. 프로세스는 새로운 터미널을 생성 할 때 제어 터미널을 포기합니다.setsid()함수; 제어 터미널로서이 터미널이있는 이전 세션에 남아있는 다른 프로세스는 계속 가지고 있습니다. 제어 터미널과 연관된 시스템 (현재 세션에 있는지 여부)의 마지막 파일 디스크립터가 닫히면 해당 터미널을 제어 터미널로 갖는 모든 프로세스가 제어 터미널을 갖는지 여부는 지정되지 않습니다. 제어 터미널이 이러한 방식으로 양도 된 후 세션 리더가 제어 터미널을 다시 획득 할 수 있는지 여부와 방법은 명시되어 있지 않습니다. 프로세스는 다른 프로세스가 계속 열려있는 경우 제어 터미널과 관련된 모든 파일 설명자를 닫아 제어 터미널을 포기하지 않습니다.

지정되지 않은 부분이 많이 있습니다. 솔직히 말해서 말이됩니다. 터미널은 핵심 사용자 인터페이스이지만 실제 하드웨어 또는 프린터와 같은 경우에는 모든 종류의 다른 것들이지만 많은 경우 xterm에는 에뮬레이터 와 같은 거의 아무것도 아닙니다. . 터미널을 유닉스보다 많이 사용하기 때문에 어쨌든 유닉스에 관심이 많지 않을 것이라고 생각합니다.

어쨌든 POSIX는 psctty가 관련된 곳 에서 어떻게 행동 해야하는지 꽤 잘 알고 있습니다.

있다 -a스위치 :

  • 터미널과 관련된 모든 프로세스에 대한 정보를 작성하십시오. 구현은이 목록에서 세션 리더를 생략 할 수 있습니다.

큰. 당회 지도자 생략 될 수 있다. 그다지 도움이되지 않습니다.

그리고 -t:

  • 용어 목록에 지정된 터미널과 관련된 프로세스에 대한 정보를 작성하십시오. 응용 프로그램은 용어 <blank>목록이 쉼표로 구분 된 목록 형식의 단일 인수인지 확인해야 합니다. 단말기 식별자는 구현 정의 형식 으로 제공되어야한다 .

... 또 다른 실망입니다. 그러나 XSI 시스템에 대해서는 다음과 같이 말합니다.

  • 장치의 파일 이름 (예 : XSI를 준수하는 시스템에서, 그들은 두 가지 형태 중 하나에 따른다 tty04) 또는 경우에 장치의 파일 이름 시작 tty, 문자 다음 바로 식별자 tty (예를 들어 04) .

그것은 조금 나아지지만 길은 아닙니다. 또한 XSI 시스템에는 다음과 같은 -d스위치가 있습니다.

  • 세션 리더를 제외한 모든 프로세스에 대한 정보를 작성하십시오.

... 적어도 분명합니다. 형식 문자열 -o과 함께 utput 스위치를 지정할 수 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

... 또는 비슷합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.