Làm thế nào để kiểm tra trình giả lập thiết bị đầu cuối nào đang được sử dụng?


15

Tôi đã cài đặt gnome-terminal và Guake. Tôi muốn cung cấp các thông báo khởi động khác nhau được hiển thị trên các trình giả lập thiết bị đầu cuối này khi chúng bắt đầu. Tôi nên viết mã nào trong .bashrc để đạt được điều này?

Câu trả lời:


10

Chức năng này sẽ thực hiện công việc:

container() {
    pid=$$
    while true; do
        pid=$(ps -h -o ppid -p $pid 2>/dev/null)
        case $(ps -h -o comm -p $pid 2>/dev/null) in
        (gnome-terminal) echo "Running in gnome terminal";return;;
        (xterm) echo "Running in xterm";return;;
        (rxvt) echo "Running in rxvt";return;;
        (python) if [ ! -z "$(ps -h -o args -p $pid 2>/dev/null | grep guake)" ]; then echo "Running in Guake"; return; fi ;;
        esac
        [[ $(echo $pid) == 1 ]] && break
    done
}
container

Câu trả lời tốt đẹp! Đừng quên gọi hàm theo containersau định nghĩa.
Rosch

Tôi mong đợi điều này là hiển nhiên nhưng bạn đã đúng, câu trả lời được cập nhật tương ứng.
jlliagre

@jlliagre Tôi đã thử mã. Nó hoạt động trơn tru trên gnome-terminal nhưng nó có vấn đề với Guake. Nó không cung cấp bất kỳ đầu ra. Thay vào đó, nó đóng băng như thể trong bế tắc. Tôi phải Ctrl + C để sử dụng nó. Không thực sự hiểu mã nên không biết nó đang sai ở đâu.
VedVals

Mã cố định. Tôi đã bỏ lỡ guake được điều hành bởi python và có một lỗi ngăn chức năng thoát ra. Cảm ơn vì bạn đã phản hồi.
jlliagre

Xin lỗi anh bạn, vẫn không hoàn toàn làm việc. Đưa ra lỗi bash: [: too many arguments. Có bash v4.2.24, python v2.7.3 nếu nó giúp.
VedVals

10

Thử đi:

echo $TERM

Điều này có thẩm quyền hơn, nhưng có thể bị các chương trình của bạn làm rối tung lên. Tuy nhiên, đối với tôi, nó nói xtermvà trên ttys nó nói linux, mà tôi nghĩ là viết tắt của Linux Console.


2
$TERMlà một biến trong đó đề cập đến đặc tả là trình tự mô phỏng đầu cuối mà bạn đang sử dụng, chứ không phải cho trình giả lập thực tế. Ví dụ, trên hệ thống của tôi, echo $TERMtrả về xtermmặc dù tôi thực sự đang chạy lxterminal. Điều gì đang xảy ra là lxterminal tự báo cáo tuân thủ xterm. lxterminal không thực sự hoàn toàn tuân thủ xterm, vì vậy bạn phải coi chừng. Các tập tin spec thường được đặt trong /usr/share/terminfo.
stazher

7

Bạn có thể lấy tên trình giả lập thiết bị đầu cuối, bằng cách lấy tên của tiến trình cha mẹ. Do đó, nó hoạt động với mọi trình giả lập thiết bị đầu cuối.

Trong bash, zsh, vv.:

basename "/"$(ps -f -p $(cat /proc/$(echo $$)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')

Với vỏ cá:

basename "/"(ps -f -p (cat /proc/(echo %self)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')

Tuy nhiên, lưu ý rằng điều này sẽ bắt các đối số chương trình khi trình giả lập thiết bị đầu cuối được khởi chạy cùng với chúng.
Robobenklein

Điều này có hoạt động nếu tôi được kết nối bằng SSH không?
dùng3731622

@ user3731622 nó sẽ không! Bạn sẽ phải chuyển tiếp nó từ khách hàng.
Enrico

2

Trên nhiều hệ thống linux echo $TERMtrở lạixterm xem bài stazher ở trên.

Để có được thiết bị đầu cuối thực tế đang sử dụng, hãy làm điều này:

1: Đóng mọi phiên bản đầu cuối hiện đang chạy.

2: Mở thiết bị đầu cuối mới bằng phương pháp thông thường của bạn.

3: Nhập lệnh như sau:

ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)

4: Trả về phải là một cái gì đó như thế:

lxterminal --geometry=135x20

Đây là sự cố:

Vậy: pslà "trạng thái quá trình"

Tùy chọn ps -olà Hiển thị thông tin được liên kết với danh sách từ khóa được phân tách bằng dấu cách hoặc dấu phẩy được chỉ định. Nghe có vẻ phức tạp, nhưng thực sự không phải vậy. (dấu cách hoặc dấu phẩy) được phân tách (danh sách từ khóa) được chỉ định.

Vì vậy, (danh sách từ khóa) 'cmd='chỉ có một từ khóa trong danh sách. Vì vậy, chỉ cần yêu cầu hiển thị lệnh để mở terminal.

Tùy chọn ps -plà "by process id" Wow đây là tùy chọn rất hay cho ps. Vấn đề là, bạn phải chuyển đến ps quá trình id này. Vì vậy, làm thế nào để có được quá trình id? Chúng tôi mở biểu hiện $(ps -o 'ppid=' -p $$)

Ở đây chúng ta phải bắt đầu suy nghĩ sâu hơn một chút. Tôi ước tôi đã phát minh ra bash one-liner này, nhưng tôi đã không làm thế. Tôi nghĩ rằng tôi đã đánh cắp nó từ https://wiki.archlinux.org/ ở đâu đó, tôi không thể tìm lại được. Những người đó thật tuyệt vời, nhưng nhiều lần tôi không thể hiểu họ nói phải làm gì cho đến khi học nhiều. Những gì chúng ta có thể làm, là hiểu nó bây giờ, bởi vì tôi sẽ giải thích.

vì vậy chúng tôi biết $là toán tử mở rộng trong bash. Tôi thích nghĩ "un-quấn". Vì vậy, $(foo -opt bar)sẽ mở khóa hoặc mở rộng "thanh foo -opt". Nhưng trong bash, nẹp tròn đơn (...)mở ra subshell.

Vì vậy, $(foo -opt bar)mở rộng "thanh foo -opt" như chạy trong vỏ con gái . Rất kỳ lạ và khó hiểu.

OK, vì vậy bây giờ chúng tôi đang chạy lại lệnh gần như giống hệt nhau, ps -o 'ppid=' -p $$nhưng lần này, trạng thái quá trình, cho chúng ta thấy những gì anh ta có thể nhìn thấy từ bên trong vỏ con gái .

-odanh sách các từ khóa, chỉ có một từ khóa như trước đây, nhưng ppid=đây là yêu cầu trực tiếp cho id quá trình của shell cha !! Từ ININ DAUGHTER SHELL! Rất thông minh, phải không? Tôi rất vui mừng khi tôi có thể hiểu điều này!

-pmột lần nữa, "by id process" và trong bash $$là process id.

Nếu bạn gọi ps -o 'ppid=' -p $$, hoặc bất kỳ lệnh nào khác yêu cầu $$trực tiếp từ shell đầu tiên, anh ta có thể nói pid = 1 hoặc pid từ xWindow hoặc từ chương trình máy tính để bàn của bạn, hoặc bạn có thể nhận được pid shell thực sự. Nếu bạn hỏi nhiều lần, bạn có thể nhận được câu trả lời khác nhau mỗi lần!

Nhưng, nếu bạn gọi một cô con gái và hỏi cô ấy "Ai là bố của bạn", cô ấy sẽ nói với bạn! Rất thông minh. Tôi ước tôi có thể là thiên tài như vậy để phát minh ra phương pháp này.


OK vì vậy AU sẽ không cho phép phân tích đúng trong một bài. Xin lỗi, không sẵn sàng chiến đấu với hệ thống blog và tạo nhiều bài viết. Có lẽ bạn có thể có được ý tưởng.
stazher

Câu trả lời khác của bạn dường như là một nhận xét phức tạp và nhiều thông tin về câu trả lời này hơn là một câu trả lời cho câu hỏi ... Sẽ thật tuyệt nếu bạn có thể kết hợp hai câu trả lời của mình thành một và xóa một trong số chúng, và thêm vào đó để nó trả lời đầy đủ câu hỏi Sử dụng ---- để vẽ một đường ở giữa? Có một nút cũng có.
Zanna

Tôi nghĩ rằng tôi đã trả lời chính xác câu hỏi của OP và chi tiết. Bạn đã nhảy vào tôi trước khi tôi có cơ hội hiểu hệ thống chỉnh sửa blog và hoàn thành. Mang về những phiếu bầu, tôi đã quen với nó.
stazher

1
Tôi không nghĩ rằng tôi đã nhảy vào bạn, tôi chỉ đang thực hiện đánh giá ... cảm ơn vì đã làm cho bài đăng của bạn hoàn thiện hơn
Zanna

Cảm ơn bạn đã phản hồi của bạn. Tôi xin lỗi, có lẽ tôi đã nhảy vào bạn. Tôi xin lỗi rất nhiều.
stazher

1

Sử dụng pstreeawklà cách dễ nhất:

pstree -sA $$ | awk -F "---" '{ print $2 }'

Giải thích

  1. Hiển thị một cây của các quá trình với pstreecác $$(quá trình atual).
  2. Các pstreeđối số:

    • -s: hiển thị cha mẹ của một quá trình
    • -A: hiển thị đầu ra trong ASCII thuần túy.
  3. Công awkcụ quét một mẫu và -Fđối số được sử dụng để phân chia các quy trình.

  4. Cuối cùng chỉ '{ print $2 }'cho awkđầu ra mẫu khớp thứ 2 (trong trường hợp này là tên giả lập thiết bị đầu cuối).

Bạn có chắc chắn về $2? Trong trường hợp của tôi, những gì được đưa vào awkthực sự là systemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree...
Enrico Maria De Angelis

@EnricoMariaDeAngelis Ya. Cảm ơn bạn đã quan sát của bạn. Trong trường hợp của tôi, trình giả lập thiết bị đầu cuối khởi tạo trực tiếp trong dịch vụ systemd. Tôi kiểm tra lại mã và chỉnh sửa nó với một sự điều chỉnh.
silvadev

Điều này không hoạt động khi tôi sử dụng phím tắt để khởi chạy trình giả lập. Trên XFCE, tôi nhận được xfsettingsdthay vì thiết bị đầu cuối tôi đang sử dụng.
Michael Hoffmann

Hoạt động tốt hơn nếu bạn bắt đầu từ cuối cùng:pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }'
lleaff

0

Bạn đã đúng, tôi chỉ đưa ra câu trả lời cho câu hỏi tiêu đề, không phải câu hỏi trong cơ thể. Vì vậy, bạn đi đây, và Bob's yer chú.

Tôi không chắc chắn về việc chuyển đổi trường hợp là gì, trong một câu trả lời hiển thị ở trên. Trường hợp chuyển đổi như vậy là không cần thiết. Kịch bản ~ / .bashrc của tôi thực sự chỉ là một dòng đơn giản, tất cả các lệnh echo chỉ để giải trí. Làm thế nào để giải thích ...

Bất kỳ thuật ngữ nào khi bắt đầu đọc ~ / .bashrc và thực thi bất kỳ lệnh nào anh ta sẽ thấy trong .bashrc. Vì vậy, bất kể thuật ngữ nào được gọi, anh ta sẽ đọc .bashrc và thực thi các lệnh, do đó, chỉ có cấu trúc cần thiết trong .bashrc là để sửa đổi hành vi của hoặc loại trừ thuật ngữ này hay thuật ngữ khác. Hành vi mong muốn là cho mọi thuật ngữ để thực hiện cùng một lệnh, vì vậy không cần chuyển đổi trường hợp. Bản thân Terminal sẽ cho bạn biết anh ta được gọi như thế nào, vì vậy không cần phải phân biệt.

Lưu ý (1) Tôi đã không kiểm tra guake, nhưng hoạt động cho tất cả những người khác được đề cập trong câu trả lời đầu tiên của jlliagre.

Lưu ý (2) Do định dạng trong đánh dấu cho wiki, bạn không thể cắt và dán như hiển thị. Bạn phải xóa từng backtick , bao gồm để xóa các ký tự gạch chân và thêm backtick thực tế, không có khoảng trắng trước pshoặc sau -p $$).

tập lệnh cho ~ / .bashrc

# show welcome message for actual terminal in use
echo "Welcome.  You are attempting to use"
echo ""
echo _backtick_ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)_backtick_
echo ""
echo "Good Luck and God Speed."

Điều này thật thú vị. Tôi đã thêm cái này vào ~ / .bashrc của riêng tôi.


mỗi Lưu ý (1), đã thử nghiệm trên Tilda, hoạt động tốt. Guake tương tự như Tilda, nhưng được viết bằng trăn, nên vẫn không biết về Guake.
stazher

0

nếu bạn đang sử dụng bash, tôi biết lệnh này sẽ giúp bạn:

which $(ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$))


0

Nếu bạn đang sử dụng ZSH, có một giải pháp tốt hơn (nhanh hơn), chỉ sử dụng các nội dung ZSH và thao tác /proc/$pid/{stat,cmdline}trực tiếp.

get-terminal-emulator() {
    if [[ $TTY = "/dev/tty"* ]]; then
        echo "linux-console"
        return
    fi
    local pid=$$ name=''
    while true; do
        proc_stat=(${(@f)$(</proc/${pid}/stat)})
        name=${proc_stat[2]//[()]/}
        case "${name}" in
            gnome-terminal|konsole|rxvt|xterm)
                echo "${name}"; return ;;
            python*)
                local cmdline=(${(@f)$(</proc/${pid}/cmdline)})
                if [[ "$cmdline" =~ "\\bguake.main\\b" ]]; then
                    echo "guake"; return
                fi
                ;;
        esac
        if test "$pid" = "1" -o "$pid" = ""; then
            echo "unknown"
            return
        fi
        pid=${proc_stat[4]}       
    done
}
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.