Çıktı bir süreçten diğerine nasıl aktarılır, ancak yalnızca ilk çıktısı varsa çalıştırılır?


23

Bu komutu yalnızca e-postaya, çıktıdan çıktığında nasıl yeniden yazabilirim mailq | grep?

mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -s 'dd' email@email

Bir hatta bu mümkün mü?

Bkz boru boşsa kontrol ve eğer değilse veriler üzerinde bir komutu çalıştırmak e-posta göndermek yerine daha genel bir durum için.


Yanıtlar:


19

Bu işlem için geçici bir dosya kullanmak zorunda kalacağınızı düşünüyorum, böylece &&işleci yalnızca posta komutunu çalıştırmak için kullanabilirsiniz , grep bu gibi eşleşmeleri olduğunu söyleyen bir çıkış durumu döndürdüyse:

TMPFILE=`mktemp /tmp/mailqgrep.XXXXXX`; mailq | egrep 'rejected|refused' -A5 -B5 > "$TMPFILE" && mail -s 'dd' email@email < "$TMPFILE"; rm "$TMPFILE"

Geçici dosyanın bir yere yapıştırılmasının sakıncası yoksa ve bunun için statik bir ad kullanabilirseniz, özel adlandırma ve silme öğelerini atlayabilirsiniz:

 mailq | egrep 'rejected|refused' -A5 -B5 > /tmp/mailqgrep && mail -s 'dd' email@email < /tmp/mailqgrep

Düzenleme: Glen'in cevabını gördükten sonra biraz daha oynadım ve görünüşe göre $()sözdizimini kullanarak bir değişken atama komutun çıkış kodunu döndürür, böylece dize uzunluğu için kullandığı testi atlayabilir ve bunun yerine kullanabilirsiniz. İşte hepsi bir komutta:

data=$(mailq | egrep 'rejected|refused' -A 5 -B 5) && mail -s 'dd' email@email <<< "$data"

Düzen 2: Simon'ın cevabını gördükten sonra mailprogramımı kontrol ettim . Varsayılan olarak tanımladığı şekilde davranmaz, ancak bunun için bir seçeneği vardır. Man sayfasından:

-EGiden bir mesaj ilk veya tek mesaj kısmında herhangi bir metin içermiyorsa, göndermeyin, sessizce atın, program başlangıcında atlamalı kullanıcı değişkenini etkin bir şekilde ayarlayın. Bu, cron (8) tarafından başlatılan komut dosyalarından mesaj göndermek için kullanışlıdır.

Bunu mümkün kılmak:

mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -E -s 'dd' email@email

1
işbirliğinin gücü !!
glenn jackman

3
En iyi çözümü en üste taşıyarak bu cevabın daha iyi yapılabileceğini öneririm .
Mark Booth

@Wildcard Bu düzenleme gerekli mktempdeğildi , giriş parametreleri verildiğinde alıntı yapılması gereken bir şey döndürmeyecek.
Caleb

2
Biliyorum. Sen tırnak anlamak rahatsız eden birkaç biri olan bazen gerekli (ve kasıtlı atlar onları). Ancak, varsayılan gerektiğini açıkça çağırmak için istemedikçe alıntı olması glob(split(var)). Burada sözcük bölme veya dosya yayılma genişlemesine ihtiyacınız yok, bu yüzden onlar için sormayın. Ayrıca, bu sitede doğru yolu göstermemiz gerekiyor .
Wildcard

@Wildcard Fuarı yeterince. Genellikle koşuyorum zshve aslında bu gibi durumlarda talep etmediğim sürece küreselleşme ya da kelime bölme alamıyorum , ancak burada cevaplar uğruna ve hedef ortamın prensipten alıntı olduğunu bilmemek gayet iyi.
Caleb

11

Yardımcı program ifne bu amaç için açıkça var: standart giriş boş değilse bir komut çalıştırmak için.

mailq | egrep 'rejected|refused' -A 5 -B 5 | ifne mail -s 'dd' email@email

İfne komutu, "Unix gençken, uzun zaman önce kimsenin yazmadığını düşünmeyen, büyüyen bir Unix araçları koleksiyonu" olarak hesaplanan moreutils paketinin bir parçasıdır .


8

Çıktıyı bir değişkene kaydedebilir ve dizenin uzunluğu sıfır değilse posta komutunu çağırabilirsiniz.

data=$(mailq | egrep 'rejected|refused' -A 5 -B 5)
[[ -n "$data" ]] && mail -s 'dd' email@email <<< "$data"

Bir satır için, iki komutu bir iki nokta üst üste ile birleştirin.


1
Temp dosyası yerine değişken kullanmak için destek. Bu, çıkış kodunun, değişken atamasını yaptığınız komuttan nereye gittiğini düşündürdü ve görünüşe göre geçti! Güncellenmiş cevabımı gör .
Caleb,

7

Seçeneği mailile kullanın -E. Mac'imde MAIL (1), -Ebayrağın boş bir gövdeyle e-posta göndermeyeceğini söylüyor .

-E Boş gövdeli mesajlar göndermeyin. Bu, cron (8) komut dosyalarındaki boru hataları için kullanışlıdır.

Mac'imde aşağıdaki testi yaptım. Dosyanın file_does_existvar olduğunu ancak dosyanın file_does__not_existmevcut olmadığını unutmayın.

Bu bana bir e-posta gönderir:

$ ls file_does_exist | egrep 'file' -A5 -B5 | mailx -E -s 'test' stefan@example.org

Bu değil. Komutun ls file_does_not_exist | egrep ...herhangi bir çıktı üretmediğini unutmayın .

$ ls file_does_not_exist | egrep 'file' -A5 -B5 | mailx -E -s 'test' stefan@example.org
ls: file_does_not_exist: No such file or directory

Caleb seni dövdü.
Gilles 'SO- kötülük'

1
Beni sadece 4.75 saate kadar yendi :). Bu cevabı uzun cevaplarında özledim.
Stefan Lasiewski

5

Bu özel durumda, sizin eğer maildesteklerin -Eseçenek , sadece onu kullanın. Genel durumda, bir karakter okumayı deneyebilirsiniz; bir tane varsa, postprocessing komutunu başlatın ve bu karakteri dosyanın geri kalanından besleyin.

pipe_if_not_empty () {
  a=$(dd bs=1 count=1 2>/dev/null; echo .)  # read at most one character
  if [ "$a" != "." ]; then                  # if there were two characters,
    { printf %s "${a%.}";                   # then output the first character
      cat; } |                              # and the rest of the input   
    "$@"                                    # into the specified program
  fi
}

mailq | egrep 'rejected|refused' -A 5 -B 5 |
pipe_if_not_empty mail -s 'dd' email@email

Yararlı kullanımına dikkat edin cat. echo .Bu fonksiyonun eklenmesi , girdideki ilk karakter yeni bir satır olsa bile çalışır ( $(…)yapının terminal yeni satırları çıkardığını unutmayın ).

Çoğu kabukla (bildiğim kadarıyla zsh dışında herhangi bir şey), dosya boş bir karakterle başlarsa, bu kodun boş olduğuna inanacaktır. Bunu düzeltmek okuyucu için bir egzersiz olarak kaldı. (İpucu: odilk alt kabukta kullanın ve printfilk baytı yazdırmak için kullanın.) (Çözüm: Borunun boş olup olmadığını kontrol etme ) Dosya geçerli olarak geçerli bir karakter olmayan bir baytla başlıyorsa aynı sorunla karşılaşabilirsiniz. yerele; Bu kodu çalıştırarak düzeltmek daha kolaydır LC_ALL=C.


Gülünç için +1, ancak başka bir senaryoda muhtemelen faydalıdır :) Meraktan, neden boş bir dize denemek yerine noktaya enjekte ve test etmelisiniz? Giriş nokta ile başlarsa bu bir sorun yaratmaz mı? Kullanarak Could readyardım bu basitleştirmek?
Caleb

@Caleb: Evet, belirli bir duruma değil, başlıktaki soruya cevap verdiğimi söylemeliydim. Noktanın açıklaması için düzenlememe bakın. Boş bir ilk satırı boş bir dosyadan readtaşınabilir sh ile ayırabileceğinizi sanmıyorum (bash, ksh veya zsh ile mümkün olabilir).
Gilles 'SO- kötülük'


1

Son zamanlarda paketin bir ifneparçası olan komut adını öğrendim moreutils. Bu özel sorunu çözmek için nerede kullanabileceğinizi.

ifne - Standart giriş boş değilse komutu çalıştır

man sayfasından örnek,

EXAMPLE
       find . -name core | ifne mail -s "Core files found" root

0

Parçadan test -s /dev/stdinherhangi bir çıktı olup olmadığını kontrol etmek için komutunuzu kullanarak yeniden yazabilirsiniz mailq | grep.

- mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -s 'dd' email@email
+ mailq | egrep 'rejected|refused' -A 5 -B 5 | (test -s /dev/stdin && cat) | mail -s 'dd' email@email
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.