40_custom 文件中“exec tail -n +3 $0”行的含义

Eyp*_*ros 17 grub2

我正在尝试了解 grub 配置文件。所以,在这个过程中,我遇到了文件/etc/grub.d/40_custom。我的文件包含以下几行:

#!/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
}
Run Code Online (Sandbox Code Playgroud)

因为我的系统是双引导,显然这是 Windows 10 的引导加载程序。

我的问题是这部分exec tail -n +3 $0
如果我正确地破译它,这只是意味着打印从文件的第三行 ( +3)开始的最后几行$0$0当然在这种情况下是实际文件/etc/grub.d/40_custom

那么,我们为什么要在40_custom文件中使用这个命令呢?据我所知,如果完全省略 ?t ,输出将是相同的。我可能想到的唯一不同是识别解释器的第一行:

#!/bin/sh
Run Code Online (Sandbox Code Playgroud)

但随后它又被执行,因为exec tail -n +3 $0它跟随它。那么,这只是一个(无用的)约定吗?

ter*_*don 16

诀窍是做什么exec

$ help exec
exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
    Replace the shell with the given command.

    Execute COMMAND, replacing this shell with the specified program.
    ARGUMENTS become the arguments to COMMAND.  If COMMAND is not specified,
    any redirections take effect in the current shell.
Run Code Online (Sandbox Code Playgroud)

exec在这种情况下,这意味着它将用任何给定的东西替换外壳tail。这是它的一个例子:

$ cat ~/foo.sh
#!/bin/sh
exec tail -n +3 "$0"
echo foo

$ ./foo.sh
echo foo
Run Code Online (Sandbox Code Playgroud)

所以echo命令没有执行,因为我们已经更改了 shell 并正在使用tail。如果我们删除exec tail

$ cat ~/foo.sh
#!/bin/sh
echo foo
$ ./foo.sh
foo
Run Code Online (Sandbox Code Playgroud)

所以,这是一个巧妙的技巧,它可以让您编写一个脚本,其唯一的工作就是输出自己的内容。据推测,任何调用都40_custom希望将其内容作为输出。当然,这就引出了一个问题,为什么不直接运行tail -n +3 /etc/grub.d/40_custom

我猜答案是因为grub 使用它自己的脚本语言,这使得它需要这种解决方法。

  • @val ...shebang 行为的标准化和便携性比您预期的要低得多。请参阅 https://en.wikipedia.org/wiki/Shebang_(Unix)#Portability 的“命令参数的解释”部分 (3认同)

Han*_*kob 9

该目录/etc/grub.d/包含许多可执行文件(通常是 shell 脚本,但也可以是任何其他可执行类型)。每当grub-mkconfig被执行时(例如,如果你运行update-grub,而且当你安装更新的内核包时,它通常有一个安装后挂钩,告诉包管理器更新grub.cfg),它们都按字母顺序执行。它们的输出都被连接起来,并最终在文件中/boot/grub/grub.cfg,带有整洁的部分标题,显示哪个部分来自哪个/etc/grub.d/文件。

这个特定的文件40_custom旨在让您只需将条目/行grub.cfg输入/粘贴到该文件中即可轻松添加条目/行。同一目录中的其他脚本执行更复杂的任务,例如查找内核或非 linux 操作系统并为它们创建菜单项。

为了允许grub-mkconfig以相同的方式处理所有这些文件(执行并获取输出),40_custom是一个脚本并使用此exec tail -n +3 $0机制输出其内容(减去“标题”)。如果它不是可执行文件,则update-grub需要一个特殊的硬编码异常来获取此文件的文字文本内容,而不是像其他所有文件一样执行它。但是,如果您(或另一个 Linux 发行版的制造商)想给这个文件一个不同的名字怎么办?或者如果您不知道异常并创建了一个名为 的 shell 脚本40_custom怎么办?

您可以在GNU GRUB 手册中阅读更多关于grub-mkconfig/etc/grub.d/*的内容(尽管它主要讨论您可以在 中设置的选项),并且还应该有一个文件指出这些文件被执行以形成./etc/default/grub/etc/grub.d/READMEgrub.cfg