Archivos de la categoría Scripts

Script en python para convertir secuencias de proteínas de Stockholm a fasta

Aquí os dejo un pequeño python script que convierte “multiple sequence alignments” del formato Stockholm a Fasta de una forma sencilla y rápida.

import sys
from Bio import SeqIO
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord 

if(len(sys.argv) <3):
    print('two arguments needed: input path, output path')
    exit(2) 

with open(sys.argv[1],'r') as inFile:
    with open(sys.argv[2], "w") as output_handle:
        SeqIO.write(list(SeqIO.parse(inFile,'stockholm')), output_handle, "fasta")

Manual para instalar OpenVPN en Ubuntu con script

Hace ya algun tiempo me hice con un servidor y lo voy usando para hacer mis cosicas. Como por ejemplo instalar rTorrent para poder bajarme ficheros el cual estuvo acompañado de otro post para mover ficheros entre el servidor y mi ordenador. Esta vez lo que quiero hacer es usar el server como túnel para evitar contenidos restringidos en el país dónde estoy y mejorar la seguridad en redes abiertas.
Primero de todo tendremos que instalar el software necesario. Para ello ejecutando la siguiente linea en la consola bastará:

wget http://git.io/vpn --no-check-certificate -O openvpn-install.sh; chmod +x openvpn-install.sh; ./openvpn-install.sh

Para los que os gusta hacerlo paso a pasa y configurarlo todo al milímetro al final del post hay un link (en inglés) que os ayudará. Para el resto de mortales el siguiente script lo hace todo, es simplemente un autoinstaller que puede generar claves, revocar certificados y desinstalar OpenVPN.

#!/bin/bash
# OpenVPN road warrior installer for Debian-based distros

# This script will only work on Debian-based systems. It isn't bulletproof but
# it will probably work if you simply want to setup a VPN on your Debian/Ubuntu
# VPS. It has been designed to be as unobtrusive and universal as possible.

if [ $USER != 'root' ]; then
echo "Sorry, you need to run this as root"
exit
fi

if [ ! -e /dev/net/tun ]; then
echo "TUN/TAP is not available"
exit
fi

if [ ! -e /etc/debian_version ]; then
echo "Looks like you aren't running this installer on a Debian-based system"
exit
fi

# Try to get our IP from the system and fallback to the Internet.
# I do this to make the script compatible with NATed servers (lowendspirit.com)
# and to avoid getting an IPv6.
IP=$(ifconfig | grep 'inet addr:' | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d: -f2 | awk '{ print $1}' | head -1)
if [ "$IP" = "" ]; then
IP=$(wget -qO- ipv4.icanhazip.com)
fi

if [ -e /etc/openvpn/server.conf ]; then
while :
do
clear
echo "Looks like OpenVPN is already installed"
echo "What do you want to do?"
echo ""
echo "1) Add a cert for a new user"
echo "2) Revoke existing user cert"
echo "3) Remove OpenVPN"
echo "4) Exit"
echo ""
read -p "Select an option [1-4]: " option
case $option in
1)
echo ""
echo "Tell me a name for the client cert"
echo "Please, use one word only, no special characters"
read -p "Client name: " -e -i client CLIENT
cd /etc/openvpn/easy-rsa/2.0/
source ./vars
# build-key for the client
export KEY_CN="$CLIENT"
export EASY_RSA="${EASY_RSA:-.}"
"$EASY_RSA/pkitool" $CLIENT
# Let's generate the client config
mkdir ~/ovpn-$CLIENT
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/ovpn-$CLIENT/$CLIENT.conf
cp /etc/openvpn/easy-rsa/2.0/keys/ca.crt ~/ovpn-$CLIENT
cp /etc/openvpn/easy-rsa/2.0/keys/$CLIENT.crt ~/ovpn-$CLIENT
cp /etc/openvpn/easy-rsa/2.0/keys/$CLIENT.key ~/ovpn-$CLIENT
cd ~/ovpn-$CLIENT
sed -i "s|cert client.crt|cert $CLIENT.crt|" $CLIENT.conf
sed -i "s|key client.key|key $CLIENT.key|" $CLIENT.conf
tar -czf ../ovpn-$CLIENT.tar.gz $CLIENT.conf ca.crt $CLIENT.crt $CLIENT.key
cd ~/
rm -rf ovpn-$CLIENT
echo ""
echo "Client $CLIENT added, certs available at ~/ovpn-$CLIENT.tar.gz"
exit
;;
2)
echo ""
echo "Tell me the existing client name"
read -p "Client name: " -e -i client CLIENT
cd /etc/openvpn/easy-rsa/2.0/
. /etc/openvpn/easy-rsa/2.0/vars
. /etc/openvpn/easy-rsa/2.0/revoke-full $CLIENT
# If it's the first time revoking a cert, we need to add the crl-verify line
if grep -q "crl-verify" "/etc/openvpn/server.conf"; then
echo ""
echo "Certificate for client $CLIENT revoked"
else
echo "crl-verify /etc/openvpn/easy-rsa/2.0/keys/crl.pem" >> "/etc/openvpn/server.conf"
/etc/init.d/openvpn restart
echo ""
echo "Certificate for client $CLIENT revoked"
fi
exit
;;
3)
apt-get remove --purge -y openvpn openvpn-blacklist
rm -rf /etc/openvpn
rm -rf /usr/share/doc/openvpn
sed -i '/--dport 53 -j REDIRECT --to-port/d' /etc/rc.local
sed -i '/iptables -t nat -A POSTROUTING -s 10.8.0.0/d' /etc/rc.local
echo ""
echo "OpenVPN removed!"
exit
;;
4) exit;;
esac
done
else
echo 'Welcome to this quick OpenVPN "road warrior" installer'
echo ""
# OpenVPN setup and first user creation
echo "I need to ask you a few questions before starting the setup"
echo "You can leave the default options and just press enter if you are ok with them"
echo ""
echo "First I need to know the IPv4 address of the network interface you want OpenVPN"
echo "listening to."
read -p "IP address: " -e -i $IP IP
echo ""
echo "What port do you want for OpenVPN?"
read -p "Port: " -e -i 1194 PORT
echo ""
echo "Do you want OpenVPN to be available at port 53 too?"
echo "This can be useful to connect under restrictive networks"
read -p "Listen at port 53 [y/n]: " -e -i n ALTPORT
echo ""
echo "Finally, tell me your name for the client cert"
echo "Please, use one word only, no special characters"
read -p "Client name: " -e -i client CLIENT
echo ""
echo "Okay, that was all I needed. We are ready to setup your OpenVPN server now"
read -n1 -r -p "Press any key to continue..."
apt-get update
apt-get install openvpn iptables openssl -y
cp -R /usr/share/doc/openvpn/examples/easy-rsa/ /etc/openvpn
# easy-rsa isn't available by default for Debian Jessie and newer
if [ ! -d /etc/openvpn/easy-rsa/2.0/ ]; then
wget --no-check-certificate -O ~/easy-rsa.tar.gz https://github.com/OpenVPN/easy-rsa/archive/2.2.2.tar.gz
tar xzf ~/easy-rsa.tar.gz -C ~/
mkdir -p /etc/openvpn/easy-rsa/2.0/
cp ~/easy-rsa-2.2.2/easy-rsa/2.0/* /etc/openvpn/easy-rsa/2.0/
rm -rf ~/easy-rsa-2.2.2
rm -rf ~/easy-rsa.tar.gz
fi
cd /etc/openvpn/easy-rsa/2.0/
# Let's fix one thing first...
cp -u -p openssl-1.0.0.cnf openssl.cnf
# Fuck you NSA - 1024 bits was the default for Debian Wheezy and older
sed -i 's|export KEY_SIZE=1024|export KEY_SIZE=2048|' /etc/openvpn/easy-rsa/2.0/vars
# Create the PKI
. /etc/openvpn/easy-rsa/2.0/vars
. /etc/openvpn/easy-rsa/2.0/clean-all
# The following lines are from build-ca. I don't use that script directly
# because it's interactive and we don't want that. Yes, this could break
# the installation script if build-ca changes in the future.
export EASY_RSA="${EASY_RSA:-.}"
"$EASY_RSA/pkitool" --initca $*
# Same as the last time, we are going to run build-key-server
export EASY_RSA="${EASY_RSA:-.}"
"$EASY_RSA/pkitool" --server server
# Now the client keys. We need to set KEY_CN or the stupid pkitool will cry
export KEY_CN="$CLIENT"
export EASY_RSA="${EASY_RSA:-.}"
"$EASY_RSA/pkitool" $CLIENT
# DH params
. /etc/openvpn/easy-rsa/2.0/build-dh
# Let's configure the server
cd /usr/share/doc/openvpn/examples/sample-config-files
gunzip -d server.conf.gz
cp server.conf /etc/openvpn/
cd /etc/openvpn/easy-rsa/2.0/keys
cp ca.crt ca.key dh2048.pem server.crt server.key /etc/openvpn
cd /etc/openvpn/
# Set the server configuration
sed -i 's|dh dh1024.pem|dh dh2048.pem|' server.conf
sed -i 's|;push "redirect-gateway def1 bypass-dhcp"|push "redirect-gateway def1 bypass-dhcp"|' server.conf
sed -i "s|port 1194|port $PORT|" server.conf
# Obtain the resolvers from resolv.conf and use them for OpenVPN
cat /etc/resolv.conf | grep -v '#' | grep 'nameserver' | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | while read line; do
sed -i "/;push \"dhcp-option DNS 208.67.220.220\"/a\push \"dhcp-option DNS $line\"" server.conf
done
# Listen at port 53 too if user wants that
if [ $ALTPORT = 'y' ]; then
iptables -t nat -A PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-port $PORT
sed -i "/# By default this script does nothing./a\iptables -t nat -A PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-port $PORT" /etc/rc.local
fi
# Enable net.ipv4.ip_forward for the system
sed -i 's|#net.ipv4.ip_forward=1|net.ipv4.ip_forward=1|' /etc/sysctl.conf
# Avoid an unneeded reboot
echo 1 > /proc/sys/net/ipv4/ip_forward
# Set iptables
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j SNAT --to $IP
sed -i "/# By default this script does nothing./a\iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j SNAT --to $IP" /etc/rc.local
# And finally, restart OpenVPN
/etc/init.d/openvpn restart
# Let's generate the client config
mkdir ~/ovpn-$CLIENT
# Try to detect a NATed connection and ask about it to potential LowEndSpirit
# users
EXTERNALIP=$(wget -qO- ipv4.icanhazip.com)
if [ "$IP" != "$EXTERNALIP" ]; then
echo ""
echo "Looks like your server is behind a NAT!"
echo ""
echo "If your server is NATed (LowEndSpirit), I need to know the external IP"
echo "If that's not the case, just ignore this and leave the next field blank"
read -p "External IP: " -e USEREXTERNALIP
if [ $USEREXTERNALIP != "" ]; then
IP=$USEREXTERNALIP
fi
fi
# IP/port set on the default client.conf so we can add further users
# without asking for them
sed -i "s|remote my-server-1 1194|remote $IP $PORT|" /usr/share/doc/openvpn/examples/sample-config-files/client.conf
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/ovpn-$CLIENT/$CLIENT.conf
cp /etc/openvpn/easy-rsa/2.0/keys/ca.crt ~/ovpn-$CLIENT
cp /etc/openvpn/easy-rsa/2.0/keys/$CLIENT.crt ~/ovpn-$CLIENT
cp /etc/openvpn/easy-rsa/2.0/keys/$CLIENT.key ~/ovpn-$CLIENT
cd ~/ovpn-$CLIENT
sed -i "s|cert client.crt|cert $CLIENT.crt|" $CLIENT.conf
sed -i "s|key client.key|key $CLIENT.key|" $CLIENT.conf
tar -czf ../ovpn-$CLIENT.tar.gz $CLIENT.conf ca.crt $CLIENT.crt $CLIENT.key
cd ~/
rm -rf ovpn-$CLIENT
echo ""
echo "Finished!"
echo ""
echo "Your client config is available at ~/ovpn-$CLIENT.tar.gz"
echo "If you want to add more clients, you simply need to run this script another time!"
fi

“Happy tunneling

Bonus: Para los que os guste un poco más el heavy metal aquí un tutorial paso a paso con explicaciones más detalladas.

Que formato es el mejor para guardar números con decimales (float)?

Hace ya algunos días que le estoy dando vueltas al crear un script que me cogiera determinados datos y los fuera guardando en un archivo. Como quiero guardar muchos datos durante un largo periodo de tiempo he pensado que quizás debería empezar por lo básico. Que formato de archivo es mejor para almacenar este tipo de datos.

Para averiguar que formato es el ideal para tal propósito he ideado un script en python que lo que hace es generar cuatro números aleatorios entre -10 y 10 por cada una de las 100.000 hileras disponibles (en total 400.000 valores). Luego, usando el mismo data set, he almacenado esta información usando distintos formatos. Los formatos que he usado son texto plano, CSV, TSV, JSON, SQLite y HDF5. Estos formatos son los que me han parecido adecuados para este tipo de tarea. He dejado fuera XML porque me pareció que tiene gran similitud con JSON y realmente no necesito la jerarquía ni flexibilidad que este formato me ofrece.

Véase que el mismo script indica el tamaño de cada fichero. El tiempo de ejecución es de unos 65 segundos en mi laptop.

El script:


import numpy as np
import os
from os import listdir
from os.path import isfile, join

import json
import csv
import sqlite3
import h5py #pip install h5py

#generated 4 rows with number_of_floats data
def data_generation(number_of_floats):
	ret = np.ndarray((number_of_floats, 4))
	for i in range(number_of_floats):
		ret[i] = np.random.uniform( -10, 10, 4 )
	return ret

#standard text saving
def save_text_file(data):
	f = open('text.txt', 'w')
	for el in data:
		f.write(str(el).strip('[]'))
		f.write('\n')
	f.close()
	return True

#saving with json files
def save_json(data):
	f = open('json.json', 'w')
	j=json.dumps(data.tolist())
	json.dump(j, f)
	f.close()
	return True

#saving numbers on csv
def save_csv(data):
	with open('csv.csv', 'w') as csvfile:
		fieldnames = ['Col_A', 'Col_B', 'Col_C', 'Col_D']
		writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
		for el in data:
			writer.writerow({'Col_A': str(el[0]), 'Col_B': str(el[1]),'Col_C': str(el[2]),'Col_D': str(el[3])})
	return True

#Tab Separated Values (TSV)
def save_tsv(data):
	with open('tsv.tsv', 'w') as tsvfile:
		writer = csv.writer(tsvfile, delimiter='\t')
		for el in data:
				writer.writerow(el)
	return True

#save data in sqlite
def save_sqlite(data):
	conn = sqlite3.connect('data.sqlite3')
	cur = conn.cursor()
	cur.execute('DROP TABLE IF EXISTS Data ')
	cur.execute('CREATE TABLE Data (Col_A REAL, Col_B REAL, Col_C REAL, Col_D REAL)')
	for el in data:
		cur.execute('INSERT INTO Data VALUES ('+str(el[0])+', '+str(el[1])+', '+str(el[2])+', '+str(el[3])+')')
	conn.commit()
	conn.close()

#save the data in a hdf file
def save_hdf(data):
	h = h5py.File('data.hdf5', 'w')
	dset = h.create_dataset('data', data=data)

#check the file size
def show_file_size():
	mypath = '.'
	onlyfiles = [ f for f in listdir(mypath) if isfile(join(mypath,f)) ]
	for fil in onlyfiles:
		statinfo = os.stat(fil)
		print 'name: '+str(fil)
		print 'size: '+str(statinfo.st_size)
		print ' '
	print onlyfiles

##############################
#
# Main
#
##############################

data = data_generation(100000)
save_text_file(data)
save_csv(data)
save_json(data)
save_csv(data)
save_tsv(data)
save_sqlite(data)
save_hdf(data)
show_file_size()
print 'Done'

Finalmente los resultados:

data-format-comparsion-plot

Formato Tamaño (Bytes)
Texto plano 4806060
CSV 5900742
TSV 7901330
JSON 8109034
SQLite 4468736
HDF5 3202144

Como se puede observar HDF5 es el ganador claramente siendo casi un 30% menor en tamaño que Sqlite que está ocupando el segundo lugar. No es de extrañar puesto que HDF es un formato de fichero diseñado especialmente para organizar y almacenar grandes cantidades de datos (ideado para supercomputadores). Para nuestra suerte las librerías tienen licencia BSD permitiendo mejoras y creación aplicaciones por parte de terceros. Lo que no me esperaba es que TSV obtuviera un tamaño similar a JSON y no a CSV. Sinceramente pensaba que CSV y TSV eran básicamente lo mismo.

Bonus: Para los interesados el script está en github.