2011-10-20 4 views
13

Как скрипт bash выполняется даже после того, как встречается оператор, чтобы удалить себя? Для, например, когда я побежал test.sh скрипт, который conains:Самоопределяющийся скрипт bash

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

end 

Скрипт выполняется до конца, прежде чем удалить себя

+3

Когда приложение выполняется, его код загружается в память. Вы просто удаляете файл на диске, который не влияет на код в памяти. –

+1

Предположительно весь сценарий считывается в память при выполнении, поэтому команды после 'rm test.sh' все еще существуют в памяти для выполнения. – MrMisterMan

+0

Это не делает копию в памяти. Так, например, если скрипт изменен во время его запуска, он выполнит изменения. Это дало мне головную боль в последнее время. Симпатичный пример: этот однострочный скрипт будет заполнять ваш диск в короткие сроки: «cat $ 0 >> $ 0». – Ned

ответ

24

Что на самом деле происходит то, что Баш держит файл открытым и rm не сделает эту остановку.

rm вызывает функцию libc «unlink()», которая удаляет «ссылку» в inode из каталога, в котором она находится. Эта «ссылка» на самом деле является именем файла вместе с номером inode (вы можете видеть inode номера с ls -i).

Индекс существует до тех пор, пока программы открываются.

Вы можете легко проверить это утверждение следующим образом:

$ echo read a> ni 
$ bash ni 

в то время как в другом окне:

$ 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 

Файл не открыт до сих пор, даже если вы больше не можете видеть это в латах. Так что это не то, что bash читает весь файл - это просто не так, пока bash не будет с ним.

+1

Вот почему программа обновления никогда не должна изменять существующие исполняемые файлы, а скорее отключать их, а затем переписывать новую версию. – curiousguy

+0

ОК, но что произойдет, если файл будет перезаписан другим процессом? Файл отсоединен, поэтому он считается «свободным пространством», не так ли? –

+0

@G_G переписывание означает, что запись в каталоге, названная именем файла, теперь связана с другим inode. Пока исходный индекс не закрыт bash, он будет существовать и будет использоваться bash. – w00t

-1

На самом деле, это явление является специфическим для оболочек (например, Баш), которые прочитать файл в память, а затем выполнить их.

Если вы выполните следующую a.bat: эхо YO1 дель a.bat эхо YO2

Вы получаете следующий вывод: C:> a.bat

C:> эхо YO1 Yo1

C:> del a.bat Пакетный файл не может быть найден.

Это за ваши ожидания :-)

+1

Это неверно; Ответ w00t правильный. Я лично видел ошибки, когда скрипт bash * отредактирован * во время его работы, указывая на то, что файл удерживается открытым и читается. –