如何在Unix控制台或Mac终端上运行Shell脚本?


Answers:


941

要运行不可执行的sh脚本,请使用:

sh myscript

要运行不可执行的bash脚本,请使用:

bash myscript

启动可执行文件(它是具有可执行权限的任何文件);您只需通过其路径指定它:

/foo/bar
/bin/bar
./bar

要使脚本可执行,请授予其必要的权限:

chmod +x bar
./bar

当文件是可执行文件时,内核负责确定如何执行该文件。对于非二进制文件,这可以通过查看文件的第一行来完成。它应包含hashbang

#! /usr/bin/env bash

hashbang告诉内核要运行什么程序(在这种情况下,命令/usr/bin/env使用参数bash)运行。然后,将脚本以及您提供给脚本的所有参数作为后续参数一起传递到程序(作为第二个参数)。

这意味着每个可执行脚本都应具有hashbang。如果不是,则您不会告诉内核它什么,因此内核不知道使用哪个程序来解释它。这可能是bashperlpythonsh,或别的东西。(实际上,内核通常会使用用户的默认Shell来解释文件,这非常危险,因为它可能根本不是正确的解释器,或者它可能能够解析其中的某些文件,但是行为上却存在细微差别,例如之间的情况下shbash)。

关于的注释 /usr/bin/env

最常见的是,您会看到像这样的哈希爆炸:

#!/bin/bash

结果是内核将运行程序/bin/bash来解释脚本。不幸的是,bash默认情况下并非总是出厂,并且也不总是可用/bin。在Linux机器上通常是这样,但bash在其他位置(例如/usr/xpg/bin/bash或)也有许多其他POSIX机器在发货/usr/local/bin/bash

因此,要编写可移植的bash脚本,我们不能依赖于对bash程序的位置进行硬编码。POSIX已经具有处理该问题的机制:PATH。这个想法是将程序安装在其中一个目录中,PATH并且当您要按名称运行程序时,系统应该能够找到您的程序。

可悲的是,您不能仅仅这样做:

#!bash

内核不会(可能会)PATH为您搜索。不过有一个程序可以PATH为您搜索env。幸运的是,几乎所有系统都在其中env安装了程序/usr/bin。因此,我们开始env使用硬编码的路径,然后进行PATH搜索bash并运行该路径,以便它可以解释您的脚本:

#!/usr/bin/env bash

这种方法有一个缺点:根据POSIX,hashbang可以有一个参数。在这种情况下,我们使用bash用作env程序的参数。这意味着我们没有空间将参数传递给bash。因此,没有办法将类似的东西转换#!/bin/bash -exu为这种方案。你必须把set -exu改用hashbang代替。

这种方法还具有另一个优点:有些系统可能附带/bin/bash,但用户可能不喜欢它,可能发现它有故障或过时,并且可能在bash其他地方安装了自己的。在OS X(Macs)上通常是这种情况,其中Apple交付了过时的产品/bin/bash,用户/usr/local/bin/bash使用Homebrew之类的软件安装了最新版本。当您使用env进行PATH搜索的方法时,您会考虑用户的偏好,并使用他的首选bash而不是系统附带的bash。


66
感谢您抽出宝贵的时间为一个简单的问题写好答案。
PA

5
如果我将其zsh用作外壳,可以使用hashbang #! /usr/bin/env zsh吗?
stefmikhail,2012年

6
@stefmikhail:没关系的shell解释器,你用它来调用脚本,你应该使用#! /usr/bin/env zsh,如果(且仅当)的代码里面的脚本应该通过Z shell执行。
Johnsyweb

1
+1以作解释。我倾向于忘记,但是知道命令的含义将帮助我重新记忆。
Angelin Nadar 2014年

2
@Carpetsmoker这是正确的,并且不仅限于hashbang。bash脚本应始终使用UNIX行结尾,否则每个命令的最后一个参数都将附加一个\ r,就像hashbang命令名称一样。
lhunath 2014年

80

要启动shell脚本'file.sh':

sh file.sh

bash file.sh

另一个选项是使用chmod命令设置可执行权限:

chmod +x file.sh

现在运行.sh文件,如下所示:

./file.sh

15

对于bourne shell:

sh myscript.sh

对于bash:

bash myscript.sh

感谢您回答这个非常明显的问题。对于像我这样的Mac家伙,很容易忘记两圈之间的旧Unix命令。
PA

10

如果您希望脚本在当前shell中运行(例如,希望脚本能够影响您的目录或环境),您应该说:

. /path/to/script.sh

要么

source /path/to/script.sh

请注意,/path/to/script.sh可以是相对的,比如. bin/script.sh运行script.shbin当前目录下的目录。


7
在使用相关路径名进行搜寻或点分时要非常小心。您应该始终以./开头。如果不这样做,并且相对路径名不包含任何斜杠,那么您将在PATH中找到某些内容,然后再在当前目录中添加某些内容!滥用非常危险。
lhunath

0

首先,授予执行权限:
chmod +x script_name

  1. 如果脚本不可执行:-
    用于运行sh脚本文件:-
    sh script_name
    用于运行bash脚本文件:-
    bash script_name
  2. 如果脚本是可执行的:
    ./script_name

注意:-您可以使用'ls -a'检查文件是否可执行。


0

文件扩展名.command被分配给Terminal.app。双击任何.command文件将执行它。


0

一点点添加,从同一文件夹运行解释器,仍然使用#!hashbang脚本中。

举个例子/ usr / bin复制的php7.2可执行文件位于hello脚本的文件夹中。

#!./php7.2
<?php

echo "Hello!"; 

要运行它:

./hello

它们的行为等同于:

./php7.2 hello
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.