не дозволяти xargs вийти з помилки


27

Згідно з довідковою сторінкою, xargs закриється, якщо одна з рядків виконання завершиться з помилкою 255:

Якщо будь-яке виклик команди закінчується зі статусом 255, xargs негайно припиняться, не читаючи жодного подальшого введення. Повідомлення про помилку видається на stderr, коли це відбувається.

Як я можу отримати xargs, щоб цього не зробити?

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

Ще краще питання, яке описує те, що я намагаюся зробити, це:

Як я можу запустити пакетний сценарій на 1500 рядків, 50 рядків одночасно, щоб він не вийшов із завдання в середині та щоб результат був захоплений у якийсь файл журналу?

Відповіді:


12

Ви можете обернути сценарій perl з іншим простим скриптом bash:

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

Це викликає команду real-command, передаючи їй всі параметри, які ви передаєте цій фальшивій команді, і вона завжди повертає код виходу 0 (це означає, що це завжди успішно), і xargs ніколи не зупиняться на цьому.



9

Ви можете написати виклик xargs, щоб замаскувати коди повернення командних рядків. Щось із таким, як описано нижче, xargsніколи не побачить повернення кодів виходу деякимкомандом :

xargs sh -c "somecommand || :"

Я придумав гарне рішення: переконайтесь, що команди, що обробляються, не виходять зі статусом 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 лише коли-небудь викликає ехо, тому він не побачить помилок. Потім друге, тому що поведінка за замовчуванням 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

4

Наступні будівельні роботи для мене:

ls | xargs -I % svn upgrade %

Навіть якщо оновлення svn на якомусь елементі не вдалося, процес було продовжено


3

Якщо ви працювали xargsз find, замість цього скористайтеся -execопцією find:

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

1
привіт. Я міг би скористатися цим, але опція -exec не паралелізує операції способом використання xargs може і робить
JDS

2
Дякую - я не знав, що xargsможе паралельно виконувати команди. Класно. Якщо ви хочете лише мінімізувати кількість викликів команд, -execмає +параметр.
Роджер Даль
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.