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 网站也提供了基于此程序的相同功能。

更多信息 (英语)

教程

社区

例子