empêcher les xargs de se fermer en cas d'erreur

27

Selon la page de manuel, xargs se fermera si l'une des lignes d'exécution se termine avec une erreur de 255:

Si une invocation de la commande se termine avec un état de 255, xargs s'arrêtera immédiatement sans lire aucune autre entrée. Un message d'erreur est émis sur stderr lorsque cela se produit.

Comment puis-je obtenir des xargs pour ne pas faire cela?

J'ai un travail par lots d'environ 1500 lignes que je veux exécuter, 50 lignes à la fois. Je trouvais qu'il mourait toujours à une certaine ligne et ne terminait pas le travail. Pas bon!

Une question encore meilleure, la question décrivant ce que j'essaie de faire, est:

Comment puis-je exécuter un script de traitement par lots de 1500 lignes, 50 lignes à la fois, afin qu'il ne quitte pas le travail au milieu et que la sortie soit capturée dans un fichier journal quelconque?

JDS
la source

Réponses:

12

Vous pouvez envelopper le script perl avec un autre script bash simple:

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

Cela appellera real-command en lui passant tous les paramètres que vous passez à cette fake-command et cela retournera toujours un code de sortie 0 (cela signifie qu'il est toujours réussi) et xargs ne s'arrêtera jamais avec cela.

user842313
la source
24

Similaire à la larsksréponse mais plus explicite:

xargs sh -c "somecommand || true"
Filippo Vitale
la source
en utilisant des sh -cwors pour moi!
hukeping
9

Vous pouvez écrire votre invocation xargs pour masquer les codes retour de vos lignes de commande. Avec quelque chose comme ce qui suit, xargsne verra jamais les codes de sortie renvoyés par une commande :

xargs sh -c "somecommand || :"
larsks
la source
J'ai trouvé une bonne solution: assurez-vous que les commandes en cours de traitement ne se terminent pas avec un état 255! Détails supplémentaires La commande en cours de traitement est un script Perl. La fonction Perl die () était utilisée à plusieurs endroits pour quitter en cas d'erreur critique (par exemple, impossible de se connecter à une base de données). Cependant, die () se termine toujours avec le statut d'erreur 255. La solution dans ce cas était de remplacer die () par une combinaison de print et exit (), avec un code d'erreur plus raisonnable ("1" fonctionnait dans ce cas).
JDS
6

Je viens de trouver une réponse amusante à celle-ci, bien que son utilité dépendra de la commande que vous essayez d'exécuter.

Si vous utilisez xargs pour assembler une liste de commandes, vous pouvez obtenir ce comportement en disant à xargs de faire écho à la commande, puis de diriger vers bash.

Par exemple, si vous essayez de supprimer une liste de choses qui peuvent ou non exister:

# 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

Cela fonctionne parce que, d'abord, xargs n'appelle que echo, donc il ne verra aucune erreur. Ensuite, parce que le comportement par défaut de bash pour continuer l'exécution après une instruction ayant échoué.

Pour être plus précis sur mon cas, j'utilisais cela pour supprimer un tas d'anciennes versions d'application d'AWS ElasticBeanstalk comme ceci:

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
matschaffer
la source
4

Travaux de construction suivants pour moi:

ls | xargs -I % svn upgrade %

Même si la mise à niveau svn a échoué sur un élément, le processus s'est poursuivi

AndreyP
la source
3

Si vous utilisiez xargsavec find, utilisez plutôt l' -execoption find:

find . -name '*.log' -exec somecommand {} \;
Roger Dahl
la source
1
salut. je pourrais l'utiliser, mais l'option -exec ne parallélise pas les opérations de la même façon que l'utilisation de xargs peut et fait
JDS
2
Merci - je ne savais pas que cela xargspouvait exécuter des commandes en parallèle. Cool. Si vous voulez seulement minimiser le nombre d'appels de commandes, -execa un +paramètre.
Roger Dahl