Gustavo Adolfo Arellano

Infraestructura de Integración Continua

Configuración, LINUX, Técnicos Comments Off on Infraestructura de Integración Continua
May 112020

Este post está dedicado a proveer instrucciones detalladas acerca de la manera en la que se debe crear una infraestructura de integración continua usando herramientas como GitLab, Jenkins, Nexus, Sonar, Swagger editor, Rancher, H2 y Keycloak. Todo lo anterior sobre AWS, pero con la asociación de nombres de dominio adecuados (subdominios) y su correspondiente SSL.

Requisitos básicos

A lo largo de este post se hará uso extensivo de conceptos, herramientas y tecnologías muy particulares que son enumeradas a continuación:

  1. Cuenta de un “Registar” como GoDaddy o Akky
  2. Cuenta AWS con privilegios para EC2 y Route53
  3. Cuenta con algún proveedor de certificados SSL
  4. Nuestra estación de trabajo deberá tener instalado el cliente de consola de aws también conocido como awscli y deberá estar configurado para que las credenciales de acceso estén creadas y disponibles para su uso

Esto último, aws cli, es posible que sea instalado en Ubuntu (probado en la versión 18.04) simplemente ejecutando el comando:

sudo apt install awscli

Posteriormente, se debreá configurar el cliente con las crdenciales requeridas. esto se puede hacer mediante:

aws configure

Durante la configuración se pedirán los siguientes datos:

  1. AWS Access Key ID
  2. AWS Secret Access Key ID
  3. Región (Yo uso: “us-east-1”)
  4. Formato (ENTER = FORMATO POR DEFAULT)

NOTA IMPORTANTE: Los valores de (1) y (2) son generados por un administrador de AWS, mediante el uso de la interfaz gráfica de AWS en la sección de seguridad. Son únicos y son revocables en cualquier momento. Sin estos datos será muy complejo continuar con este Tutorial. Es extremadamente recomendable obtenerlos en este punto antes de continuar con esta lectura.

Pasos previos a la creación de la Infraestructura

Antes de poder generar la Infraestructura de integración continua será necesario gestionar los siguiente:

I Compra de dominio

Un “Registrar” es una compañía (como GoDaddy o como Akky) que vende nombres de dominio que se encuentren disponibles. Generalmente es posible comprar un dominio “.com” o un dominio “.org” disponible por unos 10 dólares al año o menos. Hay dominios mas caros, como los dominios “.io” o los dominios “.tv” que cuestan unos 50 dólares al año.

Los dominios con nombres cortos ya han sido comprados y si se desea negociar su transferencia o venta, ésta puede llegar a costar miles de dólares. Un ejemplo es “Tesla” que fue vendido al fabricante de autos eléctricos por 75,000 dólares.

Una vez que el dominio ha sido adquirido, el “Registrar” enviará al comprador una serie de datos e instrucciones al correo que éste último indicó al momento del registro o compra del dominio. La operación completa toma al rededor de 10 minutos.

Es MUY recomendable que el correo que se indica para la compra del dominio en cuestión sea un correo dedicado para sólo este fin. En este sentido, conviene crear un correo gratuito (gmail, outlook, hotmail, yahoo o cualquier otro) y usarlo sólo para este propósito. De esta manera, si algún día decidimos vender el dominio, la transferencia será mucho mas fácil y directa.

Nota importante

II Creación de una Zona en AWS Route53

AWS Ofrece una interfaz para la gestión de dominios, sub dominios y registros A, AAA, CNAME, TXT, etc de los nombes de dominio que hayamos adquirido con un registrar. Esto es posible a través de la interfaz llamada Route53.

En el momento en el que damos de alta en Route53 un nombre de dominio que hayamos adquirido con algún “Registrar”, podremos observar que se generan cuatro cadenas de texto asociadas a los “name servers” (servidores de nombre) que AWS crea de manera automática. Se deberá tomar nota de esas cuatro cadenas ya que serán usadas en el siguiente paso.

III Alta de Name Servers en el “Registrar”

Con la información generada por AWS Route53 en referencia a las 4 cadenas de texto asociadas a los “Name Servers”, se deberá ingresar a la interfaz del “Registrar” y solicitar la redirección de los DNS’s que tiene (generalmente apuntados a servidores de nombre de si mismo) pero ahora ingresando la nueva información.

En un siguiente paso se verificará que si esto se hizo correctamente, ya que no es posible hacerlo de manera inmediata, pues este cambio generalmente toma una o dos horas en hacerse efectivo.

Mientras tanto, se deberán realizar otras actividades que se explican a continuación.

IV Generación de una IP estática, permanente y homologada

Durante este proceso, será requerida una única IP estática y homologada que será nuestra puerta de acceso a todos los servicios de nuestra infraestructura de integración continua.

La generación de una IP homologada es posible ya sea gracias a la interfaz de EC2 que provee AWS en la sección de “Elastic IP” o bien mediante la ejecución de un sencillo script para aws cli:

aws ec2 allocate-address \
    --domain vpc \
    --network-border-group us-east-1

Que nos genera la siguiente respuesta de EJEMPLO:

{
    "PublicIp": "70.224.234.241",
    "AllocationId": "eipalloc-02463d08ceEXAMPLE",
    "PublicIpv4Pool": "amazon",
    "NetworkBorderGroup": "us-east-1",
    "Domain": "vpc"
}

Evidentemente, esta respuesta será diferente cada vez que el primer comando sea invocado. El dato que nos interesa es el IP generado. En este ejemplo es “70.224.234.241”. Se deberá tomar nota de tal IP ya que será empleado en el siguiente paso.

También es MUY importante anotar el “AllocationId” asociado a esta IP, ya que será requerido al momento de asignar esta IP a una instancia de EC2, cosa que haremos hacia el final de este tutorial.

V Generación de subdominios

La generación de subdominios se realiza en la interfaz de Route53 que provee AWS y básicamente requiere de cuatro datos:

  1. Nombre del subdominio (es el conjunto de segmentos que van al inicio de nuestro nombre de dominio, como www, ftp o estructuras mas compplejas como srv01.ci, uno.dos.tres, etc)
  2. Tipo de registro, que en nuestro caso será siempre “A”, salvo un único caso que se discutirá próximamente (registro TXT)
  3. Dirección IP, que en nuestro caso es la IP estática, homologada generada en el punto IV
  4. TTL que es un número y en nuestro caso siempre será: 60 (“Time To live” representa el número de segundos de refresco)

También es posible usar el cliente consola de AWS para dar de alta tales subdominios. Si se desea realizar de esta forma, l referencia puede ser consultada en esta liga: https://docs.aws.amazon.com/cli/latest/reference/route53/index.html

Por otro lado, “en caso” de que se tenga la posibilidad de usar el sdk de aws, entonces la generación de varios dominios se puede “automatizar” con el siguiente segmento de código java que contiene sólo dos métodos:

    
    public CreateZoneSubdomains(String hostedZoneId, String domain, String ip) {
        String dns = Tools.getScriptTextPlain("zone-names.txt");
        String[] names = dns.split(" ");
        changeRecordSetTypeA(hostedZoneId, domain, ip);
        for(String name : names) {
            if(name.trim().length()>0) {
                changeRecordSetTypeA(hostedZoneId, name.trim() + ".ci."+domain, ip);
            }
        }
    }

    public ChangeResourceRecordSetsResult changeRecordSetTypeA(
            String hostedZoneId, String subdomain, String ip) {
        @SuppressWarnings("deprecation")
        AmazonRoute53Client route53Client = new AmazonRoute53Client();
   
        GetHostedZoneResult hostedZoneResult = route53Client.getHostedZone(
            new GetHostedZoneRequest(hostedZoneId));
        HostedZone hostedZone = hostedZoneResult.getHostedZone();
    
        ResourceRecordSet resourceRecordSet = new ResourceRecordSet()
            .withName(subdomain)
            .withType(RRType.A)
            .withTTL(60L)
            .withResourceRecords(new ResourceRecord().withValue(ip));
    
        ChangeResourceRecordSetsRequest request = new ChangeResourceRecordSetsRequest()
            .withHostedZoneId(hostedZone.getId())
            .withChangeBatch(new ChangeBatch()
                    .withChanges(new Change()
                            .withAction(ChangeAction.CREATE)
                            .withResourceRecordSet(resourceRecordSet)
                     )
             );
        Tools.prn("Se ha creado el subdominio: [%s] en el ip: [%s]\n", subdomain, ip);
        return route53Client.changeResourceRecordSets(request);
     }

VI Solicitud de certificados SSL

Con la información de propiedad de nombre de dominio es posible realizar la compra de certificados SSL. Para este caso, será INDISPENSABLE solicitar un certificado de tipo WILDCARD. Esto nos permitirá usarlo en cualquier subdominio del dominio asociado. Es recomendable que se pida del tipo “green”. Estos certificados, después de pagados los podemos empezar a usar de manera inmediata. El proceso completo de compra y descarga, posterior a la compra no toma mas de 10 minutos y los proveedores que ofrecen estos servicios son variados: Verisign, Commodo, CheapSSL, etc. Un certificado WILDCARD “green” de Verisign puede costar unos 50 usd al año, aproximadamente.

Próximamente tales certificados serán requeridos en la configuración del servidor Nginx, ya que habrá que indicar su trayectoria en un apartado similar al siguiente:

ssl_certificate     /some/path/fullchain.pem;
ssl_certificate_key /some/path/privkey.pem;

fullchain.pem is a concatenation of cert.pem and chain.pem in one file. In most servers you’ll specify this file as the certificate, so the entire chain will be send at once.

Fuente: Super Goose

En caso de que en un futuro se desee emplear otro servidor web, como Apache, por ejemplo, quizá sea necesario generar mas archivos asociados al SSL y si el vendedor no los generó ni envió de manera previa, la herramienta (libre) openssl quizá nos podría ser de utilidad para tal efecto.

En el momento de solicitar la generación de los archivos asociados al certificado SSL, es posible que el proveedor de certificados (por ejemplo, Verisign) nos pida crear un registro TXT en Route53. Sería un procedimiento prácticamente igual al que hicimos para la creación manual de subdominios en Route53, pero en vez de usar “A” sería “TXT”.

VII Creación del servidor de “Front”

En esta sección se creará un servidor EC2 al cual le asignaremos en su momento, la IP estática que nos entregó AWS y que responderá (via un servidor nginx) adecuadamente ante cada petición de nombre de dominio hacia tal IP.

Para este efecto, se requerirá de tener los siguientes recursos ya creados:

  1. Grupo de seguridad con puertos abiertos: 22, 80, 443, 1521, 5005 para el CIDR: 0.0.0.0./0
  2. Grupo de seguridad con puertos abiertos: 0-65535 para el CIDR: 171.31.0.0/16
  3. Keypair de acceso ssh para el servidor de Front (vale la pena crear este recurso en la interfaz de EC2)
  4. La IP estática y homologada generada en pasos previos (requeriremos el “id” asociado a esta IP. Si no lo anotamos cuando se creó, podemos recuperarlo en la interfaz de EC2)
  5. Archivo de Pre-Configuración e instalación de Software inicial.

Se recuerda que todas las operaciones, configuraciones y ajustes descritos en este documento, pueden ser gestionados directamente desde la interfaz de AWS, pero que también es posible usar la interfaz de linea de comandos “aws cli” para el mismo efecto. Dicho lo anterior, para la mayoría de solicitudes se mostrará el código asociado a ejecutar desde la interfaz de comandos “aws cli”.

El siguiente código nos permite crear un grupo de seguridad con las carecterísticas que se mencionan en párragos anteriores:

aws ec2 create-security-group \
--group-name my-sg-any-name \
--description "My security group description" \
--vpc-id vpc-4b8d0531

Obtendremos la siguiente respuesta:

{
    "GroupId": "sg-0824778f9d1e68ac1"
}

Con el “ID” obtenido, podremos agregar “reglas” a tal grupo. En este caso, la regla es la apertura del rango de puertos del 3389 al 4123, que serán accesibles sólo desde el rango de IP’s 172.31.0.0/16

aws ec2 authorize-security-group-ingress \
--group-id sg-0824778f9d1e68ac1 \
--protocol tcp \
--port 3389-4123 \
--cidr 172.31.0.0/16

Con 256×256 direcciones capacez de conectar con ese rango de puertos de la vpc existente de la región. El rango de IP’s fué calculado usando la herramienta en la siguiente liga: http://www.subnet-calculator.com/cidr.php

La bandera “–port” soporta un rango de puertos (como el que se usó) o un simple número, como 22, por ejemplo.

En este punto se deberá crear un “Keypair” y la mejor manera de hacer esto es via la interfaz de EC2. Para este ejemplo, el nombre del “Keypair” será “frontKey”

Nota importante !!!

Para crear una instancia de EC2, se deberá usar este código:

aws ec2 run-instances \
--image-id ami-085925f297f89fce1 \
--count 1 \
--instance-type t2.small \
--key-name frontKey \
--security-group-ids sg-058aa6ea0649c0f92 \
--user-data file://script_00.txt \
--block-device-mappings "[{\"DeviceName\":\"/dev/sda1\",\"Ebs\":{\"VolumeSize\":20,\"DeleteOnTermination\":false}}]"

Con lo anterior, se solicita la creación de una (–count=1) instancia de EC2 de Ubuntu 18_04 (ami-085925f297f89fce1), con 1 CPU y 2 Gigas de memoria RAM (t2.small), 20 Gb de disco SSD, con llave de acceso “frontKey”, en elgrupo de seguridad dado (sg-058aa6ea0649c0f92) y ejecutando la serie de comandos descritos en el archivo “script_00.txt”

El contenido del archivo “script_00.txt” es el siguiente:

#!/bin/bash

sh -c "echo 'LC_ALL=en_US.UTF-8\\nLANG=en_US.UTF-8' >> /etc/environment"

apt update
apt install -y docker-ce
apt install -y docker-compose
apt install -y s3fs
apt install -y sshfs

gpasswd -a ubuntu docker

mkdir -p /home/ubuntu/{.ssh,services,shared-s3,shared-ssh}
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDjybz2kqMxcryhVVOCRWPlBt9//gDTcQECrleQZyO2F1diR+7ANZ7iHFB1+ZdDRv6qi45aL7EaNDAtIxAJp4IxSYAiQeycdUfoiTX/HYkQWj5+13Zc0Rw+SARFJ9KnRZM8Al2olEOfqnCUxBkTj24sozfeSViAi+CfzANL/TlS1lfvbF/icbRgDqvXeqqqdOMxFf6rWYJG5nqIirfa6EpOWjsEnjLSWAyZCfuV/A6wk0fosSBQnzs/K6f8aSe2AZtDX7RRYQELeW7i2J2KS9DqpptMRRD1ysRBKp9qxqS7SKBEFVOMsUVLHRPbJcpdDc0SHLu7j/7sv3JGXJPyja2b" >> /home/ubuntu/.ssh/authorized_keys

wget --no-check-certificate 'https://cutt.ly/gzvViBW' -O /home/ubuntu/bridge.tar.gz

tar xzvf /home/ubuntu/bridge.tar.gz -C /home/ubuntu
chown -R ubuntu:ubuntu /home/ubuntu timedatectl set-timezone America/Mexico_City

Una vez que la instancia de EC2 está en estado operacional, se deberá asignar la IP estática homologada a tal instancia. Como siempre, esto puede ser realizado via la interfaz gráfica de AWS en la sección de EC2 (elastic IP) o bien via la ejecución del siguiente comando:

aws ec2 associate-address \
--instance-id i-0b263919b6498b123 \
--allocation-id eipalloc-64d5890a

Con lo anterior, hemos asociado el “id” de una dirección ip estática al “id” de una instancia EC2.

En este punto, ya es posible usar la llave privada de “frontKey” que generamos en la interfaz gráfica de AWS (módulo EC2) para acceder al servidor de front con la ip estática que acabamos de asociar y hasta lo podemos hecer con alguno de los nombres de dominio que hemos asociado a esa IP al inicio de este Tutorial. La forma de acceder se la siguiente:

ssh -i frontKey.pem -o "StrictHostKeyChecking no" ubuntu@server.com.mx

Una vez dentro…

1. correr el script de search & replace para el nombre del dominio
2. colocar los certificados en una ruta adecuada
3. correr el script para la generación del keystore de java
4. correr el script de arranque de Nginx
5. verificar que se llega a los dominios indicados

listo !!!! To be continue…

Mediterráneo... Un regalo de Serrat

General, Personal Comments Off on Mediterráneo… Un regalo de Serrat
Apr 042020

Quizás porque mi niñez
Sigue jugando en tu playa
Y escondido tras las cañas
Duerme mi primer amor,
Llevo tu luz y tu olor
Por dondequiera que vaya,
Y amontonado en tu arena
Guardo amor, juegos y penas.
Yo, que en la piel tengo el sabor
Amargo del llanto eterno
Que han vertido en ti cien pueblos
De algeciras a estambul
Para que pintes de azul
Sus largas noches de invierno.
A fuerza de desventuras,
Tu alma es profunda y oscura.
A tus atardeceres rojos
Se acostumbraron mis ojos
Como el recodo al camino.
Soy cantor, soy embustero,
Me gusta el juego y el vino,
Tengo alma de marinero.
Qué le voy a hacer, si yo
Nací en el mediterráneo.
Y te acercas, y te vas
Después de besar mi aldea.
Jugando con la marea
Te vas, pensando en volver.
Eres como una mujer
Perfumadita de brea
Que se añora y que se quiere
Que se conoce y se teme.
Ay, si un día para mi mal
Viene a buscarme la parca.
Empujad al mar mi barca
Con un levante otoñal
Y dejad que el temporal
Desguace sus alas blancas.
Y a mí enterradme sin duelo
Entre la playa y el cielo…
En la ladera de un monte,
Más alto que el horizonte.
Quiero tener buena vista.
Mi cuerpo será camino,
Le daré verde a los pinos
Y amarillo a la genista.
Cerca del Mar porque yo
Nací en el mediterráneo.

Code formatter... que bien se ve !!!

Configuración, General, Personal, Técnicos Comments Off on Code formatter… que bien se ve !!!
Mar 272020
var arreglo = [2,3,20,10,1,23];
arreglo.sort(function (a,b){
   return a-b
});

function ok() {
  console.log(arreglo);
}

Se ve genial, no?


Este es otro estilo
Y es mas compacto..

Y… este es el tercer estilo:

echo "usage: wherein <dir> <file-pattern> <string>"

for i in $(find $1 -name $2);
    do 
      if grep -i $3 "$i"; 
        then echo "$i"; 
      fi; 
done;

Gallito

General, Personal Comments Off on Gallito
Mar 272020

Yo, Gustavo

General, Personal, Técnicos Comments Off on Yo, Gustavo
Mar 182020

Técnicamente se hacer muy pocas cosas y tardo un poco en aprender cosas nuevas, pero las pocas cosas que sé hacer y que he tardado en aprender las sé hacer muy bien:

1. Puedo levantar una infraestructura de CI/CD de principio a fin con sus respectivos certificados SSL (Green) para cada servicio y mecanismos de backup y restauración en una infraestructura AWS. Se incuye GitLab, Jenkins, Nexus (+ registry Docker privado), SonarQube, OpenGrok y Rancher (front gráfico de Kubernetes)

2. Puedo desarrollar aplicativos Rest/Springboot/MyBatis/VueJs completamente Dockerizados, basados en una arquitectura de microservicios y listos para despliegue en una infraestructura de H.A. que también puedo preparar.

3. Puedo integrar al 100% una sub infraestructura de autorización y autenticación en Keycloak.

3. Conozco y practico el Agilismo y soy capaz de formar equipos de alto desempeño muy productivos y muy felices de hacer su trabajo.

4. Me gusta mucho transmitir conocimiento y mis alumnos, a lo largo de los años, dicen que lo hago muy bien.

¿A quién le gustaría contratarme?

Sólo cobro 5,000 usd al mes.

Abrazos,
Gus

Http proxy tunnel

Configuración, LINUX, Mis PCs Comments Off on Http proxy tunnel
Mar 112020
  1. Se debe de tener acceso SSH a un servidor remoto con acceso libre (sin restricciones) a las páginas que se desea acceder desde una red que no las permite. En nuestro ejemplo será el servidor ficticio ubuntu@gus.com
  2. Antes de iniciar cualquier configuración, se debe averiguar la dirección IP pública de nuestro equipo. La página https://www.whatismyip.com/es/ muestra tanto la ipv4 como la ipv6
  3. Abrimos una terminal de sistema en nuestro equipo y tecleamos:
    ssh -D 1337 -q -C -N  ubuntu@gus.com
  4. Abrimos nuestro firefox y en configuración del proxy en la sección “configuración manual del proxy” ponemos:
  5. Servidor SOCKS: localhost
  6. Puerto: 1337
  7. Proxy DNS cuando uses SOCKS v5: SI
  8. Guardar configuración
  9. Verificar nueva dirección IP en la página descrita en el punto 2
  10. Si la IP ya cambió, entonces ya podemos navegar a donde nos agrade…

Cheers,

Descarga de un archivo de plantilla

Configuración, Ingeniería de Software, Técnicos Comments Off on Descarga de un archivo de plantilla
Mar 042020

Este es un ejemplo del proceso de descarga de un archivo de plantilla (o template) de tipo MSWord (.doc)

Como el SEO solicita que existan al menos 300 palabras en este cuerpo, el presente párrafo intenta cumplir con esa directiva.

Al mismo tiempo, esta página intenta ejemplificar cómo poder bajar un documento (que en este caso es una plantilla Word para minutas) para su uso en repetidas ocasiones.

Bajar template para minuta de trabajo

Debería de ser trivial bajarlo.

Esta es una liga interna: interna

 


Este es un ejemplo del proceso de descarga de un archivo de plantilla (o template) de tipo MSWord (.doc)

Como el SEO solicita que existan al menos 300 palabras en este cuerpo, el presente párrafo intenta cumplir con esa directiva.

Al mismo tiempo, esta página intenta ejemplificar cómo poder bajar un documento (que en este caso es una plantilla Word para minutas) para su uso en repetidas ocasiones.

 

Este es un ejemplo del proceso de descarga de un archivo de plantilla (o template) de tipo MSWord (.doc)

Como el SEO solicita que existan al menos 300 palabras en este cuerpo, el presente párrafo intenta cumplir con esa directiva.

Al mismo tiempo, esta página intenta ejemplificar cómo poder bajar un documento (que en este caso es una plantilla Word para minutas) para su uso en repetidas ocasiones.

 

Este es un ejemplo del proceso de descarga de un archivo de plantilla (o template) de tipo MSWord (.doc)

Como el SEO solicita que existan al menos 300 palabras en este cuerpo, el presente párrafo intenta cumplir con esa directiva.

Al mismo tiempo, esta página intenta ejemplificar cómo poder bajar un documento (que en este caso es una plantilla Word para minutas) para su uso en repetidas ocasiones.


Este es un ejemplo del proceso de descarga de un archivo de plantilla (o template) de tipo MSWord (.doc)

Como el SEO solicita que existan al menos 300 palabras en este cuerpo, el presente párrafo intenta cumplir con esa directiva.

Al mismo tiempo, esta página intenta ejemplificar cómo poder bajar un documento (que en este caso es una plantilla Word para minutas) para su uso en repetidas ocasiones.

 

Descarga de un archivo de plantilla
Math as always…
Mar 042020

Bueno, actualmente ya tenemos un conjunto de poderosas herramientas, técnicas y estrategias que nos permiten desarrollar de una manera mas productiva y profesional (mucho menos artesanalmente) que como lo hacíamos hace tiempo. A la fecha he identificado siete grandes bloques que han sido construidos con mucho esfuerzo y que requirieron de mucho tiempo para su elaboración, a saber:

  1. Servicio en alta disponibilidad (HA) con balanceo automático de las instancias que sean creadas.
  2. Infraestructura de CI/CD incluyendo Gitlab, Jenkins, Nexus, Sonar, Rancher con backups automáticos en AWS S3 y posterior corrimiento a “S3 Glacier”.
  3. Servicio gestor de identidad (KeyKloak) totalmente desacoplado.
  4. Frontend Reactivo de tipo VueJS integrado al servicio de Keycloak
  5. Despliegue bajo un proxy que aplica SSL
  6. Generador automático de código + Arquetipo maven + Swagger
  7. Uso de Springboot, c3p0, jasypt, mail, jwt, docker, h2, jUnit

find file containing specific text on tree

Configuración, LINUX, Técnicos Comments Off on find file containing specific text on tree
Mar 012020

Este es un Script (extremadamente portable) para buscar una cadena de texto de manera recursiva en un árbol de directorios.

echo "usage: wherein <dir> <file-pattern> <string>"

for i in $(find $1 -name $2);
    do 
      if grep -i $3 "$i"; 
        then echo "$i"; 
      fi; 
done;

No olvidar 2 cosas:

  • 1.- chmod 777 whereis.sh
  • 2.- cp whereis.sh /usr/local/bin

Ya lo puedes usar desde donde sea con:

whereis.sh /home/ubuntu *.java "new Factura"

Razón por la cual sonreir hoy

General, Personal Comments Off on Razón por la cual sonreir hoy
Feb 252020

Un hermoso arcoiris… Un cielo despejado y ninguna preocupación en la mente… Soy libre.

Ahora sólo me hace falta una razón por la cual estar totalmente apasionado. Una causa, una meta, un hogar.

Hubo, sin embargo, un tiempo y un espacio (algo breve, por cierto) en el que fuí totalmente feliz…

Pero lo mejor de todo es que me acerco cada vez mas a verdes pastos y cielos azules, con amables nubes que me hacen saber que por fin llegué a mi destino…

© 2020 Goose Workshop Suffusion theme by Sayontan Sinha