Как ускорить изменение имен папок и замену в файлах по sFTP/SSH?

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 788
Благодарностей
2 454
Баллы
113
Есть задача изменить названия примерно для 100 000 папок.
В каждой папке в одном файле произвести замену в определенной строке.

В данный момент использую примерно такой метод (исходник ниже), в который подаю подключение один раз и в цикле прохожу по нужным папкам.
Проблема в том, что работа с одной папкой занимает около 2-3 секунд.
Можно ли как-то ускорить процесс (например можно ли работать с SftpClient в многопотоке?)?
Может быть кто-то предложит какой-то более рациональный вариант?

Всё скачать и залить обратно - не вариант (время загрузки одной папки по FTP многократно превышает время изменение имени и замены в файле).
C#:
        public static bool ReplaceDomainEndDir(SftpClient ftp, string olddomain, string newdomain){
            string line = string.Empty;
            string old_php = string.Format(@"/var/www/{0}/index.php",olddomain);
            string old_dir = string.Format(@"/var/www/{0}",olddomain);
            string new_dir = string.Format(@"/var/www/{0}",newdomain);
            string new_php = string.Format(@"/var/www/{0}/index.php",newdomain);
            bool check_out = false;
            try {
                using (var ms = new MemoryStream()) {
                        bool check = ftp.Exists(old_dir);
                        line += check ? "1" : "0";
                        check = ftp.Exists(old_php);
                        line += check ? "1" : "0";      
                      
                        if(check) { // Замена содержимого файла
                            ftp.DownloadFile(old_php, ms);      
                            string txt = Convert.ToBase64String(ms.ToArray());  
                            txt = Encoding.UTF8.GetString(Convert.FromBase64String(txt));
                            txt = Regex.Replace(txt, @"(?<=\$domain\ =\ 'http://).*?(?=';)", newdomain, RegexOptions.IgnoreCase);
                            using (var mss = new MemoryStream(Encoding.UTF8.GetBytes(txt))) {
                                ftp.UploadFile(mss, old_php, null);
                            }          
                        }
                      
                        check = ftp.Exists(new_dir);
                        line += check ? "1" : "0";  
                        check = ftp.Exists(new_php);
                        line += check ? "1" : "0";  
                              
                        if(!check) ftp.RenameFile(old_dir, new_dir);
                      
                        check = ftp.Exists(old_dir);
                        line += check ? "1" : "0";
                        check = ftp.Exists(old_php);
                        line += check ? "1" : "0";  
                      
                        check = ftp.Exists(new_dir);
                        line += check ? "1" : "0";  
                        check = ftp.Exists(new_php);
                        line += check ? "1" : "0";      
                      
                    }
            }
            catch {
             // ошибка line != "11000011"
            }
            if(line == "11000011") check_out = true;
            return check_out;
        }
 

Yuriy Zymlex

Moderator
Команда форума
Регистрация
24.10.2016
Сообщения
6 518
Благодарностей
3 371
Баллы
113
Заготавливайте bash скрипт, загружайте на сервер и запускайте. Можно и на C# (.net core) попробовать.
 
  • Спасибо
Реакции: BAZAg

ZULI

Client
Регистрация
09.09.2020
Сообщения
423
Благодарностей
165
Баллы
43
Согласен с Zymlex, загрузи скрипт на сервер и запусти, в 100500 раз быстрее будет
 

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 788
Благодарностей
2 454
Баллы
113
Согласен с Zymlex, загрузи скрипт на сервер и запусти, в 100500 раз быстрее будет
За такой скриптик требуют 3000 рублей, и это при том, что он получится совсем не гибкий в работе (сегодня мне одни файлы заменять - завтра другие, сегодня одной регуляркой что-то менять - завтра в нескольких местах придётся). В том, насколько он будет стабильно работать, как извлекать потом ошибки его работы, а вдруг при его работе ляжет сервер - очень много переменных, за которыми придётся следить, чтобы всё это работало само по себе на расписании...
В идеале - использовать Зенно + C#.

В данный момент узнал, что по SSH можно подключаться под одним пользователем сколько угодно раз.
В результате-запустил обычный многопоток -получается обрабатывать 5-10 папок в секунду.
Но, процессор не загружен у меня, на сервере также не загружен на 100%.
Итого - подозреваю, что можно как-то в 100 раз примерно ускорить решение - только пока ещё не нашел как.
А тему создал - вдруг кто-то уже подобное решал- не придётся велосипед изобретать.
 

Yuriy Zymlex

Moderator
Команда форума
Регистрация
24.10.2016
Сообщения
6 518
Благодарностей
3 371
Баллы
113
За такой скриптик требуют 3000 рублей, и это при том, что он получится совсем не гибкий в работе (сегодня мне одни файлы заменять - завтра другие, сегодня одной регуляркой что-то менять - завтра в нескольких местах придётся). В том, насколько он будет стабильно работать, как извлекать потом ошибки его работы, а вдруг при его работе ляжет сервер - очень много переменных, за которыми придётся следить, чтобы всё это работало само по себе на расписании...
В идеале - использовать Зенно + C#.

В данный момент узнал, что по SSH можно подключаться под одним пользователем сколько угодно раз.
В результате-запустил обычный многопоток -получается обрабатывать 5-10 папок в секунду.
Но, процессор не загружен у меня, на сервере также не загружен на 100%.
Итого - подозреваю, что можно как-то в 100 раз примерно ускорить решение - только пока ещё не нашел как.
А тему создал - вдруг кто-то уже подобное решал- не придётся велосипед изобретать.
Учите C# и сможете задавать любую гибкость.
https://docs.microsoft.com/ru-ru/dotnet/api/system.threading.thread.start?view=netframework-4.6.2 (но FTP API постера не рассчитывался на такое многопоточное выполнение, т.е. могут быть проблемы)
 
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 788
Благодарностей
2 454
Баллы
113
Учите C# и сможете задавать любую гибкость.
https://docs.microsoft.com/ru-ru/dotnet/api/system.threading.thread.start?view=netframework-4.6.2 (но FTP API постера не рассчитывался на такое многопоточное выполнение, т.е. могут быть проблемы)
Код, который в шапке одел в параллельный цикл - 4-5 папок в секунду:
Код:
System.Threading.Tasks.Parallel.For(0, temp.Count, (j) => {
    /// code
}
Одел в AsParallel - 5-10 в секунду.
Код:
    list.AsParallel().Select(x=>{
        // code
        return true;})
Явных каких-то проблем пока не наблюдаю, за исключением того, что не знаю пока как загрузить на 100% процессор у себя и на сервере, чтобы благодаря этому увеличить скорость обработки...
 

Yuriy Zymlex

Moderator
Команда форума
Регистрация
24.10.2016
Сообщения
6 518
Благодарностей
3 371
Баллы
113
Да, это вариант даже лучше, так как не всегда требует поднимать потоки.

Но скорее всего, лучшим вариантом будет этакий "клиент" на сервере, который будет получать список для работы.
 
  • Спасибо
Реакции: BAZAg

Кто просматривает тему: (Всего: 2, Пользователи: 0, Гости: 2)