¿Cómo encontrar el pid del proceso que ha eliminado un archivo?

13

Estoy trabajando en un proyecto relacionado con la migración de VM. A veces, la imagen de VM desaparecerá y solo quiero saber quién es el culpable. Traté de seguir procesos sospechosos pero fue en vano.

Mohammad
fuente
Tenía la esperanza de encontrar una manera de rastrear la llamada al sistema de desvinculación de todos los procesos en lugar de sólo uno, pero supongo que no hay manera fácil de hacer esto ...
Mohammad

Respuestas:

14

Finalmente encontré la respuesta aquí .

El demonio de Auditoría de Linux hará el truco.

sudo auditctl -w /path/to/somefile -p wra

y entonces

ausearch -f /path/to/somefile -i
Mohammad
fuente
bien, pero ¿cómo afecta el rendimiento?
vartec
@vartec no demasiado, después de sintonizar linux-audit.com/tuning-auditd-high-performance-linux-auditing
Nikolay Fominyh
1

Puede encontrar el PID de un proceso, que tiene algún archivo abierto usando lsof.

Una vez que el archivo se cierra y se elimina, no puede obtener esa información.

Por cierto. Tenga en cuenta que eliminar un archivo es una operación en el directorio en el que se encuentra, no en un archivo en sí.

vartec
fuente
Lamentablemente, no es necesario abrir un archivo para eliminarlo. Al menos, por ejemplo, la salida "strace rm some-file" no muestra que el comando rm abra primero el archivo y luego lo elimine. Entonces supongo que lsof no es útil.
Mohammad
Lea la última oración de mi respuesta
vartec
1

Permítanme sugerir una alternativa con sysdig ya que las respuestas anteriores están envejeciendo. Deje visualizar el pidy namede los procesos que eliminan el archivo /tmp/test. Primero creamos el archivo con touch /tmp/test. Luego comenzamos sysdigcon el siguiente filtro:

$ sudo sysdig -p'%proc.pid,%proc.name' '(evt.type=unlinkat and (evt.arg.name=test or evt.arg.name=/tmp/test)) or (evt.type=unlink and evt.arg.path=/tmp/test)'

unlinkat(2)requiere un orfiltro si la ruta (por ejemplo evt.arg.name) puede ser relativa . Para manejar tanto unlink(qué llamadas unlink(2)) como rm(qué llamadas unlinkat(2)en su versión GNU), el filtro debe coincidir con ambas llamadas al sistema.

sysdigdebe ejecutarse cuando un proceso elimina el archivo. Luego, cuando ejecutamos dichos comandos:

$ unlink /tmp/test
$ touch /tmp/test
$ rm /tmp/test
$ cd /tmp; touch test; rm test

Mostrará tal salida:

11380,unlink
11407,rm
11662,rm

Consulte la guía del usuario de sysdig para obtener una explicación sobre el filtrado y la salida.

Como el filtro es bastante largo, me pareció conveniente escribir un cincel. Es un script lua asociado con un sysdigcomando:

description = "displays processes that delete a file"
short_description = "spy file deletion"
category = "files"

args = 
{
    {
        name = "path", 
        description = "the path of the file to monitor", 
        argtype = "string"
    },
}

function on_set_arg(name, val)
    path = val
    return true
end

function on_init()
    local filename = path
    for i in string.gmatch(path, "[^/]+") do
        filename = i
    end
    chisel.set_event_formatter("%proc.pid\t%proc.name")
    chisel.set_filter(
        "(evt.type=unlinkat and (evt.arg.name=" .. path .. " or \
                             evt.arg.name=" .. filename .. ")) or \
     (evt.type=unlink and evt.arg.path=" .. path .. ")")
    return true
end

Siéntase libre de comentar y mejorarlo. Puede colocar el script lua en un spy_deletes.luaarchivo dentro de un directorio y ejecutarlo sysdigen este directorio para que el cincel esté disponible. Al escribir sudo sysdig -cllo verá como:

Category: files
---------------
spy_deletes         spy file deletion

Ahora puedes llamarlo:

$ sudo sysdig -c spy_deletes /tmp/test

Y en otro tipo de terminal:

$ touch test; unlink test
$ touch test; unlink /tmp/test
$ touch test; rm test
$ touch test; rm /tmp/test

Producirá:

16025   unlink
16033   unlink
16041   rm
16049   rm

El unlinkatfiltro merecería ser más preciso y solo coincidir con la ruta absoluta. Esto requeriría recuperar el fd del directorio pasado unlinkat(2).

Greg Leclercq
fuente
No tengo salida con tu comando.
AB
Estaba escribiendo rm /tmp/testen otra terminal. Edité mi respuesta para hacerlo más claro.
Greg Leclercq