bash脚本:以$开头!代替 #!并有神秘的行为。发生了什么?

时间:2011-10-19 02:48:44

标签: bash

我意外地使用$!而不是#!启动了一个bash脚本,并得到了一些非常奇怪的行为。我想弄清楚发生了什么。

如果你试试这个剧本:

$!/bin/bash
echo Hello world!

您将获得以下行为:

$ chmod +x hello
$ ./hello
[nothing happens, get prompt back]
$ exit
exit
Hello world!
$

所以看起来这件事发生了:

  1. 产生了一个新的bash shell。
  2. 退出时,脚本的其余部分已执行。
  3. 怎么了?怎么样都发生了?如果没有#!,shell如何知道使用bash来解释脚本?

    显然这是“满足我的好奇心”而不是“解决我的问题”的问题。谷歌搜索不会产生太大的影响,可能是因为查询中的#!$!不会让谷歌机器人感到高兴。

3 个答案:

答案 0 :(得分:9)

$ something 是一个参数(“variable”)扩展,但$!特别返回一个未在脚本中设置的值,所以它扩展为零长度字符串。

因此,您的脚本是正确的,相当于:

/bin/bash
echo Hello world!

shebang magic number是Unix的一个老功能,但shell更老了。内核不能执行的执行位设置的文本文件(因为它实际上没有编译)由子shell执行。也就是说,shell故意运行另一个shell并将路径名作为参数传递。这就是在shebang发明之前执行shell脚本编写的命令,它仍然存在于代码中。

答案 1 :(得分:8)

美元爆炸得到了最后一个背景过程的PID。

http://tldp.org/LDP/abs/html/internalvariables.html(搜索'$!')

答案 2 :(得分:3)

对@ DigitalRoss的答案进行了扩展:

第一行没有#!的可执行脚本由/bin/sh执行 - 即使您是从bash(或tcsh)执行的。这不是shell功能,它在内核中。

因此,当您执行脚本时,它由/bin/sh执行(这意味着,在大多数系统上,它将无法使用特定于bash的功能),$!扩展为无(因为该shell没有启动任何后台进程),第一行调用交互式 /bin/bash shell。然后退出该交互式shell,脚本执行echo Hello world!行并终止,将您带回原始shell。

例如,如果您将echo Hello world!更改为echo $BASH_VERSION,您会发现它不会打印任何内容 - 并且如果您从调用的交互式bash shell中键入history,它不会显示任何内容。