我知道,忘记它,重新学习。是时候写下来了。
- 一路写上行投票列车到声誉站
- 不会为了欣赏你犯下的可怕错误而上票的!
要运行不可执行的sh脚本,请使用:
要运行不可执行的bash脚本,请使用:
要启动可执行文件(这是具有可执行权限的任何文件);只需按其路径指定即可:
1 2 3
| /foo/bar
/bin/bar
./bar |
要使脚本可执行,请授予它必要的权限:
当一个文件是可执行的,内核负责找出如何执行它。对于非二进制文件,这是通过查看文件的第一行来完成的。它应该包含一个hashbang:
hashbang告诉内核运行什么程序(在本例中,命令/usr/bin/env与参数bash一起运行)。然后,将脚本(作为第二个参数)连同您给脚本的所有参数作为后续参数传递给程序。
这意味着每个可执行的脚本都应该有一个hashbang。如果没有,就不能告诉内核它是什么,因此内核不知道用什么程序来解释它。可能是bash、perl、python、sh或其他什么东西。(实际上,内核经常使用用户的默认shell来解释文件,这是非常危险的,因为它可能根本不是正确的解释器,或者它可能能够解析其中的一部分,但具有细微的行为差异,例如sh和bash之间的情况)。
关于
/usr/bin/env的说明
最常见的情况是,您会看到散列刘海,如下所示:
结果是内核将运行程序/bin/bash来解释脚本。不幸的是,bash并不总是默认发货,并且在/bin中并不总是可用。虽然在Linux机器上通常是这样,但也有一系列其他的POSIX机器,其中bash在不同的位置(如/usr/xpg/bin/bash或/usr/local/bin/bash上)发货。
因此,要编写一个可移植的bash脚本,我们不能依赖于对bash程序的位置进行硬编码。posix已经有了一个处理这个问题的机制:PATH。其思想是将程序安装在PATH中的某个目录中,当您想按名称运行程序时,系统应该能够找到该程序。
不幸的是,你不能这样做:
内核不会(有些可能)为您进行PATH搜索。有一个程序可以为你做一个PATH搜索,但它被称为env。幸运的是,几乎所有系统都在/usr/bin中安装了一个env程序。因此,我们使用硬编码路径启动env,然后执行PATH搜索bash并运行它,以便它可以解释您的脚本:
这种方法有一个缺点:根据posix,hashbang可以有一个参数。在这种情况下,我们使用bash作为env程序的参数。这意味着我们没有空间向bash传递参数。所以没有办法把像#!/bin/bash -exu这样的东西转换成这个方案。你必须把set -exu放在hashbang之后。
这种方法还有另一个优点:有些系统可能附带有/bin/bash,但用户可能不喜欢它,可能会发现它有问题或过时,并且可能在其他地方安装了自己的bash。在OSX(macs)上,苹果通常会发布过时的/bin/bash,用户使用类似于自制的东西安装最新的/usr/local/bin/bash。当您使用执行PATH搜索的env方法时,您会考虑到用户的偏好,并使用其首选的bash而不是其系统附带的bash。
- 感谢您花时间为一个简单问题写出一个好答案。
- 如果我使用zsh作为外壳,我会使用hashbang#! /usr/bin/env zsh吗?
- @stefmikhail:使用哪个shell解释器调用脚本并不重要,如果(并且仅当)脚本中的代码应该由z shell执行,则应该使用#! /usr/bin/env zsh。
- +1解释。我倾向于忘记,但知道命令的含义会帮助我回忆起来。
- 一个小小的警告是,当使用DOS(
行结尾)保存文件时,哈希爆炸通常不起作用(无论如何,不在Linux&bsd上)。您需要使用Unix风格的行尾(
)。
- @地毯吸烟者这是正确的,不限于哈斯邦。bash脚本应该始终使用unix行尾,否则每个命令的最后一个参数都会附加一个
,就像hashbang命令名一样。
- @卢纳特,为什么这是个问题?
- @tjt263为什么在每个命令的最后一个参数上附加
是一个问题?因为现在rm foo不会删除foo,所以会删除foo
。任何不是echo的命令都将被破坏。
- 如果你试图运行cron脚本,env可能会咬你。
要启动shell脚本"file.sh",请执行以下操作:
1 2 3
| sh file.sh
bash file.sh |
另一个选项是使用chmod命令设置可执行权限:
现在运行.sh文件,如下所示:
- TNX的人帮我学了一个新命令
- 谢谢,授予可执行权限解决了我的问题:)
对于Bourne Shell:
巴什:
- 谢谢你回答这个显而易见的问题。对于像我这样的Mac用户来说,很容易忘记LAPS之间的旧Unix命令。
如果希望脚本在当前shell中运行(例如希望它能够影响目录或环境),则应该说:
或
1
| source /path/to/script.sh |
注意,/path/to/script.sh可以是相对的,例如. bin/script.sh在当前目录下的bin目录中运行script.sh。
- 在寻找或使用相关路径名时要非常小心。您应该总是以./开头。如果不这样做,并且相对路径名不包含任何斜线,那么您将在当前目录中的某个内容之前在路径中查找某个内容!虐待非常危险。
"文件扩展.command terminal.app分配两个冰淇淋。双clicking在任何.command will execute文件信息。
第一,提供给执行权限: chmod +x script_name
如果冰槽executable脚本: SH为运行脚本文件: sh script_name 行走的bash脚本文件: bash script_name
如果冰executable脚本: ./script_name
注意:如果你可以检查文件executable冰或不使用的是城市A’