bash 脚本:以 $! 开头而不是#!并出现了神秘的行为。发生了什么?
我不小心用 $!
而不是 #!
启动了 bash 脚本,并得到了一些非常奇怪的行为。我正在努力弄清楚发生了什么事。
如果您尝试此脚本:
$!/bin/bash
echo Hello world!
您将得到以下行为:
$ chmod +x hello
$ ./hello
[nothing happens, get prompt back]
$ exit
exit
Hello world!
$
所以看起来发生了这样的情况:
- 生成了一个新的 bash shell。
- 退出后,执行脚本的其余部分。
这是怎么回事?怎么回事?如果没有#!
,shell 如何知道使用bash
来解释脚本?
显然这是一个“满足我的好奇心”而不是“解决我的问题”的问题。谷歌搜索不会产生太多结果,可能是因为查询中的 #!
和 $!
并不能让 Google 机器人满意。
I accidentally started a bash script with $!
instead of #!
and got some very weird behavior. I'm trying to figure out what happened.
If you try this script:
$!/bin/bash
echo Hello world!
you will get the following behavior:
$ chmod +x hello
$ ./hello
[nothing happens, get prompt back]
$ exit
exit
Hello world!
$
So it looks like this happened:
- A new bash shell spawned.
- Upon exit, the rest of the script executed.
What's up? How is anything at all happening? Without #!
, how does the shell know to use bash
to interpret the script?
Obviously this is a "satisfy my curiosity" rather than "solve my problem" question. Googling does not yield much, probably because #!
and $!
in queries don't make the Google-bot happy.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
$something 是参数 ("variable") 扩展,但
$!
特别返回一个未在脚本中设置的值,所以它扩展为零长度字符串。因此,您的脚本是正确的,相当于:
shebang magic number是 Unix 的一个古老功能,但 shell 更古老。内核无法执行(因为它实际上没有编译)的执行位设置的文本文件由子 shell 执行。也就是说,shell 故意运行另一个 shell 并将路径名作为参数传递。这就是在 shebang 发明之前以 shell 脚本形式编写的命令的执行方式,并且它仍然存在于代码中。
$something is a parameter ("variable") expansion, but
$!
in particular returns a value that isn't set in your script, so it expands as a zero length string.Therefore your script is, you are correct, the equivalent of:
The shebang magic number is an old feature of Unix, but the shell is even older. A text file with the execute bit set that the kernel cannot exec (because it's not actually compiled) is executed by a subshell. That is, the shell deliberately runs another shell and passes the pathname as the parameter. This is how commands written as shell scripts were executed before shebang was invented, and it's still there in the code.
Dollar-bang 获取最后一个后台进程的 PID。
http://tldp.org/LDP/abs/html/internalvariables.html(搜索“$ !')
dollar-bang gets the PID of the last backgrounded process.
http://tldp.org/LDP/abs/html/internalvariables.html (Search for '$!')
稍微扩展一下@DigitalRoss 的答案:。
第一行没有
#!
的可执行脚本由/bin/sh
执行——即使您从bash
执行它(或者tcsh)。这不是 shell 功能,而是内核中的功能。因此,当您执行脚本时,它是由
/bin/sh
执行的(这意味着,在大多数系统上,它将无法使用 bash 特定的功能),$!
扩展为空(因为该 shell 尚未启动任何后台进程),并且第一行调用一个交互式/bin/bash
shell。然后,您退出该交互式 shell,您的脚本将执行echo Hello world!
行并终止,将您带回原始 shell。例如,如果您将
echo Hello world!
更改为echo $BASH_VERSION
,您会发现它不会打印任何内容 - 并且如果您输入history
从调用的交互式 bash shell 中,它不会显示任何内容。Expanding a bit on @DigitalRoss's answer:.
An executable script with no
#!
on the first line is executed by/bin/sh
-- even if you execute it frombash
(ortcsh
). This isn't shell functionality, it's in the kernel.So when you executed your script, it was executed by
/bin/sh
(which means, on most systems, that it won't be able to use bash-specific features),$!
expanded to nothing (because that shell hasn't launched any background processes), and the first line invokes an interactive/bin/bash
shell. Then you exit from that interactive shell, and your script execute theecho Hello world!
line and terminates, putting you back in your original shell.For example, if you change
echo Hello world!
toecho $BASH_VERSION
, you'll find that it doesn't print anything -- and if you typehistory
from the invoked interactive bash shell, it won't show anything.