Comience a usar systemd como solucionador de problemas

Nadie consideraría realmente a systemd como un solucionador de problemas, pero cuando encontré un problema en mi servidor web, mi creciente conocimiento de systemd y algunas de sus funciones me ayudaron a localizar y solucionar el problema.

El problema era que mi servidor, yorktown, que brinda servicios de nombres, DHCP, NTP, HTTPD y servicios de correo electrónico SendMail para la red de mi oficina en casa, no pudo iniciar el demonio Apache HTTPD durante el inicio normal. Tuve que iniciarlo manualmente después de darme cuenta de que no estaba funcionando. El problema ha persistido durante algún tiempo y recientemente intenté solucionarlo.

Algunos de ustedes dirán que systemd en sí mismo es la causa de este problema y, según lo que sé ahora, estoy de acuerdo con usted. Sin embargo, he tenido problemas similares con SystemV. (En el primer artículo de esta serie, analicé la controversia sobre systemd como reemplazo del antiguo programa de inicio SystemV y los scripts de inicio. Si está interesado en obtener más información sobre systemd, lea también el segundo y tercer artículo). Sin software es perfecto y ni systemd ni SystemV son una excepción, pero systemd proporciona mucha más información para la solución de problemas de la que SystemV jamás ofreció.

Índice

Determinación de problemas

El primer paso para encontrar el origen de este problema es determinar el estado del servicio httpd:

[root@yorktown ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Thu 2020-04-16 11:54:37 EDT; 15min ago
     Docs: man:httpd.service(8)
  Process: 1101 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
 Main PID: 1101 (code=exited, status=1/FAILURE)
   Status: "Reading configuration..."
      CPU: 60ms

Apr 16 11:54:35 yorktown.both.org systemd[1]: Starting The Apache HTTP Server...
Apr 16 11:54:37 yorktown.both.org httpd[1101]: (99)Cannot assign requested address: AH00072: make_sock: could not bind to address 192.168.0.52:80
Apr 16 11:54:37 yorktown.both.org httpd[1101]: no listening sockets available, shutting down
Apr 16 11:54:37 yorktown.both.org httpd[1101]: AH00015: Unable to open logs
Apr 16 11:54:37 yorktown.both.org systemd[1]: httpd.service: Main process exited, code=exited, status=1/FAILURE
Apr 16 11:54:37 yorktown.both.org systemd[1]: httpd.service: Failed with result 'exit-code'.
Apr 16 11:54:37 yorktown.both.org systemd[1]: Failed to start The Apache HTTP Server.
[root@yorktown ~]#

Esta información de estado es una de las características de systemd que encuentro mucho más útil que cualquier otra cosa que ofrezca SystemV. La cantidad de información útil presentada aquí me lleva fácilmente a una conclusión lógica que me indica la dirección correcta. Todo lo que obtuve del viejo chkconfig El comando indica si el servicio se está ejecutando o no y el ID del proceso (PID) si es así. No es muy útil.

La entrada clave en este informe de estado muestra que HTTPD no puede conectarse a la dirección IP, lo que significa que no puede aceptar solicitudes entrantes. Esto indica que la red no se está iniciando lo suficientemente rápido como para estar lista para que el servicio HTTPD se vincule a la dirección IP porque la dirección IP aún no se ha configurado. Esto no debería suceder, así que exploré los archivos de configuración de inicio del sistema de servicio de red; todo parecía estar correcto con las declaraciones "después" y "requiere". aquí está el /lib/systemd/system/httpd.servicio archivos de mi servidor:

# Modifying this file in-place is not recommended, because changes                                                                                    
# will be overwritten during package upgrades.  To customize the                                                                                      
# behaviour, run "systemctl edit httpd" to create an override unit.                                                                                  
                                                                                                                                                     
# For example, to pass additional options (such as -D definitions) to                                                                                
# the httpd binary at startup, create an override unit (as is done by                                                                                
# systemctl edit) and enter the following:                                                                                                            
                                                                                                                                                     
#       [Service]                                                                                                                                    
#       Environment=OPTIONS=-DMY_DEFINE                                                                                                              
                                                                                                                                                     
[Unit]                                                                                                                                                
Description=The Apache HTTP Server                                                                                                                    
Wants=httpd-init.service                                                                                                                              
After=network.target remote-fs.target nss-lookup.target httpd-init.service                                                                            
Documentation=man:httpd.service(8)                                                                                                                    
                                                                                                                                                     
[Service]                                                                                                                                            
Type=notify                                                                                                                                          
Environment=LANG=C                                                                                                                                    
                                                                                                                                                     
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND                                                                                                      
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful                                                                                                      
# Send SIGWINCH for graceful stop                                                                                                                    
KillSignal=SIGWINCH                                                                                                                                  
KillMode=mixed                                                                                                                                        
PrivateTmp=true                                                                                                                                      
                                                                                                                                                     
[Install]                                                                                                                                            
WantedBy=multi-user.target

El httpd.servicio unit especifica explícitamente que debe cargarse después de la red.objetivo y el httpd-init.servicio (entre otros). Traté de encontrar todos estos servicios usando el systemctl lista-unidades y búsquelos en el flujo de datos resultante. Todos estaban allí y deberían haberse asegurado de que el servicio httpd no estuviera cargado antes de configurar la dirección IP de la red.

Primera solución

Una pequeña investigación en Internet confirmó que otros habían encontrado problemas similares con httpd y otros servicios. Esto parece estar sucediendo porque uno de los servicios solicitados le dice a systemd que terminó de iniciarse, pero en realidad genera un proceso secundario que no ha terminado. Después de un poco más de investigación, se me ocurrió una elusión.

No podía entender por qué la dirección IP tardó tanto en asignarse a la NIC. Por lo tanto, pensé que si podía retrasar el inicio del servicio HTTPD durante un período de tiempo razonable, la dirección IP estaría asignada en ese momento.

Afortunadamente, el /lib/systemd/system/httpd.servicio el archivo anterior proporciona alguna orientación. Incluso si dice no modificarlo, indica cómo proceder: Utilice el comando systemctl modifica httpd, que crea automáticamente un nuevo archivo (/etc/systemd/system/httpd.service.d/override.conf) y abre la GNU Nano editor. (Si no está familiarizado con Nano, asegúrese de consultar los consejos en la parte inferior de la interfaz de Nano).

Agregue el siguiente texto al nuevo archivo y guárdelo:

[root@yorktown ~]# cd /etc/systemd/system/httpd.service.d/
[root@yorktown httpd.service.d]# ll
total 4
-rw-r--r-- 1 root root 243 Apr 16 11:43 override.conf
[root@yorktown httpd.service.d]# cat override.conf
# Trying to delay the startup of httpd so that the network is
# fully up and running so that httpd can bind to the correct
# IP address
#
# By David Both, 2020-04-16

[Service]
ExecStartPre=/bin/sleep 30

El [Service] la sección de este archivo de reemplazo contiene una sola línea que retrasa el inicio del servicio HTTPD durante 30 segundos. El siguiente comando de estado muestra el estado del servicio durante el tiempo de espera:

[root@yorktown ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/httpd.service.d
           └─override.conf
           /usr/lib/systemd/system/httpd.service.d
           └─php-fpm.conf
   Active: activating (start-pre) since Thu 2020-04-16 12:14:29 EDT; 28s ago
     Docs: man:httpd.service(8)
Cntrl PID: 1102 (sleep)
    Tasks: 1 (limit: 38363)
   Memory: 260.0K
      CPU: 2ms
   CGroup: /system.slice/httpd.service
           └─1102 /bin/sleep 30

Apr 16 12:14:29 yorktown.both.org systemd[1]: Starting The Apache HTTP Server...
Apr 16 12:15:01 yorktown.both.org systemd[1]: Started The Apache HTTP Server.
[root@yorktown ~]#

Y este comando muestra el estado del servicio HTTPD después de que expire el retraso de 30 segundos. El servicio está funcionando correctamente:

[root@yorktown ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/httpd.service.d
           └─override.conf
           /usr/lib/systemd/system/httpd.service.d
           └─php-fpm.conf
   Active: active (running) since Thu 2020-04-16 12:15:01 EDT; 1min 18s ago
     Docs: man:httpd.service(8)
  Process: 1102 ExecStartPre=/bin/sleep 30 (code=exited, status=0/SUCCESS)
 Main PID: 1567 (httpd)
   Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec:   0 B/sec"
    Tasks: 213 (limit: 38363)
   Memory: 21.8M
      CPU: 82ms
   CGroup: /system.slice/httpd.service
           ├─1567 /usr/sbin/httpd -DFOREGROUND
           ├─1569 /usr/sbin/httpd -DFOREGROUND
           ├─1570 /usr/sbin/httpd -DFOREGROUND
           ├─1571 /usr/sbin/httpd -DFOREGROUND
           └─1572 /usr/sbin/httpd -DFOREGROUND

Apr 16 12:14:29 yorktown.both.org systemd[1]: Starting The Apache HTTP Server...
Apr 16 12:15:01 yorktown.both.org systemd[1]: Started The Apache HTTP Server.

Podría haber experimentado para ver si incluso un retraso más corto funcionaría, pero mi sistema no es tan crítico, así que decidí no hacerlo. Funciona de manera confiable tal como está, así que estoy feliz.

Como recopilé toda esta información, la informé a Red Hat Bugzilla como un error 1825554. Creo que es mucho más productivo reportar errores que quejarse de ellos.

La mejor solucion

Un par de días después de informar esto como un error, recibí una respuesta que decía que systemd es solo el administrador y si httpd debe ordenarse después de cumplir algunos requisitos, debe expresarse en el archivo de la unidad. La respuesta me apuntó a la httpd.servicio página de manual Ojalá lo hubiera encontrado antes porque es una solución mejor que la que he encontrado. Esta solución está dirigida explícitamente a la unidad de destino de requisitos previos en lugar de un retraso un tanto aleatorio.

Desde httpd.servicio página man:

Iniciar el servicio al inicio

Las unidades httpd.service y httpd.socket son Discapacitado por defecto. Para iniciar el servicio httpd al inicio, ejecute: systemctl habilita httpd.service. De forma predeterminada, el demonio httpd aceptará conexiones en el puerto 80 (y, si mod_ssl está instalado, conexiones TLS en el puerto 443) para cualquier dirección IPv4 o IPv6 configurada.

Si httpd está configurado para depender de una dirección IP específica (por ejemplo, con una directiva "Escuchar") que solo puede estar disponible durante el inicio, o si httpd depende de otros servicios (como un demonio de base de datos), el servicio deber configurarse para garantizar el orden de inicio correcto.

Por ejemplo, para garantizar que httpd se ejecute solo después de que se hayan configurado todas las interfaces de red configuradas, cree un archivo desplegable (como se describe anteriormente) con la siguiente sección:

[Unit]
Después = red-online.objetivo
Deseo = red-online.objetivo

Sigo pensando que esto es un error porque es bastante común, al menos en mi experiencia, usar un Escucha directiva en httpd.conf archivo de configuración. siempre he usado Escucha directivas, incluso en hosts con una sola dirección IP, y se requiere claramente en hosts con múltiples tarjetas de interfaz de red (NIC) y direcciones de protocolo de Internet (IP). Al agregar las líneas anteriores a la /usr/lib/systemd/system/httpd.servicio archivo predeterminado no causaría problemas para las configuraciones que no utilizan un Escucha directiva y evitaría este problema a quienes lo hacen.

Mientras tanto, usaré la solución sugerida.

Próximos pasos

Este artículo describe un problema que encontré al iniciar el servicio Apache HTTPD en mi servidor. Lo guía a través de los pasos de determinación de problemas que he tomado y muestra cómo he usado systemd para ayudar. También cubrí la elusión que implementé usando systemd y la mejor solución, seguida de mi informe de errores.

Como dije al principio, lo más probable es que esto sea el resultado de un problema con systemd, especialmente la configuración para iniciar httpd. Sin embargo, systemd me ha dado las herramientas para identificar la fuente probable del problema y para formular e implementar una elusión. Ninguna de las soluciones realmente resuelve el problema a mi satisfacción. Por ahora, la causa raíz del problema aún existe y debe abordarse. Si es simplemente para agregar las líneas recomendadas a /usr/lib/systemd/system/httpd.servicio archivo, que funcionaría para mí.

Una de las cosas que descubrí durante este proceso es que necesito saber más sobre cómo definir las secuencias en las que comienzan las cosas. Lo exploraré en mi próximo artículo, el quinto de esta serie.

Recursos

Hay mucha información sobre systemd disponible en Internet, pero mucha de ella es concisa, obtusa o incluso engañosa. Además de los recursos mencionados en este artículo, las siguientes páginas web ofrecen información más detallada y confiable sobre cómo iniciar systemd.

  • El proyecto Fedora tiene una buena y práctica. guía arreglar. Tiene prácticamente todo lo que necesita saber para configurar, administrar y mantener un ordenador Fedora usando systemd.
  • El proyecto Fedora también tiene una ventaja hoja de trucos que cruza los comandos SystemV antiguos con comandos systemd comparables.
  • Para obtener información técnica detallada sobre systemd y los motivos de su creación, consulte Freedesktop.org'S descripción del sistema.
  • Linux.com"More systemd fun" ofrece sistemas más avanzados información y sugerencias.

También hay una serie de artículos profundamente técnicos para administradores de sistemas Linux escritos por Lennart Poettering, diseñador y desarrollador principal de systemd. Estos artículos fueron escritos entre abril de 2010 y septiembre de 2011, pero son tan relevantes ahora como lo fueron entonces. Gran parte de todo lo que se ha escrito sobre systemd y su ecosistema se basa en estos documentos.

Artículos de interés

Subir