• Publicidad

Modificar activar/desactivar servicio o cron desde Perl

¿Eres administrador de sistemas? Este foro es para todos aquellos temas relacionados con el uso de Perl para administración de sistemas.

Modificar activar/desactivar servicio o cron desde Perl

Notapor miguel_vor » 2012-11-02 10:12 @466

Muy buenas,

Estoy intentando administrar un script que se ejecuta continuamente para proporcionar failover a un sistema bajo IPCop. Este script es un bucle que se ejecuta cada n minutos, donde n es un parámetro que deseo configurar desde el cgi y que se modifique en el script a través de la lectura de un fichero de configuración. Para realizar esto necesito detener el script, que lea el nuevo parámetro y se ejecute en consecuencia.

Lo he realizado de dos formas:

1) mediante un cron de tal forma que modifico el fichero /var/spool/cron/root.orig insertando la siguiente línea:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. */n * * * * failover.sh >> logfailover
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Y luego mediante el uso de
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. fcrontab -z
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
se actualizaría el cron y lo ejecutaría, pero no funciona, ya que utilizo, system(), exec, qx y ``, y nada no, realiza ninguna acción.

2) he creado un servicio con el siguiente código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. # Script template para demonios
  2. #!/bin/sh
  3.  
  4.  
  5. start(){
  6.  echo -n $"Starting service: "
  7.  startup=`/scripts/failover_fase5_3.sh --start`
  8.  RETVAL=$?
  9.  echo
  10. }
  11.  
  12. stop(){
  13.  echo -n $"Stopping service: "
  14.  shutdown=`/scripts/failover_fase5_3.sh --stop`
  15.  RETVAL=$?
  16.  echo
  17. }
  18.  
  19. restart(){
  20.  stop
  21.  sleep 2
  22.  start
  23. }
  24.  
  25. # Dependiendo del parámetro que se le pase
  26. #start - stop - restart ejecuta la función correspondiente.
  27. case "$1" in
  28. start)
  29.  start
  30.  ;;
  31. stop)
  32.  stop
  33.  ;;
  34. restart)
  35.  restart
  36.  ;;
  37. *)
  38.  echo $"Usar: $0 {start|stop|restart}"
  39.  exit 1
  40. esac
  41.  
  42. exit 0
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


En el fichero CGI pongo lo siguiente:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. my $activar = system("/scripts/failover_fase5_3.sh --start");                  
  2.                         print $activar;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Al realizar esta tarea el navegador se queda esperando, veo los procesos mediante el comando:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. ps auxw | grep failover | grep -v grep
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Y los resultados son que failover --start, pero no realiza ninguna acción, ya que no escribe nada en el fichero de log.

Ya no sé qué hacer, porque desde el CGI no me deja ejecutar comandos para poder iniciar/detener el servicio o cron, de tal forma que pueda parar el script que resulta ser un bucle infinito.

Ayuda, por favor.

Muchas gracias.
miguel_vor
Perlero nuevo
Perlero nuevo
 
Mensajes: 7
Registrado: 2012-11-02 09:32 @439

Publicidad

Re: Modificar activar/desactivar servicio o cron desde Perl

Notapor explorer » 2012-11-02 11:46 @532

Bienvenido a los foros de Perl en Español, miguel_vor.

¿Has tenido en cuenta a los usuarios?

Si ejecutas un proceso CGI desde fuera, este proceso se ejecuta con la autoría del usuario que ejecuta el servidor web (nobody, www-data, etc.). Y si estás intentando modificar el cron del root, pues como que no va a poder (no tendrá, normalmente, permisos para ello).

Lo mismo pasa en el segundo caso. Al ejecutar el failover, lo estás haciendo como el usuario web, y habría que ver si ese usuario tiene permisos de escritura en el archivo de registro (log).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Modificar activar/desactivar servicio o cron desde Perl

Notapor miguel_vor » 2012-11-02 12:29 @562

Muchas gracias por tu respuesta,

La verdad es que no he tenido en cuenta a los usuarios, yo trabajo todo el rato con root y el cron lo he realizado sobre ese usuario. Para utilizar root ¿qué tendría que hacer, anteceder la llamada a fcrontab -z con el comando sudo? El inconveniente sería que me solicitara el password. Podría crear un cron para el usuario nobody a pesar de no existir ese usuario en Linux o ¿quizás el nobody hace referencia a eso mismo, que no existe el usuario?

Por otro lado, he buscado por todas partes la manera de poder modificar un cron por comandos pero no he encontrado nada. La manera que he encontrado es la de modificar el archivo /var/spool/cron/root.orig y posteriormente hacer la llamada al comando
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. fcrontab -z
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


No sé si esto es lo más correcto. ¿Existe alguna otra forma? Es que creo que no es lo más correcto, ya que hay que cambiar los permisos al fichero y no me parece una buena forma, ya que al utilizar
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. fcrontab -e
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

al salir como que realiza una instalación en un fichero temporal y se aplican los cambios, como si se reiniciara el cron.

Muchas gracias.
miguel_vor
Perlero nuevo
Perlero nuevo
 
Mensajes: 7
Registrado: 2012-11-02 09:32 @439

Re: Modificar activar/desactivar servicio o cron desde Perl

Notapor explorer » 2012-11-02 13:52 @619

El usuario nobody es un ejemplo. No sé qué usuario es el que está ejecutando tu servidor web en tu servidor.

Para que un cgi pueda modificar algo como root, se puede hacer que el propietario del cgi sea el propio root. O configurar el archivo sudoers para que cuando el usuario web ejecute ese cgi, lo haga con permisos de root (es más fácil la primera opción, claro).

Yo nunca he manejado fcrontab, pero sí crontab. No sé las diferencias, pero parece que hacen lo mismo.

Una opción que simplificaría mucho el problema es que el usuario web tuviera su crontab particular, y el cgi solo tendría que crear un nuevo archivo cron, y activarlo con

crontab archivo

El sistema se dará cuenta inmediatamente de que ha cambiado la definición cron para ese usuario.

No es nada recomendable modificar el archivo que está en /var/spool/cron/crontabs. Es mejor siempre usar el comando crontab:

crontab -l > anterior
cp anterior nuevo
echo "$nuevalinea" >> nuevo
crontab < nuevo # o crontab nuevo


También se puede hacer (usando el mecanimos SuExec de Apache) que el servidor web adopte la personalidad de un determinado usuario del sistema, en el momento de la ejecución del cgi. Éste modificará su archivo crontab como he visto, y el sistema lo agregará a la tabla de procesos cron. Pero seguimos hablando de un usuario particular, así que todo se debería ejecutar bajo la autoría de ese usuario (ahora no recuerdo si SuExec permite que ese usuario sea el root).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Modificar activar/desactivar servicio o cron desde Perl

Notapor miguel_vor » 2012-11-05 06:32 @314

El usuario que usa el navegador es nobody, he creado un cron para el usuario nobody pero no me permite realizar la acción de modificar el cron mediante

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. fcrontab archivo nobody
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Me aparece un error 256, que es lo que devuelve system.

He creado un nuevo usuario llamado failover pero no me permite crear cron. Al ejecutarlo me devuelve el siguiente error:

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. 12:00:56 could not change euid to 104: Operation not permitted
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


La otra opción, la de crear un servicio que llame a un script que se ejecute de forma indefinida cada x minutos, se queda pillado el navegador esperando al script por tiempo indefinido, esto sucede al ejecutar la orden

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. system("failover start");
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Que según se puede ver en el código del servicio lo que hace es un start del script. He probado cambiando los permisos del log, pero no parece que funcione, ya que en los procesos se visualiza pero no escribe nada en el log y en los procesos se muestra lo siguiente:

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. nobody   26436  0.0  0.0   2968   784 ?        S    12:23   0:00 sh -c /etc/rc.d/rc.failover start &
  2. nobody   26446  0.0  0.1   2972  1464 ?        S    12:23   0:00 /bin/bash /failover.sh --start
  3.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Ya no sé por dónde tirar y es que no puedo ver los errores, ya que sólo muestra un número y eso no me dice nada, no sé si se pueden ver los literales de los errores para ver qué pasa, porque parece que hace algo, pero resulta que no.

Muchas gracias
miguel_vor
Perlero nuevo
Perlero nuevo
 
Mensajes: 7
Registrado: 2012-11-02 09:32 @439

Re: Modificar activar/desactivar servicio o cron desde Perl

Notapor explorer » 2012-11-05 13:39 @610

miguel_vor escribiste:El usuario que usa el navegador es nobody, he creado un cron para el usuario nobody pero no me permite realizar la acción de modificar el cron mediante

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. fcrontab archivo nobody
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Me aparece un error 256, que es lo que devuelve system.
256 implica que el resultado de la ejecución es un '1' por parte de fcrontab que según su manual, es un fallo general (sin más detalles).

¿Seguro que es con fcrontab la forma en que tu sistema debes cambiar el sistema de cron? ¿No será con el comando crontab?


miguel_vor escribiste:He creado un nuevo usuario llamado failover pero no me permite crear cron. Al ejecutarlo me devuelve el siguiente error:

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. 12:00:56 could not change euid to 104: Operation not permitted
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Justo: el usuario nobody no puede hacerse pasar por el usuario 104.


miguel_vor escribiste:La otra opción, la de crear un servicio que llame a un script que se ejecute de forma indefinida cada x minutos, se queda pillado el navegador esperando al script por tiempo indefinido, esto sucede al ejecutar la orden

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. system("failover start");
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Que según se puede ver en el código del servicio lo que hace es un start del script. He probado cambiando los permisos del log, pero no parece que funcione.
No se puede ejecutar un programa de forma indefinida desde el navegador web... el Apache siempre cortará la conexión pasado un tiempo.

Lo que sí puedes hacer es instalar un servicio en el sistema, en el cron del root o del usuario que quieras con tal de que tenga permisos de lectura/escritura/ejecución sobre los archivos/directorios/comandos que quieras que actúe, y que se levante cada X minutos, dejando el resultado en archivos en un directorio que sea accesible a los procesos CGI que lanzará el cliente web.


miguel_vor escribiste:Ya no sé por dónde tirar y es que no puedo ver los errores, ya que sólo muestra un número y eso no me dice nada, no sé si se pueden ver los literales de los errores para ver qué pasa, porque parece que hace algo, pero resulta que no.
Si quieres ver los errores, debes primero saber por dónde generan la salida los diversos comandos que ejecutas: la salida estándar, la salida estándar de errores, algún archivo log, etc. Si se trata de archivos log, pues es fácil saber dónde. Si es la salida estándar, puedes redirigir esas salidas con las opciones de redirección del shell (usar '>' en el lugar adecuado). Si ejecutas un comando desde Perl, recuerda que si usas system() solo verás el resultado (un valor numérico) de la ejecución. Si el comando genera alguna salida en la salida estándar, y quieres verlo, es mejor usar qx(), ya que te lo devolverá a la variable escalar que le digas.

Se puede resolver esto de varias formas. Dices al principio que se trata de un script que se ejecuta continuamente, en un bucle, cada X minutos. ¿Tu puedes modificar ese script? Si, por ejemplo, se tratase de un script Perl, bastaría con poner una serie de líneas en el bucle, primero para comprobar que el archivo que contiene el parámetro 'n' ha cambiado. Segundo, leer ese parámetro 'n', y a continuación, ejecutar un exec() del *propio* script, y pasándole como argumento ese parámetro 'n'. exec() sustituirá el script actual por el ejecutable que le digas. Si es él mismo, entonces estarás relanzando el script.

Es más... ¿para qué reiniciar el script, si te vale con leer el parámetro 'n' en cada vuelta?

Lo importante es que el script tenga permiso de lectura del archivo que el cgi modifica.

Luego lo hemos complicado con la idea del cron. Entonces, yo he entendido que el script realmente no se ejecuta de forma continuada, si no que queremos que todo el script se ejecute cada 'n' minutos a través del cron.

Se puede hacer una cosa: Instala el script en el cron del sistema, para que se ejecute cada minuto. En cada ejecución, lo primero que debe hacer es comprobar si, el minuto de tiempo en que está, es múltiplo del valor 'n' del archivo externo. Y si lo es, se ejecuta el resto.

Y si no puedes modificar el script, por ser código cerrado, tampoco hay problema: Crea una envoltorio Perl que haga las operaciones anteriores, y que ejecute el script si se dan las condiciones. Algo así:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. #
  3. # Este envoltorio (wrapper) se ejecuta cada minuto, a través del cron del sistema
  4. #
  5.  
  6. # Leemos el minuto en que estamos
  7. my $minuto = (localtime)[1];
  8.  
  9. # Leemos el valor de 'n' del archivo externo, un entero
  10. my $n = 0+ do { open F, '/tmp/n.txt'; <F> };
  11.  
  12. # Comprobamos si estamos en múltiplo de esa cantidad de minutos
  13. if ($minuto % $n == 0) {
  14.     system('/opt/IPCop/bin/ipstats');
  15. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Ya solo queda hacer un cgi que modifique el valor de '/tmp/n.txt'.

No es óptimo, desde luego, pero todo depende de si podemos meterle mano al script de IPCop o no. Si no podemos, pues hay que hacer estas trampas.

Se puede hacer de más formas, desde luego.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Modificar activar/desactivar servicio o cron desde Perl

Notapor miguel_vor » 2012-11-06 11:44 @531

Muchas gracias por tu valiosísima ayuda, he conseguido resolver el problema.

Aquí te paso la prueba de que es fcrontab y no crontab:

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. root@utm:/ # crontab -l
  2. -bash: crontab: command not found
  3. root@utm:/ # fcrontab -l
  4. 17:29:24 listing root's fcrontab
  5. #
  6. # $Id: crontab 5480 2011-02-23 06:28:13Z dotzball $
  7. #
  8. SHELL=/bin/bash
  9. PATH=/sbin:/bin:/usr/sbin:/usr/bin
  10. HOME=/
  11. !mailto()
  12.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Finalmente he creado un cron para un usuario llamado failover que se ejecuta cada minuto. He establecido en el script condiciones a través de variables almacenadas en un fichero, de tal forma que establece si el script está on/off y un valor numérico para controlar cada cuántos minutos se va a ejecutar realizando la operación del módulo que me has recomendado. Por lo que el script se ejecuta cada minuto y realizará el cuerpo de éste en caso de tener el valor de la variable a 'on' y corresponda el minuto en base a la operación de módulo.

No ha sido necesario realizar el envoltorio (wrapper) ya que el script lo he desarrollado yo, por lo que tengo pleno acceso al código. En otras ocasiones haré los scripts en Perl que resulta más amigable.

Muchas gracias por tu dedicación, da gusto tener profesionales tan buenos al otro lado de la pantalla, que ayudan de forma desinteresada en favor del desarrollo.
miguel_vor
Perlero nuevo
Perlero nuevo
 
Mensajes: 7
Registrado: 2012-11-02 09:32 @439


Volver a Administración

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron