mirror of
https://github.com/certbot/certbot.git
synced 2026-01-13 10:22:20 +03:00
74 lines
2.9 KiB
Python
74 lines
2.9 KiB
Python
"""Plugin utilities."""
|
|
import logging
|
|
import socket
|
|
|
|
import psutil
|
|
import zope.component
|
|
|
|
from letsencrypt import interfaces
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def already_listening(port, renewer=False):
|
|
"""Check if a process is already listening on the port.
|
|
|
|
If so, also tell the user via a display notification.
|
|
|
|
.. warning::
|
|
On some operating systems, this function can only usefully be
|
|
run as root.
|
|
|
|
:param int port: The TCP port in question.
|
|
:returns: True or False.
|
|
|
|
"""
|
|
try:
|
|
net_connections = psutil.net_connections()
|
|
except psutil.AccessDenied as error:
|
|
logger.info("Access denied when trying to list network "
|
|
"connections: %s. Are you root?", error)
|
|
# this function is just a pre-check that often causes false
|
|
# positives and problems in testing (c.f. #680 on Mac, #255
|
|
# generally); we will fail later in bind() anyway
|
|
return False
|
|
|
|
listeners = [conn.pid for conn in net_connections
|
|
if conn.status == 'LISTEN' and
|
|
conn.type == socket.SOCK_STREAM and
|
|
conn.laddr[1] == port]
|
|
try:
|
|
if listeners and listeners[0] is not None:
|
|
# conn.pid may be None if the current process doesn't have
|
|
# permission to identify the listening process! Additionally,
|
|
# listeners may have more than one element if separate
|
|
# sockets have bound the same port on separate interfaces.
|
|
# We currently only have UI to notify the user about one
|
|
# of them at a time.
|
|
pid = listeners[0]
|
|
name = psutil.Process(pid).name()
|
|
display = zope.component.getUtility(interfaces.IDisplay)
|
|
extra = ""
|
|
if renewer:
|
|
extra = (
|
|
" For automated renewal, you may want to use a script that stops"
|
|
" and starts your webserver. You can find an example at"
|
|
" https://letsencrypt.org/howitworks/#writing-your-own-renewal-script"
|
|
". Alternatively you can use the webroot plugin to renew without"
|
|
" needing to stop and start your webserver.")
|
|
display.notification(
|
|
"The program {0} (process ID {1}) is already listening "
|
|
"on TCP port {2}. This will prevent us from binding to "
|
|
"that port. Please stop the {0} program temporarily "
|
|
"and then try again.{3}".format(name, pid, port, extra),
|
|
height=13)
|
|
return True
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
# Perhaps the result of a race where the process could have
|
|
# exited or relinquished the port (NoSuchProcess), or the result
|
|
# of an OS policy where we're not allowed to look up the process
|
|
# name (AccessDenied).
|
|
pass
|
|
return False
|