Postgres da record set a csv

Oggi mi è capitato di dover ottenere un csv a partire da un record set di chiavi. Supponiamo quindi di avere un'entita che ha una chiave numerica e di voler ottenere un csv con tutte le chiavi.

L'entità è così formata:

test=> \d utente
           Table "public.utente"
 Column |         Type          | Modifiers 
--------+-----------------------+-----------
 id     | numeric(9,0)          | not null
 name   | character varying(50) | 
Indexes:
    "utente_id_key" UNIQUE CONSTRAINT, btree (id)
 
test=> 
test=> select * from utente;
 id |   name   
----+----------
  1 | ciccio
  2 | paperino
  3 | pluto
  4 | minnie
  5 | paperina
(5 rows)
 
test=>

Per avere il csv di tutte le chiavi useremo la seguente query che sfrutta la funzione string_agg:

test=> select string_agg(id::text, ',') as csv from (select id from utente) as foo;
    csv    
-----------
 1,2,3,4,5
(1 row)
 
test=>

Questa e altre funzioni le trovate documentate nel sito di postgres.

Blog: 

Programmazione: 

Backup dei dati su nastro in Linux

Considerata la vasta offerta di spazio disco in cloud, parlare di backup casalingo su nastro potrebbe sembrare anacronistico. Bisogna però considerare che non tutti hanno a disposizione una connessione di rete veloce e con bassa latenza, quindi il trasefrimento di grosse moli di dati risulta ancora oggi un collo di bottiglia non indifferente.

Di seguito descrivo come ho realizzato un piccolo sistema di backup casalingo su nastro usando principalmente devices usati e a buon mercato.

Ho inizialmente rispolverato un vecchio pc dei tempi dell'università nel quale ho inserito una scheda SCSI. Alla scheda SCSI ho collegato un HP Dat-40 trovato usato su ebay, per il quale si trovano ancora cassette nuove sempre su ebay.

Ho quindi installato la debian sul vecchio pc e ho configurato il kernel in modo che il driver st imposti il buffer a 64kb:

 root@goldrake:~# dmesg | grep bufsize
 [   20.258059] st: Version 20101219, fixed bufsize 32768, s/g segs 256
 root@goldrake:~#
 
 # vim /etc/default/grub
     GRUB_CMDLINE_LINUX_DEFAULT="quiet st.buffer_kbs=64"
 # update-grub
 # reboot
 # dmesg | grep bufsize
 [   20.233873] st: Version 20101219, fixed bufsize 65536, s/g segs 256

Questa modifica rende più veloce la lettura/scrittura sul dat. Infatti supponiamo di dover scrivere un file da 2GB, i tempi nel caso di 32K sono:

        $ mkdir temp && cd temp
        $ dd if=/dev/zero of=dati bs=1024k count=2000
        $ find -L . -print0 | cpio --null -ovH crc -C 32768 -O root@goldrake:/dev/st0 --rsh-command=/usr/bin/ssh
 
        real    8m35.567s
        user    0m4.248s
        sys     0m10.189s
 
        $ cd && mkdir temp2 && cd temp2
        $ cpio -ivmud -H crc -C 32768 -I root@goldrake:/dev/st0 --rsh-command=/usr/bin/ssh
 
        real    8m48.068s
        user    0m9.837s
        sys     0m24.074s
 
        $ diff dati ../temp/dati
        $

mentre nel caso dei 64k:

        gtrev@gundam:~/temp$ find -L . -print0 | cpio --null -ovH crc -C 65536 -O root@goldrake:/dev/st0 --rsh-command=/usr/bin/ssh                                    
 
        gtrev@gundam:~/temp$ cd ..
        gtrev@gundam:~$ mkdir temp3
        gtrev@gundam:~$ cd temp3/
        gtrev@gundam:~/temp3$ time cpio -ivmud -H crc -C 65536 -I root@goldrake:/dev/st0 --rsh-command=/usr/bin/ssh
 
        real    7m40.068s
        user    0m9.717s
        sys     0m23.261s
        gtrev@gundam:~/temp3$ diff dati ../temp/dati
        gtrev@gundam:~/temp3$

Poiché la dimensione di una cassetta DAT compatibile con l'HP DAT 40 è di 20GB non compressi, ho definito un filesystem di esattamente 20GB nel server casalingo: questo è il filesystem che viene regolarmente salvato su nastro. Poiché il server è configurato con lvm, devo eseguire le seguenti operazioni per creare il nuovo filesystem:

  • Verifico di avere spazio su disco:
       root@gundam:/# vgdisplay gundam | grep "Free  PE"
         Free  PE / Size       105379 / 411.64 GiB
       root@gundam:/#
  • Creo un nuovo logical volume di nome backup con dimensione 20G:
       root@gundam:/# lvcreate -L20G -nbackup gundam
  • Creo il filesystem ext4 sul LV appena creato:
       root@gundam:/# mkfs.ext4 /dev/gundam/backup
  • Creo la directory dove voglio montare il nuovo filesystem:
       root@gundam:/# mkdir /backup
  • Aggiorno /etc/fstab con la riga:
       /dev/mapper/gundam-backup /backup        ext4    defaults        0       2
  • Monto il filesystem:
       root@gundam:/# mount -a  

A questo punto il backup consiste nell'inserire la cassetta nel dat ed eseguire il seguente comando:

    $ find -L . -print0 | cpio --null -ovH crc -C 65536 -O root@goldrake:/dev/st0 --rsh-command=/usr/bin/ssh

mentre se dobbiamo estrarre i dati dalla cassetta:

    $ cpio -ivmud -H crc -C 65536 -I root@goldrake:/dev/st0 --rsh-command=/usr/bin/ssh

Blog: 

Programmazione: 

Un mediacenter con Serviio



Serviio è una applicazione che fornisce tutte le funzionalità tipiche di un media center. Di seguito vedremo come installarla su un server debian headless.

Per prima cosa dovremo installare Java: l'ultima versione attualmente disponibile di serviio richiede che sia installato java 8. Per l'installazione di java rimando ad un mio vecchio post.

Unaa volta installato java dovremo installare ffmpeg. La versione di ffmpeg che si trova nei repository debian è piuttosto vecchia quindi consiglio di prendere quella compilata staticamente per la propia architettura (32/64 bit) direttamente da qui.

Arrivati a questo punto possiamo scaricare Serviio da questo link.

L'installazione prevede di scompattare l'archivio scaricato in una directory a piacere. Nel caso si esegua un upgrade è sufficiente ricordarsi di portare la directory library dalla precedente versione, in questo modo non si perdono i riferimenti alle librerie che si sono condivise.

Se si vuole far partire serviio all'avvio del computer si può creare uno script di init. A questo link ne ho trovato uno che riporto qui per completezza: in

/etc/default

si deve creare il file con nome serviio con il seguente contenuto:

#########################################################
#- Daemon Script Configuration for Serviio Media Server
#- By Ian Laird
#- /etc/default/serviio
#########################################################
 
NAME="Serviio Media Server"
DAEMON="/opt/serviio-current/bin/serviio.sh"    ## Update this to point at serviio_root/bin/serviio.sh
SERVICE_ACCOUNT="gtrev"                       ## change to an appropriate username, DON'T RUN UNDER ROOT!

mentre in:

/etc/default

si deve inserire:

#!/bin/bash
#
#########################################################
#- Daemon script for Serviio media server
#- By Ian Laird; converted for Debian by Jacob Lundberg
#- /etc/init.d/serviio
#########################################################
#
### BEGIN INIT INFO
# Provides:          serviio
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# X-Interactive:     true
# Short-Description: Start/stop serviio media server
# Description:       The Serviio media server makes your media available to
#                    all kinds of networked devices.
### END INIT INFO
 
 
. /lib/lsb/init-functions
 
if [ -f /etc/default/rcS ]; then
        . /etc/default/rcS
fi
 
 
DAEMON_STOP=" -stop"
NAME="$(basename $0)"
PIDFILE="/var/run/serviiod.pid"
TIMEOUT=10
 
if [ -f /etc/default/serviio ]; then
        . /etc/default/serviio
fi
 
[ -x "$DAEMON" ] || exit 0
 
 
running() {
        if [ "x$1" == "x" ]; then
                echo 0
                return 1
        fi
 
        PS=$(ps h -p $(echo $1 | sed -r 's/[\t \n]+/ -p /') | wc -l)
        echo $PS
 
        if [ $PS -gt 0 ]; then
                return 0
        else
                return 1
        fi
}
 
 
start() {
        log_daemon_msg "Starting Serviio media server daemon" "$NAME"
        start-stop-daemon --start -q -b -p "$PIDFILE" -m -c "${SERVICE_ACCOUNT}" -x "${DAEMON}"
        log_end_msg $?
}
 
stop() {
        log_daemon_msg "Stopping Serviio media server daemon" "$NAME"
        if [ -r "$PIDFILE" ]; then
                PIDS=$(pstree -p $(<"$PIDFILE") | awk -F'[\(\)]' '/^[A-Za-z0-9]/ { print $2" "$4; }')
                if running "$PIDS" > /dev/null; then
                        "${DAEMON}" "${DAEMON_STOP}"
                        for PID in $PIDS; do
                                if running $PID > /dev/null; then
                                        kill -TERM $PID
                                fi
                        done
                fi
                COUNTDOWN=$TIMEOUT
                while let COUNTDOWN--; do
                        if ! running "$PIDS" > /dev/null; then
                                break
                        fi
                        if [ $COUNTDOWN -eq 0 ]; then
                                for PID in $PIDS; do
                                        if running $PID > /dev/null; then
                                                kill -KILL $PID
                                        fi
                                done
                        else
                                echo -n .
                                sleep 1
                        fi
                done
        fi
 
        if running "$PIDS" > /dev/null; then
                log_end_msg 1
        else
                rm -f "$PIDFILE"
                log_end_msg $?
 
        fi
}
 
status() {
        echo -n "$NAME should be"
        if [ -r "$PIDFILE" ]; then
                echo -n " up with primary PID $(<"$PIDFILE")"
                PIDS=$(pstree -p $(<"$PIDFILE") | awk -F'[\(\)]' '/^[A-Za-z0-9]/ { print $2" "$4; }')
                RUNNING=$(running "$PIDS")
                if [[ $RUNNING && $RUNNING -gt 0 ]]; then
                        echo -n " and $RUNNING processes are running."
                else
                        echo -n " but it is not running."
                fi
        else
                echo -n " stopped."
        fi
        echo
}
 
 
case "${1:-}" in
        start)
                start
        ;;
        stop)
                stop
        ;;
        restart)
                stop
                start
        ;;
        status)
                status
        ;;
        *)
                log_success_msg "Usage: /etc/init.d/$NAME {start|stop|restart|status}"
                exit 1
        ;;
esac
 
exit 0

Dopo aver creato i file con il contenuto esposto si deve:

  # chmod 755 /etc/init.d/serviio
  # update-rc.d serviio defaults

In questo modo ad ogni riavvio della macchina il servizio ripartirà in automatico.

Per controllare serviio possiamo usare il suo client facendo attenzione che il client richiede che sia attivo il server X. Ovviamente nel caso in cui, come me, abbiate installato serviio in un server headless è sempre possibile connettersi al servizio dall'esterno. Bisognerà disporre di un computer che abbia l'ambiente grafico attivo: si dovrà scompattare l'archivio di serviio e modificare il file serviio-console.sh indicando l'IP del server che abbiamo prima configurato:

--- /tmp/serviio-console.sh     2015-03-26 23:14:55.916278243 +0100
+++ serviio-console.sh  2014-04-03 20:01:28.731745698 +0200
@@ -54,7 +54,7 @@
 SERVIIO_CONSOLE_CLASS_PATH="$SERVIIO_CONSOLE_HOME/lib/*:$SERVIIO_CONSOLE_HOME/config"
 
 # Setup Serviio specific properties
-JAVA_OPTS="-Dserviio.home=$SERVIIO_CONSOLE_HOME -Djava.net.preferIPv4Stack=true"
+JAVA_OPTS="-Dserviio.remoteHost=10.0.0.12 -Dserviio.home=$SERVIIO_CONSOLE_HOME -Djava.net.preferIPv4Stack=true"
 
 # For Cygwin, switch paths to Windows format before running java
 if $cygwin; then

e sarà sufficiente attivare la console:

gtrev@debian-laptop:~$ cd serviio/serviio-1.4.1.2/bin/
gtrev@debian-laptop:~/serviio/serviio-1.4.1.2/bin$ ./serviio-console.sh 

Blog: 

Programmazione: 

Pagine

Subscribe to gtrev RSS