Bash (简体中文)

From ArchWiki
翻译状态:本文是 Bash翻译。上次翻译日期:2021-06-24。如果英文版本有所更改,则您可以帮助同步翻译。

Bash (Bourne-again Shell) 是一个来自 GNU命令行解释器/编程语言。它的名字是向它的前身——很早以前的 Bourne shell 致敬。Bash可以运行在大部分类 UNIX 操作系统中,包括 GNU/Linux。

Bash是Arch Linux的默认命令行解释器。

调用

Bash 的运行方式会取决于 Bash 被调用的方式。下面是一些不同模式的描述。

如果 Bash 以TTY中的loginSSH 守护进程、或者其它类似的方式派生出来,我们称之为登录 (login) shell。你可以使用命令行选项 -l--login 来使用这种模式。

如果 Bash 的标准输入输出和标准错误输出都连接到终端(比如说,一个终端模拟器),并且在启动的时候既没有使用 -c 选项和非选项参数(比如说,bash script),我们称之为交互 (interactive) shell。所有的交互式 shell 都会执行/etc/bash.bashrc~/.bashrc 文件中的配置,而登录shell还会执行/etc/profile~/.bash_profile 中的配置。

注意: 在 Arch Linux 中 /bin/sh (过去是 Bourne shell 的执行文件名) 是 /bin/bash 的符号链接。如果 Bash 通过 sh 方式调用,它会尽量模拟历史上 sh 的启动行为,包括 POSIX 兼容能力。

通过在Bash启动时使用 --posix 命令行参数或者在启动后执行 ‘set -o posix’ 来使Bash在增强的POSIX标准下运行。

配置文件

Bash会在启动时按照不同的启动方式执行一系列启动文件。关于更详尽的描述,您可以参考GNU Bash 指南中/usr/share/doc/bash/bashref.html (Bash启动文件)这一节。

文件 描述 登录 shell

(见下)

交互 shell

非登录

/etc/profile 加载全部储存在 /etc/profile.d/*.sh/etc/bash.bashrc 中的配置。
~/.bash_profile 针对每个用户,紧接 /etc/profile 执行。如果这个文件不存在,会顺序检查 ~/.bash_login~/.profile 文件。框架文件 /etc/skel/.bash_profile 同时会引用 ~/.bashrc
~/.bash_logout 针对每个用户,退出登录 shell 后。
/etc/bash.bash_logout 取决于 -DSYS_BASH_LOGOUT="/etc/bash.bash_logout" 编译标记。退出登录 shell 后。
/etc/bash.bashrc 取决于编译标志 -DSYS_BASHRC="/etc/bash.bashrc"。加载 /usr/share/bash-completion/bash_completion 配置。
~/.bashrc 针对每个用户,在 /etc/bash.bashrc 后加载。
注意:

Shell 与环境变量

Bash的行为和通过它启动的程序会被许多环境变量影响。环境变量用于储存有用的值,比如命令搜索路径,或者默认浏览器。当一个新的 shell 或者脚本被启动时,这个 shell 会继承它的父进程的环境变量,从而这个 shell 会带有内部 shell 变量[1]

这些内部 shell 变量可以以此导出以变成环境变量:

VARIABLE=content
export VARIABLE

或者

export VARIABLE=content

环境变量依照惯例放置在~/.profile或者/etc/profile中,这样其他兼容 Bourne shell 的 shell 也可以使用。

关于更详尽的内容,您可以参考Environment variables (简体中文)

命令行

Bash 的命令行由一个叫做 Readline 的分离库来管理。Readline 提供了emacsvi 风格的快捷键用于操作命令行,比如说,以单词为基准前后移动、删除等。管理输入历史也是 Readline 的职责。它还允许你创造

Tab 键补全

Tab 键补全,提供在按下 tab 键后自动补全命令的功能(这个功能默认启用)。

Tab 按下的次数

可能最多需要按三次 tab 才能显示所有的补全选项。如果希望减少这个数值,请参考 更快的补全操作

常用命令的选项补全

通常来讲,Bash 中按下 tab 只会补全命令、文件名和变量。安装 bash-completion 包,并加载 /usr/share/bash-completion/bash_completion 文件中的配置(这个文件应该已经在Arch的/etc/bash.bashrc中加载了),可以提供更多针对常见命令的选项的 tab 补全。安装这个包后,常规的补全(比如说 $ ls file.*<tab><tab>)可能会表现得不同。但是,您可以通过{ic|$ compopt -o bashdefault program}}命令来重新启用。(更多细节,请参考 [2] and [3]。)

自定义命令补全

注意: 使用 complete 功能可能与 bash-completion 冲突。

通常来讲,Bash 中按下 tab 只会补全命令后的文件名。通过complete -c命令,Bash 可以规定某些命令后的补全形式为命令,比如:

~/.bashrc
complete -c man which

或通过-cf命令,规定补全形式为命令和文件,比如:

complete -cf sudo

更多补全形式,请参考Bash的手册页。

历史

历史补全

您可以绑定上下键来在 Bash 的历史中查找(请参考 Readline (简体中文)#历史 and Readline 启动文件语法):

~/.bashrc
 bind '"\e[A": history-search-backward'
 bind '"\e[B": history-search-forward'

或者所有 Readline 程序:

~/.inputrc
"\e[A": history-search-backward
"\e[B": history-search-forward

更近的历史记录

HISTCONTROL变量可以避免历史记录记录特定的命令,比如不记录重复的命令

~/.bashrc
export HISTCONTROL=ignoredups

将其设置为 erasedups 可以让 Bash 的历史记录对一条命令只保留一个历史记录(与顺序无关)。更多选项,请参考Bash的手册页。

禁用历史记录

临时禁用历史记录:

$ set +o history

现在输入的命令将不会存入$HISTFILE

比如说,你现在可以执行 printf secret | sha256sum 来生成密码文件的散列值,或是隐藏您使用GPG的历史,如执行gpg -eaF secret-pubkey.asc命令。这些秘密不会被写入磁盘。

开启历史记录:

$ set -o history
提示: 如果 HISTCONTROL 变量包含了 ignorespace,以空格开头的命令将不会记入历史。这样可以更加方便地控制历史记录。更多细节,请参考bash(1) § Shell Variables

禁用所有的 Bash 历史:

~/.bashrc or /etc/profile
export HISTSIZE=0

为了保险(这会永远清除所有的历史记录):

$ wipe -i -l2 -x4 -p4 "$HISTFILE"
$ ln -sv /dev/null "$HISTFILE"

模仿 Zsh 的帮助功能

Zsh 可以在光标指向命令的时候按 Alt+h 来调用这个命令的手册。 相同的行为可以通过这个 Readline (简体中文) 绑定在 Bash 中开启:

~/.bashrc
run-help() { help "$READLINE_LINE" 2>/dev/null || man "$READLINE_LINE"; }
bind -m vi-insert -x '"\eh": run-help'
bind -m emacs -x     '"\eh": run-help'

这个操作假设你使用(默认的)Emacs 编辑模式

别名

别名(alias)是可以让您用另一个字符串来替换一个字符串的命令。这个命令常常被用来缩短系统命令,或者用来将默认参数加入到常用命令中。

推荐将针对用户的别名保存在~/.bashrc, 而将系统级的别名(这些会影响所有用户)存放在/etc/bash.bashrc。别名的示例,请参考 [4]

关于函数,请参考 函数

提示与技巧

自定义提示符

参见 自定义提示符

找不到命令

pkgfile 提供了一个"找不到命令"的钩子,可以在输入未知命令后自动查找官方的软件包。

你需要加载这个钩子来启用它,如下:

~/.bashrc
source /usr/share/doc/pkgfile/command-not-found.bash

现在,运行一个不可用的命令将会显示如下信息:

$ abiword
abiword may be found in the following packages:
  extra/abiword 3.0.1-2	/usr/bin/abiword
注意: 需要先更新 pkgfile 的数据库才能运作。更多细节,请参考pkgfile (简体中文)#安装

另一个"找不到命令"的钩子由 command-not-foundAUR 包提供,它看起来像这个样子:

$ abiword
The command 'abiword' is provided by the following packages:
abiword (2.8.6-7) from extra
	[ abiword ]
abiword (2.8.6-7) from staging
	[ abiword ]
abiword (2.8.6-7) from testing
	[ abiword ]

在终端内禁用Ctrl+Z

你可以相这样包装你的命令,来关闭 Ctrl+Z 功能(暂停/关闭程序)。通过在这个脚本中包装命令

#!/bin/bash
trap "" 20
adom

这时如果你在玩 adomAUR 要按 Shift+Z 组合键时不小心按下了 Ctrl+Z 组合键,你的游戏就不会停止运行了,因为我们已经禁用了Ctrl+Z

登出后清空屏幕

当登出虚拟终端时,清空屏幕:

~/.bash_logout
clear
reset

输入路径自动添加"cd"

Bash 可以自动在输入的一个路径前添加 cd 。比如说:

$ /etc
bash: /etc: Is a directory

但是如果在 .bashrc 文件里添加一行:

~/.bashrc
...
shopt -s autocd
...

你会得到:

[user@host ~]$ /etc
cd /etc
[user@host etc]$

自动跳转

autojump-gitAUR 允许在用户访问最多的路径中搜索文件系统。

安装完后,加载 /etc/profile.d/autojump.bash 来启动这项功能。

防止覆盖文件

在当前的会话中,防止 shell 输出重定向覆盖一个已有的文件:

$ set -o noclobber

这和set -C命令是一样的。

如果想让该用户一直生效:

~/.bashrc
...
set -o noclobber

在设定 noclobber 的情况下强制覆盖文件:

$ echo "output" >| file.txt

错误排除

修正窗口大小调整时的换行

如果您调整了终端模拟器的大小,Bash 可能并没有得到大小重调的信号,你键入的文本就不会正确的换行,并且与已输入内容重叠。启用 checkwinsize 选项可以在每一个命令后检查窗口的大小,并按需更新 LINESCOLUMNS 的值来调整。

~/.bashrc
shopt -s checkwinsize

设置 ignoreeof 后 shell 仍然退出

如果您设置了 ignoreeof 选项,但是如果重复按下 ctrl-D shell 仍然会退出。因为这个选项只允许忽略 10 次连续的EOF记号(即 Ctrl+D)。

如果需要将这个次数调的更高,需要使用 IGNOREEOF 变量。

比如:

export IGNOREEOF=100

分析代码以检查错误

shellcheck 可以分析bash脚本(以及其他脚本),显示可能存在的问题,并对优化代码质量提出意见。

shellcheck.net 网站也提供了基于此程序的相同功能。

更多信息 (英语)

教程

社区

例子