44 votes

empêcher xargs de s'arrêter en cas d'erreur

Selon la page de manuel, xargs s'arrêtera 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 statut de 255, xargs s'arrête immédiatement sans lire aucune autre entrée. Un message d'erreur est émis sur stderr lorsque cela se produit.

Comment puis-je faire en sorte que xargs no faire ça ?

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

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

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

43voto

userM1433372 Points 151

Similaire à larsks réponse mais plus explicite :

xargs sh -c "somecommand || true"

0 votes

En utilisant sh -c wors pour moi !

4 votes

Si vous cherchez à exécuter une seule commande pour chaque ligne, vous aurez besoin de -i aussi. Ça devrait marcher : xargs -i sh -c "somecommand {} || true"

15voto

user842313 Points 831

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

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

Ceci appellera commande réelle en lui passant tous les paramètres que vous passez à cette fausse commande et il retournera toujours un code de sortie 0 (ce qui signifie qu'il est toujours réussi) et xargs ne s'arrêtera jamais avec cela.

12voto

matschaffer Points 329

Je viens de trouver une réponse amusante à cette question, bien que son utilité dépende 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 en faisant un piping 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, premièrement, xargs n'appelle jamais que echo, donc il ne verra pas d'erreurs. Ensuite, parce que le comportement par défaut de bash est de continuer l'exécution après une déclaration échouée.

Pour être plus précis sur mon cas, je l'utilisais pour supprimer un tas d'anciennes versions d'applications d'AWS ElasticBeanstalk comme suit :

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

2 votes

Je l'éviterai car le piping vers bash semble élégant jusqu'à ce que vous essayiez d'annuler avec CTRL+C. J'ai dû annuler une fois pour chaque commande qui restait à traiter. Y a-t-il quelque chose qui me manque pour pouvoir annuler au niveau de xargs plutôt qu'au niveau de bash ?

0 votes

Je pense que vous devrez tuer le processus de premier niveau (probablement le terminal Shell) qui a démarré le tuyau pour cela.

10voto

Eric Noob Points 531

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

xargs sh -c "somecommand || :"

0 votes

J'ai trouvé une bonne solution : assurez-vous que les commandes traitées ne sortent pas avec un statut 255 ! Détails supplémentaires La commande traitée est un script Perl. La fonction Perl die() était utilisée à plusieurs endroits pour sortir en cas d'erreur critique (par exemple, impossibilité 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).

6voto

shakaran Points 166

La construction suivante fonctionne pour moi :

ls | xargs -I % svn upgrade %

Même si la mise à jour de svn a échoué sur un élément, le processus a été poursuivi.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X