Básicos Git (III): Revert

VisualStudio proporciona una opción de deshacer cambios que permite deshacer los cambios a los ficheros antes de crear el commit, esta opción de deshacer no realiza ninguna acción en Git.

Por ejemplo si realizamos cambios en uno o varios ficheros veremos que en la sección changes del plugin nos indica los ficheros que hemos cambiado y tendremos la opción de realizar undo changes.

Esta imagen tiene un atributo ALT vacío; su nombre de archivo es image.png
undo changes

Esto eliminará los cambios pendientes y dejará los archivos en su estado original sin crear un commit.

Revert pertenece a ese grupo de comandos pensado para deshacer cambios, en este caso revert lo que hace es crear un nuevo commit que contiene los ficheros originales previos al cambio, en este caso Git si se ve afectado.

El historial se mantiene por lo que no hay problema de usarlo con el equipo de desarrollo, si alguien del equipo está trabajando con la rama o la fusiona con una existente solo tendré que añadir el nuevo commit.

En el ejemplo hemos creado una rama develop y queremos deshacer el commit marcado en rojo (#3).

situación inicial

A continuación para deshacer un commit solo tendremos que ir al historial de la rama, seleccionar el commit que queremos deshacer y seleccionar la opción revert.

creando un revert

Esto provocará un nuevo commit con el nombre por defecto Revert «comentario del commit a deshacer».

comentario de un revert

Este revert se queda en el historial, por lo tanto se podrá ver tanto el commit original como el commit que lo deshizo, este nuevo commit lo que contiene son los contenidos originales que había en el commit #2 que fueron modificados por el commit #3.

A su vez este contenido de la forma habitual se puede fusionar con la rama master por lo que nos quedaría un árbol así.

merge con master de un revert.
Básicos Git (III): Revert

Básicos Git (II): Rebase

Existe otra forma de hacer una fusión de ramas y es con un comando rebase. Rebase lo que hace es insertar una rama dentro de otra en el mismo punto donde se creo de tal forma que parezca una sola rama.

Situación inicial

Para poder entenderlo bien vamos a manejar dos ramas, master y develop, creamos dos commits en develop y otros dos en master, el orden no es importante (Figura 1).

Situación inicial

En este punto master y develop divergen y tienen commits diferentes, vamos a aplicar un rebase para crear una sola rama con todos los cambios.

Aplicando rebase

Para tener una sola rama rama vamos a hacer un rebase, nos posicionamos en la rama master con los parámetros que se ven en la imagen y pulsamos rebase.

comando rebase usando el plugin de VisualStudio

Conflictos

Esto provocará varios conflictos, el rebase irá aplicando primero cada cambio de master a develop, los conflictos que se aplicarán a develop son:

situación final
  1. El primer commit de develop (que sería el existente) con el primer commit de master (Commit C1).
  2. El resultado del commit anterior con el segundo commit de master (Commit C2).
  3. Así sería sucesivamente si hubiera más commits.

Estos nuevos commits tendrán como comentarios los correspondientes a su commit de master.

Ahora para terminar el rebase solo queda aplicar estos cambios de la rama develop en la rama master provocando un último conflicto (Commit R), en este caso si que habrá que indicar un comentario.

Resultado

En la imagen anterior si nos fijamos en la rama master vemos que están todos los commits de develop insertados en la rama master (recuadro rojo) justo en el punto que se creo la rama develop, por lo que en master queda un arbol límpio con todos los commits.

Este sistema se suele utilizar más para actualizar ramas locales que para actualizar la rama master ya que se está alterando el historial de una rama (master en este caso).

Esto también provoca que se altere el cronograma por lo que podemos ver commits más recientes que aparecen más tarde en el historial, ya que prima el orden de creación más que la fecha de los mismos.

alteración del cronograma de git por rebase

Este sistema también puede crear un problema para el resto de desarrolladores que hayan creado otras ramas de master a posteriori lo que genera conflictos a veces complicados de resolver.

Generalmente no se recomienda hacer un rebase sobre ramas remotas por el peligro que conlleva para otros desarrolladores, sin embargo en ramas locales suele haber más disparidad de criterio.

Básicos Git (II): Rebase

Básicos Git (I): Cherry pick

El uso básico de Git es bastante conocido sin embargo hay algunos conceptos que se suelen nombrar y quizás a veces inducen al error, en este caso comentaré los más habituales que se suelen ver en el plugin de VS2017 para Git.

Para este ejemplo se ha creado una rama master y una rama develop que hereda de master. En el historial de Git del plugin de VisualStudio se vería de la siguiente forma.

historial de Git

Aquí podemos ver que nos está indicando con la marca roja master que master ha tenido commits hasta el commit id 9e3acdb5, con la marca roja develop vemos que esta rama está avanzada y tiene más commits que master.

Para este ejemplo solo hemos añadido un fichero en master y después en la rama develop hemos continuado haciendo modificaciones sobre este fichero.

Cuando fusionemos las ramas las dos estarán sincronizadas por lo que veremos algo como esto, las dos marcas rojas alineadas.

master y develop sincronizado

Cherry pick

El concepto de cherry pick es poder coger uno o varios commits de una rama y copiarlos a otra rama distinta, este concepto lo vamos a aplicar a la fusión (merge) de ramas.

La idea de un merge es fusionar dos ramas entre sí, la forma más habitual es fusionar en una rama destino (en este caso master con los commits en blanco) una rama origen (develop con los commits en azul) incluyendo en la rama destino tantos commits y en el mismo orden como commits tiene la rama origen. (Figura 1).

Existe otra opción que consiste en fusionar todos los cambios de una rama origen en una rama destino en un solo commit, es decir todos los commits de la rama origen se agrupan en uno solo y es este el que se inserta en la rama destino. (Figura 2).

merge vs cherry pick

El comando merge por defecto no hace un cherry pick, el plugin de VisualStudio permite hacerlo de dos formas diferentes, en ambos casos el comentario que se verá en la rama destino será el del último commit.

Cherry pick de una rama

En el caso de una rama entera habría que posicionarse en la rama origen de los commits y después hacer click en la opción cherry pick en la rama que va a recibir los commits.

En este ejemplo la rama develop va a recibir todos los commits de master.

cherry pick de una rama

Esta acción genera un conflicto al contrario que un merge normal, esto se debe a que cherry pick solo transfiere commits no es un merge en el sentido estricto, los errores de conflicto se solucionan de la forma habitual.

Cherry pick de commits individuales

Otra opción es seleccionar específicamente uno o varios commits y transferirlos a otra rama, en este caso nos situamos en la rama destino y abrimos el historial de la rama origen, seleccionamos los commits que nos interesen y hacemos click en cherry pick.

En este caso solo habrá conflictos si seleccionamos varios commits o elegimos uno que no sea inmediatamente posterior tanto en la rama origen como destino, es decir que si hicieramos cherry pick de cada commit en el mismo orden en la rama destino no deberíamos tener conflictos, realmente esta última forma es lo mismo que emular un merge normal.

cherry pick de commits individuales
Básicos Git (I): Cherry pick

El intermediario

Cuando vi esta escena de la grandísima serie que es Halt and Catch Fire tuve que sobreponerme a las ganas de empezar a aplaudir, esta serie que en muchos momentos recoge lo mejor del mundo tecnológico lo había vuelto a conseguir y si a eso le sumamos este artículo que leí hace poco (los programadores son más importantes para las empresas que los directores de TI) la cosa se pone aún mejor.

Esta escena muestra bastante bien lo que muchos desarrolladores piensan sobre sus jefes de proyecto y posiblemente los jefes de proyecto pensarán aquello de “si te digo todo lo que pasa que no te quiero contar…”, esta situación acaba llevando a un sutil enfrentamiento y sectarismo entre “gente con traje vs gente sin traje”.

Siempre ha existido un miedo irracional hacia lo desconocido que confunde y a menudo irrita al ser humano haciéndole tomar actitudes que generalmente no son muy correctas o sensatas, más o menos la actitud que toma un jefe de proyecto ante un grupo de desarrolladores cuando estos le intentan explicar algo, generalmente el jefe de proyecto no es técnico -ni intención que tiene- solo le interesa saber cuándo se va a entregar algo y que no le engañen diciendo cuatro meses cuando pueden ser tres.

De todas formas, ante la duda el jefe de proyecto siempre sacará alguna queja –puede que sin demasiado sentido- y de paso te quitará dos semanas, -que seguro que ya será menos el tiempo que hace falta-, lo que el jefe de proyecto no sabe es que ante esto la próxima vez el desarrollador le meterá un mes más, como el lazarillo de Tormes si tu coges dos uvas yo cojo tres, pero no nos decimos nada, -y la rueda del absurdo sigue girando-.

Tomando una actitud “zen” -que llegado cierto punto es la mejor opción- la respuesta fácil sería decir, las probabilidades de que un proyecto se cumpla en plazo es inversamente proporcional a su tamaño, es decir que si dices que entregas en una semana puede que sea verdad, pero si dices que entregas en un año, seguro que al final es año y tres meses.

En cualquier caso esta sensación de “no sé qué me han contado” del jefe de proyecto también la tiene el cliente, el jefe de proyecto que no se acaba de enterar muy bien le habla a su cliente sobre el proyecto -y le transmite esta inseguridad-, este acaba haciendo lo mismo, realmente no se está enterando muy bien de que le están hablando pero tampoco va a parecerlo así que plantea dudas, quejas y plazos que igual no tienen nada que ver con el proyecto, y en particular con lo que el cliente realmente necesita -pero llegado ese punto el jefe de proyecto hace un «si a todo»-, lo cual se traslada finalmente al equipo de desarrollo que se queda pensando aquello de “hay días que no se para que me molesto”, -el grado de frustración pasa de lineal a exponencial-.

Algunos dirían que esto se arregla con un jefe de proyecto con antecedentes tecnológicos, el problema es que la tecnología avanza a veces demasiado rápido y es fácil quedarse atrás y acabar volviendo al punto anterior encima con la idea de “yo que fui desarrollador…” el desenlace final suele ser aún peor.

Sin embargo hay matices, depende de la empresa, del cliente, con quien trabajes… es posible que los plazos se puedan mantener y todo vaya bien, pero si la empresa no es muy grande y no tiene capacidad negociadora, o el cliente es demasiado importante o el presupuesto escaso… entonces los plazos se piden por cortesía pero es probable que acaben siendo otros –y volvemos al primer punto-.

Hace algún tiempo desde una empresa me contactaron para un proceso de selección que necesitaba a una persona que sirviera de enlace entre el equipo de desarrollo y el de gestión, que fuera capaz de “entender” a los programadores y luego “traducir” todo eso en plazos y tiempos de forma razonada, algo así como “no sé si los desarrolladores me engañan o es verdad, pero tengo que dar una fecha y plazos que tengan sentido y se cumplan».

Yo he de reconocer que me alegré, no porque me hubieran contactado –que también- sino que por fin después de años alguien se había dado cuenta que hace falta “un intermediario” que sea capaz de hacer ese trabajo, que por un lado sea técnico –generalmente de buen nivel- y ejerza como tal pero que también entienda que los proyectos se hacen para entregarlos y sea capaz tanto de trasmitir esa idea al equipo, así como a su vez transmitir a gestión por parte del equipo aquella gran frase de “nueve mujeres no paren en un mes”.

De hecho, yendo más allá en los últimos tiempos he tenido ocasión de observar empresas creadas solamente por desarrolladores y aunque es verdad que hace falta gente de todo tipo en una empresa- la verdad es que les está yendo muy bien.

Quizás lo que algunas empresas necesitan es un perfil así, no solo mejorarían su productividad, sino que la empatía entre “gente con traje vs gente sin traje” aumentaría, lo que posiblemente es el mayor beneficio.

 

 

 

El intermediario

Torrent en Raspberry Pi (Deluge & Transmission) con Apache

Actualizado a 3 de Septiembre de 2020

Instrucciones para instalar torrent manualmente en un servidor ya existente para proporcionarle más funcionalidad, en este caso estas son las instrucciones para los dos más populares, Deluge y Transmission.

Primero actualizar la Raspberry pi

sudo rpi-update
sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade

Vamos a utilizar el cliente Deluge así que instalamos los paquetes:

sudo apt-get install deluged
sudo apt-get deluge-console

Ahora hay que arrancar el demonio en Linux y después lo paramos, esto es para que cree la configuración por defecto.

sudo deluged 
sudo pkill deluged

Primero un backup de la configuración original y editamos el archivo, al haber instalado con sudo los ficheros estarán en la carpeta /root.

sudo cp /root/.config/deluge/auth /root/.config/deluge/auth.old.nano
sudo nano /root/config/deluge/auth

Ahora hay que cambiar la línea que aparece en fichero con este formato user:password:level, esta cuenta sirve para administrar raspberry, en este caso usamos los valores por defecto de raspberry como ejemplo, donde 10 indica máximo nivel de permisos, pi:raspberry:10 y ahora arrancamos el demonio y arrancamos la consola.

sudo deluged 
sudo deluge-console

En esta consola arrancamos los siguientes comandos: config -s allow_remote True, esto habilita las conexiones remotas, para verificar el valor se puede usar el comando config allow_remote, para salir basta con usar exit.

Ahora reiniciar para hacer efectivos los cambios.

sudo pkill deluged
sudo deluged

En web de Deluge existen clientes de escritorio para instalar, pero en este caso vamos a usarlo vía web.

sudo apt-get install python-mako
sudo apt-get install deluge-web
sudo deluge-web &

El puerto por defecto es 8112, si se quiere cambiar se puede hacer con el siguiente comando, en el fichero cambiar la línea port por el puerto (superior a 1000), en este mismo fichero completamos la línea: «default_daemon»:»localhost:58846″

sudo pkill deluge-web
sudo nano /root/.config/deluge/web.conf

Ahora se puede acceder a la dirección web http://raspberry:8112 la cual abrirá una web con una contraseña que por defecto es deluge.

Después de esto es necesario reiniciar y arrancar de nuevo.

sudo pkill deluged
sudo deluged

Ahora solo queda configurar Deluge para que arranque en el inicio, para esto editamos el archivo /etc/rc.local y agregamos las siguientes líneas al final del archivo (antes de la línea exit 0)

sudo -u pi /usr/bin/python /usr/bin/deluged
sudo -u pi /usr/bin/python /usr/bin/deluge-web

Ahora vamos a instalar transmission:

Primero instalar los paquetes:

sudo apt-get update
sudo apt-get install transmission transmission-daemon

Ahora paramos el servicio para poder editar los ficheros de configuración

sudo service transmission-daemon stop

Ahora editamos el fichero:

sudo nano /etc/transmission-daemon/settings.json

Y modificamos los siguientes parámetros, en este caso los parámetros «download-dir» y «incomplete-dir» apuntan a la carpeta donde se guardará el torrent y la carpeta temporal donde se ubican mientras se van descargando. La carpeta «watch-dir» es la carpeta donde se dejan los torrent que se descargarán automaticamente.

"blocklist-enabled": true,
"blocklist-url": "http://john.bitsurge.net/public/biglist.p2p.gz",
"download-dir": "/mnt/samba/hdd/download", 
"incomplete-dir": "/mnt/samba/hdd/temp", 
"incomplete-dir-enabled": true, 
"rpc-password": "TuPassWord", 
"rpc-username": "transmission", 
"rpc-whitelist-enabled": false,
"watch-dir":"/mnt,
"rpc-host-whitelist-enabled": false,

Ahora tenemos que cambiar el usuario con el que se ejecuta para poder hacerlo con el usuario pi, esto es especialmente útil sobre todo si hemos usado el usuario pi para mapear una unidad de red o una unidad USB.

Primero detenemos el demonio.

service transmission-daemon stop

Cambiamos el usuario

sudo nano /etc/init.d/transmission-daemon

y cambiamos:

USER=debian-transmission por USER=pi

También tenemos que editar el siguiente fichero:

nano /etc/systemd/system/multi-user.target.wants/transmission-daemon.service

Y ponemos esto:

[Unit]
Description=Transmission BitTorrent Daemon
After=network.target
[Service]
User=pi
Type=forking
PIDFile=/var/lib/transmission-daemon/.config/transmission-daemon/trans.PID 
ExecStart=/usr/bin/transmission-daemon --pid-file /var/lib/transmission-daemon/.config/transmission-daemon/trans.PID --config-dir /var/lib/transmission-daemon/.config/transmission-daemon/ 
[Install] 
WantedBy=multi-user.target

Ahora creamos el archivo pid y configuramos los permisos:

touch /var/lib/transmission-daemon/.config/transmission-daemon/trans.PID 
chown pi.pi /var/lib/transmission-daemon/.config/transmission-daemon/trans.PID

Ahora cambiamos el propietario de los ficheros:

chown -R pi.pi /var/lib/transmission-daemon 
chown -R pi.pi /etc/transmission-daemon/settings.json 
chown -h pi.pi /var/lib/transmission-daemon/info/settings.json

La dirección por defecto para acceder es:

http://127.0.0.1:9091/transmission

Hay que tener en cuenta que el fichero settings.json se tiene que editar cuando el servicio esté parado de lo contrario al pararse sobreescribe con los cambios actuales.

Ahora vamos a ver como configurar estas rutas por algo más fácil de recordar, para ello en Apache creamos un virtual host que nos haga de proxy con el servidor de torrent, creamos un fichero en la carpeta /etc/apache2/sites-available/004-torrent.conf con el siguiente contenido, obviamente deberemos tener un sistema DNS que nos resuelva correctamente el nombre torrent, vamos a suponer que el servidor está en la dirección 192.168.1.4

 <VirtualHost torrent:80>
   ServerName torrent.domain
   ServerAlias torrent
   ProxyPreserveHost Off
   ProxyRequests On
   ProxyPass / http://192.168.1.4:9091/
   ProxyPassReverse / http://192.168.1.4:9091/
   CustomLog /var/log/apache2/torrent.log combined
   ErrorLog /var/log/apache2/torrent.error.log
 </VirtualHost>

Ahora habilitamos el sitio usando el archivo de configuración que hemos creado

sudo a2ensite 004-torrent.conf

Después de reiniciar el servidor podremos acceder al servidor torrent usando la dirección http://torrent

Finalmente es posible que haya problemas con las carpetas watch de torrent si están en un disco externo ya que es posible que no detecte los cambios, así que vamos a configurar una carpeta por samba para poder dejar los ficheros ahí, así que editamos el fichero /etc/samba/smb.conf e incluimos el siguiente contenido:

[torrent]
comment = Carpeta para dejar torrents que se descargarán automaticamente
path = /media/torrent
read only = No
force user = pi
force group = pi
create mask = 0660

En este caso estamos suponiendo que la carpeta donde se colocarán los torrent está en /media/torrent

En caso de reinstalar la aplicación si no aparecen todos los ficheros que hemos descargado previamente es porque tenemos que rellenar la carpeta torrents con todos los torrents que nos hayamos descargado, podemos copiar el contenido de la antigua carpeta torrents en la nueva.

Enlaces:

https://www.alvaroreig.com/como-configurar-un-proxy-inverso-con-apache/

https://www.vichaunter.org/como-se-hace/cambiar-nombre-usuario-transmission-linux

https://www.vichaunter.org/como-se-hace/instalar-configurar-transmission-raspbian-raspberry-pi

Torrent en Raspberry Pi (Deluge & Transmission) con Apache

Configuración servidor de impresión y escaner con Raspberry Pi

Con una impresora antigua y una Raspberry es posible crear un servidor de impresión, estos son los pasos:

Primero como siempre actualizar Raspberry.

sudo apt-get update
sudo apt-get upgrade

Ahora instalamos CUPS, el servidor de impresión por excelencia de UNIX.

sudo apt-get install cups

Esto nos creará un grupo de administración de impresoras llamado lpadmin, agregamos el usuario pi a este grupo, se puede elegir cualquier usuario y cuando se acceda a través de web será este el usuario que se tendrá que validar.

sudo usermod -a -G lpadmin pi

Tenemos que habilitar el acceso remoto más allá de localhost, para que se puedan administrar las impresoras desde otra máquina en la red de área local.

sudo cupsctl --remote-any
sudo /etc/init.d/cups restart

Ahora podemos probar la web, usando la dirección de la Raspberry y el puerto 631 que es el de defecto, si quisiéramos cambiar el puerto se puede editar desde /etc/cups/cupsd.conf en la línea marcada como Port.

Si no tenemos instalado samba, estos serían los pasos rápidos:

sudo apt-get install samba

Ahora hay que editar el archivo de configuración de samba para agregar la entrada de la impresora, realmente esta entrada ya está creada solo hay que verificar que sea igual que esta:

# CUPS printing.  
[printers]
comment = All Printers
browseable = no
path = /var/spool/samba
printable = yes
guest ok = yes
read only = yes
create mask = 0700

# Windows clients look for this share name as a source of downloadable
# printer drivers
[print$]
comment = Printer Drivers
path = /var/lib/samba/printers
browseable = yes
read only = no
guest ok = no

También tenemos que establecer correctamente el valor del parámetro workgroup y de wins support:

workgroup = my_workgroup
wins support = yes

Ahora reiniciamos samba para hacer efectivos estos cambios.

sudo /etc/init.d/samba restart

Ahora a través de la web accedemos a la sección de administración, desde allí agregamos una impresora con el botón «Add printer» posiblemente haya que acceder con la cuenta que hemos agregado anteriormente al grupo lpadmin, si CUPS es capaz de detectar la impresora la veremos aquí como una impresora local, la seleccionamos y continuamos, cambiamos nombre y descripción o aceptamos las que vienen por defecto y marcamos compartir impresora «Share this printer» con esto ya tendremos una impresora configurada en red.

Esta es una configuración por defecto que funcionará tanto para pcs como para dispositivos móviles.

Mas info:

https://pimylifeup.com/raspberry-pi-print-server/

 

Configuración servidor de impresión y escaner con Raspberry Pi

Crítica velada a TDD

Empezaré diciendo que no he sido nunca un gran practicante de TDD pero sin embargo no critico las pruebas unitarias y si creo que son útiles por multiples razones.

TDD ha calado entre la comunidad poco más o menos como «la solución definitiva» a la calidad del software ganando un montón de adeptos que se han hecho fanáticos de este sistema como es habitual entre la comunidad cuando llega una nueva teoría que gana adeptos muy rapidamente y arrasa haciendo que todo el mundo tenga que aceptarla so pena de parecer un ignorante, aunque hablar de estas olas que más parecen modas que realmente grandes avances sería tema de otro artículo.

TDD surgió como un método para proporcionar una alta calidad a las aplicaciones algo en lo que no pongo dudas ya que todo el desarrollo está centrado en las pruebas, lo cual proporciona el rol dominante a las pruebas por encima de otras consideraciones.

Esto implica varias cosas, TDD impone algunos requisitos de una forma más o menos explícita, por ejemplo cosas obvias como que es necesario tener un buen conocimiento de frameworks de tests unitarios pero tambien otras no tan obvias.

Por ejemplo la refactorización constante, el test siempre va primero esto quiere decir que durante el desarrollo a medida que se implementen nuevos requisitos o cambien algunos habrá que ajustar la aplicación respetando las pruebas unitarias que constituyen la parte principal en este sistema, esto implica continuos cambios en el código para evitar que quede disperso y sin estructura, para mantener la calidad del código a este nivel hace falta tener buenos desarrolladores.

Tambien cualquier sistema de pruebas, no solo TDD, implica tener que hacerlas esto quiere decir una inversión de tiempo, obviamente más pruebas implica más tiempo y cuanto más centrado este el sistema en las pruebas más tiempo conlleva.

Aquí llegamos a un punto clave, la combinación tiempo y recursos, estos dos factores conllevan inevitablemente un aumento del coste y con TDD este coste no es precisamente bajo, necesitas buenos desarrolladores y tiempo para hacer la aplicación.

Habrá quien diga que este sistema no excluye programadores junior que pueden estar realizando otras tareas de bajo nivel y que en el futuro aprenderán un buen sistema de desarrollo, habrá también quien diga que el producto de calidad implica tiempo y no se pueden pedir las cosas «de un día para otro», incluso dirán que un equipo disciplinado en TDD no implica una variación sustancial en tiempo.

La realidad no es esa, no todos los clientes van a aceptar algo así y no todas las empresas pueden permitirse ofertar ese tipo de desarrollos, independientemente de que se vendan como productos de alta calidad.

Tampoco pretendo quitar valor a TDD, simplemente que no sirve para todos los desarrollos, en mi opinión tiene cabida en sectores críticos, por ejemplo: defensa, sanidad, … donde la calidad ha de ser máxima y los errores implican grandes pérdidas ya sean materiales o humanas.

A fin de cuentas la conclusión es, si para que TDD funcione necesitas, aparte de una gran comprensión por parte del cliente,  tiempo y recursos, ¿cómo de malo tendría que ser para que aún asi no funcionase?

Crítica velada a TDD

Desplegando en una Raspberry Pi Parte III (Depurando con XDebug)

Finalmente suele ser útil y práctico poder depurar las aplicaciones, principalmente he manejado dos sistemas de depuración en PHP, XDebug y Zend Debugger, Zend Debugger es propietario y XDebug es libre, el problema principal viene dado porque el binario de Zend Debugger no está disponible para la arquitectura arm de Raspberry así que optaremos por XDebug.

Así mismo hay varios editores que permiten depurar con XDebug, en este caso el ejemplo lo hago con PHPStorm, primero hay que hacer la configuración del lado servidor.

Una vez instalado el módulo de XDebug (verificar con phpinfo()) tendremos que configurarlo, editamos el fichero xdebug.ini y establecemos los siguientes valores.

zend_extension=/usr/lib/php5/20131226/xdebug.so
xdebug.remote_enable=1
xdebug.remote_handler=dbgp
zdebug.remote_mode=req
xdebug.remote_host=192.168.1.99
xdebug.remote_port=9000
xdebug.idekey="phpstorm"

Lo importante aquí es establecer como xdebug.remote_host la dirección IP del cliente, es decir donde está instalado PHPStorm que es desde desde donde queremos depurar y lo mismo para el puerto, estas opciones normalmente son configurables a partir del entorno pero el puerto por defecto 9000 es estándar.

xdebug.idekey es un valor que se pasa al depurador para identificar la sesión no es necesario establecerlo pero suele ser buena idea indicar el mismo que el IDE usado.

Si se quiere poder depurar desde cualquier máquina se puede usar el valor xdebug.remote_connect_back, para más detalles ver aquí.

Como ya vimos una buena opción es compartir vía Samba la carpeta de Apache de la Raspberry y usarla para editar directamente los ficheros eso nos ahorra de cara a PHPStorm el paso de desplegar, por lo tanto de cara a crear un nuevo proyecto en PHPStorm indicamos que trabajaremos en local con la ventaja añadida de que tendremos también git integrado (si está configurado git en la carpeta del servidor).

Ahora solo nos queda desde el menú «Run» usar la opción «Start Listening for PHP Debug Connections«.

Ahora desde aquí creamos los enlaces que se usará para arrancar el depurador y conectar al cliente, lo recomendable es arrastrarlos a la barra de navegación del navegador que estemos usando, principalmente usaremos «Start debugger«.

Una vez que empiece el sistema de depuración PHPStorm nos mostrará una ventana en la que nos indicará cual es el mapeo correspondiente entre el fichero a depurar y la ubicación física del mismo, si no puede realizar esta asociación al crear un punto de interrupción aparecerá éste con una X indicándolo, esto es muy probable que pase para los ficheros fuente que están fuera de las carpetas públicas (habitual si se usa frameworks tipo Symfony) en ese caso desde «Run -> Edit Configurations» veremos debajo de «PHP Remote Debug» el host detectado dentro de éste solo tenemos que indicar los mapeos correspondientes dentro del servidor (las rutas físicas de Linux), es necesario pulsar enter para que se quede la ruta establecida.

 

Desplegando en una Raspberry Pi Parte III (Depurando con XDebug)

Desplegando en una Raspberry Pi Parte I (LAMP && Samba)

Hay muchas formas automatizadas de crear un servidor de desarrollo, en este caso vamos a usar una Raspberry Pi con sistema LAMP, primero configuraremos el sistema LAMP y después configuraremos las carpetas.

Vamos a considerar que tenemos una empresa Acme que tiene un proyecto de nombre Coyote.

Primero tenemos que actualizar la Raspberry para ponerlo todo en orden.

Se puede actualizar el kernel así como el firmware de Raspberry aunque no es estrictamente necesario, esto se realiza con el comando rpi-update, si no está instalado se puede descargar vía apt-get.

# sudo rpi-update

Ahora actualizamos la distribución, este paso es recomendable.

# sudo apt-get update
# sudo apt-get upgrade
# sudo apt-get dist-upgrade

Ahora instalamos primero la base de datos, en este caso MariaDB, durante el proceso de instalación se pedirá una contraseña para el usuario root, se recomienda indicar una.

# sudo apt-get install mariadb-server mariadb-client

Ahora instalamos el servidor Apache 2.

# sudo apt-get install apache2

Ahora instalamos PHP 5 y el módulo de PHP 5 para Apache 2.

# sudo apt-get install php5 libapache2-mod-php5

PHP 5 tiene muchos módulos pero uno de los más importantes y que va a ser necesario es el módulo de PHP 5 para base de datos, en este caso para MariaDB

# sudo apt-get install php5-mysqlnd

Como optimizador de código intermedio de PHP 5 vamos a instalar ACPu.

# sudo apt-get install php5-acpu

Ahora solo queda reiniciar Apache 2.

# sudo service apache2 restart

Ahora vamos a usar Samba para poder acceder a la carpeta de Apache desde Windows, si trabajamos en entornos híbridos es una comodidad para poder acceder al código fuente.

En Raspberry vamos a usar la carpeta por defecto de Apache para desplegar (/var/www/apache/html) en esta carpeta creamos la carpeta Acme y dentro de esta la carpeta Coyote.

#cd /var/www/html
#sudo mkdir acme
#cd acme
#sudo mkdir coyote

Ahora podemos instalar Samba.

#sudo apt-get install samba samba-common-bin

Una vez hecho esto vamos a crear un usuario por proyecto, en este caso creamos el usuario coyote, no nos interesa que tenga ni una shell ni una carpeta de usuario porque es un usuario que solo vamos a usar para acceder por red y así proporcionamos más seguridad al sistema, en resto de los valores que nos pida podemos establecer cualquier valor.

# sudo adduser -shell /bin/false --no-create-home coyote

Ahora añadimos el usuario a la lista de usuarios de Samba y le indicamos una contraseña para acceder por red.

# sudo smbpasswd -a coyote

Tenemos que dejar que el usuario de apache (www-data) pueda acceder a las carpetas para poder mostrarlas, pero también tenemos que dejar que el usuario coyote pueda acceder y realizar modificaciones desde el exterior a través de la red, así que vamos a crear el grupo acme y añadir a ambos usuarios a ese grupo.

# sudo addgroup acme
# sudo adduser coyote acme
# sudo adduser www-data acme

Empezamos con los permisos, vamos a asignar como propietario de los ficheros a www-data pero el grupo para la carpeta acme lo vamos a asociar al grupo acme, la carpeta html la dejamos como está (propietario y grupo para root para permisos 775).

# cd /var/www/html
# sudo chown -R www-data acme
# sudo chgrp -R acme acme

Ahora asignamos permisos, damos permiso total al usuario y grupo.

# sudo chmod -R 770 *

Tanto el usuario coyote como el usuario www-data necesitan acceder a la carpeta así que vamos a establecer el bit setgid para que los permisos se orienten por grupo y no por usuario así ambos usuarios podrán utilizar los ficheros indistintamente y también configuramos los permisos en la carpeta.

# sudo chmod g+s acme
# sudo chmod -R 755 acme

Ahora solo nos queda hacer visible la carpeta a través de la red, para eso modificamos el fichero /etc/samba/smb.conf y añadimos lo siguiente.

[coyote]
comment = El proyecto Coyote de Acme
path = /var/www/html/acme/coyote
read only = No
valid users = coyote
write list = coyote #Usuarios que pueden escribir
create mask = 0660 #Mascara de creación de archivos
directory mask = 0770 #Máscara de creación de directorios

Finalmente podemos comprobar que toda la configuración es correcta con el uso del comando testparm.

# testparm

Que debería indicarnos que todo es correcto, si es así reiniciamos Samba.

# sudo service smbd restart

 

Desplegando en una Raspberry Pi Parte I (LAMP && Samba)

Recopilatorio

Esta vez toca recopilatorio, sobre artículos que escribí en mi antigua empresa y que ahora agrupo para todos aquellos que les pueda resultar de utilidad o interés, tanto en castellano como inglés, los coloco cronológicamente aunque realmente se pueden leer en cualquier orden.

[Spanish]

Si … o no si ( To if or not to if )

Desmontando a imperativo (Deconstruyendo imperativo)

Bit veo, bit quiero

Quo vadis: Filosofía del programador

Cui bono? O el arte de la reutilización de código

[English]

Si … o no si ( To if or not to if )

Desmontando a imperativo (Deconstructing imperative)

Bit I see, bit I want

Quo vadis: Programmer’s Philosophy

Cui bono? Or the art of code reusing

Recopilatorio