跳转至内容

Bash

来自 ArchWiki

Bash (Bourne-Again SHell) 是 命令行 Shell/编程语言,由 GNU Project 开发。它的名字暗指其前身,已长期弃用的 Bourne shell。Bash 可以在大多数 类 Unix 操作系统上运行,包括 GNU/Linux

BashArch Linux 上的默认命令行 Shell。

调用

Bash 的行为可以根据其调用方式进行更改。下面是一些不同模式的描述。

如果 Bash 是由 login 在 TTY 中启动,或者由 SSH 守护进程或类似方式启动,它就被认为是 **login shell**。此模式也可以通过 -l/--login 命令行选项启用。

当 Bash 的标准输入、输出和错误连接到终端(例如,在终端模拟器中运行时),并且没有使用 -c 选项或 非选项参数(例如,bash script)启动时,它就被认为是 **interactive shell**。所有交互式 Shell 都会 source /etc/bash.bashrc~/.bashrc,而交互式 *login* shell 还会 source /etc/profile~/.bash_profile

注意 在 Arch 中,/bin/sh(以前是 Bourne shell 可执行文件)被符号链接到 bash。如果 Bash 以 sh 名称调用,它会尝试模仿旧版 sh 的启动行为,包括 POSIX 兼容性。

配置文件

Bash 会尝试根据其调用方式执行一组启动文件。有关完整描述,请参阅 GNU Bash 手册的 Bash Startup Files 部分。

文件 描述 Login shells (见注释) 交互式,*非login* shells
/etc/profile /etc/profile.d/*.sh/etc/bash.bashrc 中的应用程序设置。
~/.bash_profile 用户级别,在 /etc/profile 之后。如果此文件不存在,则按顺序检查 ~/.bash_login~/.profile。骨架文件 /etc/skel/.bash_profile 也会 source ~/.bashrc
~/.bash_logout 用户级别,在 login shell 退出后。
/etc/bash.bash_logout 取决于 -DSYS_BASH_LOGOUT="/etc/bash.bash_logout" 编译标志。在 login shell 退出后。
/etc/bash.bashrc 取决于 -DSYS_BASHRC="/etc/bash.bashrc" 编译标志。Source /usr/share/bash-completion/bash_completion
~/.bashrc 用户级别,在 /etc/bash.bashrc 之后。

Shell 和环境变量

Bash 的行为以及由它运行的程序可以受到许多环境变量的影响。 环境变量用于存储有用的值,例如命令搜索目录或要使用的浏览器。当启动新的 Shell 或脚本时,它会继承其父变量,从而以一组内部 Shell 变量开始[1]

这些 Bash 中的 Shell 变量可以被导出,以成为环境变量

VARIABLE=content
export VARIABLE

或使用快捷方式

export VARIABLE=content

环境变量通常放在 ~/.profile/etc/profile 中,以便其他 Bourne 兼容的 Shell 可以使用它们。

有关更一般的信息,请参阅 环境变量

命令行

Bash 命令行由名为 Readline 的独立库管理。Readline 提供 emacsvi 风格的快捷方式来与命令行交互,例如按单词为单位前后移动、删除单词等。管理输入命令的 历史记录也是 Readline 的职责。最后但同样重要的是,它允许您创建

Tab 自动补全

Tab 自动补全是通过按 Tab 键自动完成输入的命令的选项(默认启用)。

单次 Tab

可能需要按三次 Tab 键才能显示命令的所有可能补全。要减少所需的 Tab 键次数,请参阅 Readline#Faster completion

常用程序和选项

默认情况下,Bash 只会自动补全命令、文件名和变量。 bash-completion 包通过添加对常用命令及其选项更专业的 Tab 自动补全来扩展此功能,可以通过 source /usr/share/bash-completion/bash_completion 来启用(这在 Arch 的 /etc/bash.bashrc 中已经 source)。使用 bash-completion 后,普通补全(例如 ls file.* Tab Tab)的行为会不同;但是,可以使用 compopt -o bashdefault program 重新启用它们(有关更多详细信息,请参阅 [2][3])。

自定义每条命令

注意 使用 complete 内建命令可能会与 bash-completion 产生冲突。

默认情况下,Bash 只会自动补全命令后面的文件名。您可以使用 complete -c 将其更改为补全命令名

~/.bashrc
complete -c man which

或使用 -cf 补全命令名和文件名

complete -cf sudo

有关更多补全选项,请参阅 bash(1) § Programmable Completion

历史

历史记录补全

您可以将上箭头和下箭头键绑定到 Bash 历史记录的搜索(参见:Readline#HistoryReadline Init File Syntax

~/.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

删除除最后一次相同的命令之外的所有命令

~/.bashrc
export HISTCONTROL=erasedups

避免保存以空格开头的命令

~/.bashrc
export HISTCONTROL=ignorespace

避免保存连续相同的命令,以及以空格开头的命令

~/.bashrc
export HISTCONTROL=ignoreboth

删除除最后一次相同的命令之外的所有命令,以及以空格开头的命令

~/.bashrc
export HISTCONTROL="erasedups:ignorespace"

有关详细信息,请参阅 bash(1) § HISTCONTROL

禁用历史记录

仅临时禁用 bash 历史记录

$ set +o history

现在输入的命令不会被记录到 $HISTFILE

例如,现在您可以使用 printf secret | sha256sum 对密码进行哈希处理,或者隐藏 GPG 用法,例如 gpg -eaF secret-pubkey.asc,这样您的秘密就不会写入磁盘。

启用历史记录

$ set -o history

禁用所有 bash 历史记录

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

……只是为了确保,永远删除您的旧 histfile

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

模仿 Zsh 的 run-help 功能

ZshAlt+h 可以调用光标前命令的手册。在 Bash 中使用此 Readline 绑定可以获得类似的行为

~/.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 编辑模式

跨机器共享 bash 历史记录

atuin 使用 SQLite 数据库替换您现有的 Shell 历史记录,并记录命令的额外上下文。此外,它还通过 Atuin 服务器提供跨机器历史记录的可选且完全加密的同步。

在同步之前启用 bash 历史记录时间戳(export HISTTIMEFORMAT="%F %T ")。 Atuinblesh-gitAURcmd-wrapped 等工具配合使用,可在跨机器时提供增强的终端体验。

别名 (Aliases)

别名(alias)是一个命令,它允许将一个词替换为另一个字符串。它通常用于缩写系统命令,或为经常使用的命令添加默认参数。

个人别名可以存储在 ~/.bashrc 或从 ~/.bashrc source 的任何单独文件中。系统范围的别名(影响所有用户)应放在 /etc/bash.bashrc 中。有关示例别名,请参阅 [4]

有关函数,请参阅 Bash/Functions

技巧与提示

提示符自定义

请参阅 Bash/Prompt customization

语法高亮和自动建议

ble.sh (Bash Line Editor),打包为 blesh-gitAUR,是一个用纯 Bash 编写的命令行编辑器,是 GNU Readline 的替代品。它具有许多增强功能,如语法高亮、自动建议、菜单补全、缩写、Vim 编辑模式和钩子函数。其他有趣的功能包括状态行、历史记录共享、右提示符、瞬时提示符和 xterm 标题。

安装后,在交互式会话中 source 它。

~/.bashrc
source /usr/share/blesh/ble.sh

配置在 ~/.blerc 文件和 wiki 中有详细说明。稳定的 bleshAUR 包也可用。

命令未找到

pkgfile 包含一个“命令未找到”钩子,当输入未知命令时,它会自动搜索官方仓库。

您需要 source 钩子以启用它,例如

~/.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#Installation

禁用终端中的 Ctrl+z

您可以通过像这样包装您的命令来禁用 Ctrl+z 功能(暂停/关闭您的应用程序)

#!/bin/bash
trap "" 20
adom

现在,当您不小心在 adomAUR 中按 Ctrl+z 而不是 Shift+z 时,将不会发生任何事情,因为 Ctrl+z 会被忽略。

注销后清屏

在虚拟终端注销后清屏

~/.bash_logout
clear
reset

输入路径时自动 cd

Bash 可以在 Shell 中输入路径时自动预置 cd 。例如

$ /etc
bash: /etc: Is a directory

但在向 .bashrc 文件添加一行后

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

您将获得

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

Autojump

autojump-gitAUR 是一个 Python 脚本,它允许通过搜索用户最常访问路径的数据库来进行文件系统导航。

zoxide 是一个替代方案,它具有额外的功能和性能改进,与原始 autojump 相比,可以作为 autojump 的即插即用替换。

防止覆盖文件

对于当前会话,不允许通过 Shell 输出重定向来覆盖现有常规文件

$ set -o noclobber

这与 set -C 相同。

为您的用户永久更改

~/.bashrc
...
set -o noclobber

当设置了 noclobber 时,手动覆盖文件

$ echo "output" >| file.txt

使用目录栈进行导航

pushdpopd 可用于在切换到目录时将目录推入或弹出到栈中。这对于“回放”您的导航历史记录很有用。

[user@host ~] pushd /tmp/dir1
[user@host /tmp/dir1] pushd /var/lib
[user@host /var/lib] popd
[user@host /tmp/dir1] popd
[user@host ~]

请参阅 bash(1) § DIRSTACK

故障排除

窗口调整时自动换行

调整 终端模拟器大小时,Bash 可能不会收到resize信号。这将导致输入的文本无法正确换行并与提示符重叠。checkwinsize Shell 选项会在每条命令后检查窗口大小,并在必要时更新 LINESCOLUMNS 的值。

~/.bashrc
shopt -s checkwinsize

即使设置了 ignoreeof,Shell 也会退出

如果您设置了 ignoreeof 选项,并发现反复按 ctrl-d 导致 Shell 退出,这是因为该选项只允许连续调用此按键绑定 10 次(或者更准确地说,10 个连续的 EOF 字符),之后才会退出 Shell。

要允许更高的值,您必须使用 IGNOREEOF 变量。

例如:

export IGNOREEOF=100

通过分析脚本来检查错误

软件包 shellcheck 分析 bash(和其他 shell)脚本,打印可能的错误,并建议更好的编码方式。

还有同目的的网站 shellcheck.net,它基于此程序。

参见

教程

社区

示例