MySQL Proxy

Questo documento e' inutile! C'era gia' ottima documentazione su: Wikipedia (IT), O'Reilly, MySQL, documentazione ufficiale (strutture interne), [NdE i link su MySQL non sono piu' validi: MySQL Proxy non e' piu' distribuito/supportato e non e' mai stato ufficialmente in GA] ... Ma visto che avevo scritto altri documenti su MySQL ho deciso di scriverlo lo stesso per completezza!

MySQL Proxy e' un tool che opera come proxy di un server MySQL. Nella configurazione di default non fa nulla di piu' di un proxy verso localhost:3306 ma e' molto semplice programmarlo per introdurre funzionalita' di logging, load balancing, SQL injection, ...
La programmazione si effettua con LUA: un semplice e potente linguaggio embedded interpretato.

Nel seguito sono riportate alcune informazioni su MySQL Proxy organizzate in paragrafi specifici: Introduzione Installazione Configurazione/Lancio Programmazione (esempi: login, tempi di risposta, sincrono, ...), Architettura, Amministrazione, Esempi (completi).

Introduzione

Meglio un esempio di tante parole:

mysql-proxy --proxy-backend-addresses=collsql.xenialab.it:3306 --proxy-lua-script=/usr/local/proxy/my_trace.lua
Con il comando precedente si attiva MySQL Proxy in ascolto sulla porta 4040 che ridirige tutto il traffico SQL sul DB MySQL di backend specificato. Basta ora creare questo semplice script per disporre di un trace su MySQL:
# my_trace.lua
function read_query( packet )
    print(
        os.date('%Y-%m-%d %H:%M:%S ') .. string.sub(packet, 2) )
end
Viene cosi' tracciato ogni statement SQL richiesto dai client. Poiche' lo script viene valutato a runtime e' possibile modificare in ogni momento il trace senza interrompere il servizio.

MySQL Proxy e' molto utile... insomma: continuate a leggere!

Installazione

MySQL Proxy e' ancora in release Alpha, non sono quindi forniti pacchetti autoinstallanti. Sono comunque stati generati da MySQL AB gli eseguibili per la maggioranza delle piattaforme ed e' quindi sufficiente effettuare il download dal sito ufficiale MySQL e scaricare il contenuto sul proprio server per avere un ambiente funzionante.
Questo documento e' stato preparato utilizzando MySQL Proxy 0.7.0 su un Linux/GNU CentOS 5.4, ma gli elementi contenuti sono validi, mutatis mutandis, anche per tutte le altre releases di MySQL Proxy e di sistema Unix ospite.

Configurazione/Lancio

Non e' necessaria alcuna configurazione. Tutti i parametri possono essere passati da linea di comando.

# ./mysql-proxy --proxy-backend-addresses=collsql.xenialab.it:3306

# ./mysql-proxy --help-all
Usage:
  /usr/local/mysql-proxy/libexec/mysql-proxy [OPTION...] - MySQL App Shell

Help Options:
  -?, --help                                          Show help options
  --help-all                                          Show all help options
...
admin-module
  --admin-address=<host:port>                         listening address:port of the admin-server (default: :4041)
  --admin-password=<string>                           password to allow to log in (default: secret [N.d.A.])
  --admin-lua-script=<filename>                       script to execute by the admin plugin (default: not set [N.d.A.])
...
proxy-module
  --proxy-address=<host:port>                         listening address:port of the proxy-server (default: :4040)
  --proxy-read-only-backend-addresses=<host:port>     address:port of the remote slave-server (default: not set)
  --proxy-backend-addresses=<host:port>               address:port of the remote backend-servers (default: 127.0.0.1:3306)
  --proxy-lua-script=<file>                           filename of the lua script (default: not set)
...
Application Options:
  -V, --version                                       Show version
  --defaults-file=<file>                              configuration file
  --daemon                                            Start in daemon-mode
...

I parametri riportati nell'esempio sono quelli maggiormente utilizzati con i relativi valori di default... Le versioni piu' recenti di MySQL Proxy consentono il logging su syslog e l'utilizzo di un file di configurazione.

Programmazione

MySQL-Proxy puo' intercettare tutti i tipi di pacchetti scambiati tra client e DB Server e svolgere le azioni desiderate che possono essere sia di logging, tracing che di modifica dei dati scambiati. Il diagramma seguente (mi perdonino i puristi UML...) riporta i diversi scambi di messaggi tra client e MySQL Server e le funzioni che e' possibile utilizzare con LUA per intercettarli.

MySQL Proxy - State Diagram - UML life lines
La programmazione si effettua con il linguaggio LUA. In pratica e' necessario programmare le azioni di svolgere a fronte del passaggio di un messaggio. Se non viene definito nulla il messaggio passa inalterato e non viene svolta alcuna azione. Le funzioni che e' possibile programmare sono quelle riportate nel disegno ovvero:
connect_server()
read_auth_result()
read_handshake()
read_auth()

read_query()
read_query_result()
I dati sui messaggi scambiati e gli oggetti coinvolti sono disponibili nella struttura proxy e possono essere semplicemente acceduti con il LUA. Ad esempio l'attributo proxy.connection.client.src.address contiene l'IP del client che si connette al DB. La sintassi del LUA? Leggetela nella documentazione LUA ufficiale! L'elenco completo degli oggetti e degli attributi? Leggetelo sulla documentazione MySQL ufficiale!
Nel seguito riporto solo qualche mio piccolo esempio...

Ecco un esempio che riporta tutte le operazioni di login:

function read_auth_result( auth )
   print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" .. 
             "command=LOGIN" .. ";" .. 
             "source=" .. proxy.connection.client.src.name .. ";" .. 
             "destination=" ..proxy.connection.server.dst.name
        )
end
Ma in realta' e' possibile tracciare molto di piu' iniziando dalle fasi iniziali dello scambio di messaggi con il client (quindi anche gli eventuali accessi diretti alla porta 3306). Ecco un esempio che cattura in modo completo lo scambio di dati in fase di login:
function connect_server()
   print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" .. 
          "command=CONNECT" .. ";" .. 
          "source="..proxy.connection.client.src.name .. ";" 
        )
end

function read_handshake()
   print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" .. 
          "command=HANDSHAKE" .. ";" .. 
          "source="..proxy.connection.client.src.name .. ";" .. 
          "destination="..proxy.connection.server.dst.name .. ";" .. 
          "version="..proxy.connection.server.mysqld_version .. ";" .. 
          "thread="..proxy.connection.server.thread_id ..";" 
        )
end

function read_auth()
   print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" .. 
          "command=AUTH" .. ";" .. 
          "source="..proxy.connection.client.src.name .. ";" .. 
          "destination="..proxy.connection.server.dst.name .. ";" .. 
          "username="..proxy.connection.client.username .. ";" .. 
          "default_db="..proxy.connection.client.default_db .. ";" 
        )
end

function read_auth_result( auth )
   local state = auth.packet:byte()

   print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" .. 
             "command=LOGIN" .. ";" .. 
             "source="..proxy.connection.client.src.name .. ";" .. 
             "destination="..proxy.connection.server.dst.name
        )
   if state == proxy.MYSQLD_PACKET_OK then
      print( "status=OK" )
   elseif state == proxy.MYSQLD_PACKET_ERR then
      print( "status=KO" )
   else
      print( "status=UNKNOWN" )
   end
end
E' possibile catturare informazioni su ogni comando lanciato sulla base dati... ad esempio per raccogliere i tempi di risposta. Per analizzare le risposte di una query con read_query_result() e' necessario aver effettuato l'injection in read_query().
function read_query( packet )
        if packet:byte() == proxy.COM_QUERY then
                proxy.queries:append(1, packet )
                return proxy.PROXY_SEND_QUERY
        end
end

function read_query_result(inj)
        print(" query: " .. inj.query)
        print(" query-time: " .. (inj.query_time / 1000) .. "ms\n")
        print(" response-time: " .. (inj.response_time / 1000) .. 'ms\n')
end
E' anche possibile trattare i dati restituiti dalle query e modificarli... Poiche' questo introduce un ritardo per default i dati vengono restituiti direttamente al client senza renderli disponibili al Proxy. Per trattare il resultset con gli script LUA del proxy e' necessario indicarlo in modo esplicito con proxy.queries:append(1, packet, { resultset_is_needed = true } ). Poiche' l'esempio di costruzione di un resultset e' un poco piu' complicato l'abbiamo tenuto al fondo!

Il tracing degli statement deve essere immediato per il debugging. La funzione LUA print() utilizzata negli esempi precedenti opera con il buffering, quindi non e' adatta. Ma il LUA e' molto potente (e molto vicino al linguaggio C in questo caso) e consente di controllare l'IO:

print("Starting MyTrace script " .. os.date('%Y-%m-%d %H:%M:%S'))
local fh = io.open("/var/log/MyProxy.log", "a+")

function read_query( packet )
        fh:write(
                os.date('%Y-%m-%d %H:%M:%S')
                .. string.format("%6d ", proxy.connection.server["thread_id"])
                .. "CMD[".. string.format("%d",string.byte(packet)).."]: "
                .. string.sub(packet, 2).. '\n')
        fh:flush()
        if packet:byte() == proxy.COM_QUERY then
                proxy.queries:append(1, packet )
                return proxy.PROXY_SEND_QUERY
        end
end

function read_query_result(inj)
        fh:write(" query: " .. inj.query)
        fh:write(" query-time: " .. (inj.query_time / 1000) .. "ms\n")
        fh:write(" response-time: " .. (inj.response_time / 1000) .. 'ms\n')
        fh:flush()
end

In realta' in molti casi basta un semplice io.stdout:flush()... ma altrimenti come lo giustificavo l'esempio?

Architettura

MySQL e' costituito da un unico processo in ascolto su una porta (4040 di default) che ribalta ogni richiesta sul DB MySQL di backend configurato (localhost:3306 di default). Se e' definito uno script MySQL Proxy esegue i relativi comandi ad ogni evento configurato. Lo script puo' effettuare I/O (eg. per il logging/tracing/debugging), puo' modificare i messaggi sia in ingresso (alterando una query), sia in uscita (mascherando i risultati) e puo' indirizzare le richiste verso DB MySQL di backend differenti. Il livello di controllo possibile con MySQL Proxy e' quindi molto elevato.
Il ritardo introdotto da MySQL Proxy e' molto limitato (soprattutto se non vengono analizzati i result set) ed e' quindi utilizzabile senza particolari problemi per le prestazioni.

Volevo disegnare uno schema di esempio... ma l'immagine seguente e' troppo bella per rifarla! (provenienza sito ufficiale MySQL):

MySQL Proxy Architecture

MySQL Proxy puo' essere installato sullo stesso sistema su cui e' presente il DB MySQL oppure su un altro sistema. E' importante notare che le connessioni al database risulteranno provenire dal server che ospita il Proxy e non dal client iniziale. Questo e' molto importante poiche' su MySQL e' possibile distinguere gli utenti e le loro abilitazioni a seconda del server di provenienza. Vi e' quindi un impatto sia sulla definizione delle GRANT che nel tracciabilita' degli IP degli utenti. Per rintracciare i client che si connettono alla base dati e' necessario utilizzare l'interfaccia di amministrazione del proxy oppure... sfruttare l'SQL injection per rendere visibile l'IP del client come commento iniziale alla query!

function read_query( packet )
   if string.byte(packet) == proxy.COM_QUERY then
      local query = "/* " .. proxy.connection.client.src.address .. " */ " .. string.sub(packet, 2)
      proxy.queries:append(1, string.char(proxy.COM_QUERY) .. query )
      return proxy.PROXY_SEND_QUERY
   end
end

MySQL Proxy in an highly secure configuration Non tutte le connessioni verso una base dati MySQL debbono necessariamente provenire dal Proxy: e' possibile realizzare sofisticate architettura con differenti livelli di sicurezza a seconda della provenienza delle connessioni.
Nella figura a lato e' mostrata un'implementazione che consente di soddisfare i requisiti della attuale legge italiana.

La legge in vigore e' il Codice in materia di protezione dei dati personali (d.lg. 30 giugno 2003, n. 196) e, in particolare, gli artt. 31 ss. e 154, comma 1, lett. c) e h), nonche' il disciplinare tecnico in materia di misure minime di sicurezza di cui all'allegato B del medesimo Codice. Tale legge inquadra in modo completo la materia ma, dal punto di vista pratico, sono molto importanti i provvedimenti del Garante. Il provvedimento del Garante del 27 novembre 2008 (Rif. Misure e accorgimenti prescritti ai titolari dei trattamenti... ) relativo a "Misure e accorgimenti prescritti ai titolari dei trattamenti effettuati con strumenti elettronici relativamente alle attribuzioni delle funzioni di amministratore di sistema" e' stato pubblicato sulla G.U. n. 300 del 24 dicembre 2008. Tale provvedimento prevede al comma 4.5 "Devono essere adottati sistemi idonei alla registrazione degli accessi logici (autenticazione informatica) ai sistemi di elaborazione e agli archivi elettronici da parte degli amministratori di sistema." Sono inoltre definiti i dettagli sulla ritenzione dei log, sulla loro archiviazione, i controlli e la loro frequenza, ... Il provvedimento e' stato ulteriormente modificato con provvedimento del 25 Giugno 2009 (Rif. Modifiche del provvedimento del 27 novembre 2008...) che, al comma c), ne proroga l'adozione alla data definitiva del 15 Dicembre 2009.
Insomma dal 15 Dicembre 2009 vanno registrati tutti gli accessi amministrativi ai sistemi ed alle basi dati!

Su MySQL e' disponibile il parametro init_connect che consente di lanciare statement custom al momento della connect. Ma il parametro init_connect non si applica agli utenti DBA, quindi non e' possibile utilizzarlo per tracciare le utenze amministrative. Per tale ragione viene utilizzato il proxy per il logging delle sessioni amministrative. L'altra soluzione, tecnicamente possibile poco pratica nella maggioranza dei casi, sarebbe stata quella di tracciare ogni statement SQL e poi filtrali...

Un altro importante utilizzo di MySQL Proxy e' il load balancing. Se vengono definiti piu' MySQL backend la politica di default e' il round robin. Ma con il LUA e' possibile programmare qualsiasi altro tipo di associazione si voglia. Ad esempio MySQL Proxy puo' essere utilizzato per separare il carico applicativo riconoscendo il tipo di statement richiamati ed indirizzandoli verso una complessa architettura replicata. In questo caso non e' necessaria alcuna modifica applicativa e si puo' ottenere una scalabilita' orizzontale elevatissima sfruttando la replicazione di MySQL:

MySQL Proxy Replication Scalability
Amministrazione

Generalmente MySQL Proxy non richiede alcuna amministrazione. E' tuttavia disponibile un plugin di amministrazione che presenta un'interfaccia "SQL" (porta 4041 di default). I contenuti possono essere programmati con un apposito script richiamato dal parametro admin-lua-script. Ad esempio per ottenere informazioni sui server di backend MySQL ed il numero di connessioni presenti:

# mysql --host=127.0.0.1 --port=4041 --user=root --password=secret
...
mysql> show;
+-----------------------+--------------------+
| object                | value              |
+-----------------------+--------------------+
| Proxy Version (hex)   | 1794               |
|                       |                    |
| Backend #             | 2                  |
| Backend 1             | 10.123.123.69:3306 |
| Backend 1 connections | 7                  |
| Backend 2             | 10.123.123.70:3306 |
| Backend 2 connections | 6                  |
+-----------------------+--------------------+
E' necessario un script come il seguente:
function read_query(packet)
    if packet:byte() ~= proxy.COM_QUERY then
        proxy.response = {
            type = proxy.MYSQLD_PACKET_ERR,
            errmsg = "Command supported: SHOW" }
        return proxy.PROXY_SEND_RESULT
    end

    if string.sub(packet, 2):lower() == 'show' then
            return show_info()
    else
            return show_help()
    end
end

function show_help()
  proxy.response.type = proxy.MYSQLD_PACKET_OK
  proxy.response.resultset = {
    fields = {
      { type = proxy.MYSQL_TYPE_STRING, name = "command", },
      { type = proxy.MYSQL_TYPE_STRING, name = "description", }, },
    rows = {
        {'SHOW', 'Show all useful information.'}, } }
  return proxy.PROXY_SEND_RESULT
end

function show_info()
  proxy.response.type = proxy.MYSQLD_PACKET_OK
  proxy.response.resultset = {
    fields = {
      { type = proxy.MYSQL_TYPE_STRING, name = "object", },
      { type = proxy.MYSQL_TYPE_STRING, name = "value", }, },
    rows = {
        {'Proxy Version (hex)', proxy.PROXY_VERSION},
        {'', ''},
        {'Backend #', #proxy.global.backends},
    }
  }
  local a = proxy.response.resultset["rows"]
  for i = 1, #proxy.global.backends do
    local b = proxy.global.backends[i]
    a[#a + 1] = { "Backend " .. i, b.dst.name }
    a[#a + 1] = { "Backend " .. i .. " connections", b.connected_clients }
  end
  return proxy.PROXY_SEND_RESULT
end

Nelle versioni precedenti (<0.7) l'interfaccia di amministrazione era preprogrammata nel sorgente C e riconosceva tre specifiche query:

mysql> select * from help;
+---------------------------------+--------------------------------------------+
| command                         | description                                |
+---------------------------------+--------------------------------------------+
| select * from proxy_connections | show information about proxy connections   | 
| select * from proxy_config      | show information about proxy configuration | 
| select * from help              | show the available commands                | 
+---------------------------------+--------------------------------------------+

In ambiente Unix MySQL proxy gira come demone. E' quindi necessario creare uno script di startup da configurare al boot del sistema o agganciato ad un servizio cluster. Nel capitolo seguente e' riportato un esempio completo.

Esempi completi

Ecco un esempio di uno script completo che traccia tutte le attivita' di connessione al DB, riporta le query piu' lunghe, effettua una SQL injection, ... e consente, con una semplice modifica, di tracciare ogni query eseguita sulla base dati:

--[[ $%BEGINLICENSE%$

 logging.lua v.1.0.5 - Apr 31th 2010

  Enables MySQL login full tracing and long queries logging
  SQL DoS attack logging (GRANT/REVOKE/DROP commands are logged)
  Full SQL tracing easy setup
  Log format has been specifically customized for SPLUNK data collection
  Client IP addresses are injected into the queries
  stdio is flushed to avoid buffering

 Copyright (C) 2009,2010 mail@meo.bogliolo.name

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; version 2 of the License.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 $%ENDLICENSE%$ --]]


function connect_server()
  print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" ..
    "command=CONNECT" .. ";" ..
    "sourceip="..proxy.connection.client.src.name .. ";"
  )
end

function read_handshake()
  print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" ..
    "command=HANDSHAKE" .. ";" ..
    "sourceip="..proxy.connection.client.src.name .. ";" ..
    "destination="..proxy.connection.server.dst.name .. ";" ..
    "version="..proxy.connection.server.mysqld_version .. ";" ..
    "thread="..proxy.connection.server.thread_id ..";"
  )
end

function read_auth()
  print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" ..
    "command=AUTH" .. ";" ..
    "sourceip="..proxy.connection.client.src.name .. ";" ..
    "destination="..proxy.connection.server.dst.name .. ";" ..
    "thread="..proxy.connection.server.thread_id ..";" ..
    "username="..proxy.connection.client.username .. ";" ..
    "default_db="..proxy.connection.client.default_db .. ";"
  )
end

function read_auth_result( auth )
  local state = auth.packet:byte()
  if state == proxy.MYSQLD_PACKET_OK then
    print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" ..
      "command=LOGIN" .. ";" ..
      "sourceip="..proxy.connection.client.src.name .. ";" ..
      "destination="..proxy.connection.server.dst.name .. ";" ..
      "status=OK" .. ";" ..
      "thread="..proxy.connection.server.thread_id ..";" ..
      "username="..proxy.connection.client.username .. ";" ..
      "default_db="..proxy.connection.client.default_db .. ";"
    )
  elseif state == proxy.MYSQLD_PACKET_ERR then
    print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" ..
      "command=LOGIN" .. ";" ..
      "sourceip="..proxy.connection.client.src.name .. ";" ..
      "destination="..proxy.connection.server.dst.name .. ";" ..
      "status=KO" .. ";" ..
      "thread="..proxy.connection.server.thread_id ..";" ..
      "username="..proxy.connection.client.username .. ";" ..
      "default_db="..proxy.connection.client.default_db .. ";"..
      "notes=" .. string.format("%q", auth.packet:sub(10)) .. ";"
    )
  else
    print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" ..
      "command=LOGIN" .. ";" ..
      "sourceip="..proxy.connection.client.src.name .. ";" ..
      "destination="..proxy.connection.server.dst.name .. ";" ..
      "status=UNKNOWN" .. ";" ..
      "thread="..proxy.connection.server.thread_id ..";" ..
      "username="..proxy.connection.client.username .. ";" ..
      "default_db="..proxy.connection.client.default_db .. ";" ..
      "notes=" ..  string.format("%q", auth.packet) .. ";"
    )
  end
  io.stdout:flush()
end

function read_query( packet )
  if packet:byte() == proxy.COM_QUIT then
    print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" ..
      "command=LOGOUT" .. ";" ..
      "sourceip="..proxy.connection.client.src.name .. ";" ..
      "destination="..proxy.connection.server.dst.name .. ";" ..
      "thread="..proxy.connection.server.thread_id ..";" ..
      "username="..proxy.connection.client.username .. ";" ..
      "default_db="..proxy.connection.client.default_db .. ";"
    )
  io.stdout:flush()
  end
  if string.byte(packet) == proxy.COM_QUERY then
    local query = "/* " .. proxy.connection.client.src.address .. " */ " .. string.sub(packet, 2)
    -- DEBUG: comment the condition to enable full SQL tracing (if...or  end)
    if string.find(string.upper(query), "GRANT")
       or string.find(string.upper(query), "REVOKE")
       or string.find(string.upper(query), "DROP") then
      print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" ..
        "command=QUERY" .. ";" ..
        "sourceip="..proxy.connection.client.src.name .. ";" ..
        "destination="..proxy.connection.server.dst.name .. ";" ..
        "thread="..proxy.connection.server.thread_id ..";" ..
        "username="..proxy.connection.client.username .. ";" ..
        "default_db="..proxy.connection.client.default_db .. ";" ..
        "query=" .. query .. ";"
      )
      io.stdout:flush()
    end

    proxy.queries:append(1, string.char(proxy.COM_QUERY) .. query )
    return proxy.PROXY_SEND_QUERY
  end
end

function read_query_result(inj)
  if inj.response_time > 5*1000*1000 then
    print( "date="..os.date("%Y-%m-%d %H:%M:%S") .. ";" ..
      "command=QUERY" .. ";" ..
      "sourceip="..proxy.connection.client.src.name .. ";" ..
      "destination="..proxy.connection.server.dst.name .. ";" ..
      "thread="..proxy.connection.server.thread_id ..";" ..
      "username="..proxy.connection.client.username .. ";" ..
      "default_db="..proxy.connection.client.default_db .. ";" ..
      "query=" .. string.sub(inj.query, 2) .. ";" ..
      "query-time=" .. (inj.query_time / 1000) .. ";" ..
      "response-time=" .. (inj.response_time / 1000) .. ";"
    )
  io.stdout:flush()
  end
end

In ambiente Unix MySQL proxy gira come demone. Ecco l'esempio di uno script di startup da configurare al boot del sistema o agganciato ad un servizio cluster:

#!/bin/sh
# mysql_proxy v.1.0.1 startup script
#
# Usually in /etc/init.d, accepts start/stop/status commands

install_dir=/usr/local/mysql-proxy
back_end=collsql.xenialab.it:3306
script_file=$install_dir/share/my_script.lua
exec_file=$install_dir/sbin/mysql-proxy
pid_file=$install_dir/proxy.PID
log_file=$install_dir/proxy.out

mode=$1    # start or stop or status

case "$mode" in
  'start')
    # Start daemon
    echo $echo_n "Starting MySQL Proxy"
    cd $install_dir
    $exec_file --pid-file=$pid_file --proxy-backend-addresses=$back_end --proxy-lua-script=$script_file >> $log_file &2>&1
    ;;

  'stop')
    # Stop daemon.
    if test -s "$pid_file"
    then
      echo $echo_n "Shutting down MySQL Proxy"
      mysqlp_pid=`cat $pid_file`
      kill $mysqlp_pid
      rm "$pid_file"
    else
      echo "MySQL Proxy PID file could not be found!"
    fi
    ;;

  'status')
    # Check MySQL processes
    if test -s "$pid_file"
    then
      echo "MySQL Proxy: is working "
    else
      echo "MySQL Proxy: is NOT working "
    fi
    exit 0
    ;;

  *)
    # usage
    echo "Usage: $0 [start|stop|status]"
    exit 1
    ;;
esac

Testo: MySQL Proxy
Data: 1 Aprile 2008
Versione: 1.0.6 - 31 Aprile 2010
Autore: mail@meo.bogliolo.name