为什么所有脚本文件都以
#!/bin/sh
或搭配
#!/bin/csh
这是必需的吗?目的是什么?两者之间有什么区别?
Answers:
这称为Shebang
:
http://en.wikipedia.org/wiki/Shebang_(Unix)
#!解释器[optional-arg]
仅当脚本具有执行权限时(例如chmod u + x script.sh),shebang才有意义。
当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 ...
./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 Substitution替代品与茶有关。与交互式使用相比,它具有(或更确切地说已经具有;现代的实现sh
已获得)许多优势sh
,但是使用它(或其后代tcsh
)进行脚本编写几乎总是一个错误。如果您一般不熟悉Shell脚本,强烈建议您忽略它,并专注于sh
。如果您使用csh
亲戚作为登录外壳,请切换到bash
或zsh
,以便交互式命令语言将与您正在学习的脚本语言相同。
#!/usr/bin/env
是对的,但是我仍然认为这几乎总是一个坏主意。
这定义了您用于解释/运行脚本的shell(命令解释器)。每个外壳程序与用户交互并执行脚本(程序)的方式略有不同。
在Unix提示符下键入命令时,您正在与外壳进行交互。
例如,#!/bin/csh
是指C壳,/bin/tcsh
t壳,/bin/bash
bash壳等。
您可以判断出您正在使用哪个交互式外壳
echo $SHELL
命令,或者
env | grep -i shell
您可以使用chsh
命令更改命令外壳。
每个都有一个稍微不同的命令集和分配变量的方式以及它自己的一组编程结构。例如,带有bash的if-else语句看起来与C-shell中的语句不同。
该页面可能会引起关注,因为它在bash和tcsh命令/语法之间“翻译”。
在shell脚本中使用指令可以使您使用其他shell运行程序。例如,我以tcsh
交互方式使用外壳程序,但是经常使用脚本文件中的/ bin / bash运行bash脚本。
在旁边:
这个概念也扩展到其他脚本。例如,如果您使用Python编程,
#!/usr/bin/python
在Python程序的顶部
#! $SHELL
吗?这会把正确的炮弹放到射帮里吗?
!#/bin/bash
指令。它告诉系统使用什么Shell来执行Shell脚本。
$SHELL
不一定告诉您当前正在运行哪个shell;它通常会告诉您您的默认外壳。tcsh集$version
和$tcsh
; 打击套$BASH_VERSION
。并非所有的外壳都必须具有类似的机制。
#!
行必须匹配脚本的语法,而不是运行脚本的人使用的交互式外壳。
#!/bin/csh -f
;。在-f
告诉shell不要源的用户的.login
和.cshrc
,这使得脚本运行速度更快,避免了用户的设置的依赖关系。(或者更好的是,不要编写csh脚本。)不要-f
用于sh或bash脚本;它没有相同的含义。