我知道,忘掉它,重新学习.是时候写下来了.

推荐答案

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

sh myscript

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

bash myscript

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

/foo/bar
/bin/bar
./bar

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

chmod +x bar
./bar

当一个文件是可执行文件时,kernel负责弄清楚如何执行它.对于非二进制文件,这是通过查看文件的第一行来完成的.它应该包含一个hashbang:

#! /usr/bin/env bash

hashbang告诉内核要运行什么程序(在本例中,命令/usr/bin/env与参数bash一起运行).然后,脚本将被传递给程序(作为第二个参数),以及作为后续参数提供给脚本的所有参数.

这意味着every script that is executable should have a hashbang.如果它没有,你就不会告诉内核它是什么,因此内核不知道用什么程序来解释它.可能是bashperlpythonsh,或者其他什么.(实际上,内核通常会使用用户的默认shell来解释文件,这是非常危险的,因为它可能根本不是正确的解释器,或者它可能能够解析其中一些内容,但存在细微的行为差异,例如shbash之间的情况).

A note on /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可能有one argument个.在本例中,我们使用bash作为env程序的参数.这意味着我们没有空间将参数传递给bash.所以没有办法把#!/bin/bash -exu这样的东西转换成这个方案.你必须在hashbang之后加set -exu.

这种方法还有另一个优点:有些系统可能会附带/bin/bash,但用户可能不喜欢,可能会发现它有缺陷或过时,并且可能已经在其他地方安装了自己的bash.在OS X(Mac电脑)上经常会出现这种情况,苹果推出的是过时的/bin/bash,而用户则使用类似于brew 的东西安装了最新的/usr/local/bin/bash.当您使用env方法进行PATH搜索时,您会考虑用户的偏好,并使用他喜欢的bash,而不是他系统附带的bash.

Linux相关问答推荐

Linux x86_64上PIE ELF可执行文件的.Text段的基本虚拟地址

为什么仅使用&i-i标志时仍会从容器进程中输出

在c++编译期间,什么是linux命令,它给出了链接库的路径?

如何在Linux上获取clang中的模板实例化统计?

将十六进制文件名转换为十进制

如何从大页分配标准数组内存

jinja2.exceptions.TemplateSyntaxError:预期标记,,得到整数(支持十六进制,八进制和二进制整数文字)

如何在Linux下使用正则表达式更改文件名

Perl/cpan: 找不到 JSON/Parse.pm @INC

如何让xargs对 bash 脚本中find命令找到的所有文件执行?

使用 PowerShell 删除重复行所需的时间比 WSL 长得多

使用正则表达式捕获特定字符串

使用 awk 将多行文本转换为 CSV

获取S3路径的linux命令

如何更改某些文件模式/扩展名的权限?

禁用内存地址的随机化

如何从任意 pthread_t 获取线程 ID?

将 CMake 项目导入 Eclipse CDT

Linux命令将一个文件复制到多个文件

学习内核编程