我正在检查Shell脚本,并注意到以下命令-exec。exec命令执行cmdline,但我想知道:-/bin/bash
命令在这里做什么。
cmdline="$@"
exec ${cmdline:-/bin/bash}
这里有3件主要事情:
$@
是特殊的shell变量,可扩展为脚本的所有命令行参数${cmdline:-/bin/bash}
是参数扩展结构之一;如果cmdline
变量未设置或为空,则在这种情况下,整个${}
部分将替换为-
符号后的内容/bin/bash
;这是其他编程语言中if语句或三元运算符的一种简写(不完全是,但足以进行比较)exec
用于生成将超过当前进程的PID的进程,即,只需用其中的任何内容替换脚本进程 ${}
将所有这些代码放在一起,只需使用命令行参数并运行它们,如果脚本没有命令行参数,您将获得交互式bash
shell。请注意,您还可以传递exec
文档中提到的选项-compare./exec_script.sh -c env
和./exec_script.sh env
。
该方法本身看起来似乎很复杂,但是exec
在包装器脚本中经常会看到这种方法-脚本设置环境并在组织所有内容以运行实际命令之前检查变量。区别在于,在包装脚本中设置了命令-包装脚本通常设置环境和参数以仅运行一个特定程序。
相比之下,该脚本旨在运行用户在命令行上放置的任何内容。这是一个问题,因为外壳程序是如何工作的-给定包含特殊字符的命令行参数,您打算运行的命令可能会中断。这就是我的意思:
# This is how it's supposed to work
$ printf 'one%stwo' $'\t'
one two
# This is how it works with unquoted parameter expansion
$ ./exec_script.sh printf 'one%stwo' $'\t'
onetwo
想象一下,如果您试图使用该脚本来运行my_cool_command filename$'\t'with$'\t'tabs.txt
;充其量是-命令中断,但如果filenamewithtab.txt
当前文件夹中也有文件,my_cool_command
则将对完全错误的文件进行操作。引用参数扩展也无济于事,因为它会中断:
$ ./exec_script.sh printf 'one%stwo' $'\t'
./exec_script.sh: line 4: exec: printf one%stwo : not found
这是bash
(版本4.3)手册中有关参数扩展的相关部分:
$ {parameter:-word}
使用默认值。如果参数未设置或为null,则替换单词的扩展名。否则,将替换参数的值。
“特殊参数”部分:
@扩展到位置参数(从1开始)。当在双引号内进行扩展时,每个参数都会扩展为一个单独的单词。也就是说,“ $ @”等效于“ $ 1”“ $ 2” ...如果在单词中出现双引号扩展名,则第一个参数的扩展名将与原始单词的开头部分连接在一起,并且扩展名最后一个参数中的表示与原始单词的最后一部分结合在一起。当没有位置参数时,“ $ @”和$ @扩展为空(即,它们被删除)。
在“ Shell内置命令”部分中:
exec [-cl] [-a名称] [命令[参数]]
如果指定了命令,它将替换外壳程序。没有创建新的过程。自变量成为命令的自变量。如果提供了-l选项,则外壳程序在传递给command的第零个参数的开头放置一个破折号。这就是login(1)所做的。-c选项使命令在空环境中执行。如果提供了-a,则shell将name作为第零个参数传递给已执行的命令。如果由于某种原因无法执行命令,则除非启用了execfail shell选项,否则将退出非交互式shell。在这种情况下,它将返回失败。如果无法执行该文件,则交互式外壳程序将返回失败。如果未指定command,则任何重定向都将在当前shell中生效,并且返回状态为0。如果存在重定向错误,则返回状态为1。
该脚本本身在理论上有一个好主意,但在实践中却很差。该exec
命令在包装脚本中可以很好地工作,实际上,作为Unix和Linux站点上的顶级用户之一,Gilles提到:“ ... exec还可以节省一些内存(以及其他资源,例如PID等),因为它具有无需保留多余的外壳而无所事事”。但是在这种情况下,脚本的目的是重新发明轮子,并做完已经足够好的Shell程序-即运行带有参数的命令。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句