Bash shell的新手入门教程

308 阅读9分钟

Bash是(从今天起)你将接触到的大多数系统上事实上shell。Linux、macOS,以及Windows 10上的WSL。

有一些历史原因使Bash成为世界上最受欢迎的shell。早在1989年,当它首次发布时,技术世界是非常不同的。当时,UNIX世界中的大多数软件都是闭源的。Unix本身也是专有和封闭的。

要使用一个UNIX系统,你必须使用一个shell。

当时最流行的shell是闭源和专有的,你必须付钱才能使用它。它是Bourne shell,在/bin/sh 命令下可用。它被称为 "Bourne "是因为它的创造者是Steve Bourne。

在那些年里,Richard Stallman与GNU项目(以及后来的Linux)一起,即将彻底改变一切,开始了开源革命。GNU项目需要一个外壳,在自由软件基金会的帮助下,Bash诞生了。Bash在很大程度上受到Bourne Shell的启发,它的意思是Bourne-again shell,它是GNU项目的一个关键要素,也可能是它最成功的软件之一,我们今天仍然在使用。

Bash可以运行所有为sh 编写的脚本,这是它被采用的一个强制性特征,而且从早期开始,它还引入了许多其他特征,为用户提供了更好的体验。从早期开始,Bash获得了很多改进。本教程描述了你可以用它做的最流行和最有用的事情。

Bash的第一个步骤

由于Bash是许多系统中的默认shell,你只需要启动一个bash shell即可

  • 登录到系统中,如果它是一个服务器的话
  • 打开你的终端,如果是你的电脑的话

请看我的macOS终端指南,了解更多关于在Mac上使用终端的信息。

一旦你启动它,你应该看到一个提示(通常以$ 结尾)。

你怎么知道shell正在运行bash?试着输入help ,然后按回车键。

看到了吗?我们刚刚告诉Bash去执行help 命令。这个命令反过来会显示你正在运行的Bash的版本和你可以使用的命令列表。

警告:看到我这里的版本了吗?它是3.2.57。这是macOS中默认的Bash版本,由于许可问题,它不包括更高的版本。这个Bash版本是2014年的。使用Homebrew安装最新的Bash 5.x,输入brew install bash

更多的时候,你不会使用bash帮助中列出的任何命令,除非你正在创建shell脚本或高级的东西。

99%的日常shell使用是浏览文件夹和执行程序,如ls,cd 和其他公共UNIX工具。

浏览文件系统

要在文件系统中导航,你将使用ls 命令。它在/bin/ls 中可用,由于Bash在其路径列表中有/bin 文件夹,你可以直接输入ls 来使用它。

ls 列出当前文件夹中的文件。你通常从你的主文件夹开始,这取决于系统,但在macOS上是在 。我的主文件夹是在 。这与Bash无关,它更像是UNIX文件系统的东西,但参数是重叠的,如果你从来没有使用过shell,知道这一点很好。/Users /Users/flavio

要导航到其他文件夹,你可以使用cd 命令,后面跟上你要移动的文件夹的名字。

cd .. 就会回到父文件夹。

根据你的Bash配置,你会看到你当前的文件夹显示在提示($ 符号)之前。也可能没有,但你可以通过输入pwd ,然后按回车键来知道你在哪里。

pwd工作 目录路径名

命令行编辑

当你在shell中编写命令时,注意你可以用方向键左右移动。这是一个shell功能。你可以在你的命令周围移动,按退格键和纠正命令。按enter 键告诉shell去,让系统执行命令。

这是正常的、被接受的行为,但可能让早期的UNIX用户 "惊叹 "的东西。

键盘组合可以让你快速编辑,而不需要伸手去按方向键。

  • ctrl+d 删除当前选定的字符
  • ctrl+f 转到右边的字符
  • ctrl+b 转到左边的字符

自动补全

在文件系统中移动时,Bash的一个很好的功能是自动完成。试着输入cd Doc ,并按下tab ,使Bash自动完成cd Documents 。如果这些第一个字符有多个选择,Bash将返回你的列表,所以你可以再输入几个字符来帮助它消除歧义,并再次按下tab ,完成。

shell可以自动完成文件名,但也可以自动完成命令名。

外壳命令

使用shell,我们可以运行系统中可用的命令。我们可以在命令前加上完整的路径(例如,/bin/ls 来列出一个文件夹中的文件),但是shell有路径的概念,所以我们可以直接输入ls ,它就知道大多数命令在哪里可以找到(我们可以通过配置将文件夹添加到这个路径中)。

命令接受参数。例如,ls /bin 将列出/bin 文件夹中的所有文件。

参数的前缀是破折号- ,如ls -a ,它告诉ls ,也显示隐藏的文件。按照惯例,隐藏文件是以点开头的文件(和文件夹)(.)。

常见的shell命令

在任何系统上都有很多预装的命令,它们的差异很大,这取决于你所运行的是Linux/macOS还是Linux发行版。

然而,让我们对你可以运行的最常见的shell命令做一个简要的总结。这些不是由shell本身提供的,而是你可以通过shell调用的命令行命令。

当你遇到问题时,比如你不知道某个命令是做什么的,或者你不知道如何使用它,请使用man 。它可以让你得到我将列出的所有命令的帮助,还有更多。例如,运行man ls

这些是文件系统的命令。

  • ls 列出文件
  • cd 改变文件夹
  • rm 删除一个文件或文件夹
  • mv 将一个文件移到另一个文件夹,或改变一个文件名
  • cp 复制一个文件
  • pwd 显示当前工作目录
  • mkdir 创建一个文件夹

Unix文件系统中的每个文件都有权限。chmod ,允许你改变这些权限(现在不说了),chown ,允许你改变文件所有者

cat,tailgrep 是处理文件的两个超级有用的命令。

pico,nano,vimemacs 是通常安装的编辑器。

whereis 在macOS上,显示了一个命令在系统中的位置。

当然,还有更多的命令,但这些是你可能更经常碰到的几个。

执行命令

ls 和 是命令,正如我提到的,它们在 文件夹中找到。你可以执行任何文件,只要它是一个可执行文件,只要输入它的完整路径,例如 。命令不需要在 文件夹中,你可以使用 路径指示器来运行在你当前文件夹中的可执行文件。cd /bin /bin/pwd /bin ./

例如,如果你在你的/Users/flavio/scripts 文件夹里有一个runme 文件,你可以运行

然后再运行./runme 来运行它。

或者你可以从Bash运行/Users/flavio/scripts/runme ,无论你的当前文件夹在哪里。

工作

每当你运行一个命令时,如果它是一个长期运行的程序,你的shell将完全被该命令所占有。你可以使用ctrl-C 删除该命令。

在任何时候,你都可以运行jobs 来查看你正在运行的作业,以及它们的状态。

$ jobs
Job	Group	State	Command
1	72292	stopped	ftp

另一个有用的命令是ps ,它列出了运行中的进程。

$ ps
  PID TTY           TIME CMD
19808 ttys000    0:00.56 /usr/local/bin/fish -l
65183 ttys001    0:04.34 -fish
72292 ttys001    0:00.01 ftp

top 它显示了进程和它们在你的系统上所消耗的资源。

一个工作或进程可以用kill <PID>

命令历史

up 箭头键将显示你所输入的命令的历史。同样,这是一个shell的功能。按down 方向键可以让你在时间上来回浏览,看看你之前输入了什么命令,按enter 可以让你再次运行该命令。

这是对命令历史的快速访问。运行history 命令将显示在shell中输入的所有命令。

当你开始输入一条命令时, Bash可以通过参考历史上以前输入的命令来自动完成它。按esc ,然后再按tab ,试试吧。

说实话,我觉得Fish shell实现这个功能要好得多,也更容易。

设置你的默认shell

除了Bash之外,还有很多其他的shell。你有Fish, ZSH, TCSH, 和其他一些。系统中的任何用户都可以选择自己的shell。

你可以通过运行chsh -s chsh -s /bin/bash 命令来设置你的默认登录shell。你几乎不需要这样做, 除非它以前被改变过, 比如说用Fish:

chsh -s /usr/local/bin/fish

定制Bash

我曾指出,你可能(也可能不)在Bash提示符中看到你的当前工作目录。这是在哪里决定的?在Bash的配置中!

这里有一点混乱,因为Bash在不同的情况下使用不同的配置文件,而且它还会读取多个配置文件。

让我们给这个混乱的局面一些秩序。首先,Bash是否被初始化为login shell有很大区别。我们所说的login shell是指系统没有运行GUI(图形用户界面),你通过shell登录到系统中。例如,服务器就是这种情况。

在这种情况下,Bash加载这个配置文件。

/etc/profile

然后在用户的主文件夹中寻找这些文件,按照顺序,执行它找到的第一个文件。

~/.bash_profile
~/.bash_login
~/.profile

were~ 表示你的主文件夹(它由Bash自动翻译)

这意味着如果有一个.bash_profile~/.bash_login~/.profile 永远不会被运行,除非在.bash_profile 中明确执行。

如果Bash不是一个登录的shell,而是像我在macOS中那样运行,例如,作为一个普通的应用程序,那么配置文件就会改变。Bash首先加载/etc/bash.bashrc ,然后是~/.bashrc

环境变量

有时你的程序会使用环境变量。那些是你可以在程序之外设置的值,并改变程序本身的执行。例如,一个API密钥。或者一个文件的名称。

你可以使用以下语法来设置环境变量

VARIABLE_NAME=variable_value

该值可以包含空白,通过使用引号

VARIABLE_NAME="variable value"

bash脚本可以使用这个值,在前面加上一个美元符号:$VARIABLE_NAME

此外,其他编程语言的命令也可以使用环境变量,例如这里是如何用Node.js读取环境变量的。

系统为你设置了一些环境变量,例如

  • $HOME 你的主文件夹
  • $LOGNAME 你的用户名
  • $SHELL 你的默认shell的路径
  • $PATH shell寻找命令的路径

你可以通过在它们前面加上echo 来检查它们的值。

echo $LOGNAME # flavio
echo $HOME # /Users/flavio

一个特殊的环境变量:$PATH

我提到了$PATH这个变量。这是一个文件夹列表,当你输入一个命令时,shell会在其中查找。文件夹之间用冒号: ,它们是按顺序写的--Bash会进入第一个文件夹,搜索你要的命令,如果找到了就运行它。否则就会进入下一个文件夹,以此类推。

我目前的路径是。

bash-5.0$ echo $PATH
/usr/local/bin:/usr/bin: /bin:/usr/sbin: /sbin:/usr/local/go/bin

你通常会在~/.bashrc 文件中通过预加或追加项目来编辑它。

PATH = "$PATH:/Users/flavio/bin"

别名

使用别名,我们可以为常用命令设置快捷方式。例如,你可以给一个复杂的参数组合起一个快速的名字。

你可以使用以下语法来定义别名

如果命令中有空格,则使用引号。

alias <alias>="<command>"

我经常添加到我的系统中的一个别名是ll

你通常在你的~/.bashrc 文件中定义别名。

如果你的命令中有变量,请小心使用引号:使用双引号,变量在定义时被解决,使用单引号,则在调用时解决。这两个是不同的。

alias lsthis="ls $PWD"
alias lscurrent='ls $PWD'

$PWD指的是当前shell所处的文件夹。如果你现在浏览到一个新的文件夹,lscurrent 列出新文件夹中的文件,lsthis 仍然列出你定义别名时所在的文件夹中的文件。

高级命令行功能

通配符

ls 和许多其他的命令可以很好地利用通配符。你可以列出所有以image开头的文件。

或所有以image结尾的文件。

或名称中含有image的所有文件。

重定向输出和标准错误错误

默认情况下,在shell中启动的命令会把输出和错误都打印到shell中。这可能不是你想要的。你可以决定把输出写到一个文件中。

实际上,是写到一个/不同的文件/,因为在Unix中,甚至屏幕也被认为是一个文件。特别是。

  • 0 识别标准输入
  • 1 识别标准输出
  • 2 识别标准错误

你可以将标准输出重定向到一个文件,方法是在一个命令后面加上1> ,然后再加上一个文件名。

使用同样的技术,你可以使用2> 来重定向标准错误。

有一个快捷键> ,用来表示1> ,因为这个词用得比较多。

例子。

ls 1> list.txt 2> error.txt
ls > list.txt 2> error.txt

另一个快捷方式,&> ,将/both/标准输出和标准错误重定向到一个文件。

另一个经常使用的是使用2>&1 ,将标准错误重定向到标准输出。

在后台运行一个命令

你可以告诉Bash在后台运行一个程序,而不对shell进行控制,方法是在它后面加上&

top 是一个列出正在运行的进程的命令,按照最耗费资源的顺序排列。

通常会控制shell的程序现在被启动了,但似乎什么也没有发生。你可以通过输入fg (又称前台)使它重新成为焦点,但现在我们进入了进程和工作的领域,这本身就是一个很大的话题,但还是要快速浏览一下。

当一个命令正在运行时,你可以使用ctrl-Z 来暂停它,把它带到后台。shell又回到了前台,你现在可以运行bg ,以移动恢复执行之前暂停的工作。

当你准备回去的时候,运行fg ,将该程序带回前台。

你可以使用ps ,看到所有正在运行的进程,列表中显示所有的进程pid 号。使用暂停的进程pid ,你可以把一个特定的命令带到前台,例如fg 72292 。对bg 也是如此。

排列命令

你可以指示Bash在另一个命令结束后立即运行一个命令,方法是用分号把它们分开。

你可以重复这个动作来排查同一行中的多个命令.

输出重定向

一个程序可以使用< 操作符从任何文件接收输入,并使用> 操作符将输出保存到一个文件中。

echo hello > result.txt
wc < result.txt

wc 是一个将其收到的字数作为输入进行计数的命令。

管子

使用管道,任何命令的输出都可以作为第二个命令的输入。使用| 操作符将两者结合起来。在这个例子中,wcecho hello 的输出中获得输入。

分组命令

使用&& ,用 "和 "来组合两个命令。如果第一个命令的执行没有问题,就运行第二个,以此类推。

使用|| ,用 "或 "来组合两个命令。如果第一条命令的执行没有问题,第二条就不运行。

! 否定了下一个逻辑操作。

$ echo hello && echo test
hello
test
$ echo hello || echo test
hello
$ ! echo hello || echo test
hello
test

你可以使用括号来组合表达式以避免混淆,也可以改变优先级。

$ ! (echo hello) || (echo test)
hello
test
$ ! (echo hello || echo test)
hello

壳的编程

像Bash这样的shell的最大特点之一是它能够用它来创建程序,基本上是通过自动执行命令来实现的。

我将很快写一个关于Bash脚本的单独指南,它将与本教程分开,因为这个主题确实比我想在这个Bash入门指南中添加的内容更深入。

简单介绍一下:脚本是一个文本文件,以一行开始,表明它是一个shell脚本(以及它需要什么shell),然后是一个命令列表,每行一个。例子。

你可以把这个文件保存为myscript ,然后用chmod +x myscript ,使其可以执行,用./myscript./ ,意思是 "当前文件夹")运行它。

Shell脚本不在这篇文章的范围内,但我想让你知道这一点。脚本可以有控制结构和许多其他很酷的东西。

这种脚本策略同样适用于其他shell,比如Zsh。