Próbuję zrozumieć pliki konfiguracyjne grub. Podczas tego procesu natknąłem się na plik /etc/grub.d/40_custom . Mój plik zawiera następujące wiersze:
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries. Simply type the
# menu entries you want to add after this comment. Be careful not to change
# the 'exec tail' line above.
menuentry "Windows 10" --class windows --class os {
insmod part_msdos
savedefault
insmod ntfs
insmod ntldr
set root='(hd0,msdos1)'
ntldr ($root)/bootmgr
}
ponieważ mój system ma podwójny rozruch i najwyraźniej jest to program ładujący dla systemu Windows 10.
Moje pytanie dotyczy jednak tej części exec tail -n +3 $0
.
Jeśli odszyfrowuję go poprawnie, oznacza to po prostu wydrukowanie ostatnich linii, zaczynając od 3. linii ( +3
) pliku $0
. $0
oczywiście w tym przypadku jest to plik /etc/grub.d/40_custom .
Dlaczego więc używamy tego polecenia w pliku 40_custom ? Jak rozumiem, wynik byłby taki sam, gdyby ιt został całkowicie pominięty. Jedyne, o czym mógłbym pomyśleć, to pierwsza linia identyfikująca tłumacza:
#!/bin/sh
Ale potem znowu jest wykonywany, ponieważ exec tail -n +3 $0
następuje po nim. Czy to tylko konwencja (bezużyteczna)?
#!/bin/tail -n +2
jako shellbang? Czy wydrukuje resztę pliku?-n +2
wydaje się być interpretowane jako-n 2
i drukowane są tylko dwie ostatnie linie. To chyba warte własnego pytania.n
i+
. Przynajmniej w systemie Linux, po ścieżce wykonywalnej i spacji, następujące znaki są traktowane jako pojedynczy argument. Tak więc w przypadku spacji ogon ją widzi i prawdopodobnie postanawia usunąć wszelkie niepoprawne-n
argumenty prefiksu (w tym przypadku spację ia+
), dopóki nie dojdzie do liczby. Jednak, jak powiedział Charles Duffy, obecny sposób, w jaki to zrobili, jest prawdopodobnie bardziej przenośny dla innych Unices.cat <<EOF ...EOF
tamKatalog
/etc/grub.d/
zawiera wiele plików wykonywalnych (zwykle skrypty powłoki, ale możliwy jest także każdy inny typ pliku wykonywalnego). Ilekroćgrub-mkconfig
zostanie wykonany (np. Jeśli uruchomiszupdate-grub
, ale także podczas instalowania zaktualizowanego pakietu jądra, który zwykle ma hak poinstalacyjny, który informuje menedżera pakietów o aktualizacjigrub.cfg
), wszystkie są wykonywane w kolejności alfabetycznej. Wszystkie dane wyjściowe są łączone i kończą się w pliku/boot/grub/grub.cfg
, dzięki zgrabnym nagłówkom sekcji, które pokazują, która część pochodzi z którego/etc/grub.d/
pliku.Ten jeden konkretny plik
40_custom
umożliwia łatwe dodawanie wpisów / liniigrub.cfg
, po prostu wpisując / wklejając je do tego pliku. Inne skrypty w tym samym katalogu wykonują bardziej złożone zadania, takie jak wyszukiwanie jąder lub systemów operacyjnych innych niż Linux i tworzenie dla nich pozycji menu.Aby umożliwić
grub-mkconfig
traktowanie wszystkich tych plików w ten sam sposób (wykonaj i pobierz dane wyjściowe),40_custom
jest skrypt i używa tegoexec tail -n +3 $0
mechanizmu do wyświetlania zawartości (pomniejszonej o „nagłówek”). Gdyby nie był to plik wykonywalny,update-grub
potrzebowałby specjalnego, zakodowanego na stałe wyjątku, aby wziąć dosłowną zawartość tekstową tego pliku zamiast wykonywać go tak jak wszystkie inne. Ale co jeśli ty (lub twórcy innej dystrybucji linuksa) chcesz nadać temu plikowi inną nazwę? A co jeśli nie wiedziałeś o wyjątku i utworzyłeś skrypt powłoki o nazwie40_custom
?Możesz przeczytać więcej na temat
grub-mkconfig
i/etc/grub.d/*
w Podręczniku GNU GRUB (chociaż mówi głównie o opcjach, które możesz ustawić/etc/default/grub
), i powinien być również plik,/etc/grub.d/README
który stwierdza, że pliki te są wykonywane do postacigrub.cfg
.źródło
/etc/grub.d/exec
Dla możliwych do wykonania plików / skryptów i/etc/grub.d/static
dla zwykłych plików tekstowych, lub jakiś inny wskaźnik umożliwiający ich rozróżnienie. Była to jednak decyzja projektowa, z którą poszli.TL; DR : sztuczka polega na uproszczeniu dodawania nowych wpisów do pliku
Cały punkt jest opisany na jednej ze stron Wiki Ubuntu na temat grub :
Dane wyjściowe skryptów
/etc/grub.d/
stają się zawartościągrub.cfg
pliku.Co teraz robi
exec
? Może albo ponownie przesłać dane wyjściowe dla całego skryptu, albo jeśli podano polecenie - wspomniane polecenie wyprzedza i zastępuje proces skryptu. To, co kiedyś było skryptem powłoki z PID 1234, teraz jesttail
poleceniem z PID 1234.Teraz już wiesz, że
tail -n +3 $0
drukuje wszystko po 3 linii w samym skrypcie. Dlaczego więc musimy to zrobić? Gdyby grub dbał tylko o wynik, równie dobrze moglibyśmy to zrobićW rzeczywistości znajdziesz
cat <<EOF
przykład w dokumentacji Fedory , choć w innym celu. Chodzi o to w komentarzach - łatwość użytkowania dla użytkowników:Dzięki
exec
trickowi nie musisz wiedzieć, co robicat <<EOF
(spoiler, to się nazywa tutaj-doc ), ani nie musisz pamiętać, aby dodaćEOF
w ostatnim wierszu. Po prostu dodaj menu do pliku i gotowe. Dodatkowo, jeśli piszesz skrypt, dodając menu, możesz po prostu dołączyć>>
do tego pliku za pomocą powłoki.Zobacz też:
źródło
#!/bin/sh
. Podejrzewam, że jest to po prostu powód historyczny (przeniesiony z bazy kodu PUPA ) i decyzja projektowa zainspirowana skryptami typu SysV.