ChatGPT解决这个技术问题 Extra ChatGPT

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

我知道它,忘记它并重新学习它。是时候把它写下来了。


l
lhunath

要运行不可执行的 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 机器上通常是这样,但还有一系列其他 POSIX 机器,其中 bash 在不同的位置提供,例如 /usr/xpg/bin/bash/usr/local/bin/bash

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

可悲的是,你不能这样做:

#!bash

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

#!/usr/bin/env bash

这种方法有一个缺点:根据 POSIX,hashbang 可以有一个参数。在这种情况下,我们使用 bash 作为 env 程序的参数。这意味着我们没有空间将参数传递给 bash。所以没有办法将像 #!/bin/bash -exu 这样的东西转换成这个方案。您必须将 set -exu 放在 hashbang 之后。

这种方法还有另一个优点:某些系统可能附带 /bin/bash,但用户可能不喜欢它,可能会发现它有问题或过时,并且可能在其他地方安装了自己的 bash。在 OS X (Mac) 上经常出现这种情况,其中 Apple 发布了过时的 /bin/bash,而用户使用 Homebrew 之类的工具安装了最新的 /usr/local/bin/bash。当您使用执行 PATH 搜索的 env 方法时,您会考虑用户的偏好,并使用他的首选 bash 而不是他的系统附带的那个。


感谢您花时间为一个简单的问题写一个好的答案。
如果我使用 zsh 作为我的 shell,我会使用 hashbang #! /usr/bin/env zsh 吗?
@stefmikhail:您使用哪个 shell 解释器 invoke 脚本并不重要,如果(且仅当)代码 inside 脚本应该使用 #! /usr/bin/env zsh由 Z shell 执行。
+1解释。我倾向于忘记,但知道命令的含义将帮助我回忆。
@Carpetsmoker 这是正确的,不仅限于hashbang。 bash 脚本应始终使用 UNIX 行结尾,否则每个命令的最后一个参数都将附加一个 \r,就像 hashbang 命令名称一样。
C
Can Berk Güder

要启动 shell 脚本“file.sh”:

sh file.sh

bash file.sh

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

chmod +x file.sh

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

./file.sh

佚名

对于伯恩壳:

sh myscript.sh

对于 bash:

bash myscript.sh

感谢您回答这个非常明显的问题。对于像我这样的 Mac 用户来说,很容易在两圈之间忘记旧的 Unix 命令。
C
Chas. Owens

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

. /path/to/script.sh

或者

source /path/to/script.sh

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


在使用相关路径名进行采购或点缀时要非常小心。您应该始终以 ./ 开头,如果您不这样做,并且相对路径名不包含任何斜杠,那么您将在 PATH 中获取某些内容,然后在当前目录中获取某些内容!滥用非常危险。
V
Vineet Jain

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

如果脚本不可执行:- 运行 sh 脚本文件:- sh script_name 运行 bash 脚本文件:- bash script_name 如果脚本可执行:- ./script_name

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


b
benwiggy

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


N
NVRM

另外一点,要从同一个文件夹运行解释器,仍然在脚本中使用 #!hashbang。

例如,从 /usr/bin 复制的 php7.2 可执行文件位于 hello 脚本的文件夹中。

#!./php7.2
<?php

echo "Hello!"; 

要运行它:

./hello

其行为与以下内容相同:

./php7.2 hello

具有良好文档的适当解决方案可以是工具 linuxdeploy 和/或 appimage,这是在后台使用此方法。