fix(db,epf): изолированный --data на каждую ibcmd-операцию

ibcmd без --data использует общий каталог автономного сервера в
%LOCALAPPDATA%\standalone-server: он копит реестр/локи, и зависший
процесс (например, ушедший в консольный интерактив при нехватке кред)
держит его лок, блокируя ВСЕ последующие ibcmd-операции «Рабочий каталог
заблокирован процессом N».

Теперь каждая ibcmd-операция получает свой одноразовый --data=<temp> и
удаляет его после: зависший/параллельный вызов лочит только свой каталог,
не накапливается реестр («уже зарегистрирована»). База (--db-path) и
чужой автономный сервер на дефолтном каталоге не затрагиваются.

Реализация: ps1 — --data=$tempDir (создаётся до try, finally чистит на
exit); py — свой ib_data через tempfile.mkdtemp + atexit-очистка (надёжно
на любом sys.exit); stub-db-create — свой ib_data + явная очистка.

Проверено: A/B через навык с живым холдером — операция с общим --data
падает «заблокирован процессом N», навык (свой --data) проходит; очистка
temp-каталогов подтверждена (оба порта); 1cv8-ветки не затронуты.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-21 19:01:03 +03:00
parent 8fb3e9421d
commit 5bd6ba30cd
24 changed files with 94 additions and 26 deletions
@@ -1,4 +1,4 @@
# db-create v1.2 — Create 1C information base
# db-create v1.3 — Create 1C information base
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -144,6 +144,7 @@ try {
$arguments += "--load=$UseTemplate", "--apply"
}
}
$arguments += "--data=$tempDir"
Write-Host "Running: ibcmd $($arguments -join ' ')"
$output = & $V8Path @arguments 2>&1
$exitCode = $LASTEXITCODE
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# db-create v1.2 — Create 1C information base
# db-create v1.3 — Create 1C information base
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import atexit
import glob
import json
import os
@@ -106,6 +107,9 @@ def main():
arguments.append(f"--restore={args.UseTemplate}")
else:
arguments.extend([f"--load={args.UseTemplate}", "--apply"])
ib_data = tempfile.mkdtemp(prefix="ibcmd_data_")
atexit.register(shutil.rmtree, ib_data, ignore_errors=True)
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
if result.returncode == 0:
@@ -1,4 +1,4 @@
# db-dump-cf v1.2 — Dump 1C configuration to CF file
# db-dump-cf v1.3 — Dump 1C configuration to CF file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -152,6 +152,7 @@ try {
$arguments = @("infobase", "config", "save", "--db-path=$InfoBasePath")
if ($Extension) { $arguments += "--extension=$Extension" }
$arguments += "$OutputFile"
$arguments += "--data=$tempDir"
Write-Host "Running: ibcmd $($arguments -join ' ')"
$output = & $V8Path @arguments 2>&1
$exitCode = $LASTEXITCODE
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# db-dump-cf v1.2 — Dump 1C configuration to CF file
# db-dump-cf v1.3 — Dump 1C configuration to CF file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import atexit
import glob
import json
import os
@@ -109,6 +110,9 @@ def main():
if args.Extension:
arguments.append(f"--extension={args.Extension}")
arguments.append(args.OutputFile)
ib_data = tempfile.mkdtemp(prefix="ibcmd_data_")
atexit.register(shutil.rmtree, ib_data, ignore_errors=True)
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
if result.returncode == 0:
@@ -1,4 +1,4 @@
# db-dump-dt v1.2 — Dump 1C information base to DT file
# db-dump-dt v1.3 — Dump 1C information base to DT file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -134,6 +134,7 @@ try {
if ($Password) { $arguments += "--password=$Password" }
$arguments += "$OutputFile"
$arguments += "--data=$tempDir"
Write-Host "Running: ibcmd $($arguments -join ' ')"
$output = & $V8Path @arguments 2>&1
$exitCode = $LASTEXITCODE
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# db-dump-dt v1.2 — Dump 1C information base to DT file
# db-dump-dt v1.3 — Dump 1C information base to DT file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import atexit
import glob
import json
import os
@@ -106,6 +107,9 @@ def main():
if args.Password:
arguments.append(f"--password={args.Password}")
arguments.append(args.OutputFile)
ib_data = tempfile.mkdtemp(prefix="ibcmd_data_")
atexit.register(shutil.rmtree, ib_data, ignore_errors=True)
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
if result.returncode == 0:
@@ -1,4 +1,4 @@
# db-dump-xml v1.4 — Dump 1C configuration to XML files
# db-dump-xml v1.5 — Dump 1C configuration to XML files
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -193,6 +193,7 @@ try {
if ($Extension) { $arguments += "--extension=$Extension" }
$arguments += "$ConfigDir"
}
$arguments += "--data=$tempDir"
Write-Host "Running: ibcmd $($arguments -join ' ')"
$output = & $V8Path @arguments 2>&1
$exitCode = $LASTEXITCODE
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# db-dump-xml v1.4 — Dump 1C configuration to XML files
# db-dump-xml v1.5 — Dump 1C configuration to XML files
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import atexit
import glob
import json
import os
@@ -140,6 +141,9 @@ def main():
if args.Extension:
arguments.append(f"--extension={args.Extension}")
arguments.append(args.ConfigDir)
ib_data = tempfile.mkdtemp(prefix="ibcmd_data_")
atexit.register(shutil.rmtree, ib_data, ignore_errors=True)
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
if result.returncode == 0:
@@ -1,4 +1,4 @@
# db-load-cf v1.2 — Load 1C configuration from CF file
# db-load-cf v1.3 — Load 1C configuration from CF file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -152,6 +152,7 @@ try {
$arguments = @("infobase", "config", "load", "--db-path=$InfoBasePath")
if ($Extension) { $arguments += "--extension=$Extension" }
$arguments += "$InputFile"
$arguments += "--data=$tempDir"
Write-Host "Running: ibcmd $($arguments -join ' ')"
$output = & $V8Path @arguments 2>&1
$exitCode = $LASTEXITCODE
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# db-load-cf v1.2 — Load 1C configuration from CF file
# db-load-cf v1.3 — Load 1C configuration from CF file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import atexit
import glob
import json
import os
@@ -109,6 +110,9 @@ def main():
if args.Extension:
arguments.append(f"--extension={args.Extension}")
arguments.append(args.InputFile)
ib_data = tempfile.mkdtemp(prefix="ibcmd_data_")
atexit.register(shutil.rmtree, ib_data, ignore_errors=True)
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
if result.returncode == 0:
@@ -1,4 +1,4 @@
# db-load-dt v1.2 — Load 1C information base from DT file
# db-load-dt v1.3 — Load 1C information base from DT file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -148,6 +148,7 @@ try {
if ($Password) { $arguments += "--password=$Password" }
$arguments += "$InputFile"
$arguments += "--data=$tempDir"
Write-Host "Running: ibcmd $($arguments -join ' ')"
$output = & $V8Path @arguments 2>&1
$exitCode = $LASTEXITCODE
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# db-load-dt v1.2 — Load 1C information base from DT file
# db-load-dt v1.3 — Load 1C information base from DT file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import atexit
import glob
import json
import os
@@ -110,6 +111,9 @@ def main():
if args.Password:
arguments.append(f"--password={args.Password}")
arguments.append(args.InputFile)
ib_data = tempfile.mkdtemp(prefix="ibcmd_data_")
atexit.register(shutil.rmtree, ib_data, ignore_errors=True)
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
if result.returncode == 0:
@@ -1,4 +1,4 @@
# db-load-git v1.6 — Load Git changes into 1C database
# db-load-git v1.7 — Load Git changes into 1C database
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -339,6 +339,7 @@ try {
$arguments = @("infobase", "config", "import", "files") + $configFiles
$arguments += "--base-dir=$ConfigDir", "--db-path=$InfoBasePath"
if ($Extension) { $arguments += "--extension=$Extension" }
$arguments += "--data=$tempDir"
Write-Host "Running: ibcmd $($arguments -join ' ')"
$output = & $V8Path @arguments 2>&1
$exitCode = $LASTEXITCODE
@@ -351,6 +352,7 @@ try {
if ($output) { Write-Host ($output | Out-String) }
if ($UpdateDB) {
$applyArgs = @("infobase", "config", "apply", "--db-path=$InfoBasePath", "--force")
$applyArgs += "--data=$tempDir"
Write-Host "Running: ibcmd $($applyArgs -join ' ')"
$applyOut = & $V8Path @applyArgs 2>&1
$exitCode = $LASTEXITCODE
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# db-load-git v1.6 — Load Git changes into 1C database
# db-load-git v1.7 — Load Git changes into 1C database
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import atexit
import glob
import json
import os
@@ -266,6 +267,9 @@ def main():
arguments += [f"--base-dir={args.ConfigDir}", f"--db-path={args.InfoBasePath}"]
if args.Extension:
arguments.append(f"--extension={args.Extension}")
ib_data = tempfile.mkdtemp(prefix="ibcmd_data_")
atexit.register(shutil.rmtree, ib_data, ignore_errors=True)
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
if result.returncode != 0:
@@ -281,6 +285,7 @@ def main():
exit_code = 0
if args.UpdateDB:
apply_args = ["infobase", "config", "apply", f"--db-path={args.InfoBasePath}", "--force"]
apply_args.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(apply_args)}")
ar = subprocess.run([v8path] + apply_args, capture_output=True, encoding="utf-8", errors="replace")
exit_code = ar.returncode
@@ -1,4 +1,4 @@
# db-load-xml v1.8 — Load 1C configuration from XML files
# db-load-xml v1.9 — Load 1C configuration from XML files
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -213,6 +213,7 @@ try {
if ($Extension) { $arguments += "--extension=$Extension" }
$arguments += "$ConfigDir"
}
$arguments += "--data=$tempDir"
Write-Host "Running: ibcmd $($arguments -join ' ')"
$output = & $V8Path @arguments 2>&1
$exitCode = $LASTEXITCODE
@@ -226,6 +227,7 @@ try {
if ($UpdateDB) {
$applyArgs = @("infobase", "config", "apply", "--db-path=$InfoBasePath", "--force")
$applyArgs += "--data=$tempDir"
Write-Host "Running: ibcmd $($applyArgs -join ' ')"
$applyOut = & $V8Path @applyArgs 2>&1
$exitCode = $LASTEXITCODE
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# db-load-xml v1.8 — Load 1C configuration from XML files
# db-load-xml v1.9 — Load 1C configuration from XML files
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import atexit
import glob
import json
import os
@@ -158,6 +159,9 @@ def main():
if args.Extension:
arguments.append(f"--extension={args.Extension}")
arguments.append(args.ConfigDir)
ib_data = tempfile.mkdtemp(prefix="ibcmd_data_")
atexit.register(shutil.rmtree, ib_data, ignore_errors=True)
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
if result.returncode != 0:
@@ -173,6 +177,7 @@ def main():
exit_code = 0
if args.UpdateDB:
apply_args = ["infobase", "config", "apply", f"--db-path={args.InfoBasePath}", "--force"]
apply_args.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(apply_args)}")
ar = subprocess.run([v8path] + apply_args, capture_output=True, encoding="utf-8", errors="replace")
exit_code = ar.returncode
@@ -1,4 +1,4 @@
# db-update v1.2 — Update 1C database configuration
# db-update v1.3 — Update 1C database configuration
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -160,6 +160,7 @@ try {
if ($Dynamic -eq "+") { $arguments += "--dynamic=auto" }
elseif ($Dynamic -eq "-") { $arguments += "--dynamic=disable" }
if ($Extension) { $arguments += "--extension=$Extension" }
$arguments += "--data=$tempDir"
Write-Host "Running: ibcmd $($arguments -join ' ')"
$output = & $V8Path @arguments 2>&1
$exitCode = $LASTEXITCODE
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# db-update v1.2 — Update 1C database configuration
# db-update v1.3 — Update 1C database configuration
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import atexit
import glob
import json
import os
@@ -110,6 +111,9 @@ def main():
arguments.append("--dynamic=disable")
if args.Extension:
arguments.append(f"--extension={args.Extension}")
ib_data = tempfile.mkdtemp(prefix="ibcmd_data_")
atexit.register(shutil.rmtree, ib_data, ignore_errors=True)
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
if result.returncode == 0:
@@ -1,4 +1,4 @@
# epf-build v1.2 — Build external data processor or report (EPF/ERF) from XML sources
# epf-build v1.3 — Build external data processor or report (EPF/ERF) from XML sources
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -157,6 +157,7 @@ try {
# --- ibcmd branch: build EPF/ERF via config import --out ---
$srcDir = Split-Path $SourceFile -Parent
$arguments = @("infobase", "config", "import", "$srcDir", "--out=$OutputFile", "--db-path=$InfoBasePath")
$arguments += "--data=$tempDir"
Write-Host "Running: ibcmd $($arguments -join ' ')"
$output = & $V8Path @arguments 2>&1
$exitCode = $LASTEXITCODE
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# epf-build v1.2 — Build external data processor or report (EPF/ERF) from XML sources
# epf-build v1.3 — Build external data processor or report (EPF/ERF) from XML sources
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import atexit
import glob
import json
import os
@@ -125,6 +126,9 @@ def main():
# --- ibcmd branch: build EPF/ERF via config import --out ---
src_dir = os.path.dirname(os.path.abspath(args.SourceFile))
arguments = ["infobase", "config", "import", src_dir, f"--out={args.OutputFile}", f"--db-path={args.InfoBasePath}"]
ib_data = tempfile.mkdtemp(prefix="ibcmd_data_")
atexit.register(shutil.rmtree, ib_data, ignore_errors=True)
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
if result.returncode == 0:
@@ -1,4 +1,4 @@
# stub-db-create v1.1 — Create temp 1C infobase with metadata stubs for EPF/ERF build
# stub-db-create v1.2 — Create temp 1C infobase with metadata stubs for EPF/ERF build
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -1256,12 +1256,17 @@ $propsXml </Properties>$childObjLine
$stubEngine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
if ($stubEngine -eq "ibcmd") {
Write-Host "Creating infobase (ibcmd): $TempBasePath"
$ibData = Join-Path $env:TEMP "stub_data_$(Get-Random)"
New-Item -ItemType Directory -Path $ibData -Force | Out-Null
$ibArgs = @("infobase", "create", "--db-path=$TempBasePath", "--create-database")
if ($hasRefTypes) { $ibArgs += "--import=$(Join-Path $TempBasePath 'cfg')", "--apply", "--force" }
$ibArgs += "--data=$ibData"
$ibOut = & $V8Path @ibArgs 2>&1
if ($LASTEXITCODE -ne 0) {
$ibRc = $LASTEXITCODE
Remove-Item -Path $ibData -Recurse -Force -ErrorAction SilentlyContinue
if ($ibRc -ne 0) {
if ($ibOut) { Write-Host ($ibOut | Out-String) }
Write-Error "Failed to create stub infobase (code: $LASTEXITCODE)"
Write-Error "Failed to create stub infobase (code: $ibRc)"
exit 1
}
if ($hasRefTypes) { Remove-Item -Path (Join-Path $TempBasePath "cfg") -Recurse -Force -ErrorAction SilentlyContinue }
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# stub-db-create v1.1 — Create temp 1C infobase with metadata stubs for EPF/ERF build
# stub-db-create v1.2 — Create temp 1C infobase with metadata stubs for EPF/ERF build
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -1037,11 +1037,15 @@ def main():
# Stub via ibcmd (one call: create [--import --apply])
stub_engine = "ibcmd" if os.path.basename(args.V8Path).lower().startswith("ibcmd") else "1cv8"
if stub_engine == "ibcmd":
import shutil
print(f'Creating infobase (ibcmd): {temp_base}')
ib_data = tempfile.mkdtemp(prefix="stub_data_")
ib_args = [args.V8Path, 'infobase', 'create', f'--db-path={temp_base}', '--create-database']
if has_ref_types:
ib_args += [f'--import={os.path.join(temp_base, "cfg")}', '--apply', '--force']
ib_args.append(f'--data={ib_data}')
result = subprocess.run(ib_args, capture_output=True, encoding='utf-8', errors='replace')
shutil.rmtree(ib_data, ignore_errors=True)
if result.returncode != 0:
if result.stdout:
print(result.stdout)
+2 -1
View File
@@ -1,4 +1,4 @@
# epf-dump v1.2 — Dump external data processor or report (EPF/ERF) to XML sources
# epf-dump v1.3 — Dump external data processor or report (EPF/ERF) to XML sources
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -158,6 +158,7 @@ try {
if ($engine -eq "ibcmd") {
# --- ibcmd branch: dump EPF/ERF via config export --file ---
$arguments = @("infobase", "config", "export", "--file=$InputFile", "$OutputDir", "--db-path=$InfoBasePath")
$arguments += "--data=$tempDir"
Write-Host "Running: ibcmd $($arguments -join ' ')"
$output = & $V8Path @arguments 2>&1
$exitCode = $LASTEXITCODE
+5 -1
View File
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# epf-dump v1.2 — Dump external data processor or report (EPF/ERF) to XML sources
# epf-dump v1.3 — Dump external data processor or report (EPF/ERF) to XML sources
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import atexit
import glob
import json
import os
@@ -122,6 +123,9 @@ def main():
if engine == "ibcmd":
# --- ibcmd branch: dump EPF/ERF via config export --file ---
arguments = ["infobase", "config", "export", f"--file={args.InputFile}", args.OutputDir, f"--db-path={args.InfoBasePath}"]
ib_data = tempfile.mkdtemp(prefix="ibcmd_data_")
atexit.register(shutil.rmtree, ib_data, ignore_errors=True)
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
if result.returncode == 0: