Как запустить bash-функции параллельно и объединить все выходные данные в одну строку по порядку? - PullRequest
1 голос
/ 23 июня 2019

Я пишу несколько функций bash-prompt в стиле oh-my-git , и я хочу, чтобы они работали параллельно и объединяли свои выходные данные по порядку. Скорость важна, и я хочу избежать записи в любую файловую систему, будь то в памяти или на жестком диске.

Моя идея состояла в том, чтобы попытаться установить переменные параллельно, но это невозможно в одной и той же области видимости. GNU Parallel и parset не сшиваются для получения функций bash.

Конец моего .bashrc:


: "${ORIGINAL_PS1:=$PS1}"

PROMPT() {

    git="$(GIT_PROMPT)"
    pamac="$(PAMAC_PROMPT)"
    busich="$(BUSICH_PROMPT)"

    PS1="$git$pamac$busich$ORIGINAL_PS1"

}

PROMPT_COMMAND="PROMPT; $PROMPT_COMMAND"

(GIT_PROMPT, PAMAC_PROMPT и BUSICH_PROMPT являются источниками функций bash)

Ответы [ 2 ]

1 голос
/ 23 июня 2019

Чтобы узко ответить на вопрос, порождая три замены процесса и объединяя их результаты, работа будет выполняться параллельно, генерируя выходные данные в известном порядке:

PS1=$(cat <(GIT_PROMPT) <(PAMAC_PROMPT) <(BUSICH_PROMPT))

Аналогично, в bash 4.1 или более поздней версии,Вы можете явно запустить внешний процесс и прикрепить автоматически назначенный файловый дескриптор, который будет использоваться для чтения его выходных данных:

# start GIT_PROMPT function in the background
exec {git_prompt_fd}< <(GIT_PROMPT)

# ...do other stuff...

# now, later, read its output
git_prompt=$(</dev/fd/$git_prompt_fd)

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


Тем не менее, я вообще не рекомендую, чтобы особенно в коде, чувствительном к производительности, как подсказка,Намного лучше было бы проверить ваши функции и запретить им иметь любые операции вилки, любое использование внешних команд и т. Д .;вместо добавления еще больше вилок во имя распараллеливания.

0 голосов
/ 23 июня 2019

Решение 1: Используйте env_parallel

env_parallel --session
GIT_PROMPT() { echo stdoutgit; echo stderrgit >&2; sleep 2; }
PAMAC_PROMPT() { echo stdoutpamac; echo stderrpamac >&2; sleep 2; }
BUSICH_PROMPT() { echo stdoutbusich; echo stderrbusic >&2; sleep 2; }
PS1=`env_parallel -k ::: GIT_PROMPT PAMAC_PROMPT BUSICH_PROMPT`
env_parallel --endsession

Решение 2: функции экспорта

GIT_PROMPT() { echo stdoutgit; echo stderrgit >&2; sleep 2; }
export -f GIT_PROMPT
PAMAC_PROMPT() { echo stdoutpamac; echo stderrpamac >&2; sleep 2; }
export -f PAMAC_PROMPT
BUSICH_PROMPT() { echo stdoutbusich; echo stderrbusic >&2; sleep 2; }
export -f BUSICH_PROMPT
PS1=`parallel -k ::: GIT_PROMPT PAMAC_PROMPT BUSICH_PROMPT`

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

(GNU Parallel использует временные файлы в /tmp, но очень старается их очистить - обычно менее 1 мс после создания файла. Файл остается открытым, поэтому активностьс файлом обычно происходит , после он удаляется).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...