Сидел я сегодня такой, развлекался с Nix'ом и внезапно обнаружил, что конструкции вида
nix shell nixpkgs#hello -c bash в шебанге и Linux и MacOS отрабатывают совершенно по-разному.
Краткая справка: Шебанг (shebang) - это конструкция вида
#!interpreter [args] (
#! обязателен), расположенная строго в начале файла, и говорящая операционной системе запустить
interpreter [args] [original file] [original args].
Была придумана, чтобы не писать руками
python script.py, а сделать
./script.py, условный.
Когда функциональность уровня ядра ведет себя как-то неправильно, первое и логичное решение... пойти копаться в сорцах этого самого ядра.
Спасибо эплу, некоторым лицензиям, и неизвестному самаритянину (насколько я знаю, это неофициальное зеркало) - у нас есть код XNU (ядро MacOS) на
гитхабе.
Непродолжительные поиски действительно привели меня к
строке, в которой определяется условие конец шебанга, где концом строки считается либо
#, либо
\n.
Окей, теперь я знаю, что у меня нет шизофрении
(на самом деле есть), и это действительно ядро ведет себя так странно.
Встает следующий вопрос: а почему оно так себя ведет?
Если посмотреть на путь к файлу
kern_exec.c, можно увидеть, что он начинается с папки
bsd.
Так возможно это не у apple что-то с головой, а они просто бэкпортировали какое-то странное изменение из ядра *BSD? (Да, XNU основан во многом на BSD)
Быстро пробежавшись по старым *BSD ядрам (4.3BSD, FreeBSD версий 2-3) я ничего полезного не нашел, там этой
особенности не было.
Дальше я решил вернуться обратно к blame'у сорцов XNU. К сожалению, текстов коммитов нет (разве что где-то в недрах Apple), поэтому остается довольствовать описаниями версий, в которых что-то меняли.
Таким образом я узнал, что
это добавили в XNU-517.
Быстрый гуглеж по XNU-517 shebang наконец-то привел меня к цели всего поста: шедевральной страничке
https://www.in-ulm.de/~mascheck/various/shebang/, содержащей огромный и очень информативный текст (я не шучу, сходите сами почитайте!) про историю шебангов.
Конкретно про обработку второй
# -
тут.
Как оказалось, я смотрел слишком ранние версии FreeBSD - это действительно внесли именно в ней, в 4.0 ветке, а потом убрали в 6.0.
XNU бэкпортировали это к себе, но так и не убрали, только рефакторя код год за годом (стало кстати объективно лучше, тоже забавное наблюдение).
Итак. Изначальной причиной появления такого способа обработки
# в шебангах была...
Рекомендация в документации к perl'у писать шебанг следующим образом:
#!/bin/sh -- # -*- perl -*- -p
чтобы избегать каких-то странных кроссплатформенных проблем (да, утилиту
env тогда ещё не придумали).
Зайдите ещё в комменты, там есть парочка мемов, которые не влезли в пост =)