SSL Reverse proxy con Apache

Un ejemplo que sirve para Meteor:


SSLProxyEngine On
# snake oil certs in proxyied service -> skip checks
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off

ProxyRequests Off
ProxyPreserveHost On

ProxyPass /websocket ws://localhost:3000/websocket
ProxyPassMatch ^/sockjs/(.*)/websocket ws://localhost:3000/sockjs/$1/websocket

ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
ProxyPassReverseCookiePath / /
ProxyPassReverseCookieDomain 127.0.0.1 52.211.154.50
RequestHeader set X-Forwarded-Proto "https"

Parece que en nginx la configuración análoga es trivial. Quizá sea un buen argumento para convertirse…

Secure cookies over reverse proxy with https

HTML

Etiquetas básicas

# Estructura:
<body>, <section>, <article>, <nav>, <aside>, <header>, <footer>, <h1>..<h6>, <details>, <summary>
# aside se aconseja para barras lateras, textos explicativos, bloques destacados...

# Semántica:
<a>, <p>, <form>, <img>, <table>, <ol>, <ul>, <dl>, <code>, <small>, <cite>, <quote>, <abbr>, <mark>, <dfn>, <data>, <time>, <var>, <address>, <figure>, <figcaption>

# Estilo:
# Ojo que tanto <div> como <span> no siguen una estructura jerárquica (aún cuando se aniden)
 <div>, <span>

<!-- Comentario -->

Etiquetas obsoletas

<b> -> font-style:bold / <strong>
<i> -> font-style:italic / <em>
<u> -> text-decoration:underline
<acronym> -> <abbr>
<tt>, <xmp>
<applet> -> <object>
<center>, <font>, <big>
<frame>
# atributos: align, background, bgcolor 

Caracteres referenciados

Lista completa (W3C)

Los más habituales:

# espacio en blanco
&nbsp;

# acentos -> acute
&Aacute; &oacute

# acentos invertidos -> grave
&egrave;

# tilde, ñ
&atilde; &ntilde;

# ampersand, copyright, grado
&amp; &copy; &deg;

# dolar, euro
&dollar; &euro;

# flechas -> arrow
&leftarrow; &uparrow; &rightarrow; &downarrow; 

Ejemplo de página básica

<!DOCTYPE html>
<head>
   <meta charset="UTF-8" />
   <title>Título de la página</title>
   <style>...</style>
</head>
<body>
  <header>
    <h1>Título cabecera (Nombre del sitio web)</h1>
  </header>
   
  <nav>
    <header>
      <h2>Título navegación</h2>
    </header>
    <ul>... </ul>
  </nav>
   
  <article>
    <header>
      <h1>Título del artículo</h1>
      <h2>Subtítulo del artículo</h2>
    </header>
     
    <section>
      <h3>Título de la sección</h3>
    </section>
    
    <footer>
      <h4>Título del pie del artículo</h4>
    </footer>
  </article>
   
  <aside>
    <h2>Título del texto explicativo</h2>
     
    <section>
    </section>
  </aside>
   
  <footer>
     Pie de página
  </footer>
</body>

Referencias

“Dive into HTML5”, por Mark Pilgrim.

Text level semantics

Smashing Magazine:

HTML5 semantics
Designing a HTML5 layout from scratch

MDN HTML Developer Guide:

Using HTML sections & outlines

Obsolete things to avoid

HTML5Doctor:

Details & summary elements

Analizar datos estructurados desde la línea de comandos

Para texto plano basta con herramientas clásicas como awk, pero para datos dentro de páginas HTML o en Json hay alternativas más cómodas:

  • jq: JSON
  • scrape: HTML (XPath)

Patrones

Extraer las celdas de una tabla

# -a permite seleccionar sólo uno de los atributos de los elementos encontrados
# la expresion Xpath puede contener "|" para elegir varios elementos según diferentes criterios
# para quedarse sólo con el texto debería bastar /text() , pero en scrape no funciona...
scrape -a id -e '//td[@class="temperature"]' < fichero

Unir dos líneas

# cada - une una nueva linea
paste - -
sed 'N'

Eliminar etiquetas HTML

sed 's_<[^>]*>__g'

Cambiar de separador

# de : a espacio
tr ":" " "

Pasar de hora a época

# actualizar base a la época correspondiente al dia
# en el ejemplo, se añaden 16 días extra 
# el fichero de entrada tiene tres columnas: hora, minuto, dato
awk 'BEGIN{base=1465596000+(16*24*3600)}{print ($1*3600 + $2*60 + base) " " $3}'

Gráfica de dos series de tiempos

gnuplot
plot "serie1.txt" using 1:2, "serie2.txt" using 1:2

Más info: Data science at the command line / Introducción a Xpath

lynx, xmllint y ejemplos Xpath

Más ejemplos de XPath

Maquetar con Scribus

Para variar el tamaño de una imagen, cambiar el tamaño del marco con la opción Imagen/”Escalar al tamaño del marco” seleccionada. Para “recortarla”, cambiar a Imagen/”Escalado libre” y cambiar el tamaño del marco.

Para cambios rápidos, se pueden usar los comandos “ajustar marco a imagen” y “ajustar imagen a marco”

Para rotar una imagen, XYZ/Rotar.

Para numerar las páginas, entrar en Editar/Páginas maestras, añadir un marco de texto y dentro de él insertar Caracter/Número de página

Para exportar a CMYK, activar la gestión de color en las preferencias del documento. En las opciones de “Exportar como PDF”, elegir compatibilidad “PDF/X3” y en la pestaña color, “salida dirigida a impresora”.

Para reducir el tamaño del PDF, elegir “compresión JPEG con pérdidas”, limitar la resolución (por ejemplo, a 300 ppp) y seleccionar una calidad de compresión media.

Interfaces X11 tradicionales en la nube

No todas las herramientas que uno quiere utilizar en la nube se han desarrollado en base a las APIs específicas, con lo cual puede ser necesario montar capas intermedias de adaptación para que al usuario final le resulte igual de cómodo.

Una de las opciones más interesantes es Guacamole, un paquete que encapsula de forma eficiente el acceso a un servicio X11. Una vez instalado, el usuario se autentica y puede disponer de un escritorio remoto como si fuese local. Eso sí, conviene delimitar sus posibilidades para que no lo utilice con fines ajenos a la aplicación.

La instalación de guacamole en Ubuntu es relativamente sencilla:

# instalar servidor VNC
apt-get install tightvncserver

# instalar dependencias del servidor Guacamole
apt-get install libjpeg-turbo8-dev libcairo2-dev libossp-uuid-dev libpng12-dev libvncserver-dev tomcat6

# "compilar" el servidor
cd guacamole-server-0.9.9/
./configure --with-init-dir=/etc/init.d
make -j 4
make install
# añadir a /etc/bash.bashrc
export LD_LIBRARY_PATH=/usr/local/lib
export GUACAMOLE_HOME=/etc/guacamole

# instalar dependencias del cliente Guacamole
apt-get install maven2

# instalar cliente
cd guacamole-client-0.9.9/
mvn package
cp guacamole/target/guacamole-0.9.9.war /var/lib/tomcat6/webapps/

# configuración básica guacamole
# guacamole.properties
guacd-hostname: localhost
guacd-port:     4822
## Auth provider class (authenticates user/pass combination, needed if using the provided login screen)
auth-provider: net.sourceforge.guacamole.net.basic.BasicFileAuthenticationProvider
basic-user-mapping: /etc/guacamole/user-mapping.xml

# user-mapping.xml - cambiar USERNAME, PASSWORD y VNCPASS 😉
<user-mapping>
    <authorize username="USERNAME" password="PASSWORD">
        <protocol>vnc</protocol>
        <param name="hostname">localhost</param>
        <param name="port">5900</param>
        <param name="password">VNCPASS</param>
    </authorize>
</user-mapping>

# configurar el conector de Tomcat en /etc/tomcat6/server.xml
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               URIEncoding="UTF-8"
               address="127.0.0.1"
     redirectPort="8443" />

# arrancar demonio guacamole y reiniciar Tomcat
/etc/init.d/guacd restart
/etc/init.d/tomcat6 restart

# instalar "escritorio ligero"
apt-get install lxde
# arrancar servidor VNC
vncserver -localhost

# configurar el proxy en apache
ProxyPass /guacamole/ http://localhost:8080/guacamole-0.9.9/ flushpackets=on
ProxyPassReverse /guacamole/ http://localhost:8080/guacamole-0.9.9/

En caso de problemas, puede obtenerse información adicional en los ficheros /var/log/tomcat6/catalina.out, /var/log/syslog, ~/.vnc/HOSTNAME.log

En “create a Guacamole appliance” vienen cómo configurar la autenticación contra una base de datos MySQL.

La guía de usuario de Guacamole está bastante completa.

Otras opciones son novnc (que parece menos maduro) y x2go (bastante potente, pero de momento require modificar el equipo cliente, aunque sólo sea para instalar el plugin para el navegador…) Dentro del software commercial: Remote visualization, de Adaptive Computing.

Distribución de programas en Linux. Construcción estática

La comodidad de instalar la mayoría de los programas “localmente” (con herramientas tipo apt, yum, zypper…) nos hace olvidar uno de los puntos débiles de Linux: la distribución de programas.

Cuando el código fuente está disponible y las dependencias son pocas, lo normal es que el programa se compile sin demasiados dolores de cabeza.

En otro caso, la cosa se complica. Lo habitual es compilar el programa para las distribuciones más comunes, y ofrecerlo para descarga en el formato de paquete correspondiente (.deb, .rpm…) O bien, montar un repositorio público que se pueda añadir a la lista de orígenes de paquetes.

En estos tiempos de tiendas de aplicaciones para todos, comienza a sonar raro lo de querer instalar un programa “a mano”, pero es algo que al menos en Linux sigue siendo necesario. Por ejemplo, cuando careces de privilegios en un servidor remoto. Si el servidor tiene un entorno más o menos propicio a la compilación, suele bastar con bajarse el código y crear los binarios.

En este sentido, hay que reconocerle a Windows el mérito de soportar binarios de versiones antiguas (incluyendo bastante de la época MS-DOS). Siempre que no se recurriese a enlace dinámico (que lleva al famoso “dll hell”)

Algunas referencias para los valientes que quieran penetrar el mundillo de los binarios Linux portables:

# Origen: http://insanecoding.blogspot.in/2012/07/creating-portable-linux-binaries.html
ldd app
objdump -T app | grep GLIBC_
# enlace estático curl, ssl, crypto; dinámico zlib, dl, threads, rt
gcc -o app *.o -static-libgcc -Wl,-Bstatic -lcurl -lssl -lcrypto -Wl,-Bdynamic -lz -ldl -lpthread -lrt 

# Origen: http://askubuntu.com/questions/315907/libc-so-6-version-glibc-2-16-not-found
/catbed/ld-linux.so.3 --library-path=/catbed:/whatever-else /usr/bin/python -python-args
# como especificar parametros enlace estático en cmake
# origen: http://cmake.3232098.n2.nabble.com/Howto-compile-static-executable-td5580269.html
  set(CMAKE_EXE_LINKER_FLAGS -static)
    set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
    set(CMAKE_EXE_LINK_DYNAMIC_C_FLAGS)       # remove -Wl,-Bdynamic
    set(CMAKE_EXE_LINK_DYNAMIC_CXX_FLAGS)
    set(CMAKE_SHARED_LIBRARY_C_FLAGS)         # remove -fPIC
    set(CMAKE_SHARED_LIBRARY_CXX_FLAGS)
    set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS)    # remove -rdynamic
    set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) 

Comandos útiles Linux

# simple way to make propagate "execute" permissions (X sets execute if x is already set in some of the classes)
chmod -R a+X start_dir

# account expiration -> chage
chage -l USER

# disable bell / beep in terminal
xset b off

# ssh tunnels
# basic: VNC tunnel for display :4
ssh -L 5904:localhost:5904 usr23@remote-desktop.atwork.com

# Scenario 1: final is behind NAT, firewall at work, gateway host
# at final, create a "reverse tunnel" T1 from gateway to final. You will connect to port 22 of final (standard SSH) through port 8022 at gateway
ssh -R  8022:final.atwork.com:22 usr2@gateway.atwork.com
# at L, create a tunnel T2 from your laptop L port 8122 to port 8022 of gateway
ssh -L 8122:gateway.atwork.com:8022 usr2@gateway.atwork.com
# at L, connect to final through T2
ssh -p 8122 usr3@localhost

# Scenario 2: "only" problem is that final is behind work firewall
# at final
ssh -R  8022:final.atwork.com:22 usr2@laptop.athome.com
# at L
ssh -p 8022 usr3@localhost

# nc
# send file to peano and exit (without -q 0, nc keeps waiting for more data)
cat file | nc peano 8765 -q 0

AUDIO

# extract audio
ffmpeg -i input.wmv output.mp3

# Reduce audio volume
sox input.wav output.wav gain -n -24
# change sample frequency
sox input.wav -r 44.1k output.wav
# Convert audio (m4a to ogg)
ffmpeg -i Gimme_Gimme.m4a -map 0:0 -c:a libvorbis Gimme_Gimme.m4a.ogg
# flac to MP3 320 kbps
ffmpeg -i input.flac -b:a 320k output.mp3
# Rip CD audio
abcde -o vorbis

# Grabar CD audio
# 1: convertir a formato red book (stereo, 44.1KHz, 16 bits)
for f in $(ls *.mp3); do ffmpeg -i "$f" -map 0:0 "$f.wav" ; done
# 2: renombrar segun orden deseado
# 3: tostar (cdrtools)
wodim  -v -pad dev=/dev/sr0 -dao -swab *.wav

VIDEO

# convertir video a formato compatible con Windows Media Player (ideal para incrustar videos en Powerpoint)
# @see https://trac.ffmpeg.org/wiki/Encode/WindowsMediaPlayer
ffmpeg -r 30 -i foo.flv -codec:v mpeg4 -flags:v +qscale -global_quality:v 0 -codec:a libmp3lame foo.avi

# split video (ffmpeg)
ffmpeg  -i input.avi -ss hh:mm:ss -to hh:mm:ss -c copy output.avi

# multiplex audio & video
ffmpeg -i audio.m4a -strict -2 -i video.mp4 -strict -2 -c:a copy -c:v copy final.mp4

# resize video (ffmpeg)
ffmpeg -i IN.MP4 -c:v libx264 -c:a copy -s 800x600 OUT.mp4

# convert mjpeg video (ffmpeg)
# we may need to specify audio frequency because input video uses a strange frequency which is not automatically adapted
ffmpeg -i MVI_6229.AVI -c:v h264  -c:a mp3 -ar 44100  MVI_6229.AVI.mp4

# rip dvd (simple title-oriented movie; you may try -t 0 to rip all titles)
# -a -> select audio track, -E -> audio encoding (copy, vorbis, mp3, flac24...)
HandBrakeCLI -i /dev/cdrom -t 1 -o ~/output.m4v -e x264 -E "copy:*"

# a more specific approach: rip VOB by VOB (-strict -2 is required since AAC codec is considered experimental...)
ffmpeg -i /mnt/cdrom/VIDEO_TS/VTS_12_1.VOB -strict -2 vob_12_1.m4v

# Resize image (Imagemagick's convert)
# use mogrify to resize "overwriting" the input image
convert input.jpg -resize 25%  image_scaled.jpg

# Rotate image
jpegtran -rotate 90 -outfile output.jpg input.jpg

# It's good to sharpen to compensate from the scale softness
# -unsharp RadiusxSigma+Amount+Threshold
convert input.jpg -resize "600x" -unsharp 2x0.5+0.7+0 -quality 98 output.jpg

# Raster
# http://www.imagemagick.org/Usage/transform/
convert autotrace:heart.gif  heart_traced.gif

# Clean whiteboard
convert img.gif -morphology Convolve DoG:15,100,0 -negate -normalize -blur 0x1 -channel RBG -level 60%,91%,0.1 $2

# Visual image directory
display 'vid:*.jpg'

# OCR image 09.jpg into 09.txt asuming portuguese language
tesseract 09.jpg 09 -l por

# Spell check (aspell)
# Usar -a para pipes (en vez de ficheros)
aspell -t -d pt_BR -c etimologia.tex

# Capture screen
scrot

# Image to pdf
convert *.png output.pdf

# Unir varios PDF en uno - por defecto comprime, a costa de la calidad (queda granulado -> -dPDFSETTINGS=/screen por defecto)
# Para mejor calidad, usar -dPDFSETTINGS=/prepress
gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=proyecto.pdf -dBATCH proyecto-p*.pdf

# Dividir un PDF en varios (uno por página)
gs -q -o proyecto-p%02d.pdf -sDEVICE=pdfwrite proyecto.pdf 

# Reduce PDF size (gs): use maximum 150 dpi for images
gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dEmbedAllFonts=true -dSubsetFonts=true -dAutoRotatePages=/None -dColorImageDownsampleType=/Bicubic -dColorImageResolution=150 -dGrayImageDownsampleType=/Bicubic -dGrayImageResolution=150 -dMonoImageDownsampleType=/Bicubic -dMonoImageResolution=150 -sOutputFile=t.pdf input.pdf

# Convert PDF to JPG
# 200 DPI
gs -q -o output_p%04d.jpg -sDEVICE=jpeg -dPDFFitPage -r200 input.pdf

# Thumbnail of first page
gs -q -o output.jpg -sDEVICE=jpeg -dPDFFitPage -dLastPage=1 -g200x300 input.pdf

# Convert JPGs to single PDF
convert page1.jpg page1.pdf

Imprimir – Artículo relacionado: Comandos configuración CUPS

# Opciones más habituales de Cups: -n copies / -P page-list / -o sides=[one-sided|two-sided-long-edge|two-sided-short-edge]
# -o number-up=2
# <a href="https://www.cups.org/documentation.php/options.html">Listado completo de opciones Cups</a>
lp -d printer -o fit-to-page -o landscape XX.pdf
lp -d printer -o fit-to-page -o sides=two-sided-long-edge XX.pdf

# Añadir impresora
# PPDs from http://www.openprinting.org/printers
lpadmin -p name -E -v lpd://printer.localdomain/`hostname` -P xerox8560.ppd || exit 1
lpadmin -d $DEFAULT
lpoptions -p name -o Duplex=DuplexNoTumble -o PageSize=A4

# Lista colas
lpstat -a

# Imposicion (organizar paginas para folleto A5)
# pstops -> psutils
# Es importante especificar el tamaño de papel en ps2pdf, para que no se lie con la salida apaisada de pstops
pdftops input.pdf - | pstops -pa4 '4:-3L@.7(21cm,0)+0L@.7(21cm,14.85cm),1L@.7(21cm,0)+-2L@.7(21cm,14.85cm)' | ps2pdf -sPAPERSIZE=a4 - output.pdf
# Si las páginas de entrada ya están en A5, no hace falta escalarlas:
pdftops input.pdf - | pstops -pa4 '4:-3L(21cm,0)+0L(21cm,14.85cm),1L(21cm,0)+-2L(21cm,14.85cm)' | ps2pdf -sPAPERSIZE=a4 - output.pdf
# Unir dos páginas a5 en una página A4
pdftops INPUT - | psnup -pa4 -Pa5  -2 | ps2pdf -sPAPERSIZE=a4 - OUTPUT
# Más ejemplos de pstops: https://twiki.cern.ch/twiki/bin/view/Main/AVFedotovHowToPstops
# Crontab Fields
#minute hour day_of_month month day_of_week user  command
#/first 5 fields can be replaced by a special string, like/ @daily (run every midnigh), or @reboot (run once after reboot)
#List: 1,3,5,7,9. Range: 1-9/2 (2 is the step, optional)

# sudoers y sudoers.d/* tiene que tener permisos 440
# El orden importa, la ultima regla tiene precedencia sobre las anteriores
# Syntax: user/group doing sudo, host=(target user) [NOPASSWD:] comma list of commands (absolute path)
nagios  ALL=(ALL) NOPASSWD: /usr/cmd1,/usr/cmd2

# text conversion: UTF16 -> ascii
iconv -f utf16 fichero

# Calculators
bc
qcalc

# strace
# Opciones interesantes:
# -fp: conectarse a un proceso. Los descriptores de fichero se pueden consultar con lsof
# -c: contar número llamadas. Util para ver donde gasta el tiempo un proceso
# -T: cronometrar cada llamada al sistema

tcpdump

# Listar solicitudes DHCP
tcpdump  -s 1500 '((port 67 or port 68) and (udp[8:1] = 0x1))'
# Mostrar paquetes ARP
tcpdump -vvv arp
# Mostrar solicitudes a DNS de Google
tcpdump -n "dst host 8.8.8.8 and dst port 53"

Cómo comprimir en paralelo en Debian

Paralelismo en el compresor

De momento, la opción -T de xz no está activa, con lo cual hay que recurrir a las versiones paralelas de los clásicos: pigz o pbzip2.

Una vez instalado, basta con especificar el compresor en los parámetros de tar (normalmente, estos comandos paralelos detectan los cores disponibles, con lo cual no hace falta especificar nada):

tar cf test.tar.bz2 -I pbzip2 test

Paralelismo en los trabajos

Para comprimir muchos ficheros, una solución obvia es comprimir varios a la vez. Esto sólo requiere alguna herramienta que reparta los ficheros entre los compresores. Gnu parallel viene como anillo al dedo:

# 2 ejemplos del manual
# comprimir todos los ficheros "*.html"
parallel gzip ::: *.html
# convertir todos los "*.wav" en mp3 con LAME
parallel lame {} -o {.}.mp3 ::: *.wav

# comprimir con xz todos los ficheros del listado "files",
# usando un máximo de 4 cores:
parallel -P 4 xz < files

WordPress en Docker

# PASOS PRELIMINARES (opcionales, según las circunstancias 😉 )
# Arrancar Docker
docker -d -s="devicemapper"
# Descargar imagen MySQL 
docker pull mysql:5.7
# Descargar imagen WordPress
docker pull wordpress

# ARRANCAR CONTENEDORES (necesario cada vez que no estén arrancados 😉 )
# Arrancar contenedor MySQL 
docker run --name wordpressdb -e MYSQL_ROOT_PASSWORD=clave -e MYSQL_DATABASE=wordpress -d mysql:5.7
# Arrancar contenedor WordPress
# Los ficheros de WordPress se instalarán en la ruta que pasemos con -v
# (en este ejemplo, /home/yo/Dropbox/Webs/wordpress/)
docker run -e WORDPRESS_DB_PASSWORD=clave -d --name wordpress --link wordpressdb:mysql -p 127.0.0.2:8080:80 -v "/home/yo/Dropbox/Webs/wordpress/":/var/www/html  wordpress

Con esto ya tenemos disponible un WordPress para desarrollo local en 127.0.0.2:8080

Recuperar ficheros borrados de un sistema de ficheros ext3 ext4

Lo primero, detener todas las posibles escrituras.

Reiniciar con un Live CD, por ejemplo el estupendo Kali Linux (que además incluye extundelete).

Hacer una imagen de la partición (o volumen) de la que se quieren recuperar los datos. La imagen se puede guardar en otra partición, en un disco externo, en otro ordenador…

Después, se puede pasar a intentar recuperar los ficheros a partir de la imagen, con herramientas como extundelete:

extundelete --recover-all imagen.img

extundelete ofrece opciones para concretar el qué intentar recuperar (y así ahorrar algo de tiempo)

Obviamente, lo suyo es recuperar de una copia de seguridad (backup), pero no siempre es posible…

Ampliar disco fijo NTFS en Virtualbox

Virtualbox permite ampliar más o menos fácilmente un disco cuando es de tipo “dinámico” (el cual crece según va haciendo falta)

Cuando el disco es de tamaño fijo, la cosa se complica un poco. Una posible receta es:

  1. Crear un nuevo disco en Virtualbox del tamaño deseado
  2. Clonar el disco antiguo en el disco nuevo usando Clonezilla
  3. Desconectar el disco antiguo de la máquina virtual
  4. Ampliar el tamaño de la partición NTFS con GParted
  5. Hacer un chequeo del sistema de ficheros ampliado (si es la partición de Windows, se hace automáticamente al arrancar)

git

# git notes - http://git-scm.com/docs/git-notes
# Anotar un commit 
git notes add -m 'Anotación extra' 72a144e2
# listado de anotaciones
git notes list
# añadir sólo un subconjunto de los últimos cambios -> modo interactivo
# esta variante de add funciona con menus. Vamos escogiendo con la opcion "patch" y cuando terminamos salimos con "quit"
git add -i 

# comparar dos ramas (si la rama es remota, puede hacer falta usar la ruta, origin/ramaX)
# La comparación puede servir como "vista previa" de un merge
git diff rama1..rama2
# si estamos en rama1, se puede omitir:
git diff ..OTRA_RAMA
# También se puede usar un hash para elegir con qué commit comparar

# Excluir del repositorio los ficheros de backup de emacs
# Añadir a .gitignore
*~
.#*

# Registrar cambios: add+commit
# Incluir fichero f
git add f
git commit -m "Consecuencia de aplicar los cambios"
# (una vez en el repositorio, se puede incluir automaticamente todos los ficheros con la opción -a de commit)
# Cambiar el mensaje del ultimo commit
git commit --amend

# deshacer add
git rm --cached
# "Deshacer" ultimo commit
git reset --soft HEAD~1

# Publicar cambios
# normalmente, "donde" es origin, y "rama" es master
git push donde rama

# Descargar cambios (fetch + merge)
git pull 

# Mostrar cambios en un commit
# (con -w ignora cambios solo en espacios en blanco,
# y con --word-diff solo muestra cambios en palabras,
# en lugar de líneas enteras)
git diff COMMIT^ COMMIT


# Mostrar ficheros de un commit:
git show --name-only -r commit_id
git ls-tree --name-only -r commit_id
# Ficheros modificados...
# ...desde ultimo commit
git status
# ...en los ultimos commit
git diff-tree -r commit_id

# Informe de cambios
git log
# ...en una linea
git log --pretty=oneline
# ... para un fichero
git log --follow -p FILE

# Restablecer un fichero...
# ... a la última "versión"
git checkout f
# ...a la versión del commit hash
git checkout hash f

# RAMAS
# cambiar a rama r3
git checkout r3
# crear rama r4 a partir de r3
git checkout -b r4
# fusionar rama r2 con actual
git merge r2

# aplicar un commit de otra rama a la rama actual
git cherry-pick COMMIT

# copiar un fichero de otra rama
git checkout otra_rama fichero.py

# Etiquetas: Versiones / Releases
git tag -a v1.0 -m "Release 1.0"
git push origin v1.0

Hooks

La base para publicar sitios web usando git (ver git website howto)

# En el servidor, editar hooks/post-receive 
# (asegurarse de que tiene permiso de ejecucion...)
#!/bin/sh
GIT_WORK_TREE=/var/www/www.example.org git checkout -f

Como siempre, para hacer push hay que añadir el origen remoto (en este caso, el servidor web)

Chuletas: SphereDev, Seth Robertson, Publicar una web usando Git, Little things I like to do with git

Gestión de recursos en Debian

Una forma sencilla de controlar el uso de recursos es con ulimit o pam_limits (en /etc/security/limits.conf, y los servicios de /etc/pam.d pertinentes)

Si queremos gestionar recursos como el tráfico de red, los dispositivos o la entrada/salida; o necesitamos flexibilidad para afinar a qué procesos aplicar restricciones, podemos recurrir a los grupos de control (cgroups)

Las opciones con cgroups son múltiples (ver documentación al final). Una de ellas es asignar las restricciones por usuarios / grupos (en la tradición pam). Para ello, los pasos a seguir son:

  1. Instalar los paquetes de cgroups+pam. En Debian, cgroup-bin y libpam-cgroup
  2. Si vamos a usar el controlador de memoria, habilitarlo en grub: añadir “cgroup_enable=memory swapaccount=1” a GRUB_CMDLINE_LINUX_DEFAULT en /etc/default/grub, ejecutar update-grup y reiniciar
  3. Definir los grupos en /etc/cgconfig.conf:
    # Ejemplo sencillo: el grupo common_mem_pool solo puede usar 192GB de RAM.
    # Si un proceso del grupo se encuentra se recursos, se queda en pausa
    # (en lugar de recurrir al OOM killer)
    # Es importante limitar también el swap, ya que si no los procesos empiezan a tirar de él
    # cuando copan la RAM delimitada...
    group common_mem_pool {
            memory {
                   memory.oom_control = 1;
                   memory.limit_in_bytes = 210G;
                   memory.memsw.limit_in_bytes = 210G;
            }
    }
    
  4. Incorporar los cambios de cgconfig.conf con
    cgconfigparser -l /etc/cgconfig.conf
    

    Para configurar la ejecución automática de cgconfigparser durante el arranque, podemos añadir la línea anterior a /etc/rc.local

  5. Probar las definiciones con cgexec (y un programa adecuado, que intente sobrepar las limitaciones):
    cgexec -g memory:common_mem_pool mem_eater
    
  6. Definir las reglas de asignación de grupos en /etc/cgrules.conf:
    # Sintaxis:
    # usuario:nombre_proceso controlador grupo
    # Si el grupo de control no está definido en cgconfig, pam se quejará con algo tipo
    # "cannot make/remove an entry for the specified session"
    
    # Aplicar al usuario alex y al grupo devel las restricciones de common_mem_pool
    alex        memory          common_mem_pool
    @devel        memory          common_mem_pool
    
  7. Habilitar pam-cgroup en los ambitos pertinentes. Por ejemplo, si los usuarios acceden por ssh, en /etc/pam.d/sshd:
    session    required   pam_cgroup.so
    

    (otras posibilidades interesantes son /etc/pam.d/su y /etc/pam.d/sudo)

  8. Configurar el montaje del sistema de ficheros /sys/fs/cgroup. Si tenemos instalado Docker en el sistema, /etc/init.d/docker ya se encarga de montarlo. Si no, lo más sencillo es añadir a cgconfig.conf algo tipo…
    # Si ya está montado, cgconfigparser da un error (tipo "request came in from non owner").
    # En cuyo caso, lo más simple es comentar esta sección
    mount {
            cpu = /sys/fs/cgroup;
            memory = /sys/fs/cgroup;
            cpuacct = /sys/fs/cgroup;
    }
    

Para obtener información relacionada con cgroups, disponemos de los siguientes comandos:

# ver grupos de control de los procesos
ps -O cgroup
# grupos disponibles
cat /proc/cgroups
lscgroup
# informacion sobre un grupo en particular
cgget common_mem_pool

Los controladores a priori más apetecibles son cpu, memory (ver ejemplo más arriba) y blkio:

  • cpu.shares: porcentaje de CPU para el grupo
  • blkio.weight: porcentaje de E/S para el grupo
  • blkio.throttle.read_bps_device, blkio.throttle.read_iops_device, blkio.throttle.write_bps_device, blkio.throttle.write_iops_device: límite de velocidad (en bytes por segundo) en acceso a un dispositivo

Para adaptar el funcionamiento del OOM killer, podemos modificar indirectamente oom_score ajustando el parametro oom_adj de los procesos (-17 si queremos apartar al proceso de la mira de OOM, -16 si queremos que su muerte sea muy poco probable, 15 si muy probable). Ruth (root) juega con ventaja, por defecto a sus procesos se les reduce su probabilidad de ser exterminados por OOM.

Para saber más…

cgroups:

Memoria:

Cuotas XFS

Una de las ventajas del sistema de ficheros XFS es que permite establecer cuotas de disco por directorio (“proyecto”, en terminología XFS). A continuación la chuleta para ello.

Montar el sistema de ficheros con las opciones de quotas (previsoramente añadiendolas a fstab):

# habilitar quotas de usuario y de proyecto
/dev/sdd3 /mnt/projects xfs defaults,uquota,pquota 0 3

Después, para cada proyecto seguir este protocolo:

# vincular el id de proyecto (100) con su directorio (p1)
echo 100:/mnt/projects/p1 >> /etc/projects
# asociar el nombre del proyecto (project1) al id
echo project1:100 >> /etc/projid
# habilitar la quota para el proyecto
xfs_quota -xc 'project -s project1' /mnt/projects
# limitar el proyecto a 20 GB
xfs_quota -xc 'limit -p bhard=20g project1' /mnt/projects
# informe de las quotas del sistema de ficheros (/mnt/projects)
xfs_quota -xc 'report -p' /mnt/projects

Obviamente, con XFS también se pueden hacer operaciones más “básicas”:

# informe de las cuotas, por usuario 
xfs_quota -xc report /mnt/projects
# definir una cuota de 500GB para "joe"
xfs_quota -xc 'limit bsoft=490g bhard=500g joe' /mnt/projects
# desactivar las cuotas para "joe"
xfs_quota -xc 'limit bsoft=0 bhard=0 joe' /mnt/projects