我当前的系统是:
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 8.1 (jessie)
Release: 8.1
Codename: jessie
与内核:
$ uname -a
Linux debian 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1+deb7u2 x86_64 GNU/Linux
我更新到新内核:
$ sudo apt-get install linux-image-3.16.0-4-amd64
....
Setting up linux-image-3.16.0-4-amd64 (3.16.7-ckt11-1+deb8u2) ...
/etc/kernel/postinst.d/initramfs-tools:
update-initramfs: Generating /boot/initrd.img-3.16.0-4-amd64
/usr/share/initramfs-tools/hooks/fsck: syntax error at line 60: `MNT_FSNAME=$' unexpected
/usr/share/initramfs-tools/hooks/keymap: syntax error at line 57: `value=$' unexpected
/usr/share/initramfs-tools/hooks/resume: syntax error at line 44: `RESUME=$' unexpected
/usr/share/initramfs-tools/hooks/zz-busybox: syntax error at line 33: `$' unexpected
/usr/share/initramfs-tools/scripts/init-premount/plymouth: syntax error at line 19: `$' unexpected
/usr/share/initramfs-tools/scripts/init-top/all_generic_ide: syntax error at line 16: `$' unexpected
....
我注意到脚本中有错误/usr/share/initramfs-tools/hooks/fsck
,我检查了它并注意到它以#!/bin/sh
第 60 行开头:
MNT_FSNAME=$(resolve_device "$MNT_FSNAME")
好吧,我发现错误来自命令替换语法。我的/bin/sh
符号链接dash
当然dash
支持该语法。
我的系统也有sh from 传家宝工具箱,它安装在 中/usr/5bin/sh
,并且该 shell 不支持$(...)
语法。因此,该脚本似乎是使用该 shell 运行的,而不是/bin/sh
作为其 shebang 运行的。
是什么造成了这种奇怪的行为以及如何解决它?
更新
还有一个/sbin/sh
which 是 的符号链接/usr/5bin/sh
。我删除此链接后问题解决了。所以更新 initramfs 的过程似乎使用它而不是/bin/sh
.
答案1
原因是运行 initramfs 挂钩的脚本是用 调用的/sbin/sh
,它是我系统中传家宝工具箱中的旧 Bourne shell,而不是/bin/sh
.
Astrace
可以验证一下:
$ strace -fe execve apt-get install linux-image-3.16.0-4-amd64
...
22900 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22918, si_status=0, si_utime=0, si_stime=0} ---
22919 execve("/sbin/sh", ["sh", "-n", "/usr/share/initramfs-tools/hooks"...], [/* 40 vars */]) = 0
...
答案2
Linux 上的问题是许多脚本需要不可移植的 bash 功能,但没有在 #! 中标记这一点。线。
还有其他类似的问题,例如调用“awk”而不是“gawk”但依赖于gawk 功能的脚本。
有些脚本使用 GNUism 调用实用程序,例如不可移植的长选项。
有些人将其称为 Linux 的供应商锁定。发生这种情况的原因很可能是 Linux 的文档。 Linux 手册页没有提到不可移植的“功能”,也没有鼓励人们只使用可移植的选项。
回到外壳。使用传家宝外壳根本不是一个好主意,因为它并不真正便携。事实上,它仍然使用 sbrk() 而不是 malloc() 来分配内存,这在各个平台上导致了各种问题。在某些 Linux 发行版上可能存在与此相关的隐藏问题。例如,由于这个原因,它在 Cygwin 上根本不起作用。 Heirloom shell 没有修复 SVr4 shell 中的任何众所周知的错误,这似乎是由于半年后开发停止所致。
如果传家宝 shell 是可移植的,那么它可以用作手动脚本检查的测试工具 - 对于需要在任何地方运行的脚本。对于日常使用来说,传家宝外壳并不是正确的选择。
顺便说一句:如果您喜欢 Svr4 Bourne shell 的便携式版本用于测试目的,我推荐在 Schily 工具集中编译为“osh”的 Bourne Shell。如果您想尝试在日常使用中使用 Bourne Shell,我鼓励人们从 Schily 工具集中检查 Bourne Shell“bosh”。它包含第一个历史编辑器,因此不会让您在尝试使用它时一直尖叫。