Ожидайте процесса для окончания прежде, чем идти в следующую строку в сценарии оболочки

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

$ bash -c 'GROUPSTATUS=foo; echo GROUPSTATUS is $GROUPSTATUS'
GROUPSTATUS is foo
$ bash -c 'GROUPSTATUS=foo | :; echo GROUPSTATUS is $GROUPSTATUS'
GROUPSTATUS is 

В Вашем случае, так как Вы только заботитесь обо всем следовании команд, можно составить поток кода состояния.

{ tar -cf - my_folder 2>&1 1>&3 | grep -v "Removing leading" 1>&2;
  ! ((PIPESTATUS[0])); } 3>&1 |
gzip --rsyncable > my_file.tar.gz;
if ((PIPESTATUS[0] || PIPESTATUS[1])); then rm my_file.tar.gz; fi

Если Вы хотите вытащить больше чем 8 битов информации из левой стороны канала, можно записать в еще один дескриптор файла. Вот пример доказательства принципа:

{ { tar …; echo $? >&4; } | …; } | { gzip …; echo $? >&4; } \
  4>&1 | ! grep -vxc '0'

После того как Вы получаете данные по стандартному выводу, можно подать его в переменную оболочки, использующую замену команды, т.е. $(…). Замена команды читает из стандартного вывода команды, поэтому если бы Вы также означали печатать вещи к стандартному выводу сценария, то они должны временно пройти другой дескриптор файла. Следующий отрывок использует fd 3 для вещей, которые в конечном счете переходят к stdout сценария и fd 4 для вещей, которые получены в $statuses.

statuses=$({ { tar -v … >&3; echo tar $? >&4; } | …; } |
           { gzip …; echo gzip $? >&4; } 4>&1) 3>&1

Если необходимо получить вывод от различных команд в различные переменные, я думаю, что нет никакого прямого пути даже в “усовершенствованных” оболочках, таких как удар, ksh или zsh. Вот некоторые обходные решения:

  • Используйте временные файлы.
  • Используйте единственный поток вывода, с, например, префикс на каждой строке для указания на ее источник и фильтр на верхнем уровне.
  • Используйте более усовершенствованный язык, такой как Perl или Python.
6
10.12.2011, 10:49
2 ответа

Вы уже делаете его.

Ожидание команды для окончания является нормальным поведением оболочки. (Попытайтесь ввести sleep 5 при приглашении оболочки.) Единственное время, которого не происходит, - когда Вы добавляете & к команде, или когда сама команда делает что-то к эффективно фону самому (последний является определенным упрощением).

Можно удалить wait %% управляйте из своего сценария; это, вероятно, просто производит сообщение об ошибке как wait: %%: no such job. (Вопрос: это на самом деле печатает такое сообщение?)

У Вас есть какое-либо доказательство что tar команда не завершается перед /home/ftp.sh команда запускается?

Кстати, это немного нечетно, чтобы иметь вещи кроме корневых каталогов пользователей непосредственно под /home.

(Я знаю, что большая часть из этого была уже охвачена в комментариях, но я думал, что должен быть фактический ответ.)

9
27.01.2020, 20:27

Можно использовать:

wait $!

Удалите wait %% из Вашего сценария.

-2
27.01.2020, 20:27

Теги

Похожие вопросы