Last active 1769406298

tmux migration session to inventory files

en2zmax's Avatar en2zmax revised this gist 1769406298. Go to revision

1 file changed, 199 insertions

mig_s.py(file created)

@@ -0,0 +1,199 @@
1 + #!/usr/bin/env python3
2 + """
3 + Скрипт миграции tmux сессий в новую структуру инвентарей
4 + """
5 +
6 + import os
7 + import re
8 + import shutil
9 + from pathlib import Path
10 +
11 + class SessionMigrator:
12 + def __init__(self):
13 + self.source_dir = Path.home() / '.config' / 'tmux' / 'sessions'
14 + self.target_dir = Path.home() / '.config' / 'tmux-sessions' / 'inventory'
15 +
16 + def parse_session_file(self, file_path):
17 + """Парсит файл сессии и извлекает данные"""
18 + with open(file_path, 'r', encoding='utf-8') as f:
19 + content = f.read()
20 +
21 + # Базовые данные
22 + data = {
23 + 'filename': file_path.name,
24 + 'session_name': None,
25 + 'sshpass_path': None,
26 + 'servers': []
27 + }
28 +
29 + # Парсим имя сессии
30 + session_match = re.search(r'session_name=(["\']?)([^"\'\n]+)\1', content)
31 + if session_match:
32 + data['session_name'] = session_match.group(2).strip()
33 +
34 + # Парсим путь к паролю
35 + sshpass_match = re.search(r'sshpass=\$\(pass ([^)\n]+)\)', content)
36 + if sshpass_match:
37 + data['sshpass_path'] = sshpass_match.group(1).strip()
38 +
39 + # Парсим серверы из массива servers
40 + servers_match = re.search(r'servers=\(([^)]+)\)', content, re.DOTALL)
41 + if servers_match:
42 + servers_content = servers_match.group(1)
43 + # Извлекаем строки серверов
44 + server_lines = re.findall(r'"([^"]+)"', servers_content)
45 + for line in server_lines:
46 + parts = line.strip().split(' ', 1)
47 + if len(parts) == 2:
48 + data['servers'].append(f'"{parts[0]} {parts[1]}"')
49 +
50 + # Обработка специального формата для Приморье
51 + if 'Приморье' in file_path.name:
52 + data = self._parse_primorye_format(content, data)
53 +
54 + return data
55 +
56 + def _parse_primorye_format(self, content, data):
57 + """Специальный парсинг для файла Приморье с другим форматом"""
58 + # Имя сессии
59 + session_match = re.search(r'SESSION=([^\n]+)', content)
60 + if session_match:
61 + data['session_name'] = session_match.group(1).strip()
62 +
63 + # Путь к паролю
64 + sshpass_match = re.search(r'SSHPASS=\$\(pass ([^)\n]+)\)', content)
65 + if sshpass_match:
66 + data['sshpass_path'] = sshpass_match.group(1).strip()
67 +
68 + # Извлекаем серверы из tmux new-window команд
69 + servers = []
70 + window_matches = re.findall(r'tmux new-window[^>]+-n ([^\s]+)[^>]+"sshpass[^>]+ssh ([^"\s]+)"', content)
71 + for server_name, server_connect in window_matches:
72 + servers.append(f'"{server_name} {server_connect}"')
73 +
74 + data['servers'] = servers
75 + return data
76 +
77 + def generate_config_content(self, data):
78 + """Генерирует содержимое нового конфигурационного файла"""
79 + lines = [
80 + f"# Конфигурация для проекта {data['filename'].replace('.session', '')}",
81 + f"SESSION_NAME=\"{data['session_name']}\"",
82 + f"SSHPASS_PATH=\"{data['sshpass_path']}\"",
83 + "",
84 + "# Список серверов в формате \"имя_вкладки подключение\"",
85 + "SERVERS=("
86 + ]
87 +
88 + # Добавляем серверы
89 + for server in data['servers']:
90 + lines.append(f" {server}")
91 +
92 + lines.extend([
93 + ")",
94 + ""
95 + ])
96 +
97 + return '\n'.join(lines)
98 +
99 + def sanitize_filename(self, filename):
100 + """Очищает имя файла от недопустимых символов"""
101 + # Убираем расширение .session
102 + clean_name = filename.replace('.session', '')
103 + # Заменяем пробелы и другие проблемные символы
104 + clean_name = re.sub(r'[^\w\-_.]', '_', clean_name)
105 + return clean_name + '.conf'
106 +
107 + def migrate(self):
108 + """Основная функция миграции"""
109 + print("🚀 Начинаем миграцию tmux сессий...")
110 + print(f"📁 Исходный каталог: {self.source_dir}")
111 + print(f"📁 Целевой каталог: {self.target_dir}")
112 + print()
113 +
114 + # Создаем целевой каталог если не существует
115 + self.target_dir.mkdir(parents=True, exist_ok=True)
116 +
117 + # Получаем список файлов сессий
118 + session_files = list(self.source_dir.glob('*.session'))
119 +
120 + if not session_files:
121 + print("❌ Не найдено файлов сессий для миграции")
122 + return
123 +
124 + migrated_count = 0
125 + errors = []
126 +
127 + for session_file in session_files:
128 + try:
129 + print(f"📖 Обрабатываем: {session_file.name}")
130 +
131 + # Парсим файл
132 + data = self.parse_session_file(session_file)
133 +
134 + # Проверяем что все необходимые данные есть
135 + if not data['session_name']:
136 + print(f" ⚠️ Предупреждение: не найдено имя сессии в {session_file.name}")
137 +
138 + if not data['sshpass_path']:
139 + print(f" ⚠️ Предупреждение: не найден путь к паролю в {session_file.name}")
140 +
141 + if not data['servers']:
142 + print(f" ⚠️ Предупреждение: не найдены серверы в {session_file.name}")
143 +
144 + # Генерируем новое имя файла
145 + new_filename = self.sanitize_filename(session_file.name)
146 + new_file_path = self.target_dir / new_filename
147 +
148 + # Генерируем содержимое
149 + config_content = self.generate_config_content(data)
150 +
151 + # Сохраняем файл
152 + with open(new_file_path, 'w', encoding='utf-8') as f:
153 + f.write(config_content)
154 +
155 + print(f" ✅ Создан: {new_filename}")
156 + print(f" Session: {data['session_name']}")
157 + print(f" Servers: {len(data['servers'])}")
158 + print(f" Pass path: {data['sshpass_path']}")
159 + print()
160 +
161 + migrated_count += 1
162 +
163 + except Exception as e:
164 + error_msg = f"Ошибка обработки {session_file.name}: {str(e)}"
165 + print(f" ❌ {error_msg}")
166 + errors.append(error_msg)
167 +
168 + # Выводим итоги
169 + print("=" * 50)
170 + print(f"📊 Миграция завершена!")
171 + print(f"✅ Успешно мигрировано: {migrated_count}/{len(session_files)}")
172 +
173 + if errors:
174 + print(f"❌ Ошибки ({len(errors)}):")
175 + for error in errors:
176 + print(f" - {error}")
177 +
178 + # Показываем созданные файлы
179 + print(f"\n📁 Созданные файлы в {self.target_dir}:")
180 + for conf_file in sorted(self.target_dir.glob('*.conf')):
181 + print(f" 📄 {conf_file.name}")
182 +
183 + print(f"\n🎯 Теперь вы можете использовать новый лаунчер:")
184 + print(f" tmux-sessions # Меню выбора")
185 + print(f" tmux-sessions --list # Список проектов")
186 +
187 + def main():
188 + migrator = SessionMigrator()
189 +
190 + # Проверяем существует ли исходный каталог
191 + if not migrator.source_dir.exists():
192 + print(f"❌ Исходный каталог не существует: {migrator.source_dir}")
193 + return
194 +
195 + # Запускаем миграцию
196 + migrator.migrate()
197 +
198 + if __name__ == '__main__':
199 + main()
Newer Older