Встановлення pipefail для однієї команди з трубопроводом


19

Мені потрібно виконати ряд команд з оболонковою оболонкою із не-BASH-сценарію (а саме PHP-скрипту), таких як:

command1 | command2 | command3

так що, якщо command1не працює з ненульовим кодом виходу, то і інша команда виходить з ладу. Поки що я придумав:

set -o pipefail && command1 | command2 | command3

Але навіть якщо він працює з терміналу, він створює це, якщо виконується зі сценарію:

sh: 1: set: Неправомірний варіант -o pipefail


Здається, /bin/shце не подобається set -o pipefail. Це насправді bashмаскується, чи це інша оболонка? Коли bashзапускається як /bin/sh, чи приймає це set -o pipefail?
Джонатан Леффлер

@JonathanLeffler Коли я запускаю, /bin/sh set -o pipefailце говорить /bin/sh: 0: Can't open set(те ж саме з sudo). Сподіваюся, я перевірив це правильно. Система - Ubuntu 12.
Десмонд Юм

Вам потрібно буде спробувати /bin/sh -c "set -o pipefail"; як це було, оболонка намагалася виконати скрипт у поточному каталозі, який називається, setі його не знайшли.
Джонатан Леффлер

@JonathanLeffler /bin/sh -c "set -o pipefail", однак, bash -c "set -o pipefail"не працює.
Десмонд Юм

Отже, ваша проблема полягає в тому, що сценарій запускається, /bin/shякий не розпізнає set -o pipefail. Отже, вам потрібно буде переконатися, що сценарій виконується /bin/bashзамість /bin/sh. Або, якщо ви впевнені, сміливі - і, ймовірно, нерозумні - зміните, /bin/shщоб бути посиланням на або копією, /bin/bashзамість того, до якої оболонки вона пов’язана чи копія. Якщо ви впевнені, що /bin/shце так bash, ви використовуєте поведінку, яка bashне піддається, коли запускається як /bin/sh; використовувати bashяк bash.
Джонатан Леффлер

Відповіді:


18

У командному рядку Bash вам потрібно буде викликати нижню частину, щоб уникнути pipefailїї встановлення:

$ (set -o pipefail && command1 | command2 | command3)

Це обмежило б ефект цієї pipefailопції для створення підпрограми в дужках (...).

Реальний приклад:

$ (set -o pipefail && false | true) && echo pipefail inactive || echo pipefail active
pipefail active

Якщо ви використовуєте явний виклик оболонки з -cможливістю, вам не потрібна підкатегорія, bashабо з shпсевдонімом, щоб bash:

$ bash -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active
$ sh -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active

Оскільки ваш варіант shне приймає цей pipefailваріант, я повинен припустити, що це або якась стара, або модифікована версія bash- або що це фактично якась інша оболонка повністю.


1
Чи є $в першому фрагменті частиною команди це просто підказка оболонки? Спробували обидва способи, насправді не вийшло. bash -cСпосіб завжди працює, не дуже елегантний Тхо ..
Desmond Hume

6

Не впевнений, чому це не було зазначено вище, але це можливо явно скасувати pipefail, використовуючи set +o pipefail.

set -o pipefail
command1 | command2 | command3
set +o pipefail

Якщо ви виконуєте фрагмент і не знаєте про pipefailвже встановлений, ви можете скористатися цим підзаголовком, як було запропоновано раніше:

# explicitly execute with pipefail set
(set -o pipefail ; command1 | command2 | command3 )
# explicitly execute with pipefail unset
(set +o pipefail ; command1 | command2 | command3 )

0

Ви можете використовувати $ (command1) у поєднанні з $? :

a=$(echo "a")
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

Друкує "abc"

a=$(ls unexitingDir)
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

Друкує "".

"[$? -eq 0] &&" означає, що наступна команда виконується лише в тому випадку, коли попередня успішна.

Це не відповідає на ваше запитання, але це рішення вашої проблеми.


Чи означає це, що мені завжди потрібно зберігати висновок кожної з команд у змінну?
Десмонд Юм

Завжди я не знаю, але з моїм рішенням, так, ви будете (якщо вам це потрібно для наступної команди). Якщо ви не можете просто написатиcommand1 && command2 && command3
cglacet
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.