diff --git a/DIRECTORY_TREE.md b/DIRECTORY_TREE.md index 4372e22..51df0b1 100644 --- a/DIRECTORY_TREE.md +++ b/DIRECTORY_TREE.md @@ -4,6 +4,7 @@ . ├─ archive │ ├─ README.md +│ ├─ parallelizing-bash-scripts.md │ └─ round-robin.md ├─ bash_scripts │ ├─ README.en.md @@ -21,11 +22,8 @@ │ └─ repo_orchestrate.sh ├─ pictures │ ├─ README.md -│ ├─ archive.jpg -│ ├─ bash_scripts.jpg │ ├─ color-tomato-theme.jpg │ ├─ older-tomato-theme.jpg -│ ├─ pictures.jpg │ ├─ pomodoro.jpg │ └─ website.jpg ├─ .gitattributes diff --git a/archive/README.md b/archive/README.md index 4b708fd..d776d95 100644 --- a/archive/README.md +++ b/archive/README.md @@ -1,4 +1,5 @@ -| Незавершённые публикации | Язык | Обновление | -|:-----------------------------------------------------------|------|------------| -| [Циклический алгоритм распределения задач](round-robin.md) | Java | 2023.06.05 | +| Незавершённые публикации | Язык | Обновление | +|:-----------------------------------------------------------------|------|------------| +| [Распараллеливание скриптов Bash](parallelizing-bash-scripts.md) | Bash | 2024.08.15 | +| [Циклический алгоритм распределения задач](round-robin.md) | Java | 2023.06.05 | diff --git a/archive/parallelizing-bash-scripts.md b/archive/parallelizing-bash-scripts.md new file mode 100644 index 0000000..11e6649 --- /dev/null +++ b/archive/parallelizing-bash-scripts.md @@ -0,0 +1,99 @@ +# Распараллеливание скриптов Bash + +Примером последовательности действий, не зависящих друг от друга, могут быть — итерации циклов, или вызовы функций с +параметрами. Когда цикл один, или функция одна — это тривиальная задача для распараллеливания. Рассмотрим усложнённую +модель с тремя функциями и тремя параметрами для каждой — будем распараллеливать вызовы этих функций. + +Сначала кодируем параметры в HEX коды и отбрасываем разделители строк — чтобы не заниматься экранированием спецсимволов. +Затем создаём массив строк — вызовы функций с параметрами. Далее выполняем эти строки в параллельном режиме с помощью +программы `xargs` — вызываем целевые функции командой `eval`. Внутри каждой функции сначала декодируем параметры +обратно и затем работаем с ними. Дополнительно для наглядности замеряем общее время выполнения функций. + +```bash +#!/bin/bash +#---------------------------------------------------------------------------; +# три функции с тремя параметрами +#---------------------------------------------------------------------------; +# первая функция с тремя параметрами +function first_func { + p1="$(decode "$1")" + p2="$(decode "$2")" + p3="$(decode "$3")" + echo "1 ${FUNCNAME[*]} [$p1] [$p2] [$p3]" + sleep 5 # эмуляция работы 5 секунд +} +# вторая функция с тремя параметрами +function second_func { + p1="$(decode "$1")" + p2="$(decode "$2")" + p3="$(decode "$3")" + echo "2 ${FUNCNAME[*]} [$p1] [$p2] [$p3]" + sleep 5 # эмуляция работы 5 секунд +} +# третья функция с тремя параметрами +function third_func { + p1="$(decode "$1")" + p2="$(decode "$2")" + p3="$(decode "$3")" + echo "3 ${FUNCNAME[*]} [$p1] [$p2] [$p3]" + sleep 5 # эмуляция работы 5 секунд +} +#---------------------------------------------------------------------------; +# вспомогательные функции и экспорт для дочерних процессов +#---------------------------------------------------------------------------; +# удаление разделителей строк и кодирование символов в HEX коды +function encode { echo "$1" | tr -d '\r\n' | uni2ascii -aE -qps; } +# декодирование символов из HEX кодов и удаление разделителей строк +function decode { echo "$1" | ascii2uni -aE -q | tr -d '\r\n'; } +# перечисление используемых функций в дочерних процессах bash +export -f decode first_func second_func third_func +#---------------------------------------------------------------------------; +# подготовка массива строк и вывод строк массива +#---------------------------------------------------------------------------; +# параметры могут содержать любые печатные символы или быть пустыми +param0=" \$param\"" +param1= +param2='"$2"!="$1"' +# кодирование параметров +p0="$(encode "$param0")" +p1="$(encode "$param1")" +p2="$(encode "$param2")" +# массив строк — вызовы функций с параметрами +array[0]="first_func '$p0' '$p1' '$p2'" +array[1]="second_func '$p2' '$p0' '$p1'" +array[2]="third_func '$p1' '$p2' '$p0'" +# вывод строк массива для наглядности +printf '%s\n' "${array[@]}" +#---------------------------------------------------------------------------; +# параллельный вызов функций и замер общего времени выполнения +#---------------------------------------------------------------------------; +# текущее время в миллисекундах +time_ms="$(date '+%s%3N')" +# вывод строк массива и вызов функции для каждой из них в параллельном режиме +printf '%s\0' "${array[@]}" | xargs -I{} -n1 -0 -P0 bash -c 'eval "{}"' +# время работы в миллисекундах +echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." +``` + +## Вывод + +Строки массива, вызовы функций с параметрами через пробелы в кавычках +``` +first_func 'U0020U0024U0070U0061U0072U0061U006DU0022' '' 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022' +second_func 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022' 'U0020U0024U0070U0061U0072U0061U006DU0022' '' +third_func '' 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022' 'U0020U0024U0070U0061U0072U0061U006DU0022' +``` +Параллельная работа функций, порядок может изменяться +``` +3 third_func [] ["$2"!="$1"] [ $param"] +2 second_func ["$2"!="$1"] [ $param"] [] +1 first_func [ $param"] [] ["$2"!="$1"] +``` +Время работы функций в миллисекундах +``` +Общее время выполнения: 5023 мс. +``` + +--- + +© Головин Г.Г., Код с комментариями, 2024 diff --git a/bash_scripts/archive_cleanup.sh b/bash_scripts/archive_cleanup.sh index b1089c0..2b2b107 100755 --- a/bash_scripts/archive_cleanup.sh +++ b/bash_scripts/archive_cleanup.sh @@ -2,9 +2,11 @@ echo "Удаление файлов и папок из каталогов проектов перед восстановлением архива." echo "ОТМЕНА" && exit 0 # предохранитель cd ../.. # выходим из папки и из репозитория -# обходим все репозитории, расположенные на одном уровне с текущим -find . -mindepth 1 -maxdepth 1 -type d | sort -r | while read -r dir; do +time_ms="$(date '+%s%3N')" +# обход всех репозиториев, расположенных на одном уровне с текущим, кроме папки ".idea" +find . -mindepth 1 -maxdepth 1 -type d -not -name ".idea" | while read -r dir; do echo "Обработка: $dir" - # удаляем вложенные файлы и папки кроме папок ".git" и ".idea" - find "$dir" -mindepth 1 -maxdepth 1 -type f,d -not -regex ".*\.git\|.*\.idea" -print0 | xargs -0 rm -r + # внутри репозитория — удаление всех вложенных файлов и папок, кроме папки ".git" + find "$dir" -mindepth 1 -maxdepth 1 -type f,d -not -name ".git" -print0 | xargs -0 rm -r done +echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." diff --git a/bash_scripts/info_tree_license.sh b/bash_scripts/info_tree_license.sh index 01ac4e5..fd7a672 100755 --- a/bash_scripts/info_tree_license.sh +++ b/bash_scripts/info_tree_license.sh @@ -60,6 +60,6 @@ function tree_license { export -f tree_license directory_tree list_directory_contents cd ../.. # выходим из папки и из репозитория time_ms="$(date '+%s%3N')" -# запуск параллельной обработки всех репозиториев, расположенных на одном уровне с текущим -find . -mindepth 1 -maxdepth 1 -type d -print0 | xargs -I{} -n1 -0 -P0 bash -c 'tree_license "{}"' +# запуск параллельной обработки всех репозиториев, расположенных на одном уровне с текущим, кроме папки ".idea" +find . -mindepth 1 -maxdepth 1 -type d -not -name ".idea" -print0 | xargs -I{} -n1 -0 -P0 bash -c 'tree_license "{}"' echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." diff --git a/bash_scripts/repo_compose.sh b/bash_scripts/repo_compose.sh index e6d445b..79aa168 100755 --- a/bash_scripts/repo_compose.sh +++ b/bash_scripts/repo_compose.sh @@ -42,11 +42,11 @@ function compose { description="Тема оформления / Старый помидор" fi wiki="" # оглавление по страницам вёб-сайта - if [ -f "$1/WIKI.md" ]; then + if [ -f "$dir/WIKI.md" ]; then if [ "$remote" == "hub.mos.ru" ]; then - wiki="$(uni2ascii -a U -qpsn "$1/WIKI.md")" + wiki="$(uni2ascii -aU -qpsn "$dir/WIKI.md")" else - wiki="$(basenc "$1/WIKI.md" --base64 -w0)" + wiki="$(basenc "$dir/WIKI.md" --base64 -w0)" fi fi # скрипт для создания удалённого репозитория @@ -65,7 +65,7 @@ function compose { echo "token=\"$(cat "$basedir/.token_gitea")\"" cat "$basedir/repo_gitea.tmpl.sh" fi - } >"$1/.repo_remote.sh" && chmod +x "$1/.repo_remote.sh" + } >"$dir/.repo_remote.sh" && chmod +x "$dir/.repo_remote.sh" # скрипт для создания локального репозитория { echo "#!/bin/bash" @@ -74,11 +74,11 @@ function compose { echo "repo=\"$repo\"" echo "dir=\"$dir\"" cat "$basedir/repo_local.tmpl.sh" - } >"$1/.repo_local.sh" && chmod +x "$1/.repo_local.sh" + } >"$dir/.repo_local.sh" && chmod +x "$dir/.repo_local.sh" } export -f compose update_gitignore cd ../.. # выходим из папки и из репозитория time_ms="$(date '+%s%3N')" -# запуск параллельной обработки всех репозиториев, расположенных на одном уровне с текущим -find . -mindepth 1 -maxdepth 1 -type d -print0 | xargs -I{} -n1 -0 -P0 bash -c 'compose "{}"' +# запуск параллельной обработки всех репозиториев, расположенных на одном уровне с текущим, кроме папки ".idea" +find . -mindepth 1 -maxdepth 1 -type d -not -name ".idea" -print0 | xargs -I{} -n1 -0 -P0 bash -c 'compose "{}"' echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." diff --git a/pictures/README.md b/pictures/README.md index b10fadb..31d6906 100644 --- a/pictures/README.md +++ b/pictures/README.md @@ -9,9 +9,3 @@ | ![pomodoro](pomodoro.jpg) | | website | | ![website](website.jpg) | -| bash_scripts | -| ![bash_scripts](bash_scripts.jpg) | -| archive | -| ![archive](archive.jpg) | -| pictures | -| ![pictures](pictures.jpg) | diff --git a/pictures/archive.jpg b/pictures/archive.jpg deleted file mode 100644 index 2c9d1e4..0000000 Binary files a/pictures/archive.jpg and /dev/null differ diff --git a/pictures/bash_scripts.jpg b/pictures/bash_scripts.jpg deleted file mode 100644 index 3dd3e2a..0000000 Binary files a/pictures/bash_scripts.jpg and /dev/null differ diff --git a/pictures/color-tomato-theme.jpg b/pictures/color-tomato-theme.jpg index 6180d8d..4777099 100644 Binary files a/pictures/color-tomato-theme.jpg and b/pictures/color-tomato-theme.jpg differ diff --git a/pictures/older-tomato-theme.jpg b/pictures/older-tomato-theme.jpg index 333fc46..bf1024d 100644 Binary files a/pictures/older-tomato-theme.jpg and b/pictures/older-tomato-theme.jpg differ diff --git a/pictures/pictures.jpg b/pictures/pictures.jpg deleted file mode 100644 index 525cf64..0000000 Binary files a/pictures/pictures.jpg and /dev/null differ