У меня есть список файлов в NFS, который содержит более 2 миллионов узлов. Мне нужно выполнить довольно много изменений прав доступа к файлам, владельца и т. Д. Когда я выполняю такие команды, как chmod
и chown
(даже rm
или mv
), процессы требуют много времени для завершения, поскольку каждый из них должен посетить каждый узел в файловой системе.
Я хотел бы добиться некоторой квазиформы распараллеливания в этом, так как у меня есть общий доступ через NFS. Есть ли способ разбить (осколок?) Список файлов, чтобы запуск chown,chmod,rm,mv
и т. Д. На многих хостах мог завершить всю работу быстрее? Представьте себе 2 хоста, начинающих с обоих концов и встречающихся в середине сделки.
Встречайте parallel
(sudo apt install parallel
):
GNU
parallel
- это инструмент оболочки для параллельного выполнения заданий с использованием одного или нескольких компьютеров. Задание может быть отдельной командой или небольшим сценарием, который должен быть запущен для каждой строки ввода. Типичным вводом является список файлов, список хостов, список пользователей, список URL-адресов или список таблиц. Задание также может быть командой, которая читает из канала. Параллельно GNU может разделить ввод на блоки и направить блок в каждую команду параллельно.
(…)
Для каждой строки ввода GNUparallel
выполнитcommand
со строкой в качестве аргументов. Если команда не указана, строка ввода выполняется. Несколько линий будут проходить параллельно. Параллельно GNU часто можно использовать вместоxargs
илиcat | bash
.
find . -type f -print0 | parallel -0 chmod +w
Это рекурсивно найдет каждый файл в текущем каталоге и запустит chmod +w
для него, выполняя одновременно несколько процессов - по умолчанию один процесс на ядро ЦП.
Подробнее см. man parallel
, особенно удивительный список объясненных примеров. На YouTube также есть плейлист с примерами видео .
Я буду удивлен, если ограничивающим фактором не станет сервер. Поэтому я думаю, что решение десертного решения является разумным - возможно, с добавлением -j200
и -X
для запуска большего количества параллельных заданий на локальном хосте и вставки более 1 аргумента в каждую строку.
Но предположим, что у вас есть ленивые клиенты, тогда это может быть способ сделать это:
doit() {
chmod +w "$1"
# do other stuff
}
export -f doit
cat 2millionfilelist.txt |
parallel --env doit -S nfsclient1,nfsclient2,nfsclient3 doit
Это определяет функцию (адаптируется к вашим собственным потребностям). Затем эта функция копируется в каждый из 3-х nfsclients и запускается с одним аргументом из 2millionfilelist.txt. Это делается параллельно, и по умолчанию выполняется 1 задание на процессор на каждом из 3 клиентов.
Теперь GNU Parallel будет подключаться к nfsclients, используя ssh
для каждого из файлов. Таким образом, вышесказанное, вероятно, крайне неэффективно. Но мы можем добиться большего, чем это.
doitwrap() {
doit() {
chmod +w "$1"
# do other stuff
}
export -f doit
parallel doit
}
export -f doitwrap
cat 2millionfilelist.txt | parallel --env doitwrap -S nfsclient1,nfsclient2,nfsclient3 --pipe -N1000 doitwrap
doit
делает то же самое, что и раньше, но теперь у нас есть оболочка, которая читает из стандартного ввода и запускает doit
на локальной машине. Так что теперь нам просто нужно равномерно распределить 2millionfilelist.txt
среди трех клиентов.
GNU Parallel тоже может это делать. Мы передаем doitwrap каждому из трех рабочих, а затем запускаем его там. Затем мы передаем 2millionfilelist.txt
в блоках по 1000 строк 3 рабочим.