Files
cc-1c-skills/.github/skills/web-unpublish/scripts/web-unpublish.py
T
2026-05-17 11:22:33 +00:00

163 lines
6.3 KiB
Python

#!/usr/bin/env python3
# web-unpublish v1.0 — Remove 1C web publication
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
"""
Удаление веб-публикации 1С из Apache.
Удаляет маркерный блок из httpd.conf и каталог публикации.
Если Apache запущен — перезапускает для применения.
С флагом -All удаляет все публикации и останавливает Apache.
"""
import argparse
import os
import re
import shutil
import subprocess
import sys
import time
import psutil
def get_our_httpd(httpd_exe_norm):
"""Filter httpd processes by our ApachePath."""
result = []
if not httpd_exe_norm:
return result
for p in psutil.process_iter(['pid', 'name', 'exe']):
try:
if p.info['name'] and 'httpd' in p.info['name'].lower():
if p.info['exe'] and os.path.normcase(os.path.normpath(p.info['exe'])) == httpd_exe_norm:
result.append(p)
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
return result
def main():
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description='Remove 1C web publication', allow_abbrev=False)
parser.add_argument('-AppName', type=str, default='', help='Publication name')
parser.add_argument('-ApachePath', type=str, default='', help='Apache root (default: tools\\apache24)')
parser.add_argument('-All', action='store_true', help='Remove all publications')
args = parser.parse_args()
# --- Resolve ApachePath ---
apache_path = args.ApachePath
if not apache_path:
script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(script_dir))))
apache_path = os.path.join(project_root, 'tools', 'apache24')
# --- Validate params ---
if not args.All and not args.AppName:
print('Error: укажите -AppName или -All', file=sys.stderr)
sys.exit(1)
# --- Read httpd.conf ---
conf_file = os.path.join(apache_path, 'conf', 'httpd.conf')
if not os.path.exists(conf_file):
print(f'Error: httpd.conf не найден: {conf_file}', file=sys.stderr)
sys.exit(1)
with open(conf_file, 'r', encoding='utf-8-sig') as f:
conf_content = f.read()
# --- Helper: our httpd process ---
httpd_exe = os.path.join(apache_path, 'bin', 'httpd.exe')
if os.path.exists(httpd_exe):
httpd_exe_norm = os.path.normcase(os.path.normpath(os.path.realpath(httpd_exe)))
else:
httpd_exe_norm = os.path.normcase(os.path.normpath(httpd_exe))
# --- Collect app names to remove ---
if args.All:
pub_pattern = r'# --- 1C Publication: (.+?) ---'
pub_matches = re.findall(pub_pattern, conf_content)
if not pub_matches:
print('Нет публикаций для удаления')
sys.exit(0)
app_names = pub_matches
print(f'Удаление всех публикаций: {", ".join(app_names)}')
else:
app_names = [args.AppName]
# --- Remove marker blocks ---
for name in app_names:
pub_marker_start = f'# --- 1C Publication: {name} ---'
pub_marker_end = f'# --- End: {name} ---'
if re.search(re.escape(pub_marker_start), conf_content):
pattern = r'\r?\n?' + re.escape(pub_marker_start) + r'[\s\S]*?' + re.escape(pub_marker_end) + r'\r?\n?'
conf_content = re.sub(pattern, '\n', conf_content)
print(f"httpd.conf: блок публикации '{name}' удалён")
else:
print(f"Публикация '{name}' не найдена в httpd.conf")
# --- Check if any publications remain; if not, remove global block ---
remaining_pubs = re.findall(r'# --- 1C Publication: .+? ---', conf_content)
if not remaining_pubs:
global_marker_start = '# --- 1C: global ---'
global_marker_end = '# --- End: global ---'
if re.search(re.escape(global_marker_start), conf_content):
global_pattern = r'\r?\n?' + re.escape(global_marker_start) + r'[\s\S]*?' + re.escape(global_marker_end) + r'\r?\n?'
conf_content = re.sub(global_pattern, '\n', conf_content)
print('httpd.conf: глобальный блок 1C удалён (нет публикаций)')
with open(conf_file, 'w', encoding='utf-8') as f:
f.write(conf_content)
# --- Remove publish directories ---
for name in app_names:
publish_dir = os.path.join(apache_path, 'publish', name)
if os.path.exists(publish_dir):
shutil.rmtree(publish_dir, ignore_errors=True)
print(f'Каталог удалён: {publish_dir}')
else:
print(f'Каталог не найден: {publish_dir}')
# --- Restart/Stop Apache if running (only our instance) ---
httpd_proc = get_our_httpd(httpd_exe_norm)
if httpd_proc:
if remaining_pubs:
print('Перезапуск Apache...')
for p in httpd_proc:
try:
p.kill()
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
time.sleep(1)
subprocess.Popen(
[httpd_exe],
cwd=apache_path,
creationflags=subprocess.CREATE_NO_WINDOW,
)
time.sleep(2)
check = get_our_httpd(httpd_exe_norm)
if check:
print('Apache перезапущен')
else:
print('Error: Apache не удалось перезапустить', file=sys.stderr)
sys.exit(1)
else:
print('Публикаций не осталось — останавливаю Apache...')
for p in httpd_proc:
try:
p.kill()
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
time.sleep(1)
print('Apache остановлен')
print('')
if args.All:
print(f'Все публикации удалены ({len(app_names)} шт.)')
else:
print(f"Публикация '{args.AppName}' удалена")
if __name__ == '__main__':
main()