OS

TOPICS


Agosto 2020

  Docker enchulame la lista de contenedores
Agosto 1   |   Docker

Siempre que ejecuto docker ps para listar los contenedores me resulta difícil entender donde inicia y donde termina la información sobre cada contenedor:



¡Que carajos! ... el puerto ¿cúal? ... siento que casi estoy viendo la matrix

Debo admitir que después de un tiempo tus ojos se acostumbran y comienzan a hacer cosas raras pero comienzas a entender el resultado. Claro que no debería ser así, por lo que encontré que tenemos algunas opciones para mejorar el resultado.

Utilizar —format

Al utilizar la opción --format, podemos elegir de una serie campos disponibles e incluso despegarlos de forma mas ordenada usando la sintaxis table {{.FieldName}}\t. La opción format utiliza Go templates algo que me resulta familiar1.

table incluye los encabezados y \t agrega espacio entre las columnas.

 Ejemplo usando --format

            

 docker ps --format 'table {{.Names}}\t
                           {{.Status}} : {{.RunningFor}}\t
                           {{.ID}}\t
                           {{.Image}}'
            
            
        

Y obtenemos esto:

Definitivamente resulta mucho más fácil de comprender

Sacando provecho a los Go Templates

Nos podemos poner creativos y si necesitamos por ejemplo consultar los contenedores con información de red utilicemos las características de los GoLang Templates para detectar si hay puertos y desplegarlos en cada linea:

 Información de red

            

docker ps --format 'table {{.Names}}
                          \t{{.Status}}
                          \t{{.Networks}}
                          \n{{.ID}}
                          {{if .Ports}}
                            {{with $p := split .Ports ", "}}
                              {{range $p}}\t\t{{println .}}{{end}}
                            {{end}}
                          {{else}}
                            \t\t{{println "No Ports"}}
                          {{end}}'
            
            
        

Como ven mucho mejor ordenado en dos columnas y con todos los datos de la red y puertos mas legibles

Todos los containers docker ps –a

Podemos revisar todos los contenedores (activos y no activos) utilizando la opción -a. Aprovechando los templates añadamos el tamaño en disco, como utiliza la red y la imagen de donde proviene el contenedor.

 Información de todos los contenedores

            

docker ps -a -q --format 'table {{.Names}}\t
                                {{.Status}}\t
                                {{.Size}}\n
                                {{.ID}}\t
                                {{.Image}}
                                {{if .Ports}}
                                  {{with $p := split .Ports ", "}}\t
                                    {{len $p}} port(s) on {{end}}{{- .Networks}}
                                  {{else}}\tNo Ports on {{ .Networks }}
                                {{end}}\n'
            
            
        


De esta manera podemos ver en general el estado de nuestros contenedores.

Crear una función para reutilizar los comandos

Finalmente podemos crear una función para utilizar estos comandos (si estas utilizando WSL o Linux) dentro de nuestro .bash_aliases

 Crear una función bash que acepta parámetros

            

# Docker PS Prettify Function
function dock() {
  if [[ "$@" == "ps" ]]; then
    command docker ps --format 'table {{.Names}}\t{{.Status}} : {{.RunningFor}}\t{{.ID}}\t{{.Image}}'
  elif [[ "$@" == "psa" ]]; then
    # docker ps -a includes all containers
    command docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Size}}\n{{.ID}}\t{{.Image}}{{if .Ports}}{{with $p := split .Ports ", "}}\t{{len $p}} port(s) on {{end}}{{- .Networks}}{{else}}\tNo Ports on {{ .Networks }}{{end}}\n'
  elif [[ "$@" == "psnet" ]]; then
    # docker ps with network information
    command docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Networks}}\n{{.ID}}{{if .Ports}}{{with $p := split .Ports ", "}}{{range $p}}\t\t{{println .}}{{end}}{{end}}{{else}}\t\t{{println "No Ports"}}{{end}}'
  else
    command docker "$@"
  fi
}
            
            
        

Para utilizarlo basta ahora con teclear:

dock ps
Contenedores en ejecución con su imagén
dock psa
Todos los contenedores incluyendo tamaño en disco y datos de red
dock psnet
Contenedores en ejecución con información de red

Campos disponibles en docker

.ID
Identificador del contenedor
.Image
Id de la imagén
.Command
Comando de ejecución
.CreatedAt
Tiempo cuando el contenedor se creó.
.RunningFor
Tiempo transcurrido desde que se inició el contenedor.
.Ports
Puertos utilizados por el contenedor.
.Status
Estado del contenedor.
.Size
Espacio que ocupa en disco el contenedor.
.Names
Nombre del contenedor.
.Labels
Todas las etiquetas asignadas al contenedor.
.Label
Valor especifico para una etiqueta. Por ejemplo ‘{{.Label “com.docker.swarm.cpu”}}’
.Mounts
Nombre de los volúmenes montados en este contenedor.
.Networks
Nombre de las redes adjuntas al contenedor.

  1. Este blog esta desarrollado con HUGO, el cual a su vez usa GoLang html y text templates. ↩︎

Marzo 2020

  Docker solucionar el nombre duplicado de red
Marzo 25   |   Docker

El Problema

Un día tuve que reiniciar mi servidor linux y como Murphy no falla al regresar la instancia de docker estaba vacía sin ningún container, después de explorar un rato y revisar que todo estuviera en orden no encontré la causa, hice lo que se debe hacer … reinicie nuevamente el servidor y ohh sorpresa ahi estaban de nuevo todos mis containers ¡Genial! pero … al momento de intentar iniciarlos


ERROR: network xxxx is ambiguous (2 matches found based on name)

Los porques

Encontré que es valido duplicar el nombre de la red en docker, mi sospecha es que al no encontrar la configuración docker generó nuevamente toda las redes porque como pueden ver se duplicaron las redes y los drivers

 docker network list

            

$ docker network ls
NETWORK ID NAME DRIVER SCOPE
27b6c27fdc2b bridge bridge local
33f2a0c04878 bridge bridge local
c4247d693521 host host local
9b95be563bf7 host host local
590102262bb5 none null local
25e1bf9dc86 none null local
            
            
        

Asi que la solucion parece simple eliminar la red duplicada y ya esta docker network rm [ID], lo intente pero ….


Error : bridge is a pre-defined network and cannot be removed

La solución no parece ser tan trivial, en algún foro encontré que para poder eliminar la red:

  1. El servicio de docker debe estar detenido
  2. No debe existir un contenedor usando la red
  3. No tener ningún contenedor creado

Por cierto para ver cuales containers están usando la red puedes usar:

 Inspect network ID of a container

            

# Como bridge esta repetido necesitas hacerlo por Id y revisar la sección de "Containers"
docker network inspect [id || name]

"Internal": false,
{ "Network": "" },
"ConfigOnly": false,
"Containers": {},

            
            
        

La opción uno y dos no funcionaron y no podía darme el lujo de eliminar los containers y volverlos a crear pues ya los tenia configurados con sus volúmenes y otras cosas asi que la solución es:

Solución

  1. Crear una nueva red con -d especificamos el driver

docker network create -d bridge [nuevo-nombre-de-red]

  1. Desconectar el o los containers de la red ambigua

    docker network disconnect bridge [contenedor]

  2. Conectar el o los containers hacia la nueva red

    docker network connect [nuevo-nombre-de-red] [contenedor]

  3. Opcional. Purgar nuestra red para eliminar aquellas redes que no estamos utilizando.

docker network rm $(docker network ls -q)

Listo ya con esto podemos iniciar nuestro container


docker start my-happy-container

Enero 2020

  FFmpeg concatenar videos sin recodificar
Enero 12   |   Terminal

Para concatenar varios videos usando ffmpeg necesitamos tener un archivo de texto que contenga en cada linea un path a los videos:

 VideoList.txt

            

# Se pueden utilizar rutas absolutas o relativas

file '/path/to/video1.mp4'
file '/path/to/video2.mp4'
file '/path/to/video3.mp4'
            
            
        

 Ejecutar

            

# Si se utilizan rutas absolutas agremamos el parametro -safe 0
ffmpeg -f concat -safe 0 -i videolist.txt -c copy output.mp4
            
            
        

 Para generar en automatico un archivo con la lista de videos

            


# Windows
(for %i in (\*.mp4) do @echo file '%i') > videolist.txt
ffmpeg -f concat -i videolist.txt -c copy output.mp4

# Bash
for f in ./\*.mp4; do echo "file '\$f'" >> videolist.txt; done
ffmpeg -f concat -i videolist.txt -c copy output.mp4

# Zsh - Todo en una linea
ffmpeg -f concat -safe 0 -i <(for f in ./\*.mp4; do echo "file '$PWD/$f'"; done) -c copy output.mp4
            
            
        

 Repetir mismo el video

            


# Windows ... in (start,step,end)
(for /l %i in (1,1,10) do @echo file './videoloop.mp4') > mylist.txt
ffmpeg -f concat -i list.txt -c copy output.mp4

# Bash
for i in {1..4}; do printf "file '%s'\n" input.mp4 >> list.txt; done
ffmpeg -f concat -i list.txt -c copy output.mp4
            
            
        

REFERENCIAS:

  Terminal verificar si una cadena esta vacia
Enero 5   |   Terminal

Una de las tareas básicas cuando haces scripting es verificar si una cadena esta o no vacía (puede venir de un parámetro, un input de usuario, etc). Lo hacemos con los operadores -n y -z

 Cadena vacia

            

#!/bin/bash

VAR=''
if [[ -z $VAR ]]; then
echo "String is empty."
fi
            
            
        

 Cadena no vacia

            

#!/bin/bash

VAR='Linuxize'
if [[ -n $VAR ]]; then
echo "String is not empty."
fi
            
            
        

REFERENCIA: Linuxize

Julio 2019

  Limpiar la papelera de reciclaje de todos los usuarios
Julio 20   |   Windows

La emergencia 🔔

Notificación 🔔, urge que te conectes al servidor remoto para ejecutar una script de SQL, te conectas y 💥


An error occurred while executing batch. Error message is: There is not enough space on the disk....

Revisas y te das cuenta que no hay espacio en la unidad C -nada, 0, no cabe un bit mas- Resulta que el SSMS de SQL necesita espacio en C:\Users\...\AppData\Local\Temp para los resultados de un Query


Revisas archivos temporales, tu papelera, etc. luego ejecutas el asistente de limpieza de windows, nada ayuda, cuando mucho ganas unos pocos megas

WinDirStat

De pronto recuerdas esta maravillosa herramienta WinDirStat y la dejas analizar la unidad. Gracias a ella te das cuenta de dos carpetas que se estan comiendo tu espacio en el disco:

Limpia la papelera de todos los usuarios


1. Tus compañeros no son muy cuidadosos con su papelera de reciclaje

Asi que abres el terminal en modo administrador y ejecutas lo siguiente:

 Vaciar la papelara de reciclaje de todos los usuarios

            

rd /s c:\$Recycle.Bin
            
            
        
Si alguien te reclama después, puedes decirle !ey, no me culpes¡, por algo estaban en la papelera

Carpeta de instalación de Windows


2. Windows no es bueno limpiando su propio folder de instalaciones \Windows\Installer

Esto debe de abordarse con cuidado, es un error conocido que la carpeta de Windows Installer crece con el tiempo sobre todo si estas instalando muchas aplicaciones (Ahora imaginate si esta PC se comparte con mas usuarios cada uno instalando y actualizando sus propias aplicaciones). En resumen, el problema es que cuando se desinstala una app, estas no eliminan de forma correcta sus paquetes de instalación/actualización. Se supone que no deberíamos de tocar esta directorio, pero como en todo debemos de proceder con cuidado.

El fix en si es identificar los paquetes de instalación/actualización que pertenecen a aplicaciones que ya se desinstalaron del sistema.

Manualmente puedes ejecutar el siguiente VBA Script el cual genera un archivo que contiene los archivos que están instalados y que DEBEMOS de mantener en el sistema, lo demás puede ser borrado

 VBA Script

            

'' Identify which patches are registered on the system, and to which
'' products those patches are installed.
''
'' Copyright (C) Microsoft Corporation. All rights reserved.
''
'' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
'' KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
'' IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
'' PARTICULAR PURPOSE.

'Option Explicit

Dim msi : Set msi = CreateObject("WindowsInstaller.Installer")

'Output CSV header
WScript.Echo "The data format is ProductCode, PatchCode, PatchLocation"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.CreateTextFile("output.txt", True)
objFile.WriteLine "ProductCode, PatchCode, PatchLocation"
objFile.WriteLine ""
' Enumerate all products
Dim products : Set products = msi.Products
Dim productCode

For Each productCode in products
' For each product, enumerate its applied patches
Dim patches : Set patches = msi.Patches(productCode)
Dim patchCode

    For Each patchCode in patches
    	' Get the local patch location
    	Dim location : location = msi.PatchInfo(patchCode, "LocalPackage")
        objFile.WriteLine productCode & ", " & patchCode & ", " & location

    Next

Next
WScript.Echo "Data written to output.txt, these are the registered objects and SHOULD be kept!"
            
            
        

Agradecimientos a Raymond.cc en su post se detallan ademas de el script anterior algunas otras formas de limpiar este directorio.


Suerte espero que estos dos tips te ayuden a recuperar valioso espacio en tu sistema.

Marzo 2019

  Vincular una carpeta a una unidad en Windows
Marzo 18   |   Windows

Un antiguo comando DOS que permite rápidamente vincular un directorio a una unidad en Windows puede resultar muy útil para muchos escenarios, entre los más comunes están el emular entornos de producción en maquinas de desarrollo, actualmente lo he utilizado para mantener las políticas de publicación de visual studio entre las maquinas de los desarrolladores. Hay dos maneras de hacerlo:

subts

 subts

            

REM to create
subst X: "C:\Users\ProgramadorSinSuerte\MiFolder"
REM to delete
subst X: /D
            
            
        
  • Después de la unidad dejar un espacio en blanco
  • Si el directorio lleva espacios se pueden utilizar comillas “\directorio con espacios"
  • Notar que al final no se incluye el carácter diagonal “\

✍️ Este comando espera que el directorio siempre este disponible de lo contrario se volverá loco buscándolo como si de una unidad física se tratara mermando el desempeño de la maquina. Por ello se recomienda usarlo con directorios presentes de manera local.

✍️ El mapeo se elimina con cada reinicio, si se necesita que este presente siempre, se puede colocar en el directorio de inicio de Windows C:\Program Data\Microsoft\Windows\Start Menu\Programs\Startup

🔗 (WindowsKey + R, type: shell:common startup)

net use

net use D: \\localhost\c$\Users\ProgramadorSinSuerte\MiFolder

✍️ Este comando es mas tolerante a fallos en cuando a la disponibilidad del recurso. Generalmente se utiliza para recursos compartidos en red.