译文翻译_linux_1_Shebang Shenanigans

文章探讨了在不同Unix-like系统中,如Linux、macOS、FreeBSD/OpenBSD和OpenIndiana,脚本文件中shebang(#!/bin/...)的参数处理方式。在某些系统中,所有参数被视为单个字符串,而在其他系统中,每个参数独立传递。例如,使用#!/usr/bin/awk-iinplace-f在不同系统上可能不会按预期工作。作者通过编写一个C程序来展示参数传递行为,并展示了各种系统的行为差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Shebang Shenanigans

You have probably all seen the shebang at top of shell scripts, the first line starting with #!/bin/sh.

你可能看到过一些以#!/bin/sh 开头的脚本

The initial characters #! tells the OS that this isn’t a regular binary, but rather something that needs to run through an interpreter, namely the interpreter after #!. Therefore you can see lines like #!/usr/bin/perl, #!/usr/bin/awk, or #!/usr/bin/python.

#!告诉操作系统,这个文件不是一个常规的二进制文件,是需要#! 后面标注的解释器来执行的,所以你可以看到有这些写法#!/usr/bin/perl,#!/usr/bin/awk,#!/usr/bin/python

Executing a file like ./test.sh, having the shebang #!/bin/sh, is similar to calling this command: /bin/sh ./test.sh.

在命令行中执行首行标注着#!/bin/sh的脚本./test.sh 与直接执行/bin/sh ./test.sh是类似的。

While learning awk, I noticed the use of the shebang #!/usr/bin/awk -f, i.e. a shebang with extra arguments. This can also sometimes be seen for Python, usually as #!/usr/bin/python -u to enable unbuffered output.

在学习awk命令的时候,我们标注的shebang为#!/usr/bin/awk -f,也就是,一个具有额外参数的shebang,这种模式同样也出现在python中,比如#!/usr/bin/python -u去保证脚本的无缓冲输出。

实际用处?当程序输出(包括错误输出)保存到文件时,为防止乱行,一般加上此参数。

I wanted to add some extra arguments to (g)awk, ideally running it as #!/usr/bin/awk -i inplace -f, to modify the file in-place. Surprisingly (to me), this didn’t work. It turns out that this is equivalent to the command: awk "-i inplace -f" file.awk, i.e calling awk with a single argument with all flags mashed into a single string. Not what I intended, and certainly not something that worked. This led me to the question: How does different Unix-like systems handle shebang arguments?.

我想额外添加参数到awk命令上,像这样#!/usr/bin/awk -i inplace -f,使其直接对文件做inplace操作。但是另我感到吃惊的是,没用。这个shebang等价于命令行中的awk "-i inplace -f" file.awk,也就是将所有的falgs混合成一个字串组成一个参数来调用awk命令。是我始料未及的,所以我就在想,不同的unix类os如何处理shebang 的参数的。

Let’s investigate!

Helpers

To easily see how arguments are passed to a binary, a wrote a small helper application in C. It prints one line for every argument passed.

为了看到参数是如何传入到二进制命令里面的,我写个c的应用。,其打印每一个输入的参数。、

#include <stdio.h>

int main(int argc, char **argv)
{
	for (int i = 0; i < argc; ++i) {
		printf("argv[%d]: %s\n", i, argv[i]);
	}

	return 0;
}

Running it like ./args hi there reader provides the following output:

在命令行中输入./args hi there reader,有如下输出

gcc args.c -std=c99
./a.out hi there reader 
# 编译后生成的可执行文件是 a.out
$ ./args hi there reader
argv[0]: ./args
argv[1]: hi
argv[2]: there
argv[3]: reader

I copy this binary to /usr/local/bin/args, and then proceed to create the following test file, and make it executable with chmod +x file.txt.

将二进制文件复制到/usr/local/bin/args,并创建测试文件,可执行

#!/usr/local/bin/args -a -b --something
# file.txt
hello i'm a line that doesn't matter

Linux

执行

[root@linux ~]# ./file.txt
argv[0]: /usr/local/bin/args
argv[1]: -a -b --something
argv[2]: ./file.txt

As we can see, argv[1] has all flags stored as a single argument. 😦

macOS

This worked exactly as I expected initially! Here each argument is passed independently to the interpreter.

$ ./file.txt
argv[0]: /Users/linus/args
argv[1]: -a
argv[2]: -b
argv[3]: --something
argv[4]: ./file.txt

FreeBSD / OpenBSD

Nothing exciting here, it turns out both these systems work the same way as Linux regarding shebangs.

$ ./file.txt
argv[0]: /usr/local/bin/args
argv[1]: -a -b --something
argv[2]: ./file.txt

OpenIndiana

I also wanted to try out a Solaris-fork, in this case OpenIndiana, to try out different Unixes. Turns out this provided different results as well:

$ ./file.txt
argv[0]: /usr/local/bin/args
argv[1]: -a
argv[2]: ./file.txt

Copy

As we can see, OpenIndiana completely throws away anything except the first argument. (What? ಠ_ಠ )

Summary

The results can be summarized in the following table:

argv[0]argv[1]argv[2]argv[3]argv[4]
Linux/usr/local/bin/args-a -b --something./file.txt
FreeBSD OpenBSD/usr/local/bin/args-a -b --something./file.txt
macOS/usr/local/bin/args-a-b--something./file.txt
OpenIndiana/usr/local/bin/args-a./file.txt

— 总结

— 博主总结

shebang的参数最好写一块

文章来源:Shebang Shenanigans :: Linus Karlsson

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值