Title: INFO: Crear un servicio
Course: [15/16] Administración de Sistemas Operativos

INDICE
1. Entrega
2. System V
2.1 Script demonio
2.2 Script de control
3. Upstart
4. Otro script demonio

1. Entrega

- El objetivo de la práctica es la de crear nuestro propio servicio.

2. System V

- Iniciar SO Debian.
- Crear la carpeta "/etc/kup", y un fichero "/etc/kup/kup.log" vacío.

2.1 Script demonio

- Crear un script "/usr/local/bin/kupd" que será nuestro demonio. Este script será un bucle que ejecutará una tarea de forma repetitiva.

Veamos un ejemplo escrito en Bash: | Veamos un ejemplo escrito en Ruby:
#!/bin/bash
#
# Filename: /usr/local/bin/kupd
# Version: 1

ALUMNO=nombre-del-alumno
MAQUINA=`hostname`
DIRCONF=/etc/kup
LOGFILE=$DIRCONF/kup.log

touch $DIRCONF/running
echo "Iniciando el log..." > $LOGFILE

while [ -f $DIRCONF/running ]; do
MESSAGE="[$ALUMNO @ $MAQUINA] $0: `date`"
echo $MESSAGE >> $LOGFILE
sleep 1
done
#!/usr/bin/ruby
#
# Filename: /usr/local/bin/kupd
# Version: 1

ALUMNO="david"
MAQUINA=`hostname`
DIRCONF="/etc/kup"
LOGFILE=DIRCONF+"/kup.log"

system("touch #{DIRCONF}/running")
system("echo \"Iniciando el log...\" > #{LOGFILE}")

while File.exists?(DIRCONF+"/running") do
message="#{ALUMNO}@#{MAQUINA} #{$0}: "+Time.now.to_s
system("echo \"#{message}\" >> #{LOGFILE}")
sleep 1
end

- Dar permisos ejecución al script.
- Comprobar que funciona el demonio:
  - "/usr/local/bin/kupd &", para iniciarlo en background (Segundo plano).
  - En la consola ejecutar "cat /etc/kup/kup.log", para ver los mensajes que aparecen cada intervalo de tiempo.
  - "rm /etc/kup/running", para indicarle al demonio/servicio que pare.
  - Comprobar que el demonio/servicio ha terminado.
- [INFO] El error de permiso denegado al tratar de ejecutar un script, suele deberse a que NO han puesto permisos de ejecución al citado fichero.

2.2 Script de control

- Ahora vamos a crear un script "/etc/init.d/kup". Será un script que controlará el inicio/parada de nuestro demonio, al estilo System V.

Si lo hacemos en Bash, podemos crear inicialmente nuestro fichero a partir del ejemplo /etc/init.d/skeleton. Luego, modificaremos las siguientes funciones del script, personalizándolas de la siguiente forma: | Si lo hacemos en Ruby, tenemos el siguiente script de ejemplo:
#!/bin/bash
### BEGIN INIT INFO
# Provides: kup
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Should-Start: $network
# Should-Stop: $network
# Short-Description: Start kup daemon
### END INIT INFO

[...]
NAME=kupd
DAEMON=/usr/local/bin/kupd
...
SCRIPTNAME=/etc/init.d/kup
[...]

do_start() {
#Acción para iniciar el servicio
/usr/local/bin/kupd &
}

do_stop() {
#Acción para parar el servicio
rm /etc/kup/running
}

[...]
#!/usr/bin/ruby
### BEGIN INIT INFO
# Provides: kup
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Should-Start: $network
# Should-Stop: $network
# Short-Description: Start kup daemon
### END INIT INFO
#File: /etc/init.d/kup

option=ARGV.first

def show_status
if File.exists?("/etc/kup/running") then
puts "Service KUP is running"
else
puts "Service KUP is stopped"
end
end

if option=="start" then
system("/usr/local/bin/kupd &")
elsif option=="stop" then
system("rm /etc/kup/running")
elsif option=="status" then
show_status
else
puts "Modo de uso: #{$0} [start|stop|status]"
end

- Dar permisos ejecución al script.
- Probar que el guión de inicio/parada funciona correctamente con nuestro servicio, mediante "/etc/init.d/kup [start|stop|status]".
- [INFO] El comando runlevel muestra el nivel de ejecución actual. Suele ser un 2 o un 5.
- El comando "insserv kup" modifica el inicio del servicio por defecto (Consultar información sobre insserv). Comprobar que nuestro servicio se inicia automáticamente al entrar en runlevel 2. Recordar la creación de enlaces simbólicos (Comando ln -s ...) del curso pasado.
- Comprobar el inicio automático del servicio.
- Quitar nuestro servicio de runlevel 2 y comprobarlo.

3. Upstart

- Ahora vamos a configurar el servicio, al estilo Upstart.
- [INFO] Si tenemos una MV Debian. La clonamos por seguridad. Luego instalamos el paquete "upstart".
- Crear un fichero /etc/init/kup2.conf con el siguiente contenido:

#
# Ejemplo /etc/init/kup2.conf
#
description "Servicio KUP2"

start on runlevel [2345]
stop on runlevel [!2345]

pre-start script
test -x /usr/local/bin/kupd || { stop; exit 0; }
end script

exec /usr/local/bin/kupd
- Probar que el servicio funciona correctamente (Comando: service kup2 start)
- Además comprobar que el servicio se inicia automáticamente al entrar en runlevel 2.
- Quitar servicio de runlevel 2 y comprobarlo. Hay que modificar /etc/init/kup2.conf.

4. [Esto no hay que hacerlo] Otro script demonio

- Vamos a crear un script demonio rkupd.
- Vamos a programar script usando ruby preferentemente como lenguaje de scripting.
- NOTA: Es posible usar otros como bash, sh, o PowerShell, pero hablarlo antes con el profesor.

El script rkupd será un demonio para "matar" procesos de los usuarios que estén en la "lista negra" (real kill user process).
- Definir una lista (black-list) con los usuarios que NO tienen permitido iniciar procesos.
- Definir una restricción horaria (timetable).
- El script rkupd iniciará un bucle para:
  - Espera 5 segundos antes de seguir (sleep INTERVAL)
  - Comprueba que ningún usuario de la lista negra tiene procesos activos. Comando de ejemplo: "ps -u USER -o pid|grep -v 'PID'"
  - Una vez tenemos localizados los PID de los procesos, los matamos (Comando de ejemplo: kill -9 PID).

Veamos un ejemplo "incompleto":
#!/usr/bin/ruby
puts "Ejecutando #{$0}..."
action=ARGV.first

#define global variables
USERS=[ 'profesor' ]
PROCESS=[ 'nano' ]

#define methods
def show_help
..puts "Modo de uso:"
..puts " help|h , Mostrar esta ayuda"
..puts " show|s , Mostrar las 'infracciones'"
..puts " exec|e , Castigar a los 'infractores'"
end

def show_guilty
..puts "Mostrar las 'infracciones'"
..USERS.each do |user|
..print "<#{user}> "
..output=`ps -u #{user} -o pid|grep -v 'PID'`
..pids=output.split("\n")
..if pids.size > 0 then
....print "Killing #{pids.count} processes:"
....pids.each { |p| print "#{p}, " }
..end
..print "\n"
end
end

def exec_guilty
..puts "Castigar a los 'infractores'"
end

#Main block
if action=='help' or action=='h' then
..show_help
elsif action=='show' or action=='s' then
..show_guilty
elsif action=='exec' or action=='e' then
..exec_guilty
else
..show_help
end

Anexo

- El comando "netstat" nos da información de los programas que están haciendo uso de los puertos del equipo.
- El comando "service --status-all" en GNU/Linux nos muestra información de todos los servicios.
- El gestor de servicios en OpenSUSE es "systemd". Es diferente a SystemV y a Upstar.

Ejemplo del fichero /etc/apt/sources.list
#

# deb cdrom:[Debian GNU/Linux 7.6.0 _Wheezy_ - Official amd64 CD Binary-1 20140712-14:11]/ wheezy main

#deb cdrom:[Debian GNU/Linux 7.6.0 _Wheezy_ - Official amd64 CD Binary-1 20140712-14:11]/ wheezy main

deb http://ftp.es.debian.org/debian/ wheezy main
deb-src http://ftp.es.debian.org/debian/ wheezy main

deb http://security.debian.org/ wheezy/updates main
deb-src http://security.debian.org/ wheezy/updates main

# wheezy-updates, previously known as 'volatile'
deb http://ftp.es.debian.org/debian/ wheezy-updates main
deb-src http://ftp.es.debian.org/debian/ wheezy-updates main