Почему следующий скрипт удаляет себя?

84

Если вы создадите исполняемый файл со следующим содержимым и запустите его, он удалит сам себя.
Как это работает?

#!/bin/rm
user253751
источник
4
Связанные
Цифровая травма
@DigitalTrauma Хех, это была моя первая мысль, когда я увидел это.
кошка
это не о rm, это о #!. Вопрос можно перефразировать, как работает любой исполняемый скрипт с #!работающим.
njzk2
1
Как вам удалось наткнуться на это?
user1717828
1
Это определенно эпический вопрос. Сожалею, что могу поднять это только один раз.
Данила Кивер

Ответы:

112

Ядро интерпретирует строку, начинающуюся с, #!и использует ее для запуска скрипта, передавая имя скрипта; так что это в конечном итоге работает

/bin/rm scriptname

который удаляет скрипт. (Как указывает Стефан Шазелас , здесь достаточно найти сценарий - если вы указали относительный или абсолютный путь, он передается как есть, в противном случае любой путь, в котором был найден, будет добавлен, включая, возможно, строку emptry, если ваш содержит это и скрипт находится в текущем каталоге. Вы можете поиграться с эхо-скриптом -, чтобы увидеть, как это работает.)scriptnamePATHPATH#!/bin/echo

Как указал Хоббс , это означает, что ваш скрипт на самом деле является rmскриптом, а не bashскриптом - последний будет начинаться с #!/bin/bash.

Посмотрите, как программы запускаются для деталей о том, как это работает в Linux; комментарии к этой статье дают подробности для других платформ. #!называется шебанг, вы найдете много информации, выполнив поиск по этому термину (спасибо Аарону за предложение). Как указал jlp , вы также найдете его упоминаемым как «фунт взрыв» или «хэш-взрыв» ( #обычно известный как «фунт» - в странах, которые не используют £- или «хэш», и !как «взрыв») ). Википедия имеет больше информации.

Стивен Китт
источник
9
Другие названия для "#!" Вы могли бы услышать, что "удар фунта" и "взрыв хеша". Подробности смотрите в en.wikipedia.org/wiki/Shebang_(Unix) .
Jlp
@jlp Фунт взрыва? Это как "удар за доллар"? Хех ...
кошка
Напоминает мне о CrunchBang
Xen2050
1
Технически, аргументом rmбудет путь к скрипту, то есть первый аргумент системного вызова execve (), сделанного процессом. Как правило, если вы запустили скрипт как ./scriptname, это будет, ./scriptnameи если вы вызвали его как scriptname, это будет /path/to/scriptnameгде /path/toнаходится запись, $PATHгде этот скрипт был найден. Как правило, это происходит только в том scriptnameслучае, если у вас есть пустая строка, $PATHи вы вызвали скрипт как scriptnameи scriptnameесть в текущем каталоге.
Стефан Шазелас