A veces hay que aplicar alguna configuración de emergencia para resolver un problema urgente, pero la misma puede afectar a los usuarios que están conectados actualmente a un servidor. Existe una variedad de causas diferentes que pueden perjudicar a los usuarios actuales de un servicio. Por ejemplo puede hace falta reiniciar Apache, o directamente detenerlo porque es necesario reiniciar un servidor de bases de datos. También podría ser necesario reiniciar directamente el sistema operativo por un problema de hardware (se llenó un disco y hay que ampliar su capacidad, o agregar más memoria RAM). Sea como sea, los Sysadmins en general buscamos un horario fuera de oficina para este tipo de "actividades", pero en caso de emergencias, no queda otra alternativa que hacerlo en horarios de oficina. En este caso puede ser útil saber si hay usuarios actualmente conectados al servidor, para afectar a la menor cantidad de gente posible.



En este caso, supongamos que se trata de un servidor Web Apache. Por alguna razón hay que ejecutar una tarea que requiere el reinicio o la baja temporal del servidor.

Para conocer cuáles son todas las conexiones de red relacionadas al servicio apache, es posible listar utilizando la herramienta netstat todas las conexiones TCP (excepto aquellas locales) filtrando luego con grep aquellas relacionadas al proceso "apache2" o a los puertos 80 (HTTP) y 443 (HTTPS):

netstat -tpn | grep -v "127.0.0" | grep "apache\|443\|80"

Veamos un ejemplo:

root@debian7:~# netstat -tpn | grep -v "127.0.0" | grep "apache\|443\|80"
tcp        0      0 192.168.57.29:443       192.168.105.221:2827     ESTABLISHED 6484/apache2
tcp        0      0 192.168.57.29:443       192.168.105.221:2830     ESTABLISHED 6444/apache2
tcp        0      0 192.168.57.29:443       192.168.105.102:51882    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4225     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4221     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2818     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4233     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.102:51881    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2831     ESTABLISHED 6440/apache2
tcp        0      0 192.168.57.29:443       192.168.105.102:51888    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2815     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2814     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.116:52167    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4231     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.102:51885    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4263     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2823     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.102:51883    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4234     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4247     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2820     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2828     ESTABLISHED 6489/apache2
tcp        0      0 192.168.57.29:443       192.168.105.125:2738     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2826     ESTABLISHED 6488/apache2
tcp        0      0 192.168.57.29:443       192.168.105.129:4220     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.125:2736     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.102:51873    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4248     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.125:2739     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4238     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4264     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2829     ESTABLISHED 6471/apache2
tcp        0      0 192.168.57.29:443       192.168.105.116:52166    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4218     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4261     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4235     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4243     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2822     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4232     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.102:51886    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4259     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4260     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4228     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2821     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4224     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4222     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.116:52164    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.102:51894    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4244     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4245     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4246     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2817     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.125:2740     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4255     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.125:2735     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.116:52165    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.125:2737     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2816     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4262     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.129:4223     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2812     TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.116:52168    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.116:52163    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.102:51884    TIME_WAIT   -
tcp        0      0 192.168.57.29:443       192.168.105.221:2813     TIME_WAIT   -

Se observa que existen algunas conexiones establecidas (en estado "ESTABLISHED") y otras recientemente cerradas (en estado "TIME_WAIT").

El estado "TIME_WAIT" significa que la conexión ha sido cerrada, pero el socket aún permanece en espera para manejar posibles paquetes que aún estén (dando vueltas) en la red. Es posible filtrar estas conexiones para que el comando sólo muestre las establecidas:

root@debian7:~# netstat -tupn | grep -v "127.0.0" | grep "apache\|443\|80" | grep "ESTABL"
tcp        0      0 192.168.57.29:443       192.168.105.114:52071     ESTABLISHED 8359/apache2
tcp        0      0 192.168.57.29:443       192.168.105.114:52073     ESTABLISHED 8315/apache2
tcp        0      0 192.168.57.29:443       192.168.105.114:52072     ESTABLISHED 8298/apache2
tcp        0      0 192.168.57.29:443       192.168.105.114:52074     ESTABLISHED 8340/apache2
tcp        0      0 192.168.57.29:443       192.168.105.114:52070     ESTABLISHED 8334/apache2
tcp        0      0 192.168.57.29:443       192.168.105.114:52069     ESTABLISHED 8353/apache2

¿Y qué hay de las sesiones PHP?

Ahora bien, este método es muy común y conocido por todos, aunque existe otra forma de monitorear la actividad de un servidor Web, siempre que corra una aplicación PHP. Esta consiste en ver las fechas de modificación de los archivos de sesiones de PHP, por defecto almacenados en el directorio /var/lib/php5. Estos archivos almacenan los datos de cada sesión y su tiempo de vida por defecto puede ser obtenido consultando a la variable session.gc_maxlifetime, dentro del archivo php.ini. Cada vez que una aplicación PHP ejecuta una llamada a session_start() se crea un archivo correspondiente en dicho directorio.

Por ejemplo, el servidor en cuestión posee las siguiente sesiones PHP abiertas:

root@debian7:~# ls -rlt /var/lib/php5/ && date
total 16948
-rw------- 1 www-data www-data     3569 Dec 28 13:18 sess_6ihle7mveadphq3ur8bu6eiq8nvq31fd
-rw------- 1 www-data www-data     3569 Dec 28 13:24 sess_fd9v10ti77msb4n0la0du2ntav50hpr7
-rw------- 1 www-data www-data     3569 Dec 28 13:31 sess_vt9alv5hp5vvrq30cr8logo0dlu9d5g9
-rw------- 1 www-data www-data    28222 Dec 28 13:45 sess_moa8m54ik06b0q0c62drt0nptfgu6c35
-rw------- 1 www-data www-data    18021 Dec 28 13:59 sess_rm3set0u2ast757oalfch6gge5m2md7e
-rw------- 1 www-data www-data     3569 Dec 28 14:14 sess_f900h3uldn82eeqmn4834v3jje73sl33
-rw------- 1 www-data www-data    20802 Dec 28 14:20 sess_aq6k06bcq4mfcgol9cn53t1ighroi6lp
-rw------- 1 www-data www-data     3569 Dec 28 14:22 sess_k5nb6k7j8i3bhlsqgcp28kh00gmbv0e4
-rw------- 1 www-data www-data     3569 Dec 28 14:24 sess_fdulgi93fva8kd7sbps21orsstirpvli
-rw------- 1 www-data www-data    16584 Dec 28 14:25 sess_r44qh20qrk1as90ad2bittmkt80hku2m
-rw------- 1 www-data www-data    30787 Dec 28 14:26 sess_8rdhfsjs5t78qua4dqidguoc8aeaokb0
-rw------- 1 www-data www-data     4037 Dec 28 14:35 sess_879s40oi7ek6bl319rtuolktpjgd2a4c
-rw------- 1 www-data www-data     3569 Dec 28 15:00 sess_ri4vcn03rdd41k0l832nkvvrn26fmh9b
-rw------- 1 www-data www-data     3569 Dec 28 15:21 sess_5usjq9lq28tf82smk25v8lo4b63a1tkt
-rw------- 1 www-data www-data     3569 Dec 28 15:24 sess_tn88b6glp69j00c8olu9fd8uh3gs1cug
-rw------- 1 www-data www-data     4668 Dec 29 07:57 sess_t00s2ud392i0mn4lfkk5mv5mlhshb6tt
-rw------- 1 www-data www-data     7783 Dec 29 09:01 sess_asuf1cvu9erppvcf3ckgjbpi5f2a28cq
-rw------- 1 www-data www-data    12669 Dec 29 09:49 sess_i5fjmbucs9p7bb8pdeh0223dsjep19e4
-rw------- 1 www-data www-data    14659 Dec 29 09:53 sess_m3n6r8c59h2jbsel8hcqt0ngpsa6970p
-rw------- 1 www-data www-data     6037 Dec 29 09:56 sess_v45jhl05t1e3gaghk48qpr4l2leu1lh2
-rw------- 1 www-data www-data     3569 Dec 29 10:02 sess_knnloejo8r7uikiverb144cn040rtl0u
-rw------- 1 www-data www-data    12663 Dec 29 10:04 sess_9ske3kr35hv578bi0ub428l0th885881
-rw------- 1 www-data www-data     7577 Dec 29 10:17 sess_d4lf6o75n4ankv8028640le5aj84s703
-rw------- 1 www-data www-data     9860 Dec 29 10:26 sess_fv4co92lsk5371btsevtn1tvu81puauq
-rw------- 1 www-data www-data     8893 Dec 29 10:36 sess_32ofkuqfb4oic6b2b1ofv1ik8lto369n
-rw------- 1 www-data www-data     7367 Dec 29 10:44 sess_558im9kt3oo5tattndq1mntvsk4ba4g2
-rw------- 1 www-data www-data     3569 Dec 29 11:07 sess_ashkg3re988593i0i4c4vfvp0g997mgg
-rw------- 1 www-data www-data    11896 Dec 29 11:16 sess_ovh5ni9pomqdp4hbgasn9m8blv8bi947
-rw------- 1 www-data www-data     3569 Dec 29 11:22 sess_5tadm79fqncr8jrf9227g0bg0oaa4dmf
-rw------- 1 www-data www-data  2200724 Dec 29 11:30 sess_989enmkfj5gqvmqfata2klbukdnm25eo
-rw------- 1 www-data www-data    33649 Dec 29 12:01 sess_flfs55omvgta2dbto4pc78jm8e8pk0ur
-rw------- 1 www-data www-data    12984 Dec 29 12:01 sess_fb1rgo07kf3abmrgspvlam7ptffcrbim
-rw------- 1 www-data www-data     3569 Dec 29 12:10 sess_vkb3cq3t0mhopb6kopr8u69q62f7n9fd
-rw------- 1 www-data www-data     9867 Dec 29 12:27 sess_5m3tnbp3t36rrponaark9ounsijgk7lo
-rw------- 1 www-data www-data    37915 Dec 29 12:28 sess_9umn1u1hr5tsto8apiogqcfuqqbqrpup
-rw------- 1 www-data www-data     9962 Dec 29 12:31 sess_auh2b24oudsld2624u1i2ua76kbr17o2
-rw------- 1 www-data www-data    15667 Dec 29 12:34 sess_9tdhiioos9ni4d3n4hf1u8e1vcno3qu5
-rw------- 1 www-data www-data    17931 Dec 29 12:38 sess_qqbs15j95mfl0oop3e1mgqhmapfl1pqi
-rw------- 1 www-data www-data     9091 Dec 29 12:41 sess_m9hgndln3cforb0bhp4dl389a1le7cno
-rw------- 1 www-data www-data     3569 Dec 29 12:42 sess_ts1un02dkrjrbg9iipb11fte2b2kan2b
-rw------- 1 www-data www-data    22727 Dec 29 12:51 sess_5nh74vf280g6ietpjfn5hipr7qns69ql
-rw------- 1 www-data www-data     8887 Dec 29 13:06 sess_jo1qig0joorpjor8c184bm0qauof44id
-rw------- 1 www-data www-data    27509 Dec 29 13:09 sess_80rcnk9ajnt61ng6fcd1r3rl5a1faarn
-rw------- 1 www-data www-data     8836 Dec 29 13:09 sess_icqniclij5ch43639fero85f8dcfe0kd
-rw------- 1 www-data www-data    14701 Dec 29 13:11 sess_eeih2pq4nsodmgvfjrljc9rr6hkt6ogn
-rw------- 1 www-data www-data    12969 Dec 29 13:14 sess_323j6u3c3c87ngdou1n2sek17kr4pm30
-rw------- 1 www-data www-data   160650 Dec 29 13:15 sess_i9htolt4dsqi5bhen21o1didksg25jpm
-rw------- 1 www-data www-data     6444 Dec 29 13:15 sess_nk6tuc2qjiiifqh7cqkgpq1kq95ulkec
-rw------- 1 www-data www-data    11415 Dec 29 13:20 sess_nv18780l0q9rjo808km451ch6jeucn90
-rw------- 1 www-data www-data    43898 Dec 29 13:20 sess_8hg76lqvfoa53p52t7posl6i2jbh6pkg
-rw------- 1 www-data www-data     7515 Dec 29 13:22 sess_khsmbkcav7fpq43j6pdf1kodu5vljcsp
-rw------- 1 www-data www-data     3569 Dec 29 13:23 sess_1ja524tdcbu625glj1k88hnj9pkov00m
-rw------- 1 www-data www-data    19759 Dec 29 13:25 sess_ds1657pu39edlf6fltr7qp1br599lgdi
-rw------- 1 www-data www-data     3569 Dec 29 13:25 sess_at7a3a1n02tm26adsj2q4tau02sk11k1
-rw------- 1 www-data www-data     3569 Dec 29 13:25 sess_nflhadktcmigg2gfrauijrlo99n5suvb
-rw------- 1 www-data www-data    47287 Dec 29 13:26 sess_stgd934e6ec5nntktl52mlo2mkv04b8n
-rw------- 1 www-data www-data    22236 Dec 29 13:27 sess_piu5956d23tckcll86sqh1m5v2lmdp2d
-rw------- 1 www-data www-data     3569 Dec 29 13:28 sess_o7le7pqfjc7qo30kr9u6gro0vf5f2gjn
-rw------- 1 www-data www-data 14002797 Dec 29 13:29 sess_93r6vci7jgog3tbv7tdjmprptlcukcd6
-rw------- 1 www-data www-data   172870 Dec 29 13:30 sess_i7dpqkco4vs4tl0vgod879lbadj1op3h
-rw------- 1 www-data www-data    28380 Dec 29 13:31 sess_5s9cid8qk7m88crol47qie8botaavsvh
Tue Dec 29 13:31:57 ART 2015

Se observa un número importante de sesiones PHP abiertas, algunas iniciadas muy recientemente (comparar con la fecha del servidor). Esto significa que, por más que no hayan conexiones TCP establecidas con el servidor Apache, hay usuarios que tienen sesiones PHP abiertas. Lo cual indica que probablemente estén trabajando con la aplicación y es probable que algunos (o muchos) vayan a generar tráfico hacia el servidor Web a corto plazo.

Evidentemente, controlar la fecha de creación/modificación de los archivos correspondientes a las sesiones PHP nos puede dar una imagen más precisa del uso actual del servidor Web.

Otro ejemplo con netstat

Veamos un ejemplo más de la evolución de las conexiones TCP hacia el servidor Apache. Si el servidor está ocioso, la salida netstat (tal como se ha filtrado en el ejemplo previo) debería ser vacía, sin resultados. Entonces, partiendo desde un servidor Web ocioso, abrir algunas conexiones HTTP hacia el mismo desde un navegador e inmediatamente cerrarlo.

13:38:13 - El servidor Apache se encuentra ocioso:

root@debian6:~# date && netstat -tupn | grep -v "127.0.0" | grep "apache\|:443\|:80"
Tue Dec 29 13:38:13 ART 2015

No hay coincidencias, no hay ningún tipo de conexión relacionada con Apache.

13:38:26 - Apache recibe la primera petición desde un cliente:

root@debian6:~# date && netstat -tupn | grep -v "127.0.0" | grep "apache\|:443\|:80"
Tue Dec 29 13:38:26 ART 2015
tcp6       0      0 10.8.100.53:80        192.168.133.15:18117    ESTABLISHED 3756/apache2

Se observa la primera conexión establecida con el servidor.

13:38:39 a 13:38:43 - Apache recibe una serie de peticiones desde el mismo cliente:

root@debian6:~# date && netstat -tupn | grep -v "127.0.0" | grep "apache\|:443\|:80"
Tue Dec 29 13:38:39 ART 2015
tcp6       0      0 10.8.100.53:80        192.168.133.15:18117    TIME_WAIT   -
tcp6       0      0 10.8.100.53:80        192.168.133.15:45548    ESTABLISHED 3757/apache2
root@debian6:~# date && netstat -tupn | grep -v "127.0.0" | grep "apache\|:443\|:80"
Tue Dec 29 13:38:43 ART 2015
tcp        0      0 10.8.100.53:80        192.168.133.15:18830    SYN_RECV    -
tcp6       0      0 10.8.100.53:80        192.168.133.15:18117    TIME_WAIT   -
tcp6       0      0 10.8.100.53:80        192.168.133.15:45548    ESTABLISHED 3757/apache2

El tráfico hacia el servidor fluye. En este punto, el cliente cierra el navegador (cerrando así las conexiones TCP contra el servidor Web).

13:39:13 - Apache está ocioso nuevamente y todas las conexiones TCP han sido cerradas, pero quedan sockets en espera (en estado "TIME_WAIT"):

root@debian6:~# date && netstat -tupn | grep -v "127.0.0" | grep "apache\|:443\|:80"
Tue Dec 29 13:39:13 ART 2015
tcp6       0      0 10.8.100.53:80        192.168.133.15:18117    TIME_WAIT   -
tcp6       0      0 10.8.100.53:80        192.168.133.15:45548    TIME_WAIT   -

13:39:53 - Apache permanece ocioso, aunque ahora queda sólo un socket TCP en espera (timeout):

root@debian6:~# date && netstat -tupn | grep -v "127.0.0" | grep "apache\|:443\|:80"
Tue Dec 29 13:39:53 ART 2015
tcp6       0      0 10.8.100.53:80        192.168.133.15:45548    TIME_WAIT   -

13:39:59 - Apache permanece ocioso y todos los sockets TCP han sido liberados (timeout):

root@debian6:~# date && netstat -tupn | grep -v "127.0.0" | grep "apache\|:443\|:80"
Tue Dec 29 13:39:59 ART 2015

Siguiendo la línea de tiempo de este experimento, se observa que la última petición fue originada antes de las 13:38:43 y todas las conexiones han sido finalizadas después de las 13:39:53. Por ende, se puede deducir que las conexiones TCP permanecen abiertas durante algo más de un minuto.

Es posible verificar esta configuración de la pila TCP/IP en el kernel Linux consultando a la variable net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait:

root@debian6:~# sysctl net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120

El tiempo de espera para sockets en estado TIME_WAIT es de 120 segundos, lo cual coincide con el experimento.

Además de estas técnicas y herramientas, existe un módulo de Apache llamado mod_status que da información de estado del servidor. Puede ser útil para algunos Administradores de Sistemas, pero aún no lo he probado pues mi idea era resolver esta cuestión utilizando las herramientas de línea de comando a mi alcance.

La página de manual de netstat posee información detallada acerca de los estados de las conexiones TCP:

man netstat

Enlaces de interés

lognormal - Linux TCP/IP tuning for scalability

The TCP/IP Guide - TCP Connection Termination


Tal vez pueda interesarte


Compartí este artículo