предотвратить выход XARGS из-за ошибки

27

Согласно man-странице, xargs завершит работу, если одна из строк выполнения завершится с ошибкой 255:

Если какой-либо вызов команды завершается со статусом 255, xargs немедленно останавливается, не читая никаких дальнейших вводных данных. Когда это происходит, на stderr выдается сообщение об ошибке.

Как я могу заставить xargs не делать этого?

У меня есть около 1500 строк, которые я хочу запустить, по 50 строк за раз. Я обнаружил, что он всегда умирал на определенной линии, а не завершал работу. Не хорошо!

Еще лучший вопрос, описывающий то, что я пытаюсь сделать, это:

Как запустить пакетный сценарий на 1500 строк по 50 строк за раз, чтобы он не завершал работу посередине и чтобы выходные данные записывались в какой-либо файл журнала?

JDS
источник

Ответы:

12

Вы можете обернуть Perl-скрипт другим простым bash-скриптом:

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

Это вызовет настоящую команду, передающую ей все параметры, которые вы передаете этой поддельной команде, и она всегда будет возвращать код завершения 0 (это означает, что он всегда успешен), и xargs никогда не остановится на этом.

user842313
источник
24

Похоже на larsksответ, но более явно:

xargs sh -c "somecommand || true"
Филиппо Витале
источник
используя sh -cдля меня ворс!
hukeping
9

Вы можете написать свой вызов xargs, чтобы замаскировать коды возврата ваших командных строк. С чем-то вроде следующего, xargsникогда не увидит коды выхода, возвращаемые по некоторой команде :

xargs sh -c "somecommand || :"
larsks
источник
Я нашел хорошее решение: убедитесь, что обрабатываемые команды не выходят со статусом 255! Дополнительные сведения Обрабатываемая команда является скриптом Perl. Функция Perl die () использовалась в нескольких местах для выхода, если произошла какая-то критическая ошибка (например, не удалось подключиться к базе данных). Однако die () всегда завершается со статусом ошибки 255. В этом случае решение состояло в том, чтобы заменить die () комбинацией print и exit () вместе с более разумным кодом ошибки (в этом случае работало «1»).
JDS
6

Просто нашел забавный ответ на этот вопрос, хотя его полезность будет зависеть от команды, которую вы пытаетесь выполнить.

Если вы используете xargs для компоновки списка команд, вы можете получить такое поведение, сказав xargs повторить команду, а затем отправив команду bash.

Например, если вы пытаетесь удалить список вещей, которые могут или не могут существовать:

# 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

Это работает, потому что, во-первых, xargs всегда вызывает echo, поэтому он не видит никаких ошибок. Во-вторых, поведение bash по умолчанию для продолжения выполнения после неудачного оператора.

Чтобы быть более конкретным в моем случае, я использовал это для удаления нескольких старых версий приложений из AWS ElasticBeanstalk, например, так:

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
источник
4

Следующие строительные работы для меня:

ls | xargs -I % svn upgrade %

Даже если обновление svn не удалось на каком-либо элементе, процесс был продолжен

AndreyP
источник
3

Если вы использовали xargsс find, используйте -execпараметр findвместо:

find . -name '*.log' -exec somecommand {} \;
Роджер Даль
источник
1
здор`ово. я мог бы использовать это, но опция -exec не распараллеливает операции так, как это делает xargs
JDS
2
Спасибо - я не знал, что xargsмог запускать команды параллельно. Круто. Если вы хотите только минимизировать количество вызовов команд, -execесть +параметр.
Роджер Даль