为什么所有脚本文件都以
开头#!/bin/sh
或
#!/bin/csh
这需要吗?这是为了什么目的?这两者有什么区别?
答案 0 :(得分:77)
这称为Shebang
:
http://en.wikipedia.org/wiki/Shebang_(Unix)
#!interpreter [optional-arg]
仅当脚本具有执行权限(例如chmod u + x script.sh)时,shebang才有意义。
当shell执行脚本时,它将使用指定的解释器。
示例:
#!/bin/bash
# file: foo.sh
echo 1
$ chmod u+x foo.sh
$ ./foo.sh
1
答案 1 :(得分:38)
#!
行告诉内核(具体来说,execve
系统调用的实现)该程序是用解释语言编写的;后面的绝对路径名标识解释器。编译为机器代码的程序以不同的字节序列开头 - 在大多数现代Unix上,7f 45 4c 46
( ^?ELF )标识它们。
只要该程序本身不是#!
脚本,您就可以在#!
之后为所需的任何程序设置绝对路径。内核重写了
./script arg1 arg2 arg3 ...
其中./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不会),不能以“字节顺序标记“,或者内核不会将其识别为#!
脚本。#!
之后的路径必须是绝对路径(以/
开头)。它不能包含空格,制表符或换行符。#!
和/
之间添加空格是一种很好的风格,但不是必需的。不要在那里放置多个空间。#!
行上放置shell变量,它们不会被展开。#! /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
)进行脚本编写是{ {3}}。如果您不熟悉shell脚本,我强烈建议您忽略它并专注于sh
。如果您使用csh
亲戚作为登录shell,请切换到bash
或zsh
,以便交互式命令语言与您正在学习的脚本语言相同。 / p>
答案 2 :(得分:4)
这定义了您用于解释/运行脚本的shell(命令解释器)。每个shell在与用户交互并执行脚本(程序)的方式上略有不同。
在Unix提示符下键入命令时,您正在与shell进行交互。
例如,#!/bin/csh
指的是C-shell,/bin/tcsh
t-shell,/bin/bash
bash shell等。
您可以告诉使用
的交互式shell echo $SHELL
命令,或者
env | grep -i shell
您可以使用chsh
命令更改命令shell。
每个都有一个稍微不同的命令集和分配变量的方式以及它自己的一组编程结构。例如,带有bash的if-else语句看起来与C-shell中的那个不同。
This page可能会引起关注,因为它在bash和tcsh命令/语法之间进行“翻译”。
在shell脚本中使用该指令允许您使用不同的shell运行程序。例如,我以交互方式使用tcsh
shell,但经常在脚本文件中使用/ bin / bash运行bash脚本。
除了:
这个概念也扩展到其他脚本。例如,如果您使用Python编程,则需要输入
#!/usr/bin/python
位于Python程序的顶部