Kontrol terminalinin gerçek adı nasıl alınır?


13

Kontrol terminalinin gerçek adı (eğer varsa, bir hata varsa) yol adı olarak nasıl elde edilebilir?

"Gerçek ad" ile kastediyorum /dev/tty, aynı keyfi ifade etmek için diğer keyfi süreçler tarafından kullanılamaz. Cevabı mümkünse basit bir kabuk kodu (aşağıdaki örnek gibi), aksi takdirde bir C fonksiyonu olarak tercih ederim.

Bunun, standart girdi yeniden yönlendirilse bile çalışması gerektiğini unutmayın, böylece ttyyardımcı program kullanılamaz: not a ttyböyle bir durumda bir hata oluşur çünkü ttystandart girişe bağlı terminalin dosya adını yazdırır.

Linux altında aşağıdakiler kullanılabilir:

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

ancak bu POSIX'e göre taşınabilir değildir , terminal adının biçimi belirtilmez .

C fonksiyonları ile ilgili olarak, burada işe yaramaz ctermid (NULL)döner /dev/tty.

Not:zsh belgelere göre ,

zsh -c 'echo $TTY'

ancak şu anda (sürüm 5.0.7) hem standart giriş hem de standart çıkış yeniden yönlendirildiğinde başarısız olur:

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

@mikeserv Bence psçözüm çoğu sistemi kapsar (ve whodaha fazla yardımcı olmaz ps), muhtemelen tanımlayıcı tek başına ("04" gibi) işlemek için biraz daha fazla kod ile. Daha taşınabilir bir çözüm olup olmadığını merak ediyordum.
vinc17

Önceden eşleştirilmiş setlerle ilgili olabilir - belki de eski BSD tarzı pty çiftleri. Tüm pty'ler UNIX 98 türleri değildir. Her neyse, from man xterm: -Sccn Bu seçenek xtermmevcut bir program için bir g / Ç kanalı olarak kullanılmasına izin verir ... Seçenek değeri, köle modunda kullanılacak bir pty adının yanı sıra devralınan fd numarasının birkaç harfidir. Seçenek bir "/" karakteri içeriyorsa, pty adını fd'den ayırır.
mikeserv

@mikeserv çözüm ile çalışmıyor unutmayın psdan BusyBox bile GNU / Linux altında, (BTW Android, tarafından kullanılır). Eğer "ne demek istiyorsunuz xtermyani işleyebilir 04"?
vinc17

busyboxPOSIX uyumlu değil. toyboxancak, çok iyi.
mikeserv

Yanıtlar:


8

"Kontrol terminali" aka. ctty, " bir işlemin etkileşimde bulunduğu terminal " den farklıdır .

Ctty yolunu almanın standart yolu ktermiddir (3). Bunu çağırdıktan sonra, 10 sürümünden beri freebsd'de gerçek bir yol aranır [1], eski freebsd ve glibc uygulamaları [2] koşulsuz olarak "/ dev / tty"] döndürür.

Linux PS (1) 3.2.8 paketi PROCPS / Proc / * / stat sayısal girişi okumak [3] ve daha sonra yol adı kesinti tahmin kısmen [4, 5] nedeniyle sistem desteği eksikliği [6] .

Bununla birlikte, ctty ile kesinlikle ilgilenmiyoruz, ancak stdio ile ilişkili herhangi bir terminal varsa, tty (1) ttyname(fileno(stdin)), c'ye benzeyen ve bir alternatif olan stdin'e bağlı terminal yolunu yazdırır readlink /proc/self/fd/0.


Koşulsuz "/ dev / tty" davranışı ile ilgili daha az önemli düşünce: Spesifikasyonlar sadece ctermid tarafından döndürülen dizenin "bir yol adı olarak kullanıldığında, akım kontrol yolunun yerine" geçerli kontrol terminaline bakın "akımın yol adı olduğunu söylüyor kontrol terminali ". "/ Dev / tty" nin kontrol terminali olmadığı şeklinde yorumlanabilir, ancak kontrol terminaline sadece aynı işlem açıldığında (3) bakın. Dolayısıyla "bir terminal en fazla bir oturum için ctty olabilir" kuralını ihlal etmemek [7].

Başka bir sonuç, herhangi bir kontrol terminali olmadığımda, ctermidin başarısız olmasına neden olur - bu tür bir başarısızlığa spesifikasyonlar tarafından izin verilir [8] - bu yüzden bir sonraki açık başarısız olana kadar ctty'lessness'imden haberdar olabilirim (3), çünkü özellikleri de açık (3) çağrısı başarılı olmak için garanti değildir diyorlar.


psTüm işletim /procsistemlerinde bir dosya sistemi olmadığından, bu benim soruma verdiğim çözümden daha taşınabilir değil . psKendisinin üzerinde bir readlink kullandığını unutmayın /proc/self/fd/2(standart hatanın yeniden yönlendirildiği bile çalışır).
vinc17

1
düzenlendi. ve / proc / * / fd / 2 üzerindeki ps readlink, ctty'yi bulmak için değil, sayısal terminali yola eşlemek için ek bilgi aramak için, bkz. link [4] [5].

1
Mükemmel düzenleme. Ctty ile ilgili olarak; Vinc17 için konuşamıyorum, ancak muhtemelen her zaman bir yere yazabiliyor olsanız da, süreç grubunuzu canlı tutmak için açık kalması gereken tek bir dosya var.
mikeserv

1
@ vinc17 - ctty'nizde açık olan herhangi bir dosya tanımlayıcı varsa, bunları ile okuyabilirsiniz tty. stderrmuhtemelen en iyisidir çünkü açık r / w olması şarttır. Yani tty <&2.
mikeserv

1
Belirli bir terminalin en fazla bir oturum için ctty olabilmesi, glibc'yi ctermid()her zaman geri dönmesi için uygunsuz yapmaz "/dev/tty". Bu ad, her zaman , oturuma göre değişen, ona erişen işlemin denetleyici terminalini ifade eder . Terminal oturuma özeldir, ancak erişildiği adın olması gerekmez.
PellMel

5

POSIX spesifikasyonu, gerçekten Kontrol Terminali söz konusu olduğunda ve bu şekilde tanımladığı bahislerini korur:

  • Kontrol Terminali
    • Terminale atıfta bulunan birkaç özel dosyadan hangisinin kastedildiği sorusu POSIX.1'de ele alınmamıştır. Yol adı /dev/tty, bir işlemle ilişkili kontrol terminali ile eşanlamlıdır.

Tanımlar listesinde budur - ve hepsi oradadır. Ancak Genel Terminal Arayüzü'nde daha fazlası söyleniyor:

  • Bir terminal, kontrol terminali olarak bir sürece ait olabilir. Bir kontrol terminali olan bir oturumun her işlemi aynı kontrol terminaline sahiptir. Bir terminal, en fazla bir oturum için kontrol terminali olabilir. Bir oturum için kontrol terminali, oturum lideri tarafından uygulama tanımlı bir şekilde tahsis edilir. Bir oturum liderinin kontrol terminali yoksa ve O_NOCTTY seçeneğini kullanmadan bir oturumla ilişkilendirilmemiş bir terminal cihazı dosyası açarsa (bkz. Open ()), terminalin oturumun kontrol terminali olup olmadığı uygulama tanımlıdır Önder.

  • Kontrol terminali fork () fonksiyon çağrısı sırasında bir alt süreç tarafından miras alınır. Bir işlem, kontrol terminalini yeni bir oturum oluşturduğundan vazgeçirir.setsid()fonksiyonu; kontrol terminalleri olarak bu terminali kullanan eski oturumda kalan diğer işlemler devam eder. Kontrol terminali ile ilişkili sistemdeki son dosya tanımlayıcısının (mevcut oturumda olsun ya da olmasın) kapatılması üzerine, kontrol terminali olarak o terminale sahip olan tüm işlemlerin herhangi bir kontrol terminaline sahip olup olmadığı belirtilmez. Bir oturum liderinin, kontrol terminali bu şekilde bırakıldıktan sonra bir kontrol terminalini tekrar alıp almayacağı ve nasıl belirtileceği belirtilmemiştir. Bir işlem, diğer işlemler açılmaya devam ederse, kontrol terminalini kontrol terminaliyle ilişkili tüm dosya tanımlayıcılarını kapatarak bırakmaz.

Orada belirtilmemiş çok şey var - ve dürüstçe bunun mantıklı olduğunu düşünüyorum. Terminal önemli bir kullanıcı arayüzü olsa da, bazı durumlarda gerçek donanım, hatta bir tür yazıcı gibi diğer şeyler de vardır, ancak çoğu durumda pratik olarak hiçbir şey yoktur - xtermsadece bir emülatör gibi . Orada spesifik olmak zor - ve zaten Unix'in çıkarına çok fazla olacağını sanmıyorum, çünkü terminaller Unix'ten çok daha fazlasını yapıyor.

Her neyse, POSIX, psctty'nin söz konusu olduğu yerde nasıl davranması gerektiği konusunda da oldukça havalı.

Orada -aanahtarı:

  • Terminallerle ilişkili tüm işlemler için bilgi yazın. Uygulamalar oturum liderlerini bu listeden çıkarabilir.

Harika. Oturum liderleri olabilir atlanabilir. Bu çok yardımcı değil.

Ve -t:

  • Terim listesinde verilen terminallerle ilişkili işlemler için bilgi yazın. Başvuru, terim <blank>listesinin bir veya virgülle ayrılmış liste biçiminde tek bir argüman olmasını sağlamalıdır . Terminal tanımlayıcıları uygulama tanımlı bir formatta verilmelidir .

... başka bir hayal kırıklığı. Ama bunu XSI sistemleri hakkında söylemeye devam ediyoruz:

  • XSI uyumlu sistemlerde, bunlar iki formdan birinde verilmelidir: aygıtın dosya adı (örneğin tty04) veya aygıtın dosya adı ile başlarsa tty, yalnızca karakterleri izleyen tanımlayıcı tty (örneğin 04) .

Bu biraz daha iyi, ama bir yol değil. Ayrıca XSI sistemlerinde -danahtar vardır:

  • Oturum liderleri hariç tüm süreçler için bilgi yazın.

... en azından açık olan. -oUtput anahtarını ttybiçim dizesiyle de belirtebilirsiniz , ancak belirttiğiniz gibi çıktı biçimi uygulama tanımlıdır. Yine de, olabildiğince iyi olduğunu düşünüyorum. Bence - çok fazla çalışma ile - diğer bazı yardımcı programlarla birlikte yukarıdaki anahtarlar size oldukça iyi bir basketbol sahası elde edebilir. Yine de dürüst olmak gerekirse, sizin için ne zaman / nasıl kırıldığını bilmiyorum - ve içinde olacağı bir durumu hayal edemedim. Ancak, muhtemelen eklersek fuserve findyolu doğrulayabilirsek düşünüyorum .

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Şeyler aramaya altkabuklarda hiçbiri ctty bağlı 0,1,2 herhangi varken işe yarayabilir göstermek içindi. Her neyse, yazdırır:

/dev/pts/3:          mikeserv   3342 F.... (mikeserv)zsh

Şimdi yukarıdakiler makinemde tam yolu alıyor ve çoğu durumda çoğu insan için olacağını düşünüyorum. Başarısız olabileceğini de hayal edebiliyorum. Sadece kaba sezgisel tarama.

Bu muhtemelen başka birçok nedenden dolayı başarısız olabilir, ancak oturum liderinin tüm tanımlayıcıları ctty'ye bırakmasına ve spesifikasyonun izin verdiği şekilde sid olarak kalmasına izin veren bir sistemdeyseniz, bu kesinlikle yardımcı olmayacaktır. Bununla birlikte, çoğu durumda bunun oldukça iyi bir tahmin alabileceğini düşünüyorum.

Elbette ctty'nize bağlı herhangi bir tanımlayıcı varsa yapmak için en kolay şey sadece ...

tty <&2

...veya benzeri.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.