bash - возвращает статус из функции в фоновом режиме

У меня есть скрипт bash примерно следующей структуры:

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 работает в подоболочке, переменная не будет работать (присваивания происходят в подоболочке и не передаются в родительскую оболочку).

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

2 ответа

Решение

Я закончил тем, что сделал что-то похожее на то, что предложил Фред.

Прежде всего, я отказался от идеи "файл не изменен на сервере = нет ошибки" и теперь использую код возврата, чтобы просто указать, есть ли у нас загрузка для обработки - 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."

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

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

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

[[ $result = 0 ]] || process_download

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

Другие вопросы по тегам