如何在 Unix 控制台或 Mac 终端上运行 shell 脚本?
Posted
技术标签:
【中文标题】如何在 Unix 控制台或 Mac 终端上运行 shell 脚本?【英文标题】:How to run a shell script on a Unix console or Mac terminal? 【发布时间】:2010-10-18 13:01:50 【问题描述】:我知道它,忘记它并重新学习它。是时候把它写下来了。
【问题讨论】:
【参考方案1】:启动shell脚本'file.sh':
sh file.sh
bash file.sh
另一个选项是使用 chmod 命令设置可执行权限:
chmod +x file.sh
现在运行 .sh 文件如下:
./file.sh
【讨论】:
【参考方案2】:对于 bourne shell:
sh myscript.sh
对于 bash:
bash myscript.sh
【讨论】:
感谢您回答这个非常明显的问题。对于像我这样的 Mac 用户来说,很容易在两圈之间忘记旧的 Unix 命令。【参考方案3】:要运行不可执行的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
运行)。然后,脚本与您为脚本提供的所有参数一起作为后续参数传递给程序(作为第二个参数)。
这意味着每个可执行的脚本都应该有一个井号。如果没有,您就没有告诉内核它是什么,因此内核不知道使用什么程序来解释它。可能是bash
、perl
、python
、sh
或其他。 (实际上,内核通常会使用用户的默认 shell 来解释文件,这是非常危险的,因为它可能根本不是正确的解释器,或者它可能能够解析其中的一些但存在细微的行为差异,例如sh
和 bash
之间的情况。
关于/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解释器来调用脚本并不重要,你应该使用#! /usr/bin/env zsh
如果(且仅当)代码里面脚本应该由Z shell执行。
+1 用于解释。我容易忘记,但知道命令的含义会帮助我回忆。
@Carpetsmoker 这是正确的,不仅限于 hashbang。 bash 脚本应始终使用 UNIX 行结尾,否则每个命令的最后一个参数都会附加一个 \r,就像 hashbang 命令名称一样。【参考方案4】:
如果您希望脚本在当前 shell 中运行(例如,您希望它能够影响您的目录或环境),您应该说:
. /path/to/script.sh
或
source /path/to/script.sh
注意/path/to/script.sh
可以是相对的,例如. bin/script.sh
运行当前目录下bin
目录下的script.sh
。
【讨论】:
在使用相关路径名进行采购或点缀时要非常小心。您应该始终以 ./ 开头,如果您不这样做,并且相对路径名不包含任何斜杠,那么您将在 PATH 中获取某些内容,然后在当前目录中获取某些内容!滥用非常危险。【参考方案5】:首先给执行权限:-chmod +x script_name
-
如果脚本不可执行:-
用于运行 sh 脚本文件:-
sh script_name
用于运行 bash 脚本文件:-bash script_name
如果脚本是可执行的:-./script_name
注意:-您可以使用'ls -a'检查文件是否可执行
【讨论】:
【参考方案6】:文件扩展名 .command 分配给 Terminal.app。双击任何 .command 文件都会执行它。
【讨论】:
【参考方案7】:一点补充,从同一文件夹运行解释器,仍然在脚本中使用 #!hashbang。
作为示例,从 /usr/bin 复制的 php7.2 可执行文件位于 hello 脚本的文件夹中。
#!./php7.2
<?php
echo "Hello!";
运行它:
./hello
其行为等同于:
./php7.2 hello
具有良好文档的适当解决方案可以是工具linuxdeploy 和/或appimage,这是在后台使用此方法。
【讨论】:
以上是关于如何在 Unix 控制台或 Mac 终端上运行 shell 脚本?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Unix 控制台/Mac 终端中编译和运行 C/C++?
如何在 Mac 上恢复 .bash_profile?我的unix终端都没有工作[关闭]