comment
IRC Chat
play_arrow
Este sitio utiliza cookies propias y de terceros. Si continúa navegando consideramos que acepta el uso de cookies. OK Más Información.

Expulsar todas las sesiones MySQL de un usuario en particular desde un script

  • 0 Respuestas
  • 1941 Vistas

0 Usuarios y 1 Visitante están viendo este tema.

Conectado graphixx

  • *
  • Moderador
  • Mensajes: 1290
  • Actividad:
    5%
  • Reputación 18
  • Científico de BIG DATA
    • Ver Perfil
    • Sistemas y Controles
« en: Marzo 21, 2016, 10:03:04 am »
Cómo expulsar todas las sesiones MySQL de un usuario en particular desde un script bash

Muchas veces, puede que tengamos una aplicación no muy bien depurada en nuestro servidor web. A dicha aplicación le hemos dado su propio usuario MySQL y observamos que las conexiones no se cierran adecuadamente.

Temporalmente puede que la solución sea expulsar de vez en cuando todos los usuarios que siguen activos, con el fin de no saturar nuestro servidor MySQL. Puede que en otros servicios que tengamos activos hayamos visto el mensaje “Too many connections” impidiendo así el acceso a los demás servicios.

La primera detección del problema la podemos hacer gracias al comando “SHOW PROCESSLIST” de MySQL:

Código: Bash
  1. > SHOW PROCESSLIST;
  2. +---------+-------------+--------------------------------+-------------+---------+------+-------+------------------+
  3. | Id      | User        | Host                           | db          | Command | Time | State | Info             |
  4. +---------+-------------+--------------------------------+-------------+---------+------+-------+------------------+
  5. | 2485425 | gooduser    | xxx.xxx.xxx.xxx:xxxxx          | db1         | Sleep   |    4 |       | NULL             |
  6. | 2486333 | eviluser    | hostmalvado.com:57118          | devildb     | Sleep   |  243 |       | NULL             |
  7. | 2486345 | eviluser    | hostmalvado.com:57119          | devildb     | Sleep   | 1739 |       | NULL             |
  8. | 2486346 | eviluser    | hostmalvado.com:57120          | devildb     | Sleep   |  799 |       | NULL             |
  9. | 2486359 | eviluser    | hostmalvado.com:57121          | devildb     | Sleep   |  739 |       | NULL             |
  10. | 2486360 | eviluser    | hostmalvado.com:57122          | devildb     | Sleep   |  712 |       | NULL             |
  11. | 2486364 | eviluser    | hostmalvado.com:57123          | devildb     | Sleep   | 9334 |       | NULL             |
  12. | 2486365 | eviluser    | hostmalvado.com:57124          | devildb     | Sleep   | 9043 |       | NULL             |
  13. | 2486376 | eviluser    | hostmalvado.com:57125          | devildb     | Sleep   | 5955 |       | NULL             |
  14. | 2486382 | eviluser    | hostmalvado.com:57126          | devildb     | Sleep   | 5012 |       | NULL             |
  15. | 2486383 | eviluser    | hostmalvado.com:57127          | devildb     | Sleep   | 5939 |       | NULL             |
  16. | 2486384 | eviluser    | hostmalvado.com:57128          | devildb     | Sleep   | 5032 |       | NULL             |
  17. | 2486387 | eviluser    | hostmalvado.com:57129          | devildb     | Sleep   | 1603 |       | NULL             |
  18. | 2486388 | eviluser    | hostmalvado.com:57130          | devildb     | Sleep   |   16 |       | NULL             |
  19. | 2486403 | eviluser    | hostmalvado.com:57131          | devildb     | Sleep   |    5 |       | NULL             |
  20. | 2486405 | eviluser    | hostmalvado.com:57132          | devildb     | Sleep   |    1 |       | NULL             |
  21. | 2486408 | root        | xxx.xxx.xxx.xxx:xxxxx          | NULL        | Query   |    0 | init  | SHOW PROCESSLIST |
  22. | 2486412 | gooduser2   | xxx.xxx.xxx.xxx:xxxxx          | db2         | Sleep   |    0 |       | NULL             |
  23. +---------+-------------+--------------------------------+-------------+---------+------+-------+------------------+
  24. 18 rows in set (0.00 sec)
  25.  

Como vemos, tenemos los usuarios gooduser y gooduser2, que son buenos, usan la base de datos y no dan problemas. Luego tenemos root, que soy yo ahora mismo, pidiendo el listado de procesos y un montón de veces ha entrado eviluser, que además vemos que tiene conexiones abiertas desde hace mucho tiempo, la columna Time nos devuelve la cantidad de segundos que el hilo lleva en el mismo estado, lo que puede indicar una conexión no cerrada adecuadamente.

Diseño del script

Aunque podemos utilizar un bucle en MySQL, he preferido hacerlo con un script en bash que va matando uno a uno los procesos. Tal vez sea la forma más lenta de hacerlo, pero no tenemos que meter un procedure en el servidor MySQL para ejecutarlo, y copiando y pegando el código desde la página nos vale.

Script rápido

Código: Bash
  1. USER="root"
  2. PASS=""
  3. MINTIME=600
  4.  
  5. function printhelp()
  6. {
  7.     echo "Kill MySQL Sessions"
  8.     echo "Arguments:"
  9.     echo "   --user, -u : MySQL user"
  10.     echo "   --pass, -p : MySQL password"
  11.     echo "   --host, -h : MySQL host"
  12.     echo "   --socket, -s : MySQL socket"
  13.     echo "   --kick, -k : User to kick out"
  14.     echo "   --time, -t : Min. time after last state change"
  15.     exit 1
  16. }
  17.  
  18. while [ "$#" -gt 0 ]
  19. do
  20.     case "$1" in
  21.     --help)
  22.         printhelp
  23.         ;;
  24.     -u|--user)
  25.         USER="$2"
  26.         shift
  27.         ;;
  28.     -p|--pass)
  29.         PASS="$2"
  30.         shift
  31.         ;;
  32.     -h|--host)
  33.         HOST="$2"
  34.         shift
  35.         ;;
  36.     -s|--socket)
  37.         SOCKET="$2"
  38.         shift
  39.         ;;
  40.     -k|--kick)
  41.         KICKUSER="$2"
  42.         shift
  43.         ;;
  44.     -t|--time)
  45.         MINTIME="$2"
  46.         shift
  47.         ;;
  48.     *)
  49.         echo "Invalid option '$1'."
  50.         printhelp
  51.         exit 1
  52.         ;;
  53.     esac
  54.     shift
  55. done
  56.  
  57. CONDITION=""
  58. if [ -n "$KICKUSER" ]
  59. then
  60.     CONDITION="User='$KICKUSER'"
  61. fi
  62.  
  63. if [ -n "$MINTIME" ] && [ "$MINTIME" -gt 0 ]
  64. then
  65.     if [ -z "$CONDITION" ]
  66.     then
  67.     CONDITION="Time>$MINTIME"
  68.     else
  69.     CONDITION="$CONDITION AND Time>$MINTIME"
  70.     fi
  71. fi
  72.  
  73. CONNECTIONSTR=""
  74.  
  75. if [ -n "$SOCKET" ]
  76. then
  77.     CONNECTIONSTR="$CONNECTIONSTR --socket $SOCKET"
  78. else
  79.     if [ -z "$HOST" ]
  80.     then
  81.     echo "You must, at least, specify the host to connect to. -h"
  82.     exit 1;
  83.     else
  84.     CONNECTIONSTR="$CONNECTIONSTR --host $HOST"
  85.     fi
  86. fi
  87.  
  88. if [ -n "$USER" ]
  89. then
  90.     CONNECTIONSTR="$CONNECTIONSTR -u $USER"
  91. fi
  92.  
  93. if [ -n "$PASS" ]
  94. then
  95.     CONNECTIONSTR="$CONNECTIONSTR -p$PASS"
  96. fi
  97.  
  98. if [ -z "$CONDITION" ]
  99. then
  100.     read -r -p "Are you sure you want to kick out all connections? [y/N] " response
  101.     response=${response,,}
  102.     if [[ $response =~ ^(yes|y|si|s)$ ]]
  103.     then
  104.     CONDITIONSTR=""
  105.     else
  106.     echo "Action cancelled"
  107.     exit 2
  108.     fi
  109. else
  110.     CONDITIONSTR="WHERE $CONDITION"
  111. fi
  112.  
  113. THREADIDS=`echo "SELECT ID FROM information_schema.processlist $CONDITIONSTR" | mysql $CONNECTIONSTR --skip-column-names`
  114. if [ -z "$THREADIDS" ]
  115. then
  116.     echo "No users to kick out"
  117.     exit 3
  118. fi
  119. echo "Killing "$(echo "$THREADIDS" | wc -w)" connections..."
  120. for tid in $THREADIDS
  121. do
  122.     echo "Killind ID "$tid"..."
  123.     mysql $CONNECTIONSTR -e "KILL $tid"
  124. done
  125.  

De esta forma podremos expulsar los usuarios que hay actualmente conectados. Veamos detenidamente las opciones de línea de comandos para este script.

  • –user y –pass : Eso está claro, ¿no?
  • –socket : Especifica el socket unix con el que vamos a conectar, puede que tu base de datos no esté escuchando ningún puerto en nuestro host y tengamos que conectar de esta forma.
  • –host : En cualquier caso, si no conectamos por socket, debemos conectar por host, así que uno de los dos debe estar especificado.
  • –kick : Usuario que queremos expulsar, en nuestro caso eviluser.
  • –time : Tiempo mínimo sin dar señales de vida. Es decir, el tiempo que lleva la conexión sin cambiar de estado. El script, por defecto señala un tiempo mínimo de 600 segundos (10 minutos), aunque podemos variarlo, incluso poner 0 para no especificar tiempo.

Hay que tener en cuenta que si no especificamos usuario y pedimos que el tiempo sea 0, preguntará si de verdad queremos echar a todos los usuarios actuales del sistema.

Requerimientos

Como mínimo necesitamos MySQL 5.1.7 porque es cuando introdujeron la opción de consultar el listado de procesos desde la base de datos information_schema.
Y bash 4 o superior, por la pregunta al usuario cuando el tiempo es 0 y no hemos metido usuario. Si quitamos esa parte, podría funcionar sin problema con versiones muy antiguas de Bash.

Más referencias

Resultado de un SELECT de MySQL en un array de BASH

Fuente: totaki.com/poesiabinaria

 

¿Te gustó el post? COMPARTILO!



[VIDEOTUTORIAL] Monta un cluster Hadoop Big Data desde cero

Iniciado por graphixx

Respuestas: 0
Vistas: 2291
Último mensaje Septiembre 30, 2016, 06:27:59 am
por graphixx
Dumpiando base de datos desde la consola

Iniciado por syskc0

Respuestas: 2
Vistas: 2585
Último mensaje Julio 13, 2010, 09:58:56 pm
por syskc0
Curso : Base de Datos [Desde Cero]

Iniciado por Mr.Kratos

Respuestas: 0
Vistas: 676
Último mensaje Julio 27, 2018, 01:53:17 pm
por Mr.Kratos
Curso: Bases De Datos [¡Instalar y Administrar el Motor de Base de Datos MySQL!]

Iniciado por Mr.Kratos

Respuestas: 0
Vistas: 703
Último mensaje Julio 20, 2018, 04:55:30 pm
por Mr.Kratos
Base de Datos MySQL (curso básico-intermedio)

Iniciado por graphixx

Respuestas: 1
Vistas: 2751
Último mensaje Abril 03, 2018, 07:12:17 pm
por crissk8