1c-db-dump-dt
Выгрузка всей информационной базы 1С в DT-файл (полный бэкап - данные, конфигурация, пользователи). Используй когда пользователь просит сделать бэкап базы, выгрузить базу в dt, снять выгрузку ИБ, перенести базу
Install
npx skills add https://github.com/Desko77/claude-code-skills-1c/tree/main/skills/1c-db-dump-dt
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install desko77-claude-code-skills-1c@llmmart
git clone https://github.com/Desko77/claude-code-skills-1c.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole desko77/claude-code-skills-1c collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
/db-dump-dt - Выгрузка информационной базы в DT-файл
Выгружает всю информационную базу в DT-файл: конфигурация, данные, список пользователей, настройки. Это полный бэкап ИБ и стандартный способ переноса базы (в том числе файловая -> серверная и обратно).
Отличие от /db-dump-cf: CF содержит только конфигурацию, DT - всю базу целиком.
Usage
/db-dump-dt [database] [output.dt]
/db-dump-dt dev backup.dt
/db-dump-dt - база по умолчанию, файл backup.dt
Выгрузка требует монопольного доступа: активные сеансы должны быть завершены, иначе платформа вернет ошибку. На больших базах выгрузка идет долго и требует места на диске.
Параметры подключения
Прочитай .v8-project.json из корня проекта. Возьми v8path (путь к платформе) и разреши базу:
- Если пользователь указал параметры подключения (путь, сервер) - используй напрямую
- Если указал базу по имени - ищи по id / alias / name в
.v8-project.json - Если не указал - сопоставь текущую ветку Git с
databases[].branches - Если ветка не совпала - используй
defaultЕслиv8pathне задан - автоопределение:Get-ChildItem "C:\Program Files\1cv8\*\bin\1cv8.exe" | Sort -Desc | Select -First 1Если файла нет - предложи/db-list add. Если использованная база не зарегистрирована - после выполнения предложи добавить через/db-list add.
Команда
powershell.exe -NoProfile -File skills/1c-db-dump-dt/scripts/db-dump-dt.ps1 <параметры>
Параметры скрипта
| Параметр | Обязательный | Описание |
|---|---|---|
-V8Path <путь> |
нет | Каталог bin платформы (или полный путь к 1cv8.exe) |
-InfoBasePath <путь> |
* | Файловая база |
-InfoBaseServer <сервер> |
* | Сервер 1С (для серверной базы) |
-InfoBaseRef <имя> |
* | Имя базы на сервере |
-UserName <имя> |
нет | Имя пользователя |
-Password <пароль> |
нет | Пароль |
-OutputFile <путь> |
да | Путь к выходному DT-файлу |
-StrictLog |
нет | Отказ в журнале поднимает код возврата до 1, даже если платформа вернула 0 |
*- нужен либо-InfoBasePath, либо пара-InfoBaseServer+-InfoBaseRef
Расширения отдельно не выгружаются: DT всегда содержит базу целиком вместе с установленными расширениями.
Коды возврата
| Код | Описание |
|---|---|
| 0 | Успешно |
| 1 | Ошибка (см. лог) |
| 2 | Неверные аргументы (python-версия, argparse) |
После выполнения
Прочитай лог-файл и покажи результат. Если есть ошибки - покажи содержимое лога. Типовая причина ошибки - активные сеансы в базе (нужен монопольный доступ).
Примеры
# Полный бэкап файловой базы
powershell.exe -NoProfile -File skills/1c-db-dump-dt/scripts/db-dump-dt.ps1 -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\MyDB.dt"
# Серверная база
powershell.exe -NoProfile -File skills/1c-db-dump-dt/scripts/db-dump-dt.ps1 -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "MyApp_Dev.dt"
Files (claude-code-skills-1c)
-
evals
-
evals.json 2.7 KB
{ "skill_name": "1c-db-dump-dt", "evals": [ { "id": 1, "prompt": "Сделай полный бэкап базы C:\\Bases\\MyDB в файл C:\\backup\\MyDB.dt. Пользователь Admin, пароль не нужен.", "expected_output": "Скрипт db-dump-dt.ps1 запущен с параметрами -InfoBasePath C:\\Bases\\MyDB, -UserName Admin, -OutputFile C:\\backup\\MyDB.dt. Лог показан пользователю.", "expectations": [ "Скрипт db-dump-dt.ps1 вызван с параметром -InfoBasePath C:\\Bases\\MyDB", "Скрипт db-dump-dt.ps1 вызван с параметром -UserName Admin", "Скрипт db-dump-dt.ps1 вызван с параметром -OutputFile C:\\backup\\MyDB.dt", "Лог-файл прочитан и результат показан пользователю после выполнения" ] }, { "id": 2, "prompt": "Выгрузи серверную базу MyApp_Dev с сервера srv01 в dt-файл. Логин Admin, пароль secret.", "expected_output": "Скрипт db-dump-dt.ps1 запущен с параметрами -InfoBaseServer srv01, -InfoBaseRef MyApp_Dev, -UserName Admin, -Password secret, -OutputFile MyApp_Dev.dt.", "expectations": [ "Скрипт db-dump-dt.ps1 вызван с параметром -InfoBaseServer srv01", "Скрипт db-dump-dt.ps1 вызван с параметром -InfoBaseRef MyApp_Dev", "Скрипт db-dump-dt.ps1 вызван с параметром -OutputFile (имя .dt файла)", "Лог-файл прочитан, при наличии ошибок - содержимое лога показано пользователю" ] }, { "id": 3, "prompt": "Выгрузка базы в dt упала с ошибкой. В логе написано про активные сеансы. Что делать?", "expected_output": "Объяснение: выгрузка ИБ требует монопольного доступа, активные сеансы нужно завершить (закрыть клиентов, отключить фоновые задания), затем повторить выгрузку.", "expectations": [ "Названа причина: выгрузка требует монопольного доступа к базе", "Предложено завершить активные сеансы и повторить", "Не предложено выгружать конфигурацию (.cf) вместо полной базы как решение проблемы" ] } ] }
-
-
scripts
-
db-dump-dt.ps1 10.3 KB · in bundle
-
db-dump-dt.py 9.7 KB
#!/usr/bin/env python3 # db-dump-dt v1.0 - Dump 1C infobase to DT file # Source: https://github.com/Desko77/claude-code-skills-1c import argparse import glob import os import random import re import shutil import subprocess import sys import tempfile def resolve_v8path(v8path): """Resolve path to 1cv8.exe.""" if not v8path: found = sorted(glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe")) if found: return found[-1] else: print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) sys.exit(1) elif os.path.isdir(v8path): v8path = os.path.join(v8path, "1cv8.exe") if not os.path.isfile(v8path): print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path # --- Вердикт платформы (общий блок, версия 1) --- # Платформа сообщает результат тремя независимыми каналами, и ни один не самодостаточен: # нулевой код возврата при проваленной операции - ее штатное поведение. Четвертый сигнал - # постусловие: артефакт операции действительно появился и он от этого запуска. # Фразы, которыми платформа сообщает об ОТСУТСТВИИ проблем. Сверяются раньше диагностики # и целиком: строка "операция завершена с ошибками" не должна попасть под "операция завершена". PLATFORM_CLEAN_PHRASES = ( "ошибок не обнаружено", "ошибки не обнаружены", "предупреждений не обнаружено", "ошибок: 0", "предупреждений: 0", "errors were not found", "0 errors", ) # Сообщения, при которых операция провалена, даже если код возврата нулевой. PLATFORM_FATAL_PHRASES = ( "неверное свойство объекта метаданных", "не входит в состав объекта метаданных", "неизвестное имя типа", "неизвестный объект метаданных", "ни один из документов не является регистратором для регистра", "неверное значение перечисления", "не может быть приведен к типу", "необходима версия платформы не меньше", "не найден метод", "не может быть применен", ) def hide_platform_secret(text): """Замаскировать секреты в строке, уходящей в вывод.""" if not text: return text # Ключи с секретом: пароль базы, код разблокировки, пароль хранилища конфигурации. # Длинные имена стоят первыми, иначе короткое подойдет как префикс длинного. keys = r'(?:^|(?<=\s))(/ConfigurationRepositoryP|/UC|/P)' masked = re.sub(keys + r'"[^"]*"', r'\g<1>"***"', text) masked = re.sub(keys + r'([^\s"]\S*)', r'\g<1>***', masked) # Утилита администрирования принимает секрет длинным ключом со знаком равенства: # --token=, --password=, --db-pwd=. Правило для ключей платформы их не покрывает. long_keys = r'(?:^|(?<=\s))(--(?:token|password|db-pwd|pwd)=)' masked = re.sub(long_keys + r'"[^"]*"', r'\g<1>"***"', masked) masked = re.sub(long_keys + r'([^\s"]\S*)', r'\g<1>***', masked) return masked def platform_log_problems(log_text): """Строки лога, означающие провал операции при любом коде возврата.""" problems = [] if not log_text: return problems for line in log_text.splitlines(): trimmed = line.strip() if not trimmed: continue lower = trimmed.lower() if any(phrase in lower for phrase in PLATFORM_CLEAN_PHRASES): continue if any(phrase in lower for phrase in PLATFORM_FATAL_PHRASES): problems.append(trimmed) return problems def platform_result_code(result_file): """Числовой результат платформы или None, если сигнал недоступен.""" if not result_file or not os.path.isfile(result_file): return None try: with open(result_file, "r", encoding="utf-8-sig") as f: raw = f.read().strip() except Exception: return None if not raw: return None try: return int(raw) except ValueError: return None def write_platform_verdict(exit_code, result_file, log_text, success_message, failure_message, artifact_path=None, strict=False): """Свести четыре сигнала в один код возврата и напечатать вердикт.""" final_code = exit_code result_code = platform_result_code(result_file) if result_code is not None and result_code != 0 and final_code == 0: print(f"[error] platform result code: {result_code}", file=sys.stderr) final_code = 1 if final_code == 0: print(success_message) else: print(f"{failure_message} (code: {final_code})", file=sys.stderr) if log_text: print("--- Log ---") print(log_text) print("--- End ---") problems = platform_log_problems(log_text) if problems: print(f"[warning] platform reported success, but the log contains {len(problems)} problem(s):") for problem in problems: print(f" {problem}") if strict and final_code == 0: final_code = 1 if artifact_path and final_code == 0 and not os.path.exists(artifact_path): print(f"[error] platform reported success, but the expected result is missing: {artifact_path}", file=sys.stderr) final_code = 1 return final_code # --- Конец общего блока вердикта платформы --- def main(): sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") parser = argparse.ArgumentParser( description="Dump 1C infobase to DT file", allow_abbrev=False, ) parser.add_argument("-V8Path", default="") parser.add_argument("-InfoBasePath", default="") parser.add_argument("-InfoBaseServer", default="") parser.add_argument("-InfoBaseRef", default="") parser.add_argument("-UserName", default="") parser.add_argument("-Password", default="") parser.add_argument("-OutputFile", required=True) parser.add_argument("-StrictLog", action="store_true") args = parser.parse_args() v8path = resolve_v8path(args.V8Path) # --- Validate connection --- if not args.InfoBasePath and (not args.InfoBaseServer or not args.InfoBaseRef): print("Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef", file=sys.stderr) sys.exit(1) # --- Ensure output directory exists --- out_dir = os.path.dirname(args.OutputFile) if out_dir and not os.path.isdir(out_dir): os.makedirs(out_dir, exist_ok=True) # --- Temp dir --- temp_dir = os.path.join(tempfile.gettempdir(), f"db_dump_dt_{random.randint(0, 999999)}") os.makedirs(temp_dir, exist_ok=True) try: # --- Build arguments --- arguments = ["DESIGNER"] if args.InfoBaseServer and args.InfoBaseRef: arguments.extend(["/S", f"{args.InfoBaseServer}/{args.InfoBaseRef}"]) else: arguments.extend(["/F", args.InfoBasePath]) if args.UserName: arguments.append(f"/N{args.UserName}") if args.Password: arguments.append(f"/P{args.Password}") arguments.extend(["/DumpIB", args.OutputFile]) # --- Output --- # Каталог временный и уникальный на запуск, поэтому лог и файл результата не могут # достаться от прошлого прогона. out_file = os.path.join(temp_dir, "dump_dt_log.txt") result_file = os.path.join(temp_dir, "dump_dt_result.txt") arguments.extend(["/Out", out_file]) arguments.extend(["/DumpResult", result_file]) arguments.append("/DisableStartupDialogs") # --- Execute --- print(f"Running: 1cv8.exe {hide_platform_secret(' '.join(arguments))}") result = subprocess.run( [v8path] + arguments, capture_output=True, text=True, ) exit_code = result.returncode # --- Result --- log_content = None if os.path.isfile(out_file): try: with open(out_file, "r", encoding="utf-8-sig") as f: log_content = f.read() except Exception: log_content = None exit_code = write_platform_verdict( exit_code, result_file, log_content, f"Infobase dumped successfully to: {args.OutputFile}", "Error dumping infobase. Check for active sessions - dump needs exclusive access.", artifact_path=args.OutputFile, strict=args.StrictLog, ) sys.exit(exit_code) finally: if os.path.isdir(temp_dir): shutil.rmtree(temp_dir, ignore_errors=True) if __name__ == "__main__": main()
-
-
SKILL.md 4.8 KB
--- name: 1c-db-dump-dt description: Выгрузка всей информационной базы 1С в DT-файл (полный бэкап - данные, конфигурация, пользователи). Используй когда пользователь просит сделать бэкап базы, выгрузить базу в dt, снять выгрузку ИБ, перенести базу argument-hint: "[database] [output.dt]" allowed-tools: - Bash - Read - Glob - AskUserQuestion --- # /db-dump-dt - Выгрузка информационной базы в DT-файл Выгружает всю информационную базу в DT-файл: конфигурация, данные, список пользователей, настройки. Это полный бэкап ИБ и стандартный способ переноса базы (в том числе файловая -> серверная и обратно). Отличие от `/db-dump-cf`: CF содержит только конфигурацию, DT - всю базу целиком. ## Usage ``` /db-dump-dt [database] [output.dt] /db-dump-dt dev backup.dt /db-dump-dt - база по умолчанию, файл backup.dt ``` > Выгрузка требует монопольного доступа: активные сеансы должны быть завершены, иначе платформа вернет ошибку. На больших базах выгрузка идет долго и требует места на диске. ## Параметры подключения Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу: 1. Если пользователь указал параметры подключения (путь, сервер) - используй напрямую 2. Если указал базу по имени - ищи по id / alias / name в `.v8-project.json` 3. Если не указал - сопоставь текущую ветку Git с `databases[].branches` 4. Если ветка не совпала - используй `default` Если `v8path` не задан - автоопределение: `Get-ChildItem "C:\Program Files\1cv8\*\bin\1cv8.exe" | Sort -Desc | Select -First 1` Если файла нет - предложи `/db-list add`. Если использованная база не зарегистрирована - после выполнения предложи добавить через `/db-list add`. ## Команда ```powershell powershell.exe -NoProfile -File skills/1c-db-dump-dt/scripts/db-dump-dt.ps1 <параметры> ``` ### Параметры скрипта | Параметр | Обязательный | Описание | |----------|:------------:|----------| | `-V8Path <путь>` | нет | Каталог bin платформы (или полный путь к 1cv8.exe) | | `-InfoBasePath <путь>` | * | Файловая база | | `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) | | `-InfoBaseRef <имя>` | * | Имя базы на сервере | | `-UserName <имя>` | нет | Имя пользователя | | `-Password <пароль>` | нет | Пароль | | `-OutputFile <путь>` | да | Путь к выходному DT-файлу | | `-StrictLog` | нет | Отказ в журнале поднимает код возврата до 1, даже если платформа вернула 0 | > `*` - нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef` Расширения отдельно не выгружаются: DT всегда содержит базу целиком вместе с установленными расширениями. ## Коды возврата | Код | Описание | |-----|----------| | 0 | Успешно | | 1 | Ошибка (см. лог) | | 2 | Неверные аргументы (python-версия, argparse) | ## После выполнения Прочитай лог-файл и покажи результат. Если есть ошибки - покажи содержимое лога. Типовая причина ошибки - активные сеансы в базе (нужен монопольный доступ). ## Примеры ```powershell # Полный бэкап файловой базы powershell.exe -NoProfile -File skills/1c-db-dump-dt/scripts/db-dump-dt.ps1 -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\MyDB.dt" # Серверная база powershell.exe -NoProfile -File skills/1c-db-dump-dt/scripts/db-dump-dt.ps1 -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "MyApp_Dev.dt" ```
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.