Si hubiera un proceso escribiendo continuamente en un archivo, y quisiera tomar el control del archivo con root, podría hacer algo como esto:
sudo rm somefile; sudo touch somefile
¿Es posible que el proceso de adición anexe al archivo entre estos dos comandos? Si es así, ¿hay alguna manera de garantizar que no se ejecute ningún otro comando en el medio?
Respuestas:
Una línea de comando encadenada es básicamente un pequeño script de shell; ejecutará el primer comando utilizando el procedimiento habitual de fork + exec, esperará a que salga y luego ejecutará el segundo de la misma manera. Entre los dos comandos, hay una cantidad arbitraria de tiempo que el shell tarda en su contabilidad y procesamiento, durante el cual tiene lugar el multiprocesamiento ordinario y otros procesos arbitrarios pueden hacer otras cosas arbitrarias. Por tanto, la respuesta es no'. (Si realmente hace esto, encontrará que la entrada del directorio para
somefile
desaparece, pero el archivo en sí permanece (ya que es abierto por un proceso) hasta que se cierra. El espacio en disco utilizado por el archivo no será reclamado hasta que eso suceda. Mientras tanto , eltouch
comando creará un nuevo archivo no relacionado con el mismo nombre y ruta).Si desea cambiar la propiedad del archivo a raíz, simplemente hágalo
sudo chown root:root somefile
(aunque no estoy seguro de cómo eso afectará los procesos con un identificador de archivo abierto). Si desea destruir el contenido del archivo actual, intentetruncate -s 0 somefile
(el proceso en ejecución continuará anexándose al archivo ahora vacío). Si se trata de algo más, quizás aclare lo que quiere hacer.fuente
chown
ing somefile no afectará los procesos que tienen un identificador de archivo para somefile.exec 3>somefile; sudo chmod 0600 somefile; echo hello world >&3; sudo cat somefile; exec 3>&-
.No. Un
rm
comando seguido de untouch
comando no es atómico en absoluto. Pasará mucho tiempo entre los dos comandos, posiblemente en el rango de milisegundos. Pueden pasar muchas cosas durante ese tiempo. Si no tienes suerte, tus credenciales de sudo podrían incluso caducar.Un solo programa que llama
unlink
yopen
llama dejaría una ventana mucho más corta para una carrera, pero aún podría suceder.Un enfoque más seguro sería crear el nuevo archivo con un nombre temporal y usar la
rename
llamada al sistema. "Sobrescribir" un nombre con larename
llamada del sistema se garantiza que sea atómico. Esto podría lograrse usandotouch
ymv
.Pero un proceso que ha abierto el archivo antiguo para escritura puede seguir escribiendo mucho después de que se haya eliminado. Este será el caso tanto para un archivo eliminado usando
unlink
como para uno eliminadorename
.fuente
Una vez que un proceso tiene un identificador de archivo abierto para leer, no importa lo que haga con la propiedad o los permisos: el proceso puede continuar accediendo al archivo. Incluso puede eliminar el archivo y el proceso podrá continuar accediendo a él a través del controlador de archivos.
Considere los permisos como una puerta de control para obtener un identificador de archivo.
Si desea crear un archivo atómicamente, en lugar de hacerlo:
podrías considerar esto:
que reemplazará atómicamente
somefile
conanotherfile
. (Hubiera preferido usar,mv -f
pero no puedo encontrar una declaración que garantice que esto llame a larename(2)
llamada del sistema.Quizás pueda actualizar su pregunta para explicar lo que quiere decir con "tomar el control del archivo". Puede tener un problema XY aquí.
fuente
mv -f
para obtener unarename(2)
llamada al sistema. Tienes razón en queln
no, porque siempre usa lalink(2)
llamada al sistema, que no puede reemplazar atómicamente.ln -f
solo lo haceunlink(2)
en el objetivo primero.ln
en el cerebro. No estaba seguro de cómo obtener larename(2)
garantía de estar involucrado y era demasiado tarde para seguir cavandomv
"realizará acciones equivalentes a"rename(old, new)
. pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html .mv -f
actúa comomv -i
si el destino no se puede escribir, pero no es comocp -f
oln -f
dónde se desenlazará primero.No pero
sudo rm somefile; sudo touch somefile
Es seguro en la mayoría de las situaciones.
La mayoría de los procesos abren archivos y luego usan el descriptor de archivo adquirido para acceder al contenido del archivo.
Si un proceso abre algún archivo, en sh:
Luego, otro proceso es libre de desvincular (= eliminar) algún archivo y el descriptor de archivo en el que se abrió algún archivo mediante el primer proceso (3 en este caso) continuará haciendo referencia al contenido original de algún archivo, que ahora es un archivo en el limbo.
creará un archivo nuevo y no relacionado y todos los procesos que tenían abierto el archivo anterior y ahora solo están usando un descriptor de archivo para referirse a él no se verán afectados porque se refieren a un archivo diferente, uno que ahora está en el limbo.
Si un proceso no root intenta hacer referencia a algún archivo por su nombre, obtendrán un error EPERM, porque el nuevo archivo es propiedad de root.
Si desea evitar que múltiples procesos bajo el mismo usuario (por ejemplo, root) dañen un archivo, Linux tiene un bloqueo de archivos obligatorio y de aviso. Puede usar el
flock
comando en los scripts de shell para bloquear el archivo de aviso (consulte la página de manual para obtener más información).fuente