Bagaimana seseorang bisa mendapatkan nama asli dari terminal pengendali (jika ada, kalau tidak kesalahan) sebagai pathname?
Dengan "nama asli", maksud saya tidak /dev/tty
, yang tidak dapat digunakan oleh proses arbitrer lainnya untuk merujuk ke terminal yang sama. Saya lebih suka jawabannya sebagai kode shell sederhana (seperti contoh di bawah) jika memungkinkan, jika tidak sebagai fungsi C.
Perhatikan bahwa ini harus bekerja bahkan jika input standar dialihkan, sehingga tty
utilitas tidak dapat digunakan: orang akan mendapatkan not a tty
kesalahan dalam kasus seperti itu, karena tty
hanya mencetak nama file terminal yang terhubung ke input standar.
Di Linux, seseorang dapat menggunakan:
echo "/dev/`ps -p $$ -o tty | tail -n 1`"
tetapi ini tidak portabel, seperti menurut POSIX, format nama terminal tidak ditentukan .
Mengenai fungsi C, ctermid (NULL)
pengembalian /dev/tty
, yang tidak berguna di sini.
Catatan: menurut zsh
dokumentasi, seseorang harus dapat melakukannya
zsh -c 'echo $TTY'
tetapi ini saat ini (versi 5.0.7) gagal ketika input standar dan output standar dialihkan:
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null
/dev/pts/9
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null > /dev/null
/dev/tty
sumber
ps
solusinya mencakup sebagian besar sistem (danwho
tidak membantu lebih darips
), mungkin dengan kode sedikit lebih untuk menangani pengidentifikasi saja (seperti "04"). Saya bertanya-tanya apakah ada solusi yang lebih portabel.man xterm
:-Sccn
Opsi ini memungkinkanxterm
untuk digunakan sebagai saluran i / o untuk program yang ada ... Nilai opsi adalah beberapa huruf dari nama pty untuk digunakan dalam mode slave, ditambah nomor fd yang diwarisi. Jika opsi berisi karakter "/", itu membatasi nama pty dari fd.ps
dari busybox (yang digunakan oleh Android, BTW), bahkan di bawah GNU / Linux. Apa yang Anda maksud dengan "xterm
bisa mengatasinya04
"?busybox
bukan POSIX-conformant.toybox
Namun, sangat baik.Jawaban:
"Terminal pengendali" alias. CTTY, adalah distincted dari " yang proses terminal berinteraksi dengan".
Cara standar untuk mendapatkan jalur ctty adalah ctermid (3). Saat memanggil ini, Dalam freebsd sejak rilis 10, jalan yang sebenarnya dilihat [1], sementara freebsd dan implementasi glibc yang lebih lama [2] tanpa syarat mengembalikan "/ dev / tty"].
ps (1) dari paket linux procps 3.2.8, baca entri numerik di / proc / * / stat [3], dan kemudian kurangi pathname sebagian dengan menebak [4, 5] karena kurangnya dukungan sistem [6] .
Namun jika kita tidak benar-benar tertarik pada ctty tetapi terminal apa pun yang terkait dengan stdio, tty (1) mencetak jalur terminal yang terhubung ke stdin, yang identik dengan
ttyname(fileno(stdin))
di c, dan alternatifnya adalahreadlink /proc/self/fd/0
.Pikiran yang kurang penting mengenai perilaku "/ dev / tty" tanpa syarat: Spesifikasi hanya mengatakan string yang dikembalikan oleh ctermid "ketika digunakan sebagai nama jalur, merujuk ke terminal pengendali saat ini", alih-alih secara langsung "adalah nama jalur saat ini mengendalikan terminal ". Ini mungkin ditafsirkan sebagai "/ dev / tty" bukan terminal pengendali, tetapi hanya merujuk ke terminal pengendali jika proses yang sama terbuka (3). Sehingga tidak melanggar "terminal mungkin ctty untuk paling banyak satu sesi" aturan [7].
Konsekuensi lain adalah bahwa ketika saya tanpa terminal pengendali, ctermid tidak gagal - kegagalan seperti itu diizinkan oleh spesifikasi [8] -, jadi hanya saya yang bisa mengetahui ketidakberdayaan saya sampai gagal membuka berikutnya (3), yang tidak apa-apa karena spesifikasi juga mengatakan panggilan terbuka (3) tidak dijamin untuk berhasil.
sumber
ps
solusi yang saya berikan dalam pertanyaan saya, karena tidak semua OS memiliki/proc
sistem file. Perhatikan bahwaps
itu sendiri menggunakan tautan baca aktif/proc/self/fd/2
(yang berfungsi meskipun kesalahan standar dialihkan).tty
.stderr
mungkin yang terbaik karena itu spec'd menjadi terbuka r / w. Jaditty <&2
.ctermid()
selalu kembali"/dev/tty"
. Nama itu selalu merujuk ke terminal pengontrol dari proses mengaksesnya , yang bervariasi berdasarkan sesi. Terminal adalah sesi khusus, tetapi nama yang diaksesnya tidak perlu.Spec POSIX benar-benar melakukan lindung nilai taruhannya di mana Terminal Pengendali terkait, dan yang didefinisikan sebagai berikut:
/dev/tty
adalah sinonim untuk terminal pengendali yang terkait dengan suatu proses.Itu ada dalam daftar Definisi - dan hanya itu yang ada di sana. Namun dalam General Terminal Interface , beberapa kata:
Terminal dapat menjadi bagian dari suatu proses sebagai terminal pengendali. Setiap proses sesi yang memiliki terminal pengendali memiliki terminal pengendali yang sama. Terminal mungkin merupakan terminal pengendali untuk paling banyak satu sesi. Terminal pengendali untuk suatu sesi dialokasikan oleh pemimpin sesi dengan cara yang ditentukan implementasi. Jika pemimpin sesi tidak memiliki terminal pengendali, dan membuka file perangkat terminal yang belum dikaitkan dengan sesi tanpa menggunakan opsi O_NOCTTY (lihat buka ()), itu ditentukan implementasi apakah terminal menjadi terminal pengendali sesi pemimpin.
Terminal pengendali diwarisi oleh proses anak selama panggilan fungsi fork (). Suatu proses melepaskan terminal pengendali ketika membuat sesi baru dengan
setsid()
fungsi; proses lain yang tersisa di sesi lama yang memiliki terminal ini sebagai terminal pengendali mereka terus memilikinya. Setelah penutupan deskriptor file terakhir dalam sistem (apakah itu dalam sesi saat ini atau tidak) yang terkait dengan terminal pengendali, tidak ditentukan apakah semua proses yang memiliki terminal itu sebagai terminal pengendali berhenti memiliki terminal pengendali. Apakah dan bagaimana pemimpin sesi dapat memperoleh kembali terminal pengendali setelah terminal pengendali dilepaskan dengan cara ini tidak ditentukan. Suatu proses tidak melepaskan terminal pengendali hanya dengan menutup semua deskriptor file yang terkait dengan terminal pengendali jika proses lain terus membukanya.Masih banyak yang belum ditentukan - dan jujur saya pikir itu masuk akal. Walaupun terminal adalah antarmuka pengguna utama, terminal juga semua jenis hal lain dalam beberapa kasus - seperti perangkat keras yang sebenarnya, atau bahkan jenis printer - tetapi dalam banyak kasus itu hampir tidak ada sama sekali - seperti terminal
xterm
yang hanya merupakan emulator . Sulit untuk mendapatkan spesifik di sana - dan saya tidak berpikir itu akan banyak demi kepentingan Unix, karena terminal melakukan lebih banyak daripada Unix.Bagaimanapun, POSIX juga cukup rapuh tentang bagaimana
ps
seharusnya berperilaku di mana ctty bersangkutan.Itu
-a
saklarnya:Bagus. Pemimpin sesi dapat dihilangkan. Itu tidak terlalu membantu.
Dan
-t
:<blank>
daftar yang dipisahkan oleh koma. Pengidentifikasi terminal harus diberikan dalam format yang ditentukan implementasi .... yang merupakan kekecewaan lainnya. Tapi itu terus mengatakan ini tentang sistem XSI:
tty04
) atau, jika nama file perangkat dimulai dengantty
, hanya pengidentifikasi yang mengikuti karaktertty
(misalnya,04
) .Itu sedikit lebih baik, tetapi bukan jalan. Juga pada sistem XSI ada
-d
saklar:... yang setidaknya jelas. Anda dapat menentukan
-o
saklar utput juga dengantty
string format, tetapi, seperti yang telah Anda catat, format outputnya ditentukan oleh implementasi. Namun, saya pikir itu sama baiknya dengan yang didapat. Saya berpikir bahwa - dengan banyak pekerjaan - sakelar di atas dikombinasikan dengan beberapa utilitas lain dapat membuat Anda rata-rata yang bagus. Jujur saja, saya tidak tahu kapan / bagaimana hal itu merusak Anda - dan saya belum bisa membayangkan situasi di mana itu akan terjadi. Tapi, saya pikir mungkin jika kita menambahkanfuser
danfind
kita dapat memverifikasi jalurnya.Hal
/dev/null
itu hanya untuk menunjukkan bahwa itu bisa bekerja ketika tidak ada subkulit pencarian yang memiliki 0,1,2 yang terhubung ke ctty. Bagaimanapun, itu mencetak:Sekarang yang di atas mendapatkan jalur penuh pada mesin saya, dan saya membayangkan hal itu akan terjadi pada kebanyakan orang. Saya juga bisa membayangkan itu bisa gagal. Itu hanya heuristik kasar.
Ini mungkin gagal karena banyak alasan lain mungkin, tetapi jika Anda berada di sistem yang memungkinkan ketua sesi untuk melepaskan semua deskriptor ke ctty dan tetap sebagai sid maka sebagai spec memungkinkan, maka ini jelas tidak akan membantu. Yang mengatakan, saya pikir ini bisa mendapatkan perkiraan yang cukup bagus dalam banyak kasus.
Tentu saja yang paling mudah hal yang harus dilakukan jika Anda memiliki setiap deskriptor terhubung ke CTTY Anda hanya ...
... atau serupa.
sumber