以双连字符(-)开头的shebang如何工作?


14

我在RosettaCode页中发现了以下类型的shebang:

--() { :; }; exec db2 -txf "$0"

它适用于Db2,适用于Postgres。但是,我不了解整条线。

我知道双破折号是SQL中的注释,此后它使用一些参数将文件本身作为文件传递给Db2可执行文件。但是圆括号,卷曲的小节,冒号和分号又如何替换真正的shebang#呢??

https://rosettacode.org/wiki/Multiline_shebang#PostgreSQL

Answers:


18

相关:哪个shell解释器运行没有shebang的脚本?

该脚本没有shebang / hashbang / #!行,只是因为没有双破折号#!

但是,脚本将由Shell执行(请参见上面的链接的问题和解答),并且在该Shell中,如果-函数名称中的有效字符是有效的,则该行将声明一个被称为--不执行任何操作的Shell函数(嗯,它将运行:不执行任何操作),并且永不调用。

该函数以更常见的多行符号表示(只是为了使它看起来更明显,因为其奇数名称有点掩盖了它实际上是一个函数):

-- () {
  :
}

函数定义的唯一目的是在shell脚本中有一条有效的行,同时有一条有效的SQL命令(注释)。这种代码称为多语言

在声明了伪造的shell函数之后,该脚本在由shell脚本解释器执行时,将exec用运行产生的进程替换当前的shell db2 -txf "$0",这db2 -txf与在命令行中对脚本的路径名的使用相同。

此技巧可能无法在使用dash或其他ash基于外壳yash的Bourne外壳ksh88ksh93用作的系统上可靠地工作/bin/sh,因为这些外壳不接受名称包含破折号的函数。

也相关:


我想以下内容也可以使用(未​​经实际测试):

--() { exec db2 -txf "$0"; }; --

@ilkkachu现在好了吗?
库萨兰达

1
哦,是的!感谢您提醒我这种事情叫什么。:)
ilkkachu

6

正如@Kusalananda已经说过的那样,该技巧已被打破,并且无法在所有shell中使用。

这是我可移植的做法:

--/.. 2>/dev/null; exec db2 -txf "$0"

即使--当前目录中存在一个名为的文件/目录,第一个命令也应该失败,并且任何错误都将由2>/dev/null;然后,shell将继续执行第二个命令exec


它仍然不是很便携。这不是有效的脚本,并且您仍然依靠调用Shell来解决以下事实:内核将拒绝运行该脚本并ENOEXEC在尝试执行时返回。尝试在下面运行脚本strace以了解我的意思。
卡巴斯德(Kasperd)'18

@kasperd,它仍然应该是可移植的,如果exec()无法在外壳程序上运行,则该外壳程序应将脚本作为外壳程序脚本运行。“如果execl()函数由于等效于[ENOEXEC]错误的错误而失败,则shell将执行等效于命令的命令,该命令具有以命令名作为其第一个操作数的shell调用的方式,...”(请参见pubs.opengroup .org / onlinepubs / 9699919799.2018edition / utilities /…
ilkkachu,

@ilkkachu但是脚本并不总是从shell执行的。如果您尝试在可执行文件可以工作的任何其他上下文中使用脚本,则它将失败。而且,shell并不同意使用哪个解释器。因此,脚本现在将表现不同或完全失败,具体取决于从哪个上下文中调用脚本。
kasperd

@kasperd,好吧,可以肯定的是,如果exec()直接从非shell的东西访问它,它将无法正常工作。但是那会是什么情况呢?您可能想从中运行脚本cron,但是我认为它还是通过外壳运行所有内容,即使不是,也可以很容易地拼写出来db2 -txf /path/to/script,因为您只需要执行一次即可。在交互式shell上使用速记方式最有用。但是可以肯定的是,单独的包装器脚本可能更健壮。
ilkkachu

1
@kasperd我不会用文档和标准惹恼您;去尝试一下!echo 'int main(int c,char**a){execvp(a[1],a+1);}' | cc -include unistd.h -xc -; echo echo yeah > a.sh; chmod 755 a.sh; ./a.out ./a.sh; PATH=`pwd` ./a.out a.sh
比利叔叔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.