为什么所有脚本文件都以
#!/bin/sh
或与
#!/bin/csh
这是必需的吗?这样做的目的是什么?两者有什么区别?
这被称为Shebang
:
http://en.wikipedia.org/wiki/Shebang_(Unix)
#!interpreter [可选参数]
shebang 仅在脚本具有执行权限时才相关(例如 chmod u+x script.sh)。
当 shell 执行脚本时,它将使用指定的解释器。
例子:
#!/bin/bash
# file: foo.sh
echo 1
$ chmod u+x foo.sh
$ ./foo.sh
1
该#!
行告诉内核(特别是execve
系统调用的实现)该程序是用解释语言编写的;后面的绝对路径名标识解释器。编译为机器代码的程序以不同的字节序列开头——在大多数现代 Unix 上,7f 45 4c 46
( ^?ELF) 将它们标识为这样。
您可以在之后放置您想要的任何程序的绝对路径#!
,只要该程序本身不是#!
脚本即可。内核重写了一个调用
./script arg1 arg2 arg3 ...
where./script
以 开头,#! /usr/bin/perl
就好像命令行实际上是
/usr/bin/perl ./script arg1 arg2 arg3
或者,如您所见,您可以使用#! /bin/sh
编写一个旨在由sh
.
仅当您直接调用脚本(在命令行上)时#!
才会处理该行;该文件还必须是可执行的 ( )。如果您这样做,则不需要该行(如果存在则将被忽略),并且该文件不必是可执行的。该功能的重点是允许您直接调用解释语言程序,而不必知道它们是用什么语言编写的。(这样做——您会发现实际上有很多库存程序都在使用此功能。)./script
chmod +x script
sh ./script
#!
grep '^#!' /usr/bin/*
以下是使用此功能的一些规则:
#!
必须是文件中的前两个字节。特别是,文件必须是 ASCII 兼容的编码(例如 UTF-8 可以工作,但 UTF-16 不行),并且不能以“字节顺序标记”开头,否则内核将无法将其识别为#!
脚本。#!
必须是绝对路径(以 开头/
)。它不能包含空格、制表符或换行符。#!
在和之间放置一个空格是很好的风格,但不是必需的/
。不要在那里放置多个空格。#!
行中,它们不会被扩展。#! /usr/bin/awk -f
),有时它只是有用的(#! /usr/bin/perl -Tw
)。不幸的是,您不能在绝对路径之后放置两个或更多参数。#! /usr/bin/env interpreter
而不是#! /absolute/path/to/interpreter
. 这几乎总是一个错误。它使您的程序的行为取决于$PATH
调用脚本的用户的变量。并不是所有env
的系统都具备。setuid
或setgid
特权的程序不能使用#!
;它们必须被编译成机器码。(如果您不知道是什么setuid
,请不要担心。)关于csh
,它与sh
Nutrimat Advanced Tea Substitute对茶的作用大致相同。与交互式使用相比,它具有(或者更确切地说,现代实现sh
已经赶上)许多优势sh
,但是将它(或其后代tcsh
)用于脚本几乎总是一个错误。如果您对 shell 脚本不熟悉,我强烈建议您忽略它并专注于sh
. 如果您使用csh
亲戚作为您的登录 shell,请切换到bash
or zsh
,以便交互式命令语言与您正在学习的脚本语言相同。
这定义了您用于解释/运行脚本的 shell(命令解释器)。每个 shell 在与用户交互和执行脚本(程序)的方式上都略有不同。
当您在 Unix 提示符下键入命令时,您正在与 shell 交互。
例如,#!/bin/csh
指的是 C-shell、/bin/tcsh
t-shell、/bin/bash
bash shell 等。
您可以知道您正在使用哪个交互式 shell
echo $SHELL
命令,或者
env | grep -i shell
您可以使用命令更改命令外壳chsh
。
每个都有稍微不同的命令集和分配变量的方式以及它自己的一组编程结构。例如,带有 bash 的 if-else 语句看起来与 C-shell 中的不同。
这个页面可能很有趣,因为它在 bash 和 tcsh 命令/语法之间“转换”。
在 shell 脚本中使用该指令允许您使用不同的 shell 运行程序。例如,我以tcsh
交互方式使用 shell,但经常使用脚本文件中的 /bin/bash 运行 bash 脚本。
在旁边:
这个概念也扩展到其他脚本。例如,如果你用 Python 编程,你会放
#!/usr/bin/python
在 Python 程序的顶部