Làm thế nào để xác định thiết bị đầu cuối từ một kịch bản?


8

Và đừng nói " $TERM" - luôn luôn như vậy xterm.

Làm thế nào một bashkịch bản có thể cho biết thiết bị đầu cuối nào đang chạy, cụ thể là iTerm, Terminal.app hay thực sự là một xterm?

Tôi hỏi vì resetkhông hoạt động - hết hộp trên Terminal.app và iTerm2. Tuy nhiên, iTerm2 không nhận ra một chuỗi thoát để thực hiện thiết lập lại thiết bị đầu cuối ( \x1b]50;ClearScrollback\x07) và nếu tôi có thể phát hiện ra nó, tôi có thể ghi đè resetbằng một bí danh thực hiện đúng. AFAICT, Terminal.app thiếu trình tự thiết lập lại và mọi người dùng đến biện pháp tấn công lố bịch để hack xung quanh đó .

Mục tiêu cuối cùng của tôi ở đây là resetlàm việc giống nhau cho dù tôi đang làm việc trên OS X hay Linux, làm việc cục bộ hoặc từ xa thông qua SSH. (Tôi không muốn phải cố gắng nhớ đó, và nó rất hữu ích để làm reset && command-that-outputs-a-bunchvà có up-nhập làm việc.) Terminal.app và iTerm đang ném một chìa khoá trong kế hoạch này bằng cách không thực hiện resetmột cách chính xác.

Điều này có nghĩa là chỉ đơn giản là ghi đè resetkhông hoàn toàn: nếu tôi đang sử dụng máy Linux, cần biết tôi đang sử dụng gnome-terminalhay iTerm để gửi chuỗi thoát đúng.

Có cách nào (ngay cả khi tôi cần ioctl) để hỏi thiết bị đầu cuối thực sự là gì không?

Đối với mục đích của câu hỏi này, thiết lập lại sẽ xóa màn hình, đặt lại con trỏ và xóa bộ đệm cuộn lại.


Vâng, đây là một tính năng, không phải là một lỗi, hoặc vì vậy họ nói. Điều gì xảy ra nếu bạn mở Terminal.appcài đặt, tab thiết bị đầu cuối và đặt các dòng cuộn ngược về 0? Điều đó có vô hiệu hóa bất kỳ và tất cả văn bản trên dòng hiện tại, hoặc bất cứ thứ gì phía trên đầu màn hình không? Tôi biết, đó không chính xác là những gì bạn yêu cầu, đáng để thử.
nitro2k01

@ nitro2k01: Tôi không chắc điều gì sẽ thực hiện? Tôi muốn cuộn lại. Tôi chỉ muốn có thể xóa nó ngay bây giờ và sau đó, tốt nhất là với reset, vì đó là những gì ngón tay của tôi biết.
Thanatos

Đối với vấn đề thiết lập lại cài đặt của bạn, để làm rõ, bạn đang mong đợi resetlệnh xóa nội dung cuộn lại của trình mô phỏng đầu cuối, nhưng điều đó không được đảm bảo để làm điều đó, bởi vì cuộn ngược là một tính năng dành riêng cho trình giả lập thiết bị đầu cuối, không thực sự là một một phần của một thiết bị đầu cuối. Tuy nhiên, Terminal hỗ trợ một phần mở rộng của chuỗi thoát ED (Erase in Display) để xóa cuộn lại ESC [ 3 J. Bạn có thể xóa màn hình, sau đó sử dụng màn hình đó, ví dụ:reset && printf '\e[3J’
Trang Chris

Xem câu trả lời của tôi ở đây apple.stackexchange.com/a/113168/6883 để biết thêm chi tiết về phần mở rộng Erase in Display.
Chris Trang

@ChrisPage: Tôi nhận ra rằng các thiết bị đầu cuối là những thứ kỳ quặc, nhưng nếu bạn tuyên bố mình là một xterm(thông qua TERM=xterm) tôi sẽ hy vọng rằng bạn mô phỏng một superset của XTerm, nó sẽ xóa cuộn lại khi thiết lập lại. (Cũng giống như nếu bạn gửi các dãy thoát cho "màu xanh", bạn mong muốn xanh.) Cấp, xterm của tôi nói với tôi rằng Erase is backspace., mà tôi không có gì cảm ơn khác không; Điều đó thật khó chịu.
Thanatos

Câu trả lời:


10

Sử dụng $TERM_PROGRAM.

iTerm đặt nó iTerm.appvà Terminal.app thành Apple_Terminal.


Heh, OK, điều này rõ ràng tốt hơn hack của tôi, +1 :). Bản hack nên hoạt động cho bất kỳ trình giả lập thiết bị đầu cuối nào, không chỉ hai cái đó.
terdon

Không có cách duy nhất để phát hiện mọi trình giả lập thiết bị đầu cuối. Ví dụ, đối với xterm, bạn có thể kiểm tra biến $ XTERM_VERSION. Điều đó sẽ quan tâm đến những gì có lẽ là ba trình giả lập phổ biến nhất trên OS X.
Chris Page

Chấp nhận điều này, vì đó là một khởi đầu tốt. Thật không may, nó không hoàn toàn dễ dàng như vậy, vì biến này không có sẵn trong phiên SSH. Tôi nghi ngờ có những cấu hình mà tôi có thể chỉnh sửa để chuyển tiếp nó.
Thanatos

1
@Thanatos sshd_configAcceptEnvlẽ. Vì cái này (shell của bạn chạy trên một máy chủ khác với cái mà Terminal của bạn chạy) là thông tin rất quan trọng, nó thực sự nên là một phần của câu hỏi.
Daniel Beck

@DanielBeck: Không hoàn toàn đúng như vậy; Tôi muốn làm tương tự tại địa phương và từ xa. Điều tôi sẽ làm là việc gõ "reset" vào thiết bị đầu cuối sẽ gây ra thiết lập lại thiết bị đầu cuối, bất kể tôi đang dùng OS X hay Linux, làm việc cục bộ hay từ xa. Tôi đã chỉnh sửa điều này thành câu hỏi.
Thanatos

1

$TERMkhông có gì để làm với trình giả lập thiết bị đầu cuối hiện đang chạy, nó chỉ là thiết bị đầu cuối mặc định của bạn và có thể được đặt thành bất cứ điều gì cả. Để có được tên của trình giả lập thiết bị đầu cuối mà bạn đang chạy, bạn có thể sử dụng psđể lấy PID của tiến trình cha của trình bao hiện tại của bạn.

LƯU Ý: Những điều sau đây sẽ thất bại trên OSX nhưng sẽ hoạt động tốt trên Linux

PID của quá trình shell hiện tại của bạn là $$. Từ đó, bạn có thể sử dụng psđể hiển thị cây quy trình và in PID của cha mẹ của phiên shell hiện tại của bạn:

ps -axjf | awk -v pid=$$ '($2==pid){print $1}'

Sau đó, bạn có thể chuyển PID đó sang psvà yêu cầu nó in tên lệnh:

ps -o comm=  $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}')

Điều đó sẽ cắt bớt tên, nó sẽ đủ để bạn tìm ra nó nhưng có thể không tốt cho kịch bản. Để có được tên đầy đủ, bạn có thể thử

ps --no-headers $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}') | awk '{print $NF}'

Đây là những gì tôi nhận được trên hệ thống của mình bằng một vài thiết bị đầu cuối khác nhau:

  1. terminator

    $ ps --no-headers $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}') | 
       awk '{print $NF}'
    /usr/bin/x-terminal-emulator
    
  2. gnome-terminal

    $ ps --no-headers $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}') | 
       awk '{print $NF}'
    /usr/lib/gnome-terminal/gnome-terminal-server
    
  3. xterm

    $ ps --no-headers $(ps axjf | awk -v pid=$$ '($2==pid){print $1}') | 
       awk '{print $NF}'
    xterm
    

Không hoạt động trên OS X:ps: illegal option -- f
Daniel Beck

@DanielBeck cực kỳ phong cách BSD, cảm ơn. Bạn có thể thử lại với phiên bản cập nhật không? Thêm một -trước các tùy chọn sẽ hoạt động theo OSX man ps.
terdon

Tốt hơn, nhưng vẫn không làm việc. Định dạng đầu ra là khác nhau (PID là $2, PPID là $3) và quá trình cha của shell có thể là login(tùy thuộc vào cấu hình Terminal), với các thông số khác nhau. Tuy nhiên, quá trình cha mẹ của nóTerminal. --no-headerskhông tồn tại, bạn cần một cái gì đó như tail -n1. Và vì tất cả các quy trình với UI đều có đối số-psn_0_... , nên awk '{print $NF}'cũng không hoạt động.
Daniel Beck

@DanielBeck cũng shucks rồi. OK, cảm ơn tôi sẽ nói rõ rằng điều này không thành công trên OSX.
terdon

Lưu ý rằng điều này chỉ hoạt động tại địa phương. Bạn không thể sử dụng phương pháp này để tìm ra trình giả lập thiết bị đầu cuối nào đang được sử dụng trên máy khách từ xa. Câu trả lời tốt nhất là tìm kiếm các biến như $ TERM_PROGRAM (như được đề cập trong câu trả lời của @ DanielBeck) và $ XTERM_VERSION để suy ra ứng dụng giả lập.
Chris Trang

0

Đây là một cách di động để có được tên hoặc đường dẫn của quy trình cha:

iTerm 2:

$ ps -p $(ps -p $$ -o ppid=) -o comm=
/Applications/iTerm.app/Contents/MacOS/iTerm

gnome-terminal trong Ubuntu:

$ ps -p $(ps -p $$ -o ppid=) -o comm=
gnome-terminal

Terminal.app:

$ ps -p $(ps -p $$ -o ppid=) -o comm=
login

Lưu ý rằng nếu Terminal.app được đặt để mở shell mới với shell đăng nhập mặc định, tiến trình cha của shell loginkhông phải là terminal.

Các commcột là đường dẫn đầy đủ của lệnh trong OS X và tên lệnh cắt ngắn đến 15 ký tự trong việc thực hiện procps trong Linux.


Đã thử trong iTerm và đã nhận login- Tôi đã tùy chỉnh hồ sơ của mình một thời gian để chạy lại lệnh login -fp danielbeckchưa?
Daniel Beck
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.