Что не так с этим использованием PIPESTATUS в BASH? - PullRequest
0 голосов
/ 04 октября 2010

У меня есть цикл for, который я передаю через ssh на сервер, отформатированный так, чтобы он выглядел примерно так ...

i=0
for cmd in cmd_list;
do ${cmd} | sed "s/^/OUTPUT_${i}_: /" &
(( i++ ));
done;
wait

Идея состоит в том, что цикл for будет выполнять список командчто я даю это и направляю каждый к sed, где sed добавляет каждую строку вывода с номером команды (0, 1, 2, 3 и т. д.).Затем это фоны, чтобы позволить параллельное выполнение.Это позволяет мне отслеживать, с какой командой был связан вывод, поскольку данные могли возвращаться одновременно и все смешиваться.Это работает очень хорошо.В зависимости от времени, когда команды выводят информацию, и когда они завершены, вывод может выглядеть примерно так ...

OUTPUT_0_: some_data_string_from_a_command
OUTPUT_2_: some_data_string_from_a_command
OUTPUT_0_: some_data_string_from_a_command
OUTPUT_3_: some_data_string_from_a_command
OUTPUT_1_: some_data_string_from_a_command
OUTPUT_1_: some_data_string_from_a_command

Однако, что я действительно хочу сделать, это ...

do ${cmd} 2>&1 | sed "s/^/OUTPUT_${i}_${PIPESTATUS[0]}: /" &

Так что я могу вернуть это ...

OUTPUT_0_0: some_data_string_from_a_command
OUTPUT_2_1: some_error_message_from_a_command
OUTPUT_0_0: some_data_string_from_a_command
OUTPUT_3_1: some_error_message_from_a_command
OUTPUT_1_0: some_data_string_from_a_command
OUTPUT_1_0: some_data_string_from_a_command

Это прекрасно работает с первой командой, если она выходит из строя.Обычно я получаю ненулевой код выхода из $ {PIPESTATUS [0]}.Однако, когда я намеренно разместил команды в списке, который, как я знаю, потерпит неудачу (например, cat / tmp / some_non_existent_file), PIPESTATUS не даст мне правильный код завершения команды в цепочке каналов.Иногда я получаю 0 вместо реального кода выхода.

Есть идеи, почему это так?

1 Ответ

2 голосов
/ 04 октября 2010

Команды в конвейере выполняются параллельно. Это означает, что они могут не завершиться к моменту оценки PIPESTATUS, особенно потому, что PIPESTATUS расширяется оболочкой до фактического запуска команды sed.

Я действительно не понимаю, что вы пытаетесь сделать, потому что вы, кажется, хотите нарушить причинность. Вы думали об этом тщательно? Похоже, вам нужно значение выхода команды с ее выводом, но если она выводит данные, она явно не вышла. Вы полагаетесь на маленькое временное окно, которое всегда открыто. Это может быть для некоторых коротких команд во время выполнения, но это даже сомнительно, поскольку координация параллельного выполнения без операций синхронизации подвержена «случайному» отказу.

Если вы хотите захватить данные вместе с выходным статусом команды, вам нужно сохранить выходные данные где-нибудь (например, в файле), а когда процесс завершится, вывести данные с выходом состояние.

...