<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Valen Torassa</title>
    <description>The latest articles on DEV Community by Valen Torassa (@vtsecurity).</description>
    <link>https://dev.to/vtsecurity</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4194222%2Fd6e7d980-90ca-47fc-982c-f8b19d281143.png</url>
      <title>DEV Community: Valen Torassa</title>
      <link>https://dev.to/vtsecurity</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vtsecurity"/>
    <language>en</language>
    <item>
      <title>comandle: un Wordle de comandos de Linux que se juega en la terminal</title>
      <dc:creator>Valen Torassa</dc:creator>
      <pubDate>Thu, 29 Oct 2026 18:00:02 +0000</pubDate>
      <link>https://dev.to/vtsecurity/comandle-un-wordle-de-comandos-de-linux-que-se-juega-en-la-terminal-50m3</link>
      <guid>https://dev.to/vtsecurity/comandle-un-wordle-de-comandos-de-linux-que-se-juega-en-la-terminal-50m3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Cada día, un comando de Linux o de seguridad para adivinar en seis intentos, en la terminal o en el navegador. Cómo se juega, cómo elige el comando del día sin un servidor y qué cuenta la web.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cada día hay un comando de Linux o de seguridad para adivinar en seis intentos. Escribís uno con la misma cantidad de letras y cada letra queda verde si está en su lugar, amarilla si está en otra posición y gris si no está. Cuando termina la ronda, ganes o pierdas, aparece la ficha del comando: qué hace, tres ejemplos y una nota de seguridad.&lt;/p&gt;

&lt;p&gt;Se llama &lt;strong&gt;comandle&lt;/strong&gt; y lo armé para practicar comandos un rato por día. Se juega en el navegador, en &lt;a href="https://comandle.valentorassa.com/?ref=devto" rel="noopener noreferrer"&gt;comandle.valentorassa.com&lt;/a&gt;, o en la terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/legiosai/comandle@latest
comandle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Es gratis, no pide cuenta y el comando del día es el mismo en los dos lados. El #1 salió el 20 de octubre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo se juega
&lt;/h2&gt;

&lt;p&gt;La categoría se ve desde el primer intento: archivos, texto, procesos, redes, permisos, sistema, seguridad, paquetes, git o contenedores. Hay 75 comandos cargados, de 4 a 8 letras, en tres niveles: básico, intermedio y avanzado.&lt;/p&gt;

&lt;p&gt;Si le errás, el juego destapa pistas: la primera con dos intentos fallidos, la segunda con cuatro y la última con cinco. Solo valen nombres de comandos reales, de una lista de 651, así que no se puede tantear con letras sueltas. En la terminal, &lt;code&gt;?&lt;/code&gt; muestra los válidos con esa cantidad de letras; en la web están en la lista de comandos, y &lt;code&gt;tab&lt;/code&gt; completa.&lt;/p&gt;

&lt;p&gt;Al terminar copiás el resultado, que muestra cómo te fue sin decir cuál era. Esta es una ronda del #1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;comandle #1 3/6
🟨⬛⬛🟨
🟩⬛⬛🟩
🟩🟩🟩🟩
comandle.valentorassa.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En la web, un personaje ASCII comenta la partida al estilo de &lt;code&gt;cowsay&lt;/code&gt;: cambia los ojos cuando vas mal, festeja con &lt;code&gt;exit 0&lt;/code&gt; y se muere con un &lt;code&gt;segmentation fault&lt;/code&gt;. Por defecto es vt, el pingüino, y se puede cambiar por la vaca, un conejo, un gato, un búho, un cangrejo o un fantasma.&lt;/p&gt;

&lt;h2&gt;
  
  
  La ficha del final
&lt;/h2&gt;

&lt;p&gt;Ese #1 era &lt;code&gt;grep&lt;/code&gt;. Cuando la ronda termina, la ficha dice qué hace, cuándo lo usás y trae tres ejemplos para copiar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"TODO"&lt;/span&gt; ~/proyecto                    &lt;span class="c"&gt;# archivo y número de línea de cada TODO&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"error"&lt;/span&gt; app.log                       &lt;span class="c"&gt;# sin importar mayúsculas&lt;/span&gt;
&lt;span class="nb"&gt;sudo grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"Failed password"&lt;/span&gt; /var/log/auth.log   &lt;span class="c"&gt;# intentos fallidos de login por SSH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y una nota de seguridad. La de &lt;code&gt;grep&lt;/code&gt; avisa que sirve para auditar, buscando contraseñas en texto plano o IPs raras en un log, y que si no encuentra nada solo sabés que nada coincide con tu patrón.&lt;/p&gt;

&lt;p&gt;Dieciséis de las fichas suman un laboratorio en &lt;a href="https://securitylabs.valentorassa.com/?ref=devto" rel="noopener noreferrer"&gt;securitylabs.valentorassa.com&lt;/a&gt; para practicar el comando con un caso armado.&lt;/p&gt;

&lt;p&gt;Desde la terminal, la ficha de cualquier comando de la lista se pide sin jugar, y hay rondas de práctica que no suman a tus estadísticas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;comandle explicar &lt;span class="nb"&gt;chmod&lt;/span&gt;   &lt;span class="c"&gt;# la ficha de un comando&lt;/span&gt;
comandle practica         &lt;span class="c"&gt;# una ronda al azar&lt;/span&gt;
comandle practica find    &lt;span class="c"&gt;# practicar uno puntual, por ejemplo en una clase&lt;/span&gt;
comandle lista            &lt;span class="c"&gt;# los comandos de los días que ya pasaron&lt;/span&gt;
comandle stats            &lt;span class="c"&gt;# tus estadísticas y tu racha&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  El mismo comando sin un servidor
&lt;/h2&gt;

&lt;p&gt;La versión de terminal está escrita en Go y la web es HTML y JavaScript estático. Las dos leen el mismo &lt;code&gt;commands.json&lt;/code&gt; y eligen el comando del día con la misma regla, que en la web es esta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;daily&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;fnv1a32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`comandle-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El orden del archivo es el calendario: el día &lt;code&gt;n&lt;/code&gt; juega la entrada &lt;code&gt;n&lt;/code&gt;. Con 75 comandos eso alcanza hasta el 2 de enero de 2027, y si para entonces no se sumaron más, los días siguen en un orden pseudoaleatorio fijo, con FNV-1a de 32 bits, el mismo hash que &lt;code&gt;hash/fnv&lt;/code&gt; en Go. El número del día sale de la fecha en Argentina (UTC−3, sin horario de verano), así que el comando cambia a medianoche y nadie tiene que publicarlo. Un test fija que Go y JavaScript den lo mismo.&lt;/p&gt;

&lt;p&gt;Como la respuesta viaja con el juego, cualquiera que abra el código puede ver la del día. No hay un servidor que la guarde.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué cuenta la web
&lt;/h2&gt;

&lt;p&gt;La versión de terminal no se conecta a internet. Tus estadísticas quedan en un archivo que solo puede leer tu usuario.&lt;/p&gt;

&lt;p&gt;La web no usa cookies ni guarda nada que te identifique. Cuando empezás una partida, la terminás o copiás el resultado, suma 1 a un contador del día:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;al terminar, en cuántos intentos o si perdiste;&lt;/li&gt;
&lt;li&gt;cuántos días seguidos jugaste, calculado en tu navegador con el historial que ya guarda y mandado en tramos (1, 2–3, 4–7, 8–14, 15+);&lt;/li&gt;
&lt;li&gt;al entrar, el &lt;code&gt;ref&lt;/code&gt; del link y el sitio que te mandó.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;omit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;keepalive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Después de leer el &lt;code&gt;?ref=&lt;/code&gt;, la web lo saca de la barra, así el link que copiás queda limpio. Si tu navegador tiene activado Global Privacy Control, no manda nada.&lt;/p&gt;

&lt;p&gt;Con eso veo cuántas partidas hay, qué comandos cuestan más y de dónde llega la gente. Cualquiera puede mandarle eventos, así que lo leo como tendencia.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sumá un comando
&lt;/h2&gt;

&lt;p&gt;Cada comando es una entrada de &lt;code&gt;data/commands.json&lt;/code&gt;, con categoría, nivel, tres pistas, resumen, explicación, tres ejemplos, la nota de seguridad y, si hay, el laboratorio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chmod"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"permisos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"básico"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"clues"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Decide quién puede leer, escribir o ejecutar un archivo."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Acepta modos en octal, como 755 o 600."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Su nombre viene de «change mode»."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cambia los permisos de archivos y directorios."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como el orden es el calendario, los nuevos van siempre al final: mover una entrada cambiaría el comando de un día que ya pasó. Al cargar, el juego revisa todas las entradas y te muestra todos los problemas juntos, para que corrijas la tuya de una vez. Los pasos están en &lt;a href="https://github.com/legiosai/comandle/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;CONTRIBUTING.md&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;El código está en &lt;a href="https://github.com/legiosai/comandle" rel="noopener noreferrer"&gt;github.com/legiosai/comandle&lt;/a&gt;, con licencia Apache-2.0. Lo hice desde VT Security y lo publica Legios.&lt;/p&gt;




&lt;p&gt;El de hoy ya está en &lt;a href="https://comandle.valentorassa.com/?ref=devto" rel="noopener noreferrer"&gt;comandle.valentorassa.com&lt;/a&gt;. Si lo jugás, contame en cuántos lo sacaste: en el Discord de DedSec hay un canal #comandle donde todas las mañanas a las 9 sale el del día.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lo publiqué primero en &lt;a href="https://vtsecurity.com.ar/articulo/comandle-wordle-de-comandos-linux?ref=devto" rel="noopener noreferrer"&gt;vtsecurity.com.ar&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>go</category>
      <category>opensource</category>
      <category>espanol</category>
    </item>
    <item>
      <title>Address already in use: quién tiene el puerto y por qué kill -9 va al final</title>
      <dc:creator>Valen Torassa</dc:creator>
      <pubDate>Tue, 27 Oct 2026 18:00:02 +0000</pubDate>
      <link>https://dev.to/vtsecurity/address-already-in-use-quien-tiene-el-puerto-y-por-que-kill-9-va-al-final-2e5k</link>
      <guid>https://dev.to/vtsecurity/address-already-in-use-quien-tiene-el-puerto-y-por-que-kill-9-va-al-final-2e5k</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Cómo encontrar el proceso con &lt;code&gt;ss&lt;/code&gt;, ver quién lo levantó y cortarlo sin &lt;code&gt;kill -9&lt;/code&gt;. Y qué significa que esté escuchando en &lt;code&gt;0.0.0.0&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pasa así: levantás tu app, la terminal te devuelve &lt;code&gt;EADDRINUSE&lt;/code&gt; y no arranca. Buscás el error y la primera respuesta dice &lt;code&gt;kill -9 $(lsof -t -i:3000)&lt;/code&gt;. Lo corrés y anda.&lt;/p&gt;

&lt;p&gt;Casi siempre. A veces el puerto vuelve a estar ocupado un segundo después. Otras, lo que mataste era la base de otro proyecto que tenías abierto. Y en el camino se pasa por alto algo que importa más que el error: ese proceso que no sabías que seguía corriendo también podía estar atendiendo a otras máquinas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quién tiene el puerto
&lt;/h2&gt;

&lt;p&gt;El error solo dice el puerto. Para saber quién lo tiene está &lt;code&gt;ss&lt;/code&gt;, que viene en cualquier distro actual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;node &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"require('http').createServer().listen(3000)"&lt;/span&gt;
Error: listen EADDRINUSE: address already &lt;span class="k"&gt;in &lt;/span&gt;use :::3000
&lt;span class="nv"&gt;$ &lt;/span&gt;ss &lt;span class="nt"&gt;-ltnp&lt;/span&gt; &lt;span class="s1"&gt;'sport = :3000'&lt;/span&gt;
State  Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0      5            0.0.0.0:3000      0.0.0.0:&lt;span class="k"&gt;*&lt;/span&gt;    &lt;span class="nb"&gt;users&lt;/span&gt;:&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="s2"&gt;"python3"&lt;/span&gt;,pid&lt;span class="o"&gt;=&lt;/span&gt;3365731,fd&lt;span class="o"&gt;=&lt;/span&gt;3&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-l&lt;/code&gt; muestra lo que está escuchando, &lt;code&gt;-t&lt;/code&gt; TCP, &lt;code&gt;-n&lt;/code&gt; números en vez de nombres y &lt;code&gt;-p&lt;/code&gt; el proceso. La última columna es la respuesta: un &lt;code&gt;python3&lt;/code&gt; con PID 3365731. Si esa columna sale vacía, el proceso es de otro usuario y con &lt;code&gt;sudo&lt;/code&gt; adelante aparece.&lt;/p&gt;

&lt;p&gt;Con el PID, &lt;code&gt;ps&lt;/code&gt; te dice qué es y hace cuánto corre:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ps &lt;span class="nt"&gt;-o&lt;/span&gt; pid,ppid,user,etime,cmd &lt;span class="nt"&gt;-p&lt;/span&gt; 3365731
    PID    PPID USER         ELAPSED CMD
3365731 3365724 valen          00:01 python3 &lt;span class="nt"&gt;-m&lt;/span&gt; http.server 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Acá dice un segundo porque lo levanté para el ejemplo; uno olvidado suele decir días. &lt;code&gt;python3 -m http.server&lt;/code&gt; es un clásico: lo usaste para pasar un archivo y quedó corriendo en otra terminal, sirviendo la carpeta entera donde lo levantaste, archivos ocultos incluidos.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;En macOS &lt;code&gt;ss&lt;/code&gt; no existe.&lt;/em&gt; &lt;code&gt;lsof -i :3000&lt;/code&gt; te da lo mismo, y en Linux también anda.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Qué quiere decir &lt;code&gt;0.0.0.0&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Volvé a la columna &lt;code&gt;Local Address&lt;/code&gt;. &lt;code&gt;0.0.0.0:3000&lt;/code&gt; quiere decir que el proceso acepta conexiones por cualquier interfaz de la máquina: le puede hablar cualquiera que esté en tu red.&lt;/p&gt;

&lt;p&gt;En el &lt;a href="https://vtsecurity.com.ar/articulo/address-already-in-use?ref=devto#que-quiere-decir-0000" rel="noopener noreferrer"&gt;artículo original&lt;/a&gt; esto es una figura donde mandás pedidos y cambiás la dirección mientras llegan. Con &lt;code&gt;0.0.0.0&lt;/code&gt;, cualquiera en tu red llega al puerto y se baja el &lt;code&gt;.env&lt;/code&gt;. Con &lt;code&gt;127.0.0.1&lt;/code&gt;, solo tu navegador:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tu máquina: python3 -m http.server sirve .env y app.js

escucha en 0.0.0.0:3000
  tu navegador             recibe la respuesta
  otra máquina de tu red   se lleva el .env (OPENAI_API_KEY=sk-…)
  internet                 lo corta el router

escucha en 127.0.0.1:3000
  tu navegador             recibe la respuesta
  otra máquina de tu red   conexión rechazada
  internet                 lo corta el router
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Red de ejemplo. El router corta lo que entra de internet mientras nadie le abra el puerto.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lo probé con ese mismo servidor, levantado en una carpeta de prueba con un &lt;code&gt;.env&lt;/code&gt;. Desde otra máquina de la red:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; http://&amp;lt;ip&amp;gt;:3000/.env
&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-proj-demo-no-es-real
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La key es de mentira y &lt;code&gt;&amp;lt;ip&amp;gt;&lt;/code&gt; reemplaza la de mi máquina. Levantado con &lt;code&gt;--bind 127.0.0.1&lt;/code&gt;, el mismo curl devuelve &lt;code&gt;Couldn't connect to server&lt;/code&gt;. Y si lo corrés en tu home, la carpeta que se sirve incluye &lt;code&gt;.ssh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El error de Node de más arriba también lo dice: &lt;code&gt;:::3000&lt;/code&gt;. Si no le pasás una dirección, &lt;code&gt;listen(3000)&lt;/code&gt; escucha en &lt;code&gt;::&lt;/code&gt;, que son todas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Un firewall o el router pueden cortar la conexión antes.&lt;/em&gt; En una red que no es tuya, no contaría con eso.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;kill&lt;/code&gt; manda una señal
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;kill&lt;/code&gt; no mata: le manda una señal al proceso. Si no le decís cuál, manda &lt;code&gt;TERM&lt;/code&gt;, que le pide terminar y lo deja cerrar lo que tiene abierto. &lt;code&gt;kill -9&lt;/code&gt; manda &lt;code&gt;KILL&lt;/code&gt;, que el programa no puede atender: el kernel lo saca en el acto.&lt;/p&gt;

&lt;p&gt;En el &lt;a href="https://vtsecurity.com.ar/articulo/address-already-in-use?ref=devto#kill-manda-una-senal" rel="noopener noreferrer"&gt;artículo original&lt;/a&gt; hay una figura con un programa que atiende pedidos y cada tanto guarda en el disco. Le mandás una señal, lo levantás de nuevo y probás la otra. Esto es lo que pasa con cada una:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# app (PID 4321) atiende pedidos, cada tanto guarda en datos.db y tiene su lock en app.pid&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;kill &lt;/span&gt;4321       &lt;span class="c"&gt;# TERM&lt;/span&gt;
&lt;span class="c"&gt;# deja de aceptar pedidos nuevos y termina los que tenía&lt;/span&gt;
&lt;span class="c"&gt;# guarda todo en datos.db y borra app.pid&lt;/span&gt;
&lt;span class="c"&gt;# lo que llega después rebota: no hay nadie escuchando&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; 4321    &lt;span class="c"&gt;# KILL&lt;/span&gt;
&lt;span class="c"&gt;# el kernel lo saca en el acto&lt;/span&gt;
&lt;span class="c"&gt;# el pedido a medio atender se corta y los cambios que tenía en memoria se pierden&lt;/span&gt;
&lt;span class="c"&gt;# app.pid queda, y sigue diciendo que ya está corriendo (PID 4321)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Programa de ejemplo. No todos dejan un lock, pero cualquiera pierde lo que no alcanzó a escribir.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Señal&lt;/th&gt;
&lt;th&gt;Número&lt;/th&gt;
&lt;th&gt;Qué pide&lt;/th&gt;
&lt;th&gt;¿La puede atender el proceso?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HUP&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Varios servicios la usan para releer la configuración&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Es lo que manda Ctrl+C&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TERM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;Que termine: cerrar lo que tiene abierto y salir&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;KILL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;Nada. El kernel lo saca en el momento&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;El orden es &lt;code&gt;kill&lt;/code&gt;, esperar unos segundos, y &lt;code&gt;kill -9&lt;/code&gt; solo si sigue ahí.&lt;/p&gt;

&lt;h2&gt;
  
  
  Si vuelve solo, es un servicio
&lt;/h2&gt;

&lt;p&gt;A veces matás el proceso y el puerto vuelve a estar ocupado al segundo. Lo reproduje con un servicio de systemd que se reinicia solo, y pasó exactamente eso.&lt;/p&gt;

&lt;p&gt;En el &lt;a href="https://vtsecurity.com.ar/articulo/address-already-in-use?ref=devto#si-vuelve-solo-es-un-servicio" rel="noopener noreferrer"&gt;artículo original&lt;/a&gt; hay una figura donde le mandás pedidos, lo matás y mirás qué pasa con los que llegan mientras no está:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# systemd --user vigila demo-web.service (Restart=always)&lt;/span&gt;
&lt;span class="c"&gt;# python3 -m http.server, con PID 3366803, tiene el puerto :3000&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; 3366803
&lt;span class="c"&gt;# el proceso murió: lo que llega rebota hasta que systemd lo levanta&lt;/span&gt;
&lt;span class="c"&gt;# un segundo después hay otro PID, 3366835, y el puerto vuelve a contestar&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; stop demo-web
&lt;span class="c"&gt;# systemctl stop le avisa a systemd: nadie lo relanza y todo lo que llega rebota&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Los dos PID son los de la prueba real.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;El padre de ese proceso es systemd, así que matarlo no sirve. &lt;code&gt;systemctl status&lt;/code&gt; acepta un PID y te dice de qué servicio es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; status 3366835 | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-4&lt;/span&gt;
● demo-web.service - &lt;span class="o"&gt;[&lt;/span&gt;systemd-run] /usr/bin/python3 &lt;span class="nt"&gt;-m&lt;/span&gt; http.server 3000 &lt;span class="nt"&gt;--bind&lt;/span&gt; 127.0.0.1
     Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/run/user/1000/systemd/transient/demo-web.service&lt;span class="p"&gt;;&lt;/span&gt; transient&lt;span class="o"&gt;)&lt;/span&gt;
  Transient: &lt;span class="nb"&gt;yes
     &lt;/span&gt;Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Fri 2026-09-25 11:21:28 &lt;span class="nt"&gt;-03&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 1s ago
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con eso sabés qué parar: &lt;code&gt;systemctl --user stop demo-web&lt;/code&gt;. En un servidor lo normal es un servicio del sistema, y va sin &lt;code&gt;--user&lt;/code&gt;. &lt;code&gt;systemctl disable&lt;/code&gt; hace que no vuelva a arrancar con la máquina.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Si en la columna del proceso dice &lt;code&gt;docker-proxy&lt;/code&gt;&lt;/em&gt;, el puerto lo publicó un contenedor. &lt;code&gt;docker ps&lt;/code&gt; te dice cuál, y se para con &lt;code&gt;docker stop&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  El criterio
&lt;/h2&gt;

&lt;p&gt;Antes de matar un proceso, fijate qué es y quién lo levantó: &lt;code&gt;ss -ltnp&lt;/code&gt; y &lt;code&gt;ps&lt;/code&gt; te lo dicen en dos líneas. Si vuelve solo, es un servicio y se para con &lt;code&gt;systemctl stop&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Y mirá la dirección en la que escucha. Si dice &lt;code&gt;0.0.0.0&lt;/code&gt; y no sabés por qué, arreglá eso antes que el error.&lt;/p&gt;




&lt;p&gt;Practicalo en el lab: &lt;a href="https://securitylabs.valentorassa.com/labs/linux-real/proceso-socket-evidencia-demo/" rel="noopener noreferrer"&gt;Del proceso al socket: una investigación con datos de juguete&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lo publiqué primero en &lt;a href="https://vtsecurity.com.ar/articulo/address-already-in-use?ref=devto" rel="noopener noreferrer"&gt;vtsecurity.com.ar&lt;/a&gt;, donde las figuras son interactivas.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>security</category>
      <category>webdev</category>
      <category>espanol</category>
    </item>
  </channel>
</rss>
