저는 Ubuntu에서 C++ 애플리케이션을 개발 중이며 출력을 여러 터미널로 브로드캐스트해야 합니다. 예를 들어 C++ 애플리케이션에서 bash 명령을 호출하고 출력을 적절한 터미널로 보내는 등 프로그래밍 방식으로 이 작업을 수행해야 합니다. 그리고 개발된 "다중 터미널" 도구(예: Terminator 또는 기타 도구)를 설치할 수 없으며 대신 표준 bash 명령을 사용해야 합니다.
그래서:
process A -> will show its output in terminal A.
process B -> will show its output in terminal B.
process C -> will show its output in terminal C.
그런 다음 참고하세요:
- 여러 단말기에 동시에 다양한 정보를 방송하고, 특정 단말기에 특정 정보를 방송하겠습니다.
- 에어크랙 작업을 본 적이 있나요? 이 애플리케이션은 세 개의 서로 다른 터미널을 동시에 표시했고, 각 터미널은 화면의 특정 x, y 좌표에 위치했으며, 각 터미널은 서로 다른 정보를 표시했던 것으로 기억합니다. 글쎄요, 그게 제가 필요한 것 같아요.
탐색 후 다음 "gnome-terminal" 명령을 찾아 3개의 터미널을 실행하도록 조정했습니다.
gnome-terminal --geometry=45x20+10+10; gnome-terminal --geometry=45x20+505+10; gnome-terminal --geometry=45x20+950+10
일부 세부정보:
- 터미널이 gnome 터미널일 필요는 없습니다. Ubuntu는 기본적으로 xterms를 제공하는 간단한 콘솔일 수 있습니다.
- 위의 예제 명령처럼 한 번에 세 개의 터미널을 시작할 필요가 없습니다. 그러나 해당 프로세스가 터미널에 브로드캐스트해야 하는 경우 터미널이 열려 있어야 합니다.
- 프로그램은 출력을 브로드캐스트할 터미널을 어떻게 알 수 있나요? 어쩌면 터미널의 pid가 사용되고 있습니까? 그렇다면 터미널 pid가 있습니까? 출력을 해당 터미널로 어떻게 리디렉션합니까?
예를 들어 다음과 같이 각 터미널의 pid를 얻으려고 합니다.
gnome-terminal --geometry=45x20+10+10 &
그리고 pid를 변수로 리디렉션하는 방법을 찾고 있습니다(아직 찾지 못했습니다...).
답변1
Unix 세션은 시작점이 되어야 하는 TTY에 의해 처리됩니다. 이러한 모든 세션에 대해 동일한 사용자 계정을 사용하는 경우 원하는 TTY로 직접 출력을 보낼 수 있어야 합니다.
따라서 출력에 사용하려는 다양한 TTY를 사용하여 프로그램을 호출하면 해당 TTY를 출력용으로 열 수 있습니다. 방금 Gentoo와 Centos에서 아무 문제 없이 사용해 보았습니다.
세션의 TTY를 찾으려면 다음 tty
명령을 사용하십시오.
내가 선호하는 또 다른 옵션은 클라이언트 터미널이 서버 프로세스에 연결되는 클라이언트-서버 접근 방식을 사용하는 것입니다. 이는 다른 사용자를 처리할 때 보안 영향이 적기 때문입니다. 이는 3개의 출력 터미널 각각에 대해 명명된 파이프를 사용하는 것만큼 간단할 수 있습니다.
답변2
터미널 에뮬레이터를 열고 일부 데이터를 보내면 사용자의 기본 셸도 bash
그곳에서 실행될 가능성이 높다는 점을 인식해야 합니다. 이로 인해 사용 사례에서 바람직하지 않을 수 있는 몇 가지 결과가 발생합니다. 프롬프트로 인해 출력의 첫 번째 열이 잘못 정렬됩니다(주의 깊게 화면을 지우지 않는 한). 사용자가 무엇을 입력하든 화면이 더욱 복잡해지고 더 중요한 것은 쉘 명령으로 실행된다는 점입니다. 특히 사용자가 더 이상 프롬프트를 볼 수 없기 때문에 오해의 소지가 있습니다. 또한 터미널에서 데이터를 읽으려는 경우에도 안정적으로 수행할 수 없습니다(셸에 도달하든 응용 프로그램에 도달하든 키를 누를 때마다 무작위로 수행됩니다).
귀하의 질문의 맥락을 올바르게 이해했다면 이는 귀하에게 권장되지 않습니다. 열려는 터미널은 애플리케이션의 출력을 표시하는 데에만 사용해야 하며 동시에 셸을 실행해서는 안 됩니다. 따라서 기본 셸 대신 시작할 사용자 정의 명령을 지정해야 합니다. 이 사용자 정의 명령은 tty
터미널의 줄 번호(명령의 출력)를 응용 프로그램으로 다시 보내는 간단한 스크립트(또는 C++ 유틸리티)일 수 있으며 , 일부 터미널 및 신호 설정(예: 로컬 에코 끄기( stty
) 끄기, 비활성화)을 변경할 수도 있습니다. 신호) ( stty
또는 trap
)), 그리고 마지막으로 거인에 들어갑니다 sleep
.
tty 번호를 기본 애플리케이션으로 다시 보내는 방법에는 여러 가지가 있습니다. 이러한 터미널과 그 안에 있는 스크립트를 시작하는 것은 애플리케이션의 관점에서 비동기적입니다. 예를 들어, tty
고정된 파일 이름을 가진 임시 파일에 출력을 배치하는 경우 애플리케이션이 파일의 이전 버전을 너무 일찍 읽지 않도록 해야 합니다. 예를 들어, 매번 고유한 임의의 파일 이름을 만들고 해당 이름이 기본 응용 프로그램에 나타날 때까지 기다릴 수 있습니다.
이에 대해 완전히 다른 사고 방식을 제안하겠습니다.
gnome-terminal(그리고 전부는 아니지만 대부분의 다른 Gtk+ 기반 터미널 에뮬레이터)의 실제 터미널 에뮬레이션은 VTE 위젯에 의해 수행됩니다. Gtk+ 툴킷을 사용하여 애플리케이션을 작성하는 경우 VTE 위젯을 추가하는 것은 체크박스를 추가하는 것만큼 쉽습니다.
gnome-terminal
VTE 등 원하는 것을 사용하는 대신 애플리케이션 자체에 여러 VTE 위젯이 있는 그래픽 창이나 내부에 VTE가 있는 여러 그래픽 창이 표시될 수 있습니다 . xterm
대안으로, 실제 애플리케이션에서 Gtk+에 의존하고 싶지 않다면 이 작업을 위한 별도의 작은 도우미 애플리케이션을 쉽게 만들 수 있습니다(C/C++ 대신 Python 사용을 고려할 수도 있습니다).
이 경우 셸은 기본적으로 시작되지 않습니다( vte_terminal_spawn_sync()
원하는 방법을 사용하여 명시적으로 이 작업을 수행해야 합니다). 터미널 라인을 가져와서 vte_pty_get_fd()
문자열로 변환한 ptsname()
다음 기본 애플리케이션에 다시 전달하기만 하면 됩니다. 또는 단일 응용 프로그램에서 이 작업을 수행하면 vte_terminal_feed()
표시하려는 데이터를 표시할 수도 있습니다.
답변3
문제는 간단해야 합니다. 다음과 같이 사용자 이름과 터미널 이름을 제공하는 w
목록을 얻습니다 .who
$ w
19:34:00 up 7:17, 5 users, load average: 0.14, 0.08, 0.06
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
tom pts/1 michener:S.0 14:07 3:21m 15.16s 15.08s vile /tmp/foo
tom pts/4 michener:S.1 12:34 2.00s 0.22s 0.00s w
tom pts/5 michener:S.2 13:00 9:48 3.13s 2.79s vile /usr/build
thomas :0 19:32 ?xdm? 47.31s 0.34s fvwm2 -f /usr/b
thomas pts/3 :0 19:33 7.00s 0.04s 0.04s bash
$ who
tom pts/1 2016-06-04 14:07 (michener:S.0)
tom pts/4 2016-06-04 12:34 (michener:S.1)
tom pts/5 2016-06-04 13:00 (michener:S.2)
thomas :0 2016-06-04 19:32
thomas pts/3 2016-06-04 19:33 (:0)
그러나 모든 터미널이 utmp(이 정보가 저장되는 위치)를 지원하는 것은 아닙니다. Linux로만 제한되어 있다면 몇 가지 유용한 정보 /dev/pts
, 즉 소유권 정보가 있는 기기를 얻을 수 있습니다.
$ ls -l /dev/pts
total 0
crw--w---- 1 tom tty 136, 0 Jun 4 19:34 0
crw--w---- 1 tom tty 136, 1 Jun 4 16:12 1
crw--w---- 1 thomas tty 136, 2 Jun 4 19:33 2
crw--w---- 1 thomas tty 136, 3 Jun 4 19:33 3
crw--w---- 1 tom tty 136, 4 Jun 4 19:34 4
crw--w---- 1 tom tty 136, 5 Jun 4 19:24 5
c--------- 1 root root 5, 2 Jun 4 12:16 ptmx
스크립트는 이를 쉽게 확인하고, 의도된 사용자가 누구인지 결정하고, 이러한 (최종) 장치에 쓸 수 있습니다.
노트:
"프로그램이 출력을 브로드캐스트할 터미널을 어떻게 알 수 있습니까?"와 관련하여 일반적인 접근 방식은 구별할 각 터미널에서 클라이언트를 실행하고 서버와 통신하도록 하는 것입니다.
프로그램이 어떻게 아는지 묻는 댓글이 있습니다.어디고객이 화면에 나타납니다. 예를 들어 window-id로 시작하고 를 사용하여 창 속성을 사용하여 이 정보를 얻을 수 있습니다
xwininfo
. 터미널 에뮬레이터 유형과 적절한(또는 사용 가능한) window-id 간에는 차이가 있습니다. 그러나WINDOWID
각 터미널의 환경 변수는 이 정보를 얻는 일반적인 방법입니다(또는 단지 브로드캐스트를 원하지 않는 경우 클라이언트를 통해). 다음은 이 방법을 사용한 샘플 출력입니다.
xwininfo: 창 ID: 0x400023 "[!xwininfo] - 평균" 절대 왼쪽 위 모서리 X: 0 절대 왼쪽 위 모서리 Y: 23 상대 왼쪽 위 모서리 X: 0 상대 왼쪽 상단 모서리 Y: 22 폭: 486 신장: 551 깊이: 24 비전: 0x22 시각적 등급: 트루 컬러 테두리 너비: 0 클래스: 입력 및 출력 컬러맵: 0x21(설치됨) 비트 중력 상태: NorthWestGravity 창 중력 상태: NorthWestGravity 백업 저장소 상태: 쓸모 없음 저장 상태: 아니요 지도 상태: IsViewable 리디렉션 상태 무시: 아니요 코너킥: +0+23 -794+23 -794-428 +0-428 -기하학 80x40+0+1
추가 자료: