Добавлены команды для очистки lock-файлов Certbot и обработка зависших процессов. Улучшено логирование и добавлены рекомендации по устранению проблем с Certbot.
This commit is contained in:
37
README.md
37
README.md
@@ -150,6 +150,9 @@ letsencrypt-regru --help
|
|||||||
letsencrypt-regru --obtain -v
|
letsencrypt-regru --obtain -v
|
||||||
letsencrypt-regru --check -v
|
letsencrypt-regru --check -v
|
||||||
letsencrypt-regru --staging -v
|
letsencrypt-regru --staging -v
|
||||||
|
|
||||||
|
# Очистить lock-файлы Certbot (если процесс завис)
|
||||||
|
letsencrypt-regru --force-cleanup
|
||||||
```
|
```
|
||||||
|
|
||||||
#### ⚙️ Служебные команды (внутреннее использование)
|
#### ⚙️ Служебные команды (внутреннее использование)
|
||||||
@@ -1520,6 +1523,40 @@ nslookup -type=TXT _acme-challenge.example.com
|
|||||||
dig TXT _acme-challenge.example.com
|
dig TXT _acme-challenge.example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Проблема: "Another instance of Certbot is already running"
|
||||||
|
|
||||||
|
**Причина:** Предыдущий процесс Certbot не завершился корректно или остались lock-файлы.
|
||||||
|
|
||||||
|
**Решение:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Вариант 1: Принудительная очистка lock-файлов (рекомендуется)
|
||||||
|
letsencrypt-regru --force-cleanup
|
||||||
|
|
||||||
|
# Вариант 2: Ручная очистка
|
||||||
|
# Проверьте запущенные процессы certbot
|
||||||
|
ps aux | grep certbot
|
||||||
|
|
||||||
|
# Остановите зависшие процессы
|
||||||
|
sudo pkill certbot
|
||||||
|
# Или принудительно
|
||||||
|
sudo pkill -9 certbot
|
||||||
|
|
||||||
|
# Удалите lock-файлы
|
||||||
|
sudo rm -f /var/lib/letsencrypt/.certbot.lock
|
||||||
|
sudo rm -f /etc/letsencrypt/.certbot.lock
|
||||||
|
|
||||||
|
# Попробуйте снова
|
||||||
|
letsencrypt-regru --obtain
|
||||||
|
```
|
||||||
|
|
||||||
|
**Вариант 3: Подождать автоматически**
|
||||||
|
Скрипт автоматически:
|
||||||
|
1. Обнаруживает запущенные процессы Certbot
|
||||||
|
2. Ждёт их завершения (60 секунд)
|
||||||
|
3. Пытается очистить lock-файлы
|
||||||
|
4. Выдаёт рекомендации по решению проблемы
|
||||||
|
|
||||||
### Проблема: Certbot не установлен
|
### Проблема: Certbot не установлен
|
||||||
|
|
||||||
**Решение:**
|
**Решение:**
|
||||||
|
|||||||
@@ -930,6 +930,94 @@ class LetsEncryptManager:
|
|||||||
self.logger.error("Certbot не установлен!")
|
self.logger.error("Certbot не установлен!")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def check_certbot_running(self) -> bool:
|
||||||
|
"""
|
||||||
|
Проверка наличия запущенных процессов certbot
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True если процесс certbot запущен
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Проверяем через ps
|
||||||
|
result = subprocess.run(
|
||||||
|
["ps", "aux"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ищем процессы certbot (исключая текущий grep)
|
||||||
|
certbot_processes = [
|
||||||
|
line for line in result.stdout.split('\n')
|
||||||
|
if 'certbot' in line.lower() and 'grep' not in line.lower()
|
||||||
|
and str(os.getpid()) not in line # Исключаем текущий процесс
|
||||||
|
]
|
||||||
|
|
||||||
|
if certbot_processes:
|
||||||
|
self.logger.warning("Обнаружены запущенные процессы Certbot:")
|
||||||
|
for proc in certbot_processes:
|
||||||
|
self.logger.warning(f" {proc}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.debug(f"Не удалось проверить запущенные процессы: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def cleanup_certbot_locks(self) -> bool:
|
||||||
|
"""
|
||||||
|
Очистка lock-файлов certbot
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True если lock-файлы были удалены или их не было
|
||||||
|
"""
|
||||||
|
lock_files = [
|
||||||
|
"/var/lib/letsencrypt/.certbot.lock",
|
||||||
|
"/etc/letsencrypt/.certbot.lock",
|
||||||
|
]
|
||||||
|
|
||||||
|
removed = False
|
||||||
|
for lock_file in lock_files:
|
||||||
|
if os.path.exists(lock_file):
|
||||||
|
try:
|
||||||
|
os.remove(lock_file)
|
||||||
|
self.logger.info(f"Удалён lock-файл: {lock_file}")
|
||||||
|
removed = True
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning(f"Не удалось удалить lock-файл {lock_file}: {e}")
|
||||||
|
|
||||||
|
if not removed:
|
||||||
|
self.logger.debug("Lock-файлы certbot не найдены")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def wait_for_certbot(self, timeout: int = 300) -> bool:
|
||||||
|
"""
|
||||||
|
Ожидание завершения работы других процессов certbot
|
||||||
|
|
||||||
|
Args:
|
||||||
|
timeout: Максимальное время ожидания в секундах
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True если certbot больше не запущен
|
||||||
|
"""
|
||||||
|
self.logger.info("Ожидание завершения других процессов Certbot...")
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
check_interval = 5 # Проверяем каждые 5 секунд
|
||||||
|
|
||||||
|
while time.time() - start_time < timeout:
|
||||||
|
if not self.check_certbot_running():
|
||||||
|
self.logger.info("Другие процессы Certbot завершены")
|
||||||
|
return True
|
||||||
|
|
||||||
|
elapsed = int(time.time() - start_time)
|
||||||
|
self.logger.info(f"Ожидание... ({elapsed}/{timeout} секунд)")
|
||||||
|
time.sleep(check_interval)
|
||||||
|
|
||||||
|
self.logger.error(f"Превышено время ожидания ({timeout} секунд)")
|
||||||
|
return False
|
||||||
|
|
||||||
def check_certificate_expiry(self) -> Optional[int]:
|
def check_certificate_expiry(self) -> Optional[int]:
|
||||||
"""
|
"""
|
||||||
Проверка срока действия сертификата
|
Проверка срока действия сертификата
|
||||||
@@ -1115,6 +1203,26 @@ class LetsEncryptManager:
|
|||||||
else:
|
else:
|
||||||
self.logger.info("=== Запрос нового SSL сертификата ===")
|
self.logger.info("=== Запрос нового SSL сертификата ===")
|
||||||
|
|
||||||
|
# Проверяем, не запущен ли уже certbot
|
||||||
|
if self.check_certbot_running():
|
||||||
|
self.logger.warning("Обнаружен запущенный процесс Certbot")
|
||||||
|
self.logger.info("Варианты решения:")
|
||||||
|
self.logger.info(" 1. Дождитесь завершения текущего процесса")
|
||||||
|
self.logger.info(" 2. Остановите процесс вручную: sudo pkill certbot")
|
||||||
|
self.logger.info(" 3. Используйте --force-cleanup для очистки lock-файлов")
|
||||||
|
|
||||||
|
# Пытаемся подождать
|
||||||
|
if not self.wait_for_certbot(timeout=60):
|
||||||
|
self.logger.error("Не удалось дождаться завершения Certbot")
|
||||||
|
self.logger.info("Попытка очистки lock-файлов...")
|
||||||
|
self.cleanup_certbot_locks()
|
||||||
|
|
||||||
|
# Проверяем снова
|
||||||
|
if self.check_certbot_running():
|
||||||
|
self.logger.error("Certbot всё ещё запущен. Требуется ручное вмешательство.")
|
||||||
|
self.logger.error("Выполните: sudo pkill -9 certbot")
|
||||||
|
return False
|
||||||
|
|
||||||
# Формируем список доменов
|
# Формируем список доменов
|
||||||
domains = [self.domain]
|
domains = [self.domain]
|
||||||
if self.config.get("wildcard", False):
|
if self.config.get("wildcard", False):
|
||||||
@@ -1396,33 +1504,34 @@ def main():
|
|||||||
════════════════════════════════════════════════════════════════════════════════
|
════════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
Основные команды:
|
Основные команды:
|
||||||
%(prog)s -c config.json --check Проверить срок действия
|
letsencrypt-regru --check Проверить срок действия
|
||||||
%(prog)s -c config.json --obtain Получить production сертификат
|
letsencrypt-regru --obtain Получить production сертификат
|
||||||
%(prog)s -c config.json --renew Обновить сертификат
|
letsencrypt-regru --renew Обновить сертификат
|
||||||
%(prog)s -c config.json --auto Авто-режим (для cron/systemd)
|
letsencrypt-regru --auto Авто-режим (для cron/systemd)
|
||||||
|
|
||||||
Команды тестирования:
|
Команды тестирования:
|
||||||
%(prog)s -c config.json --staging Тестовый Let's Encrypt (БЕЗ лимитов!)
|
letsencrypt-regru --staging Тестовый Let's Encrypt (БЕЗ лимитов!)
|
||||||
%(prog)s -c config.json --test-cert Самоподписанный (локально)
|
letsencrypt-regru --test-cert Самоподписанный (локально)
|
||||||
%(prog)s -c config.json --test-api Проверить API reg.ru
|
letsencrypt-regru --test-api Проверить API reg.ru
|
||||||
%(prog)s -c config.json --test-dns Проверить DNS записи
|
letsencrypt-regru --test-dns Проверить DNS записи
|
||||||
|
|
||||||
Отладка:
|
Отладка:
|
||||||
%(prog)s -c config.json --obtain -v Подробный вывод
|
letsencrypt-regru --obtain -v Подробный вывод
|
||||||
|
letsencrypt-regru --force-cleanup Очистить lock-файлы Certbot
|
||||||
|
|
||||||
════════════════════════════════════════════════════════════════════════════════
|
════════════════════════════════════════════════════════════════════════════════
|
||||||
РЕКОМЕНДУЕМЫЙ WORKFLOW
|
РЕКОМЕНДУЕМЫЙ WORKFLOW
|
||||||
════════════════════════════════════════════════════════════════════════════════
|
════════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
1. Проверка настройки:
|
1. Проверка настройки:
|
||||||
%(prog)s -c config.json --test-api ✓ API доступен?
|
letsencrypt-regru --test-api ✓ API доступен?
|
||||||
%(prog)s -c config.json --test-dns ✓ DNS работает?
|
letsencrypt-regru --test-dns ✓ DNS работает?
|
||||||
|
|
||||||
2. Тестирование (неограниченно):
|
2. Тестирование (неограниченно):
|
||||||
%(prog)s -c config.json --staging ✓ Полный процесс SSL
|
letsencrypt-regru --staging ✓ Полный процесс SSL
|
||||||
|
|
||||||
3. Production:
|
3. Production:
|
||||||
%(prog)s -c config.json --obtain ✓ Боевой сертификат
|
letsencrypt-regru --obtain ✓ Боевой сертификат
|
||||||
|
|
||||||
════════════════════════════════════════════════════════════════════════════════
|
════════════════════════════════════════════════════════════════════════════════
|
||||||
СРАВНЕНИЕ РЕЖИМОВ ТЕСТИРОВАНИЯ
|
СРАВНЕНИЕ РЕЖИМОВ ТЕСТИРОВАНИЯ
|
||||||
@@ -1518,6 +1627,11 @@ def main():
|
|||||||
help="Подробный вывод для диагностики",
|
help="Подробный вывод для диагностики",
|
||||||
action="store_true"
|
action="store_true"
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--force-cleanup",
|
||||||
|
help="Принудительная очистка lock-файлов Certbot (если процесс завис)",
|
||||||
|
action="store_true"
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@@ -1526,6 +1640,66 @@ def main():
|
|||||||
create_sample_config(args.create_config)
|
create_sample_config(args.create_config)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
# Принудительная очистка lock-файлов
|
||||||
|
if args.force_cleanup:
|
||||||
|
print("=" * 80)
|
||||||
|
print("ПРИНУДИТЕЛЬНАЯ ОЧИСТКА LOCK-ФАЙЛОВ CERTBOT")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
lock_files = [
|
||||||
|
"/var/lib/letsencrypt/.certbot.lock",
|
||||||
|
"/etc/letsencrypt/.certbot.lock",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Проверяем запущенные процессы
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
["ps", "aux"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True
|
||||||
|
)
|
||||||
|
certbot_processes = [
|
||||||
|
line for line in result.stdout.split('\n')
|
||||||
|
if 'certbot' in line.lower() and 'grep' not in line.lower()
|
||||||
|
]
|
||||||
|
|
||||||
|
if certbot_processes:
|
||||||
|
print("\n⚠️ ПРЕДУПРЕЖДЕНИЕ: Обнаружены запущенные процессы Certbot:")
|
||||||
|
for proc in certbot_processes:
|
||||||
|
print(f" {proc}")
|
||||||
|
print("\nРекомендуется сначала остановить процессы:")
|
||||||
|
print(" sudo pkill certbot")
|
||||||
|
print("\nПродолжить очистку lock-файлов? (y/N): ", end='')
|
||||||
|
|
||||||
|
response = input().strip().lower()
|
||||||
|
if response != 'y':
|
||||||
|
print("Отменено.")
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Не удалось проверить процессы: {e}")
|
||||||
|
|
||||||
|
# Удаляем lock-файлы
|
||||||
|
removed_count = 0
|
||||||
|
for lock_file in lock_files:
|
||||||
|
if os.path.exists(lock_file):
|
||||||
|
try:
|
||||||
|
os.remove(lock_file)
|
||||||
|
print(f"✅ Удалён: {lock_file}")
|
||||||
|
removed_count += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Ошибка при удалении {lock_file}: {e}")
|
||||||
|
else:
|
||||||
|
print(f"ℹ️ Не найден: {lock_file}")
|
||||||
|
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
if removed_count > 0:
|
||||||
|
print(f"✅ Удалено lock-файлов: {removed_count}")
|
||||||
|
print("Теперь можно попробовать запустить Certbot снова.")
|
||||||
|
else:
|
||||||
|
print("ℹ️ Lock-файлы не найдены.")
|
||||||
|
print("=" * 80)
|
||||||
|
return 0
|
||||||
|
|
||||||
# Загрузка конфигурации
|
# Загрузка конфигурации
|
||||||
config = load_config(args.config)
|
config = load_config(args.config)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user