2017-01-27 10 views
0

У меня есть Баш скрипт с примерно следующей структурой:статус Баш-возврат из функции в фоновом режиме

function download { 
    # download a big file 
} 

function prepare_stuff { 
    # prepare some stuff 
} 

function process_download { 
    # process the downloaded file 
} 

download & prepare_stuff & wait 
process_download 

Первое, что он делает это, чтобы загрузить файл в несколько сотен мегабайт. Пока выполняется загрузка, некоторые другие вещи подготовлены в фоновом режиме. Когда оба они закончены, загрузка будет обработана.

download может закончиться тремя различными способами:

  1. Ошибка загрузки (например, сервер не доступен)
  2. Файл был загружен успешно
  3. Файл не изменился на сервере с момента последней загрузки

Случай 1 - это условие ошибки (в этом случае функция должна возвращать что-то отличное от нуля), а 2 и 3 - нет (т.е. возвращаемое значение должно быть равно нулю).

Теперь я хочу, чтобы process_download пропустил фактическую обработку при возникновении случаев 1 или 3, поэтому мне нужно передать какой-то статус с download. Поскольку download работает в подоболочке, переменная не будет работать (назначения выполняются в подоболочке и не передаются обратно в родительскую оболочку).

Как передать какое-либо значение из функции в подоболочке обратно в родительскую оболочку?

+0

Это все сводится к инструментам, используемым в функции, то есть, более конкретно экзит-кода последней выполненной команды в функции. – Inian

+0

У вас уже есть способ проверить условие 3, или вы ищете отзывы для этого? – Fred

+0

@Fred Функция загрузки может идентифицировать все три условия. – user149408

ответ

0

В итоге я сделал что-то похожее на то, что предложил Фред.

Прежде всего, я отказался от идеи «файл не изменен на сервере = нет ошибки», и теперь используйте код возврата просто для того, чтобы выразить, есть ли у нас загрузка для обработки-0, если был загружен новый файл, 1, если загрузка не удалась или изменений не было. С этим гораздо проще справиться.

Тогда:

function download { 
    # download a big file 
    # return nonzero if download failed 
    # else return nonzero if file has not changed 
    # else return 0 (download successful, file has changed) 
} 

function prepare_stuff { 
    # prepare some stuff 
} 

function process_download { 
    # process the downloaded file 
} 

download & 
PID_DOWNLOAD=$! 
prepare_stuff & 
PID_PREPARE_STUFF=$! 
wait $PID_PREPARE_STUFF 
wait $PID_DOWNLOAD && process_download || echo "Nothing to process." 
2

Вы можете сделать это:

download & 
download_pid=$! 
prepare_stuff & 
prepare_pid=$! 
result=0 
wait $download_pid || result=$? 
wait $prepare_pid 

Тогда result будет содержать код возврата предыдущей команды загрузки, и оба фоновые задания будут завершены, и вы можете сделать что-то вроде:

[[ $result = 0 ]] || process_download 

С разъяснениями относительно вашего третьего состояния я мог бы сделать ответ более полным.

+0

Я знаю, я сначала неправильно понял вопрос. Я обновил свой ответ.При этом неясно, не хочет ли OP запросить проверку условия 3 или нет, поэтому мое обновленное предложение не справляется с этим на данном этапе. – Fred

+1

@codeforester. Функция 'prepare_stuff' вызывается, когда загрузка выполняется в фоновом режиме. Команды 'wait', которые заставляют скрипт блокироваться, происходят, когда обе функции работают параллельно. – Fred

+0

Может ли быть ситуация, когда процесс загрузки заканчивается еще до того, как мы можем дождаться его? В таком случае 'wait' будет терпеть неудачу из-за неправильного pid. Таким образом, кажется, что мы должны запускать загрузку в подоболочке. Я удалил свой ответ, потому что '$!' Не был установлен после '{}' может быть из-за '&&'. – codeforester