miércoles, 29 de mayo de 2019

Cómo conectar por SSH a un EC2 Linux en AWS



Pasos a seguir para conectarse por SSH a una instancia EC2 Linux en Amazon Web Services (AWS).



Al igual que ocurre al desplegar una instancia Windows en Amazon Web Services, al desplegar una instancia Linux en AWS se debe generar un par de claves pública/privada, que luego nos servirán para acceder a la instancia. A continuación, se debe descargar la clave privada (fichero.pem), la cual actuará como "contraseña" para acceder al sistema operativo.

Con el usuario, la IP de la instancia y la clave privada, podremos conectarnos por SSH a la máquina que hayamos desplegado. El usuario para conectarse a una instancia varia según la distribución Linux.

La lista de usuarios y distribuciones soportadas es la siguiente:

Para Amazon Linux, el nombre de usuario es ec2-user.
Para CentOS, el nombre de usuario es centos.
Para Debian, el nombre de usuario es admin o root.
Para Fedora, el nombre de usuario es ec2-user o fedora.
Para RHEL, el nombre de usuario es ec2-user o root.
Para SUSE, el nombre de usuario es ec2-user o root.
Para Ubuntu, el nombre de usuario es ubuntu.


Conectarse desde Linux



Para conectarse a una instancia Linux mediante SSH desde un sistema operativo Linux, hay que especificar el archivo de clave privada (.pem), el usuario y la IP de la instancia. Por ejemplo:

HOST# ssh -i key.pem ec2-user@10.11.25.1


Conectarse desde Windows (PuTTy)



Para conectarse con PuTTY a una instancia Linux en AWS, primero hay que convertir la clave privada de la instancia mediante PuTTYgen, ya que PuTTY no admite de forma nativa claves en formato .pem. PuTTY tiene la herramienta PuTTYgen que permite convertir claves al formato que usa PuTTY (.ppk).

Para convertir la clave privada, abrir PuTTYgen y en "Type of key to generate", elegir RSA.



Clicar "Load" para cargar el fichero .pem. Recordar que hay que seleccionar la opción de mostrar todos los tipos de archivo para ver los archivos .pem.



Una vez cargado el fichero .pem, elegir "Save private key" (Guardar clave privada) para guardar la clave en un formato que PuTTY pueda usar. PuTTYgen mostrará una advertencia acerca de guardar la clave sin contraseña. Si se elije "Yes" se guardará la clave privada sin contraseña.

Opcionalmente, podemos usar una contraseña en la clave privada. Esto actúa como una capa adicional de seguridad. De esta forma, si alguien consigue robarnos la clave privada, no la podrá usar sin la contraseña. El inconveniente de usar una contraseña en una clave privada es que dificulta la automatización de tareas, puesto que la intervención humana es necesaria para, por ejemplo, iniciar sesión en una instancia.

La clave privada está ahora en el formato correcto para su uso con PuTTY.

Para conectarse a la instancia Linux mediante PuTTY, hay que insertar el nombre de usuario y la IP de la instancia en el campo "Host Name" del apartado Session, por ejemplo, ec2-user@10.1.12.34.



Comentar que se puede configurar PuTTY para que envíe datos "keepalive" a intervalos regulares para mantener la sesión activa. Esto es útil para evitar desconectarse de una instancia por inactividad. En el panel Category, elegir Connection y escribir el intervalo deseado en "Seconds between keepalives".

Para especificar la clave privada, abrir Connection, abrir SSH y elegir Auth (Autenticación).

Elegir Browse y seleccionar el archivo .ppk que se ha generado anteriormente.



Si se va a iniciar sesión frecuentemente en esta instancia, se puede guardar la sesión en la sección "Terminal" para usarla en el futuro. Para ello, elegir un nombre de sesión y clicar el botón Save.

Ahora ya se puede clicar Open para abrir una conexión SSH hacia la instancia.

NOTA: si se ha especificado una contraseña al convertir la clave privada al formato de PuTTY, se deberá introducir la contraseña en este momento.


Fuentes:

https://docs.aws.amazon.com/es_es/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html
https://docs.aws.amazon.com/es_es/AWSEC2/latest/UserGuide/putty.html
0

miércoles, 22 de mayo de 2019

libmcrypt-devel en SUSE Linux Enterprise 15



Cómo instalar libmcrypt o libmcrypt-devel en un SUSE Linux Enterprise Server 15



Instalando un daemon NRPE (Nagios Remote Plugin Executor) en un SUSE Linux Enterprise Server 15 para monitorizar el sistema, me encontré con que esta versión de SUSE Linux Enterprise Server (SLES) no incluye libmcrypt-devel en sus repositorios oficiales, a diferencia de SLES 12, que sí la incluye.

HOST# zypper install libmcrypt-devel Refreshing service 'Basesystem_Module_15_x86_64'. Refreshing service 'Desktop_Applications_Module_15_x86_64'. Refreshing service 'Development_Tools_Module_15_x86_64'. Refreshing service 'SUSE_Linux_Enterprise_Server_15_x86_64'. Refreshing service 'SUSE_Package_Hub_15_x86_64'. Refreshing service 'Server_Applications_Module_15_x86_64'. Refreshing service 'Web_and_Scripting_Module_15_x86_64'. Loading repository data... Reading installed packages... 'libmcrypt-devel' not found in package names. Trying capabilities. No provider of 'libmcrypt-devel' found. Resolving package dependencies... Nothing to do.

libmcrypt-devel es una dependencia de NRPE, y sin ella, no podía continuar con la instalación de NRPE.

Me puse en contacto con SUSE y les pregunté acerca de la disponibilidad de libmcrypt-devel para SUSE Linux Enterprise Server 15. Tras hablar con ingeniería, el soporte de SUSE me contestó que este paquete fue retirado en SLE 15 porque su código no recibía actualizaciones desde 2007, y ellos no dan soporte a software obsoleto, cosa respetable.

Llegados a este punto, tenía varias opciones: podía compilar libmcrypt desde código fuente, buscar un .rpm o buscar un repositorio que incluyera el paquete pre-compilado para SLE 15. Opté por la última opción. Busqué repositorios no oficiales en software.opensuse.org que ofrecieran este paquete, pero no encontré ninguno que ofreciera libmcrypt.

Buscando de otras formas, acabé encontrando un repositorio llamado 'SNAG-View Build Services' que incluía libmcrypt-devel para SLE 15, así que añadí este repositorio al sistema:

HOST# zypper addrepo https://download.opensuse.org/repositories/home:/snagview/SLE_15/home:snagview.repo Adding repository 'SNAG-View Build Services (SLE_15)' ..................[done] Repository 'SNAG-View Build Services (SLE_15)' successfully added URI : http://download.opensuse.org/repositories/home:/snagview/SLE_15/ Enabled : Yes GPG Check : Yes Autorefresh : No Priority : 99 (default priority) Repository priorities are without effect. All enabled repositories share the same priority.

Refresqué la lista de repositorios y acepté 'SNAG-View Build Services' como fuente de confianza:

HOST# zypper refresh Repository 'SLE-Module-Basesystem15-Pool' is up to date. Repository 'SLE-Module-Basesystem15-Updates' is up to date. Repository 'SLE-Module-Desktop-Applications15-Pool' is up to date. Repository 'SLE-Module-Desktop-Applications15-Updates' is up to date. Repository 'SLE-Module-DevTools15-Pool' is up to date. Repository 'SLE-Module-DevTools15-Updates' is up to date. Repository 'SLE-Product-SLES15-Pool' is up to date. Repository 'SLE-Product-SLES15-Updates' is up to date. Repository 'SLE-Module-Packagehub-Subpackages15-Pool' is up to date. Repository 'SLE-Module-Packagehub-Subpackages15-Pool' is up to date. Repository 'SLE-Module-Packagehub-Subpackages15-Updates' is up to date. Repository 'SUSE-PackageHub-15-Pool' is up to date. Repository 'SUSE-PackageHub-15-Pool' is up to date. Repository 'SUSE-PackageHub-15-Standard-Pool' is up to date. Repository 'SUSE-PackageHub-15-Standard-Pool' is up to date. Repository 'SLE-Module-Server-Applications15-Pool' is up to date. Repository 'SLE-Module-Server-Applications15-Updates' is up to date. Repository 'SLE-Module-Web-Scripting15-Pool' is up to date. Repository 'SLE-Module-Web-Scripting15-Updates' is up to date. Retrieving repository 'SNAG-View Build Services (SLE_15)' metadata --------[\] New repository or package signing key received: Repository: SNAG-View Build Services (SLE_15) Key Name: home:snagview OBS Project Key Fingerprint: 7689214A B23FD92F 60739D1C D3358BDA 12A73586 Key Created: Tue Dec 18 16:18:43 2018 Key Expires: Thu Feb 25 16:18:43 2021 Rpm Name: gpg-pubkey-12a73586-5c190fd3 Do you want to reject the key, trust temporarily, or trust always? [r/t/a/? shows all options] (r): a Retrieving repository 'SNAG-View Build Services (SLE_15)' metadata .....[done] Building repository 'SNAG-View Build Services (SLE_15)' cache ..........[done] Repository 'Security tools (SLE_15)' is up to date. All repositories have been refreshed.

Ahora sí, ya pude instalar libmcrypt-devel y continuar con la instalación de NRPE.

HOST# zypper install libmcrypt-devel Refreshing service 'Basesystem_Module_15_x86_64'. Refreshing service 'Desktop_Applications_Module_15_x86_64'. Refreshing service 'Development_Tools_Module_15_x86_64'. Refreshing service 'SUSE_Linux_Enterprise_Server_15_x86_64'. Refreshing service 'SUSE_Package_Hub_15_x86_64'. Refreshing service 'Server_Applications_Module_15_x86_64'. Refreshing service 'Web_and_Scripting_Module_15_x86_64'. Loading repository data... Reading installed packages... Resolving package dependencies... The following 2 NEW packages are going to be installed: libmcrypt libmcrypt-devel The following 2 packages have no support information from their vendor: libmcrypt libmcrypt-devel 2 new packages to install. Overall download size: 194.2 KiB. Already cached: 0 B. After the operation, additional 676.4 KiB will be used. Continue? [y/n/...? shows all options] (y):

Ahora, a ver cuándo Nagios actualiza NRPE y usa otra librería criptográfica...
0

miércoles, 15 de mayo de 2019

Habilitar ejecución de archivos .ps1 en Windows



Cómo habilitar la ejecución de scripts de PowerShell en Windows, cómo ejecutar archivos .ps1, cómo solucionar el error "la ejecución de scripts está deshabilitada en este sistema".



Windows permite automatizar tareas mediante scripts de PowerShell, tanto en su versión de escritorio como en un Windows Server. Sin embargo, la ejecución de scripts está deshabilitada por defecto. Veamos cómo permitir la ejecución de scripts de PowerShell en un entorno Windows.

La primera vez que ejecutemos un script de PowerShell contenido en un archivo .ps1 en un sistema operativo Windows, lo más probable es que el sistema nos devuelva el siguiente mensaje:

PS C:\Users\usuario> .\archivo.ps1 .\script.ps1 : No se puede cargar el archivo C:\Users\usuario\archivo.ps1 porque la ejecución de scripts está deshabilitada en este sistema. Para obtener más información, consulta el tema about_Execution_Policies en https:/go.microsoft.com/fwlink/?LinkID=135170. En línea: 1 Carácter: 1 + .\script.ps1 + ~~~~~~~~~~~~ + CategoryInfo : SecurityError: (:) [], PSSecurityException + FullyQualifiedErrorId : UnauthorizedAccess

Podemos ver cómo está configurada la ejecución de scripts de PowerShell en el sistema mediante:

PS C:\Users\usuario> Get-ExecutionPolicy -list        Scope ExecutionPolicy        ----- --------------- MachinePolicy      Undefined UserPolicy      Undefined Process      Undefined CurrentUser      Undefined LocalMachine      Undefined

Como se observa en el cuadro, las políticas de ejecución de scripts de PowerShell no están definidas (Undefined). Por defecto, Windows no tiene definida la ejecución de scripts, lo cual significa que deniega implícitamente su ejecución hasta que se configure un apartado como "no restringido".

Los modos de ejecución que se pueden especificar son los siguientes:

• Restricted (Restringida): es la regla por defecto. Permite la ejecución de comandos individuales pero no de archivos de scripts, incluyendo los archivos de configuración y formato (.ps1xml), los archivos de scripts de módulos (.psm1) y los perfiles de Windows PowerShell (.ps1).

• Allsigned (Solo firmas): permite ejecutar scripts firmados por un editor de confianza, incluyendo los scripts que se escriban en el equipo local. Solicita confirmación antes de ejecutar scripts de publicadores que no hayan sido clasificados como de confianza.

• Remotesigned (Firma remota): permite la ejecución de scripts descargados de internet firmados digitalmente por un editor de confianza. No requiere firma digital en los scripts que hayan sido escritos en el equipo local.

• Unrestricted (Sin restricción): permite ejecutar scripts sin firmar. Advierte al usuario antes de ejecutar archivos de configuración y scripts descargados de Internet con el fin de añadir seguridad.

• Bypass: esta directiva no bloquea nada y no muestra advertencias de seguridad. Pensado para programas que integran un script de Windows PowerShell en una aplicación compleja.

• Undefined (Indefinido): esta opción indica que no existe ninguna directiva de ejecución establecida. Si la directiva de ejecución en todos los ámbitos es Undefined, la directiva de ejecución será Restricted, que es la directiva de ejecución por defecto en Windows.

Si queremos ejecutar scripts de PowerShell en una máquina, debemos permitir antes su ejecución mediante el comando Set-ExecutionPolicy del siguiente modo:

PS C:\Users\usuario> Set-ExecutionPolicy -Scope LocalMachine unrestricted Cambio de directiva de ejecución La directiva de ejecución te ayuda a protegerte de scripts en los que no confías. Si cambias dicha directiva, podrías exponerte a los riesgos de seguridad descritos en el tema de la Ayuda about_Execution_Policies en https:/go.microsoft.com/fwlink/?LinkID=135170. ¿Quieres cambiar la directiva de ejecución? [S] Sí [O] Sí a todo [N] No [T] No a todo [U] Suspender [?] Ayuda (el valor predeterminado es "N"): S Set-Executionpolicy : Se denegó el acceso a la clave de Registro 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell'. Para cambiar la directiva de ejecución para el ámbito (LocalMachine) predeterminado, inicie Windows PowerShell con la opción "Ejecutar como administrador". Para cambiar la directiva de ejecución para el usuario actual, ejecute "Set-ExecutionPolicy -Scope CurrentUser". En línea: 1 Carácter: 1 + Set-Executionpolicy -Scope LocalMachine unrestricted + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : PermissionDenied: (:) [Set-ExecutionPolicy], UnauthorizedAccessException + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands. SetExecutionPolicyCommand

Como vemos, para modificar los permisos a nivel de máquina, debemos ejecutar el comando como administrador. Si queremos ejecutar scripts con nuestro usuario sin tener que abrir una nueva instancia de PowerShell como administrador, basta con cambiar "LocalMachine" por "CurrentUser". De esta forma, Windows no nos pide que abramos nueva instancia de PowerShell como administrador:

PS C:\Users\usuario> Set-ExecutionPolicy -Scope CurrentUser unrestricted Cambio de directiva de ejecución La directiva de ejecución te ayuda a protegerte de scripts en los que no confías. Si cambias dicha directiva, podrías exponerte a los riesgos de seguridad descritos en el tema de la Ayuda about_Execution_Policies en https:/go.microsoft.com/fwlink/?LinkID=135170. ¿Quieres cambiar la directiva de ejecución? [S] Sí [O] Sí a todo [N] No [T] No a todo [U] Suspender [?] Ayuda (el valor predeterminado es "N"): S

Si listamos las políticas de ejecución de nuevo, veremos que CurrentUser ha cambiado a "Unrestricted":

PS C:\Users\usuario> Get-ExecutionPolicy -list        Scope ExecutionPolicy        ----- --------------- MachinePolicy      Undefined UserPolicy      Undefined Process      Undefined CurrentUser      Unrestricted LocalMachine      Undefined

A partir de este momento, ya podemos ejecutar archivos .ps1 con scripts de PowerShell sin problemas.
26

miércoles, 8 de mayo de 2019

¿Máquinas virtuales o contenedores?



Analicemos qué ventajas nos ofrecen los contenedores respecto a las máquinas virtuales y en qué situaciones sería recomendable sustituir máquinas virtuales por contenedores.
¿Puedo instalar Docker en el servidor?

Así empezó todo. Con una llamada de un desarrollador preguntándome si podía instalar Docker en un servidor de test que le había aprovisionado unos días antes. Esa llamada fue el preludio de una reunión infraestructura-desarrollo en la que surgió el tema que nos ocupa: ¿máquinas virtuales o contenedores?


Conceptos



Antes de evaluar qué opción es mejor y por qué, hablemos brevemente sobre qué es una máquina virtual y qué es un contenedor, para entender así sus diferencias.





Una máquina virtual es una imagen de un sistema operativo que se ejecuta sobre otro sistema operativo, creando un sistema invitado (guest) totalmente aislado del sistema operativo huésped (host).

Tanto el sistema operativo host como los sistemas operativos guest (máquinas virtuales) usan los recursos físicos (RAM, CPU, disco...) del servidor físico donde se encuentran. La porción de esos recursos que puede usar cada máquina virtual se configura en el hipervisor.

Un contenedor, por su parte, es un paquete cerrado de software que incluye una aplicación y todas aquellas dependencias que la aplicación necesita para poder desempeñar su función.

Los contenedores, a diferencia de las máquinas virtuales, están diseñados para interactuar con el sistema operativo sobre el que se despliegan - por ejemplo, interactúan con el kernel de Linux - por lo que anteriormente, un contenedor de Linux solo se podía ejecutar sobre sistemas operativos Linux y un contenedor de Windows solo se podía ejecutar sobre sistemas operativos Windows. Sin embargo, desde el año pasado, Microsoft permite ejecutar contenedores de Linux sobre Windows, previo despliegue de un entorno Linux mínimo sobre la máquina Windows (más información y detalles del proceso aquí).

En resumen, una máquina virtual es un sistema operativo completo, aislado del sistema operativo huésped, y un contenedor es un paquete de código que interactúa con el sistema operativo huésped y que incluye todas las dependencias que necesita para ejecutarse correctamente.


Antigüedad



La principal reticencia a la hora de usar contenedores es la antigüedad de la tecnología. Su consolidación en la industria. Si tomamos como ejemplo las máquinas virtuales, nos encontramos con que los famosos ESX de VMware se lanzaron al mercado en 2001 mientras que Docker - uno de los nombres que más suena cuando se habla de contenedores - existe desde 2013. No obstante, no debemos olvidar que los contenedores como aislamiento de aplicaciones ya existían desde antes de la aparición de Docker. Concretamente, LXC (Linux Containers) se lanzó en 2008.

Si bien es cierto que la virtualización de VMware existe desde hace casi 20 años, la tecnología de contenedores tiene ya más de 10 años a sus espaldas. No estamos ante una moda surgida el año pasado. Los contenedores son una tecnología que llegó para quedarse, y compañías de la talla de VISA, Desigual o PayPal, las cuales usan Docker en producción en estos momentos, lo demuestran.


¿Máquinas virtuales o contenedores?



Ahora sí, con los conceptos ya claros, podemos hablar de qué es mejor. Y la respuesta es: depende. Depende de nuestras necesidades.

Si necesitamos servir una página web, la respuesta para mi es muy clara: contenedores.
Si necesitamos ejecutar un programa .exe en un Windows Server, necesitamos que otra aplicación se conecte a este servidor a recoger unos logs y necesitamos una tercera aplicación, que corre sobre otro sistema operativo, para que monitorice el espacio en disco de los sistemas operativos anteriores, yo me decantaría por usar tres máquinas virtuales distintas.

Bajo mi punto de vista, los contenedores nos pueden ser útiles para albergar aplicaciones que corren bajo una misma plataforma, como pueden ser aplicaciones web, ya que nos permiten reaprovechar código, nos facilitan una alta disponibilidad que nos sería más difícil de conseguir con máquinas virtuales, nos permiten autoescalado (si la demanda por el servicio sube y se requieren más recursos en un momento dado se pueden autodesplegar contenedores rápidamente) y nos aseguran que una aplicación funcionará en cualquier máquina, como ventajas principales.


Aplicaciones monolíticas vs microservicios



Si hablamos de aplicaciones web, debemos hablar de microservicios, aplicaciones monolíticas y la relación de ambos con las máquinas virtuales y los contenedores.

La primera vez que escuché la expresión "aplicaciones monolíticas" fue en SUSE Expert Days 2018 (llego tarde, lo se), donde SUSE explicó su apuesta por los contenedores como método preferente de despliegue de aplicaciones web, por encima de opciones de hipervisor en Linux como KVM o Xen.

En una máquina virtual típica, podemos tener corriendo una página web sobre, por ejemplo, Apache y MariaDB. Esto es un ejemplo de aplicación monolítica. Si usáramos microservicios, podríamos dividir el código de la web en mini aplicaciones independientes entre sí que fueran llamadas según fueran siendo requeridas por la aplicación web. Y es en estas mini aplicaciones o mejor dicho, micro servicios, donde entran en juego los contenedores, pues cada microservicio se ejecuta en un contenedor independiente que se levanta solo cuando es necesario, y por tanto, solo consume recursos cuando es necesario, además de poder ser usado por varias aplicaciones web sin tener que tener el mismo código repetido en todas las aplicaciones.


Retorno de la inversión



Tomemos como ejemplo los entornos de antaño, con una máquina física por servidor. Hoy en día sería inviable que una compañía tuviera 500 máquinas físicas funcionando en su datacenter. Sin embargo, fácilmente puede una compañía tener 500 máquinas virtuales corriendo.

¿Por qué?

Porque el coste de electricidad, componentes, mantenimiento, etc. se dispararía en el caso de tener tantas máquinas físicas, mientras que esas máquinas virtualizadas tienen un coste asumible.

¿Qué ocurriría si sustituyéramos algunas máquinas virtuales por contenedores?

Lo que ocurriría es que el coste económico se reduciría aún más, puesto que se evitaría tener que mantener levantada una máquina virtual por cada aplicación, es decir, se podrían juntar varias aplicaciones en un mismo servidor, sin prescindir del aislamiento entre ellas ni de su alta disponibilidad.

Pongamos un ejemplo. Un sistema Linux Enterprise cualquiera requiere unos 15 GB de disco y 8 GB de RAM de media para funcionar de forma óptima. Si tenemos, digamos, 100 máquinas virtuales, estamos destinando 800 GB de RAM y 1,5 TB de disco solo para mantener levantados los sistemas operativos. Si las aplicaciones que corren sobre esos sistemas se contenerizasen, podríamos evitar gastar gran parte de esos recursos, ya que se podrían ejecutar muchos contenedores sobre unos pocos sistemas operativos y se podrían ir levantando y terminando contenedores en ellos según se requiriese.

Este ahorro de recursos, es decir, de dinero, se puede notar en un entorno on-premise, pero es especialmente destacable en un entorno cloud público, donde se paga directamente por recurso asignado a una máquina. En un AWS Summit, Amazon habló de cómo el uso de contenedores en vez de instancias podía llegar a reducir las facturas de AWS a la mitad.


Conclusión



Si estamos sirviendo muchas páginas web que usan la misma tecnología (mismo CMS, mismo servidor web, mismo tipo de base de datos, etc.), lo más recomendable sería ejecutar esas páginas en contendores. Así, se aprovecharían mejor los recursos de hardware y se facilitaría el ciclo de puesta en producción de las aplicaciones, ya que el código que corre en un contenedor en el PC del desarrollador funcionará igual en su PC que en el servidor de producción, entre otras ventajas.

Si, por el contrario, tenemos un entorno heterogéneo, con muchos sistemas operativos distintos y necesidades muy variadas, lo mejor, bajo mi punto de vista, es mantenerlo en máquinas virtuales separadas. Y, en todo caso, contenerizar aquellas aplicaciones que sea posible ejecutar desde contenedores, para aprovechar sus ventajas.
0

miércoles, 1 de mayo de 2019

-bash: /usr/bin/rm: Argument list too long



Qué provoca el error "-bash: /usr/bin/rm: Argument list too long", cómo borrar muchos, decenas, cientos, miles de archivos con un nombre determinado, de un directorio en Linux.



Antes de ver qué provoca el error "-bash: /usr/bin/rm: Argument list too long", veamos primero cómo se puede llegar a desencadenar la situación que lo origina.

Todo empezó cuando una compañera me comunicó que el acceso por FTP a cierto directorio de un servidor daba problemas. Me conecté por FTP al servidor y vi que, efectivamente, el servidor daba tiemout al tratar de devolver la lista de archivos de un directorio específico:

ftp> cd directorio 250 Directory successfully changed. ftp> dir 200 PORT command successful. Consider using PASV. 150 Here comes the directory listing. Error: Connection timed out Error: Failed to retrieve directory listing

Probé a listar el contenido de ese directorio desde la terminal de Linux para ver qué ocurria. Pasado un minuto aprox., el sistema me devolvió el listado de archivos.


Causas



Me encontré con miles de archivos de unos pocos bytes en el directorio afectado. Deduje entonces que algún programa estaba creando esos archivos cada día a una hora determinada, puesto que su hora de creación era la misma, día tras día.

La presencia de este gran volumen de archivos causaba timeout en el FTP porque al sistema no le daba tiempo a generar y mostrar la lista de archivos del directorio antes de hacer timeout. Del mismo modo, bash demoraba mucho tiempo hasta tener generada la lista de archivos del directorio, por su volumen.


Consecuencias



Mientras otra persona buscaba qué aplicación estaba creando esos archivos, tuve que lidiar con la posibilidad de que el disco donde se escribían estos archivos se quedara sin inodos libres, lo cual dejaría KO las aplicaciones que corren sobre él.


Solución



Debía borrar estos archivos. Empecé por buscar patrones compartidos por todos ellos y vi que todos los archivos tenían algo en común: sus nombres eran de 32 caracteres. Esto me daba una posibilidad de borrarlos en masa. Recordemos que, en Linux, para borrar archivos cuyo nombre de archivo es de una longitud determinada, se puede usar rm seguido de tantos ? como caracteres tenga el nombre.

En mi caso:

HOST# rm ???????????????????????????????? -bash: /usr/bin/rm: Argument list too long

El sistema se quejaba de que había demasiados archivos que coincidieran con el patrón facilitado, así que bash no podía ejecutar el comando rm sobre ellos.


Método 1: rm



Probé a ir bajando el número de comodines hasta que el sistema me dejó ejecutar:

HOST# rm 12E0ECTF783B1EE88ADA????????????

Llegados a este punto, podía ir borrando los archivos restantes poco a poco: buscar un nuevo patrón, borrar los archivos que siguen ese patrón, listar los archivos restantes, borrar el siguiente patrón, etc. pero eso era una tarea demasiado manual.

Tras buscar un poco, vi que se podía atacar el problema de otra forma más efectiva.


Método 2: find



Usando el comando find, bash no se queja del número de archivos a procesar.

HOST# find . -type f -name "12E?????????????????????????????" -delete


Resolución



Acabé usando el método 2, find, para borrar de golpe todos los archivos que quería eliminar. Después de esto, el sistema volvió a listar los archivos de esa carpeta de forma habitual (en milisegundos), tanto desde el FTP como desde la terminal. Ahora, el problema era enteramente del desarrollador...


¿Por qué se da el límite de argumentos en bash?



El límite de argumentos del cual se queja bash se da en la función del kernel execve (), que es utilizada por todas las demás funciones exec () (execl, execlp, execle, etc.). Lo que hace esta función es crear un búfer de 128 K en el extremo superior del espacio de memoria y copiar la línea de comandos y el entorno para el nuevo proceso en este espacio. El kernel luego carga el nuevo programa en la memoria, establece sus punteros argv y envp, y salta al punto de entrada del programa. El mensaje de error "Argument list too long" está causado por el código de error !E2BIG, devuelto por la función execve (), cuando no puede encajar la lista de argumentos y el entorno suministrados dentro del búfer de 128K.


Fuentes:

https://wiki.debian.org/CommonErrorMessages/ArgumentListTooLong
https://stackoverflow.com/questions/13409403/delete-files-with-a-length-of-x-or-more-characters
https://superuser.com/questions/701985/linux-how-can-i-delete-all-files-whose-file-name-is-more...
0