Unix kabuğu “stdin / stdout API'leri” ne kadar kararlıdır?


20

Grepping, awking, sedding ve piping, herhangi bir Unix benzeri işletim sisteminin bir kullanıcısının günlük rutinidir, komut satırında veya bir kabuk betiğinin içinde olabilir (bundan sonra topluca filtreler olarak adlandırılır ).

Özünde, "standart" Unix CLI programları ve kabuk yerleşikleriyle (bundan sonra topluca komutlar olarak adlandırılır ) çalışırken , filtrelerin düzgün çalışması için her filtre adımında stdin, stdout ve stderr için kesin bir format gerekir. Bu komutun beklenen biçimini kesin olarak aşağıda bu komutun API'si olarak adlandırıyorum.

Web geliştirme geçmişine sahip biri olarak, veri toplama ve veri işleme tekniklerini web kazıma ile karşılaştırıyorum - veri sunumunda en ufak bir değişiklik olduğunda çok kararsız olan bir teknik.

Sorum şimdi Unix komut API'lerinin kararlılığıyla ilgili.

  1. Unix benzeri işletim sistemlerindeki komutlar, giriş ve çıkışları açısından resmi bir standardizasyona uyuyor mu?
  2. Tarihte, bazı önemli komutlarda yapılan güncellemelerin, söz konusu komutun eski bir sürümü kullanılarak oluşturulan bazı filtrelerin işlevselliğini bozmasına neden olduğu durumlar oldu mu?
  3. Unix komutları zamanla olgunlaştı mı, bazı filtrelerin kırılabileceği şekilde değiştirilmesinin kesinlikle imkansız olduğunu mu düşünüyorsunuz?
  4. Filtrelerin komut API'lerinin değiştirilmesi nedeniyle zaman zaman kırılması durumunda, geliştirici olarak filtrelerimi bu soruna karşı nasıl koruyabilirim?

Yanıtlar:


17

POSIX 2008 standardında "Kabuk ve Yardımcı Programlar" açıklanmaktadır . Genel olarak, komut dosyalarınızın muhtemelen kullanımdan kaldırmalar dışında oldukça geleceğe yönelik olması gerekiyorsa, ancak bunlar bir gecede gerçekleşmez, bu nedenle komut dosyalarınızı güncellemek için bol zamanınız olmalıdır.

Tek bir yardımcı programın çıktı biçiminin platformlar ve sürümler arasında büyük farklılıklar gösterdiği bazı durumlarda, POSIX standardı genellikle çağrılan -pveya -Pgarantili ve öngörülebilir bir çıktı biçimini belirten bir seçenek içerebilir . Bunun bir örneği , çok çeşitli uygulamalara sahip olan timeyardımcı programdır . İstikrarlı bir API / çıktı biçimine ihtiyacınız varsa kullanırsınız time -p.

POSIX standardı kapsamında olmayan bir filtre yardımcı programı kullanmanız gerekiyorsa, web kazıma yaparken uzak web geliştiricilerinin merhametindeymişsiniz gibi, dağıtım paketleyicilerinin / yukarı akış geliştiricilerinin merhametindesiniz.


12

Deneyimlerimden cevap vermeye çalışacağım.

  1. Komutlar resmi bir spesifikasyona gerçekten uymazlar, ancak satır yönelimli metinleri tüketme ve oluşturma gereksinimlerine uyurlar.

  2. Evet tabi ki. GNU uygulamalarıdır fiilen standart olmadan önce satıcılarının bir sürü özellikle ilgili olarak, ilginç çıkışına sahip olacaktır psve ls. Bu çok acı çekti. Bugün, yalnızca HP süper ilginç komutlar veriyor. Tarihsel olarak, Berkeley Yazılım Dağıtım (BSD) yardımcı programları geçmişte önemli bir kopuştu. POSIX spesifikasyonu geçmişte bir ara oldu, ancak şimdi yaygın olarak kabul edildi.

  3. Unix komutları gerçekten zaman içinde olgunlaştı. Eski bir sürüm için yazılmış bazı komut dosyalarını kırmak hala imkansız değil. UTF-8'e yönelik son eğilimi bir metin dosyası kodlaması olarak düşünün. Bu değişiklik, gibi temel araçların değiştirilmesini gerektiriyordu tr. Geçmişte, basit metin neredeyse her zaman ASCII (ya da yakın bir şey) idi, bu nedenle büyük harfler küçük harfler gibi sayısal bir aralık oluşturuyordu. UTF-8 için bu artık geçerli değil, bu nedenle tr"büyük harf" veya "alfasayısal" gibi şeyleri belirtmek için farklı komut satırı seçeneklerini kabul eder.

  4. Filtrelerinizi "sağlamlaştırmanın" en iyi yollarından biri, belirli metin düzenine bağlı olmamaktır. Örneğin, cut -c10-24bir çizginin konumlarına bağlı olan yapmayın . cut -f2Bunun yerine, sekmeyle ayrılmış 2. alanı kesecek olan kullanın . awkherhangi bir giriş satırını varsayılan olarak boşlukla ayrılmış $ 1, $ 2, $ 3 ... 'e böler. Sütun konumu gibi alt düzey kavramlardan ziyade "alanlar" gibi üst düzey kavramlara güvenin. Ayrıca, düzenli ifadeler kullanın: sedve awkher ikisi de girdideki bazı sapmaları umursamayan düzenli ifadelerle şeyler yapabilir. Başka bir hile, girdiyi, filtrenizin biçimi hakkında seçici olabilecek bir şeyle işlemektir. tr -cs '[a-zA-z0-9]' '[\n]'Metni noktalama işareti olmadan satır başına tek bir kelimeye bölmek için kullanın . Sadece yapmıyorsun


9

İlk olarak, sorularınıza çok kısa cevaplar:

  1. Giriş / çıkış sözleşmelerinin resmi standardizasyonu: hayır
  2. Değişen üretim nedeniyle geçmişte kırılma: evet
  3. Gelecekteki filtreleri kırmak kesinlikle imkansız: hayır
  4. Kendimi değişikliklere karşı nasıl koruyabilirim: muhafazakar olun

"API" dediğinizde, (iyi veya kötü) filtre giriş / çıkış kurallarında çok fazla formalite anlamına gelen bir terim kullanıyorsunuz. Çok (ve ben "çok" demek istiyorum), kolay filtrelemeye uygun veriler için birincil kurallar

  • her girdi satırı tam bir kayıttır
  • her kayıtta, alanlar bilinen bir ayırıcı karakterle ayrılır

Klasik bir örnek / etc / passwd biçimidir. Ancak, bu varsayılan sözleşmeler muhtemelen mektuba göre daha sık bir dereceye kadar ihlal edilmektedir.

  • Çok satırlı giriş biçimlerini ayrıştıran çok sayıda filtre (genellikle awk veya perl ile yazılır) vardır.
  • İyi tanımlanmış alan yapısının bulunmadığı birçok girdi paterni (örn. / Var / log / messages) vardır ve daha genel düzenli ifade tabanlı teknikler kullanılmalıdır.

Dördüncü sorunuz, çıktı yapısındaki değişikliklere karşı kendinizi nasıl koruyacağınız, gerçekten her şeyi yapabileceğiniz tek soru.

  • As söyledi jw013 @ posix standartları söylediklerine, bakmak. Elbette, posix giriş kaynakları olarak kullanmak isteyeceğiniz tüm komutları belirtmez.
  • Komut dosyalarınızın taşınabilir olmasını istiyorsanız, bazı komutların hangi sürümünün kurulu olmadığına ilişkin kimlik bilgisinden kaçınmaya çalışın. Örneğin, standart unix komutlarının birçok GNU sürümü standart olmayan uzantılara sahiptir. Bunlar yararlı olabilir, ancak maksimum taşınabilirlik istiyorsanız bunlardan kaçınmalısınız.
  • Hangi komut alt kümelerinin bağımsız değişkenlerinin ve çıktı biçimlerinin platformlar arasında sabit olma eğiliminde olduğunu öğrenmeye çalışın. Ne yazık ki, bu zamanla birlikte birden fazla platforma erişim gerektirir, çünkü bu farklılıklar hiçbir yerde, gayri resmi olarak bile yazılmayacaktır.

Sonunda, kendinizi endişe ettiğiniz sorunlardan tam olarak koruyamazsınız ve belirli bir komutun ne yapması gerektiğine dair "kesin" bir ifadeyi aramak için tek bir yer yoktur. Birçok kabuk komut dosyası için, özellikle kişisel veya küçük ölçekli kullanım için yazılanlar için, bu sadece bir sorun değildir


5

Sorunuzun yalnızca 1) sini kapsıyor.

Doğal olarak API'ler her zaman yaratıcılarının isteğine bağlı olarak değişebilir ve bu nedenle bağımlı yazılımı herhangi bir dilde bozabilir. Bununla birlikte, Unix araçlarının ' G / Ç "API'leri" fikri , pratikte hiçbirinin (belki 0x0ade satır sonu olarak) olmamasıdır . İyi bir komut dosyası, verileri Unix araçlarıyla oluşturmak yerine filtreler . Bu, komut dosyanızın girdi veya çıktı özellikleri değiştiği için bozulabileceği, ancak kodda kullanılan tek tek araçların I / O formatının (yine gerçekten bir tane olmadığı) değişmediği için değil (çünkü gerçekten var olmayan bir şey gerçekten değişemez).

Temel araçların bir listesini gözden geçirirken, sadece filtrelemenin aksine, üreticiyi de ilişkilendirebileceğim birkaç şey var :

  • wc - bayt, kelime, satır sayısını yazdırın - çok basit bir format, bu nedenle kesinlikle değişme olasılığı yoktur ve ayrıca bir komut dosyasında kullanılması pek olası değildir.
  • diff - farklı çıktı formatları gelişti ama herhangi bir problem duymadım. Ayrıca gözetim olmadan normalde kullanılmaz.
  • date - Şimdi burada, özellikle sistem yerel ayarlarıyla ilgili olarak, ürettiklerimize dikkat etmek zorundayız. Ancak aksi takdirde, tam olarak kendiniz belirtmediğiniz takdirde çıktı biçimi RFC'dir.
  • cal - bunun hakkında konuşmayalım, çıktı formatının sistemler arasında çok farklı olduğunu biliyorum.
  • ls , kim , w , son - ls ayrıştırmak istiyorsanız yardım edemem, sadece olması amaçlanmamıştı. Ayrıca, w, son olarak, kim daha etkileşimli listelerdir; Bunları bir senaryoda kullanırsanız, ne yaptığınıza dikkat etmeniz gerekir.
  • zaman başka bir yazıya işaret edildi. Ama evet, bu ls ile aynı. Etkileşimli / yerel kullanım için daha fazlası. Ve bash yerleşik GNU sürümünden çok farklıdır ve GNU sürümü yıllardır sabitlenmiş hatalara sahiptir. Sadece ona güvenme.

Belirli bir girdi biçiminin bayt akışı olmaktan daha spesifik olmasını bekleyen araçlar şunlardır:

  • bc , dc - hesap makineleri. Zaten şeylerin daha hackish tarafında (gerçekten, bunları komut dosyalarında kullanmıyorum) ve muhtemelen çok kararlı I / O formatları.

Kırılma riski çok daha yüksek olan başka bir alan var, yani komut satırı arabirimi. Çoğu araç hem sistemler arasında hem de zaman çizelgesi boyunca farklı özelliklere sahiptir. Örnekler

  • Regex - regex kullanan tüm araçlar , sistem yerel ayarlarına (örneğin LC_COLLATE) göre anlam değiştirebilir ve regex uygulamaları arasında birçok incelik ve özellik vardır.
  • Sadece süslü anahtarlar kullanmayın. man 1p findÖrneğin, sistem el kitabı yerine POSIX bulma el kitabını okumak için kolayca kullanabilirsiniz . Sistemimde yüklü manpages-posix'e ihtiyacım var.

Ve bu anahtarları kullanırken bile, normalde hatalar ustaca tanıtılmaz ve verilerinizi zehirlemez. Çoğu program bilinmeyen bir anahtarla çalışmayı reddedecektir.

Sonuç olarak, kabuğun aslında en taşınabilir dillerden biri olma potansiyeline sahip olduğunu söyleyebilirim (taşınabilir olarak komut dosyası yazdığınızda taşınabilir). Küçük hataların olduğu favori komut dosyası dillerinizle veya derlenecek olan derlenmiş programınızla karşılaştırın.

Ek olarak, uyumsuzluklar nedeniyle kırılmanın meydana gelebileceği nadir yerlerde, büyük olasılıkla zaman kaynaklı değil, farklı sistemler arasındaki çeşitlilik nedeniyle olacaktır (yani sizin için çalışıyorsa, 20 yıl önce ve 20 yıl önce yapacak) de). Bu, araçların sadeliğinin bir sonucudur.


1

Sadece fiili IO standartları vardır - boşluk ve boş ayrık çıktı.

Uyumluluk konusunda, genellikle ayrı filtrelerin sürüm numaralarını kontrol etmeye geri döneriz. Çok değiştiklerinden değil, ancak yepyeni bir özellik kullanmak ve komut dosyasının eski sürümlerde çalışmasını istediğinizde, bir şekilde "ifdef" yapmanız gerekir. Pratik olarak hiçbir yetenek raporlama mekanizması yoktur, test senaryolarını elle yazmak için saklayın.


0

Betikler, bazıları diğerlerinden daha sık kırılır. Eski ve ünlü yazılım nispeten aynı kalma eğilimindedir ve yine de değiştiğinde genellikle uyumluluk bayrakları vardır.

Bir sisteme yazılan komut dosyaları çalışmaya devam etme eğilimindedir, ancak çoğu zaman başka bir sistemi bozar.

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.