2011-10-20 25 views
13

¿Cómo se puede ejecutar un script bash incluso después de encontrar un enunciado para eliminarlo? Por ejemplo, cuando me encontré test.sh script que conains:Script bash de autodejección

<--some commands--> 
rm test.sh 
<--some more commands--> 

end 

El script se ejecuta hasta el final antes de eliminar en sí

+3

Cuando se ejecuta una aplicación, su código se carga en la memoria. Solo está eliminando el archivo en el disco, lo que no afecta el código en la memoria. –

+1

Es de suponer que toda la secuencia de comandos se lee en la memoria en la ejecución y, por lo tanto, los comandos posteriores a 'rm test.sh' aún existen en la memoria para su ejecución. – MrMisterMan

+0

No hace una copia en la memoria. Entonces, por ejemplo, si el script se modifica mientras se está ejecutando, ejecutará las modificaciones. Esto me ha estado dando dolores de cabeza recientemente. Lindo ejemplo: este script de una línea llenará tu disco en poco tiempo: 'cat $ 0 >> $ 0'. – Ned

Respuesta

24

Lo que realmente ocurre es que fiesta mantiene el archivo abierto y rm no hará que esa parada.

Entonces rm llama a la función libc "unlink()" que eliminará el "enlace" al inodo del directorio en el que se encuentra. Este "enlace" es de hecho un nombre de archivo junto con un número inodo (puede ver el inode números con ls -i).

El inodo existe mientras los programas lo tengan abierto.

Usted puede probar fácilmente esta demanda de la siguiente manera:

$ echo read a> ni 
$ bash ni 

mientras que en otra ventana:

$ pgrep -lf bash\ ni 
31662 bash ni 
$ lsof -p 31662|grep ni 
bash 31662 wmertens 255r REG 14,2   7 12074052 /Users/wmertens/ni 
$ rm ni 
$ lsof -p 31662|grep ni 
bash 31662 wmertens 255r REG 14,2   7 12074052 /Users/wmertens/ni 

El archivo todavía está abierta a pesar de que ya no se puede ver en ls. Así que no es que bash leyó todo el archivo, simplemente no se ha ido hasta que Bash termina con eso.

+1

Es por eso que un programa de actualización nunca debe cambiar los archivos ejecutables existentes, sino desvincularlos, y luego volver a escribir la nueva versión. – curiousguy

+0

bien, pero ¿qué ocurre si el archivo se sobrescribe con otro proceso? El archivo está desvinculado por lo que cuenta como "espacio libre", ¿no? –

+0

La sobreescritura de @G_G solo significa que la entrada del directorio nombrada por el nombre de archivo ahora se vincula a otro inodo. Mientras el inodo original no esté cerrado por bash, existirá y será utilizado por bash. – w00t

-1

De hecho, este fenómeno es específico de conchas (como Bash), que leen el archivo en la memoria y luego ejecútelos.

Si se ejecuta la siguiente a.bat: eco Yo1 del a.bat eco Yo2

Se obtiene el siguiente resultado: C:> a.bat

C:> echo Yo1 Yo1

C:> del a.bat No se encuentra el archivo de proceso por lotes.

Esto es por su expectativa :-)

+1

Esto es falso; La respuesta de w00t es correcta. Personalmente he visto que se producen errores cuando se edita * un script bash * mientras se está ejecutando, lo que indica que el archivo se mantiene abierto y leído. –