xargs'ın yanlışlıkla bırakmasını engelle


27

Man sayfasına göre, yürütme satırlarından biri 255 hatayla çıkarsa, xargs sonlandırılır:

Herhangi bir komutun başlatılması 255 durumundan çıkarsa, xargs daha fazla giriş yapmadan hemen durur. Bu olduğunda stderr'de bir hata mesajı verilir.

Bunu yapmaması için nasıl Xargs alabilirim ?

Çalıştırmak istediğim 1500 satırlık toplu işim var, her seferinde 50 satır. Her zaman belirli bir çizgide ölüyordu ve işi bitirmiyordum. İyi değil!

Daha iyi bir soru, ne yapmaya çalıştığımı açıklayan soru şudur:

1500 satırlık bir toplu iş komut dosyasını nasıl çalıştırabilirim, bir seferde 50 satır, böylece ortada işi bırakmaz ve çıktı bir tür günlük dosyasına yakalanır?

Yanıtlar:


12

Perl betiğini başka bir basit bash betiği ile sarabilirsiniz:

#!/bin/bash
real-command "$@" || exit 0

Bu, bu sahte komuta ilettiğiniz tüm parametreleri ileten real-komutu arayacak ve her zaman 0 çıkış kodunu döndürecektir (her zaman başarılıdır) ve xargs bununla asla durmayacaktır.



9

Komut satırlarınızın dönüş kodlarını maskelemek için xargs çağrınızı yazabilirsiniz. Aşağıdaki gibi bir şeyle, xargsçıkış komutlarının bir komut tarafından geri döndüğünü asla görmezsiniz :

xargs sh -c "somecommand || :"

İyi bir çözüm buldum: işlenmekte olan komutların 255 durumuyla çıkmadığından emin olun! Ek Detaylar İşlenmekte olan komut bir Perl betiğidir. Perl die () işlevi, bazı kritik hatalar ortaya çıktığında (örneğin bir veritabanına bağlanamadı) çıkmak için çeşitli yerlerde kullanılıyordu. Ancak, die () her zaman 255 hata durumuyla çıkar. Bu durumda çözüm, die () 'yi bir baskı ve exit () kombinasyonu ile değiştirmek, daha makul bir hata kodu ("1" bu durumda işe yaradı).
JDS

6

Sadece bunun için eğlenceli bir cevap buldum, ancak faydası koşmaya çalıştığınız komuta bağlı olacaktır.

Temel olarak bir komut listesi oluşturmak için xargs kullanıyorsanız, bu davranışı xargs komutunu yankılamasını ve ardından bash komutunu vermesini söyleyerek alabilirsiniz.

Örneğin, var olabilecek veya bulunmayacak şeylerin bir listesini silmeye çalışıyorsanız:

# presume this will fail in a similar way to your command
cat things_to_delete | xargs -n1 delete_command_that_might_exit

# instead echo the commands and pipe to bash
cat things_to_delete | xargs -n1 echo delete_command_that_might_exit | bash

Bu işe yarıyor, çünkü önce, xargs sadece hiç yankı çağırıyor, bu yüzden herhangi bir hata görmüyor. Sonra ikinci, çünkü bash'in varsayılan davranışı başarısız bir ifadeden sonra yürütmeye devam etmek.

Davam hakkında daha spesifik olmak gerekirse, bunu AWS ElasticBeanstalk'tan bir dizi eski uygulama sürümünü kaldırmak için kullanıyordum:

aws elasticbeanstalk describe-application-versions --application-name myapp |\
jq -r '.ApplicationVersions | sort_by(.DateCreated) | .[0:-10] | .[].VersionLabel' |\
xargs -n1 \
  echo aws elasticbeanstalk delete-application-version \
       --delete-source-bundle --application-name myapp --version-label |\
bash

4

Aşağıdaki inşaat işleri benim için:

ls | xargs -I % svn upgrade %

Svn yükseltme bir öğe üzerinde başarısız olsa bile, işleme devam edildi


3

Kullandığınız olsaydı xargsile findkullanmak -execseçeneği findyerine:

find . -name '*.log' -exec somecommand {} \;

1
merhaba. bunu kullanabilirim ama -exec seçeneği işlemleri xargs kullanarak yapabilecekleri işlemlerle paralelleştirmez
JDS

2
Teşekkürler - Bunun xargsparalel komutlar verebileceğini bilmiyordum . Güzel. Yalnızca komut çağrısı sayısını en aza indirmek istiyorsanız -exec, bir +parametresi vardır.
Roger Dahl
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.