Grep'e yönlendirmek için tee'yi nasıl kullanırım


13

Tee kullanma konusunda fazla deneyimim yok, bu yüzden umarım bu çok basit değildir.

Bu sorunun cevaplarından birini görüntüledikten sonra garip bir beheviour ile karşılaştım tee.

İlk satırı ve bulunan bir satırı çıkarmam için bunu kullanabilirim:

ps aux | tee >(head -n1) | grep syslog
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
syslog     806  0.0  0.0  34600   824 ?        Sl   Sep07   0:00 rsyslogd -c4

Ancak, bu ilk kez (zsh olarak) sonuç yanlış sırada, sütun başlıkları grep sonuçlarının altında idi (ancak yine de olmadı), bu yüzden etrafındaki komutları değiştirmeye çalıştım:

ps aux | tee >(grep syslog) | head -n1
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

Sadece ilk satır yazdırılır, başka bir şey kalmaz Grep'e yönlendirmek için tee'yi kullanabilir miyim, yoksa bunu yanlış mı yapıyorum?

Bu soruyu yazarken, ikinci komut aslında benim için bir kez çalıştı, tekrar beş kez çalıştırdım ve sonra bir satır sonucuna geri döndüm. Bu sadece benim sistemim mi? (Tmux içinde zsh kullanıyorum).

Son olarak, neden ilk komutla "grep syslog" bir sonuç olarak gösterilmiyor (tek bir sonuç var)?

Kontrol için burada grep olmadan tee

ps aux | grep syslog
syslog     806  0.0  0.0  34600   824 ?        Sl   Sep07   0:00 rsyslogd -c4
henry    2290  0.0  0.1  95220  3092 ?        Ssl  Sep07   3:12 /usr/bin/pulseaudio --start --log-target=syslog
henry   15924  0.0  0.0   3128   824 pts/4    S+   13:44   0:00 grep syslog

Güncelleme: Görünüşe göre head tüm komutun kısalmasına neden oluyor (aşağıdaki cevapta belirtildiği gibi), aşağıdaki komut şimdi aşağıdakileri döndürüyor:

ps aux | tee >(grep syslog) | head -n1
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
syslog     806

Sorunuza doğrudan bir cevap değil, ancak böyle bir şey yapmak çok daha temiz olurdu ps aux | sed -n -e '1p' -e '/syslog/p'.
jw013

Ben sed bile düşünmedim, ben burada ilgili soru için uygun bir cevap olabilir düşünüyorum ama aslında bu komutların tutarsız davranışı hakkında bilgi arıyorum!
Rqomey

Yanıtlar:


19
$ ps aux | tee >(head -n1) | grep syslog
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND 
syslog     806  0.0  0.0  34600   824 ?        Sl   Sep07   0:00 rsyslogd -c4

grepVe headveri kullanılabilir hale geldikçe, genellikle komutlar yaklaşık aynı zamanda başlar ve her iki kendi boş aynı giriş verilerini alır, ancak. Hatları çeviren 'senkronize olmayan' çıktıyı tanıtabilen bazı şeyler vardır; Örneğin:

  1. teeEsasen çoğullayan veriler, öncelikle uygulamasına bağlı olarak, bir işlemden önce diğerine gönderilir tee. Basit bir teeuygulama readbir miktar girdi ve sonra writeiki kez olacaktır: Bir kez stdout'a ve bir kez de argümanına. Bu, ilk olarak bu hedeflerden birinin verileri alacağı anlamına gelir.

    Ancak, boruların hepsi tamponludur. Bu arabelleklerin her biri 1 satır olabilir, ancak daha büyük olabilirler, bu da alıcı komutlardan birinin grepdiğer komut ( head) herhangi bir veri almadan önce çıktı için ihtiyaç duyduğu her şeyi (yani ped hattı) görmesine neden olabilir. herşey.

  2. Yukarıdakilere rağmen, bu komutlardan birinin verileri alması, ancak zamanında onunla hiçbir şey yapamaması ve daha sonra diğer komutun daha fazla veri alması ve hızlı bir şekilde işlemesi mümkündür.

    Örneğin , veriler bir seferde bir satır gönderilse bile headve bununla nasıl başa çıkılacağını bilmiyorsa (veya çekirdek zamanlaması ile gecikirse), şansı bile bulunmadan önce sonuçlarını gösterebilir . Göstermek için bir gecikme eklemeyi deneyin: Bu, ilk önce çıktıyı neredeyse kesin olarak verir .grepheadgrepheadps aux | tee >(sleep 1; head -n1) | grep sysloggrep

$ ps aux | tee >(grep syslog) | head -n1
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

Sık sık buraya sadece bir satır geldiğine inanıyorum, çünkü headilk girdi satırını alır ve sonra stdinini kapatır ve çıkar. Ne zaman teestdout kapalı olduğunu görür, daha sonra kendi Stdin (çıktı kapatır ps) ve çıkışları. Bu uygulamaya bağlı olabilir.

Etkili bir şekilde, gönderilecek tek veri psilk satırdır (kesinlikle, çünkü headbunu kontrol ediyor) ve belki de diğer bazı satırlar stdin tanımlayıcılarından önce headve teekapanır.

İkinci satırın görünüp görünmemesine ilişkin tutarsızlık zamanlama ile ortaya çıkar: headstdin'i kapatır, ancak psyine de veri gönderir. Bu iki olay iyi senkronize edilmemiştir, bu nedenle içeren satır sysloghala teeargümanı ( grepkomut) yapma şansına sahiptir . Bu, yukarıdaki açıklamalara benzer.

Stdin / exit komutlarını kapatmadan önce tüm girdileri bekleyen komutları kullanarak bu sorunu tamamen önleyebilirsiniz. Örneğin, tüm satırlarını okuyacak ve işleyecek awkyerine kullanın head(çıktıya neden olmasalar bile):

ps aux | tee >(grep syslog) | awk 'NR == 1'

Ancak, çizgilerin yukarıda gösterildiği gibi hala sıra dışı görünebileceğini unutmayın;

ps aux | tee >(grep syslog) | (sleep 1; awk 'NR == 1')

Umarım bu çok fazla ayrıntı değildi, ama birbirleriyle etkileşen birçok eşzamanlı şey var. Ayrı işlemler eşzamanlı olarak herhangi bir senkronizasyon olmadan çalışır, bu nedenle belirli bir çalıştırmadaki eylemleri değişebilir; bazen nedenini açıklamak için altta yatan süreçlerin derinliklerine inmeye yardımcı olur.


1
Mükemmel cevap! Aslında sordum çünkü altta yatan süreçlerle ilgileniyorum. Her şey tutarsız olduğunda ilginç buluyorum. Stdout kapatmayı ps aux | tee >(grep syslog) | head -n1durduracak çalıştırmak için daha iyi bir yolu olurdu head. Vay canına, bu komut şimdi çıktı vermeye başladı, ancak cevabınız doğrultusunda olduğu gibi, kısaltılmış görünüyorUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND syslog 806
Rqomey

1
Bunun yerine stdin'i kapatmayan bir şey kullanabilirsiniz head. Bu örnekle cevap güncelledik:ps aux | tee >(grep syslog) | awk 'NR == 1'
mrb

1
@KrzysztofAdamski, kullandığınızda >(cmd), kabuk adlandırılmış bir kanal oluşturur ve bunu command ( tee) öğesine argüman olarak iletir . Sonra teestdout'a (piped awk) ve bu argümana yazıyor . Bu aynı mkfifo a_fifo ; grep ... a_fifobir kabuk ve ps | tee a_fifo | awk ...başka.
mrb

1
@KrzysztofAdamski gnu.org/software/bash/manual/html_node/… - echo >(exit 0)Kabuğun geçtiği gerçek argümanı yansıtan deneyin (benim durumumda olur /dev/fd/63). Bu, bash ve zsh için de aynı şekilde çalışmalıdır.
mrb

1
@mrb: daha önce bilmediğim çok ilginç bir özellik, teşekkürler. Bash'da garip bir şekilde çalışıyor, ancak bkz. Pastebin.com/xFgRcJdF . Ne yazık ki şimdi bunu araştıracak zamanım yok ama yarın yapacağım.
Krzysztof Adamski

2

grep syslogzamanlamaya bağlı olduğu için her zaman gösterilmez. Kabuk boru hattını kullanırken, komutları neredeyse aynı anda çalıştırıyorsunuz. Ama buradaki anahtar şey "neredeyse" kelimesidir. Eğer psgrep önce tüm süreçleri tarayarak bitirir başlatılır, bu listede olmayacağım. Sistemin yüküne vb. Bağlı olarak rastgele sonuçlar alabilirsiniz.

Tişörtünde de benzer bir şey olur. Alt kabukta arka planda çalıştırılır ve grep'ten önce veya sonra ateşlenebilir. Bu nedenle çıktı sırası tutarsız.

Tee sorusuna gelince, bu davranış oldukça garip. Bunun nedeni normal şekilde kullanılmamasıdır. Herhangi bir argüman olmadan çalıştırılır, yani sadece stdin'den stdout'a veri kopyalaması gerekir. Ancak stdout, alt kabuk çalışan kafaya (ilk durumda) veya grep'e (2. durumda) yönlendirilir. Ancak bir sonraki komuta da iletilir. Bu durumda olanların aslında uygulamaya bağlı olduğunu düşünüyorum. Örneğin bash 4.2.28'de subshell stdin'e hiçbir şey yazılmamış. Zsh'de, her denediğimde güvenilir şekilde çalışır (hem ps'nin ilk satırını hem de aranan satırları yazdırır),


Bu zaten bir şeyi açıklıyor, tee'nin grep'i fark edilir derecede çalıştırmayı geciktirdiğine şaşırdım!
Rqomey

0

Biraz acayip, ama işte benim çözüm, psgrep()kullandığım bir kabuk işlevi şeklinde :

Redirect psiçin başlık satırını STDERR, sonra grepüzerine STDOUT, ancak ilk kaldırmak grepkomutu kendisi kaynaklanan "gürültü" satırını önlemek için grepkendisi:

psgrep() { ps aux | tee >(head -1>&2) | grep -v " grep $@" | grep "$@" -i --color=auto; }
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.