正如“已知”,一个my-script-file
以
#!/path/to/interpreter -arg1 val1 -arg2 val2
通过使用2 (!) 个参数exec
调用来执行:/path/to/interpreter
-arg1 val1 -arg2 val2
my-script-file
(而不是,正如人们可能天真地预期的那样,有 5 个参数
-arg1
val1
-arg2
val2
my-script-file
正如之前许多问题中所解释的,例如,https : //stackoverflow.com/a/4304187/850781)。
我的问题来自解释器开发人员的 POV ,而不是脚本编写者。
interpreter
与命令行相反,我如何从shebang调用的可执行文件内部检测到?然后我将能够决定是否需要按空间拆分我的第一个参数以从"-arg1 val1 -arg2 val2"
到["-arg1", "val1", "-arg2", "val2"]
或不。
这里的主要问题是其中以空格命名的脚本文件。如果我总是拆分第一个参数,我会像这样失败:
$ my-interpreter "weird file name with spaces"
my-interpreter: "weird": No such file or directory
在 Linux 上,使用 GNU libc 或 musl libc,您可以使用aux-vector来区分这两种情况。
下面是一些示例代码:
#define _GNU_SOURCE 1
#include <stdio.h>
#include <errno.h>
#include <sys/auxv.h>
#include <sys/stat.h>
int
main (int argc, char* argv[])
{
printf ("argv[0] = %s\n", argv[0]);
/* https://www.gnu.org/software/libc/manual/html_node/Error-Messages.html */
printf ("program_invocation_name = %s\n", program_invocation_name);
/* http://man7.org/linux/man-pages/man3/getauxval.3.html */
printf ("auxv[AT_EXECFN] = %s\n", (const char *) getauxval (AT_EXECFN));
/* Determine whether the last two are the same. */
struct stat statbuf1, statbuf2;
if (stat (program_invocation_name, &statbuf1) >= 0
&& stat ((const char *) getauxval (AT_EXECFN), &statbuf2) >= 0)
printf ("same? %d\n", statbuf1.st_dev == statbuf2.st_dev && statbuf1.st_ino == statbuf2.st_ino);
}
直接调用的结果:
$ ./a.out
argv[0] = ./a.out
program_invocation_name = ./a.out
auxv[AT_EXECFN] = ./a.out
same? 1
通过以 开头的脚本调用的结果#!/home/bruno/a.out
:
$ ./a.script
argv[0] = /home/bruno/a.out
program_invocation_name = /home/bruno/a.out
auxv[AT_EXECFN] = ./a.script
same? 0
这种方法当然是非常不可移植的:只有 Linux 具有该getauxv
功能。并且肯定存在它不能正常工作的情况。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句