bash破壳利用_充分利用bash

本文深入探讨Bash Shell的高级特性,包括命令行编辑、历史记录、文件完成、别名、目录堆栈及脚本改进。Bash通过增强的交互性和定制能力,显著提升了UNIX和Linux环境下系统管理的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于本系列

典型的UNIX®管理员经常使用一系列重要的实用程序,技巧和系统,以协助管理过程。 有一些关键实用程序,命令行链和脚本可用来简化不同的过程。 这些工具中的一部分随操作系统一起提供,但是大多数技巧来自多年的经验以及减轻系统管理员生活的渴望。 本系列的重点是从各种不同UNIX环境中的可用工具中获取最大收益,包括简化异构环境中管理的方法。

重击背景

UNIX和Linux®下的Shell通常根据UNIX最早版本附带的原始Shell分为两类之一。 两种类型分别是Bourne Shell和C Shell,后者是与众不同的,因为其格式和结构类似于C编程语言。

Bourne Shell比C Shell更易于使用和理解,但对于您可能希望在Shell编程环境中实现的更复杂的脚本编程而言,它不那么实用。 Korn shell提供了Bourne shell的易用性,并添加了作业控制扩展(允许您轻松管理多个后台作业),命令行编辑和历史记录,并添加了C shell的元素以简化编程。

Bourne-again shell(bash)是一个开源项目,结合了Bourne shell的原理,C shell的编程环境,Korn shell的扩展功能以及其自身的许多扩展以提供丰富的环境,仅用于编写Shell脚本,还用作控制和与计算机交互的交互式Shell环境。

命令行编辑和键绑定

bash中的主命令提示符既提供了编辑命令行的功能,又提供了历史记录功能,可以记住各个命令行,以便您可以再次执行它们。

编辑功能意味着您可以在当前显示的命令行中前进和后退,以进行更改和纠正错别字。 在bash的标准格式中,您可以使用光标键进行基本移动。 默认情况下,支持VI和emacs绑定的Readline库控制着更广泛的命令(例如,按单词向前和向后前进)。 要设置编辑模式,请在命令行或引导文件中指定您的首选模式: $ set editing-mode emacs

例如,使用emacs编辑模式,以下按键绑定有效:

  • Control-A-此键绑定将您带到行的开头。
  • Control-E-此键绑定将您带到行尾。
  • Control-K-此键绑定将所有内容删除到该行的末尾。
  • Meta-B-此键绑定返回一个单词。
  • Meta-F-此键绑定向前移动一个单词。
  • Meta-D-此键绑定将删除当前单词。

实际上,您可以使用内部bind bash命令将所需的任何键或组合绑定到特定操作。 首先,可以使用-P选项获得可用命令的列表(请参见清单1 )。

清单1.使用-P选项获取可用命令的列表
$ bind -P 

abort can be found on "\C-g", "\C-x\C-g", "\M-\C-g".
accept-line can be found on "\C-j", "\C-m".
alias-expand-line is not bound to any keys
arrow-key-prefix is not bound to any keys
backward-byte is not bound to any keys
...
yank can be found on "\C-y".
yank-last-arg can be found on "\M-.", "\M-_".
yank-nth-arg can be found on "\M-\C-y".
yank-pop can be found on "\M-y".

\C表示控制键。 \M序列指的是“元”键(某些键盘上的特殊键,通常是Alt键或Escape键)。

要设置绑定,必须指定键序列和要执行的命令,并用冒号分隔,并用双引号将键序列转义(在极端情况下,可能需要再次用单引号转义)。 例如,要将Control-B更改为逐字向后,请使用$ bind "\Cb":backward-word

您甚至可以使用绑定来执行Shell命令(例如,运行应用程序)。 为此,您必须添加-x选项,并且这是要求两者都转义的示例。 例如,要将Control-E设置为运行emacs,可以使用以下命令: $ bind -x '"\Ce"':emacs

要每次都在bash中启用键绑定,您可以在.inputrc文件中设置信息(这会影响所有启用Readline的d应用程序),也可以在启动脚本中放置特定的bash绑定,稍后将进行介绍。在这篇文章中。

命令历史

您输入的每个命令都会被记录下来,以便您返回到该命令并逐字再次运行它,或者对其进行编辑并运行编辑后的版本。 您可以使用Control-P (上一个命令)和Control-N (下一个)在命令历史记录中前进和后退(按时间顺序)。 如果您已经返回上一个命令,则只能继续下一步。

如果您知道命令的内容,但不记得它在哪里,又不想手动浏览命令列表,则可以使用Control-R进行反向智能搜索。 这将返回与您输入的第一个字母匹配的第一个命令(反向顺序)。 连续键入的字母越来越匹配。 找到所需的命令后,请按Return键逐字运行它。 要编辑找到的命令,请使用光标键(或键绑定)移动到要编辑的点。

即时定制

使用所有Shell,通常可以通过设置PS1变量的值来自定义在命令行上显示的提示。 通常,这仅限于能够设置静态字符串,或者对于Korn Shell,通常可以设置动态值,例如当前目录。

Bash进一步扩展了此功能,以允许包含用户名,主机名,甚至隐藏的字符(例如,用于着色或设置Windows和Xterms标题所需的转义符)。 每次在打印提示之前都会评估指定的字符串,以便始终保持最新状态。

通过一系列反斜杠字符可以实现特定动态值的自定义扩展。 例如,要设置由用户名和当前目录的最后一部分组成的典型提示,请使用以下命令: PS1="\u \W$"

一个更典型的解决方案是显示用户名,主机名,目录以及美元或哈希符号,具体取决于当前用户的UID。 当有效用户ID为零(root)时,后一个选项显示一个哈希符号: PS1='\u@\h:\W \$ "

表1列出了可用扩展的完整列表。

表1.可用扩展列表
转义符 描述
\ t \ t是时间,采用HH:MM:SS格式。
\ d \ d是日期,采用“日期名称月日”格式(例如,星期五10月13日)。
\ n \ n是换行符。
\ s \ s是外壳程序的名称(通常为bash,如果外壳程序是登录外壳程序,则为'-bash')。
\ w \ w是当前目录的完整路径。
\ W \ W是当前目录的最后一部分(换句话说,在'/ home / mc'中时为'mc')。
\ u \ u是您的用户名。
\H \ h是主机名。
\# \#是此命令的命令号(该值每行递增)。
\! \! 是此命令的唯一历史记录编号。
\ nnn \ nnn是由八进制nnn标识的字符。
\ $ 如果有效UID为零,则\ $为#字符,否则为$字符。
\\ \\是反斜杠。
\ [ \ [开始一个转义序列; 通常用于终端控制字符的着色和标题。
\] \]结束转义序列。

转义序列字符可用于发送终端控制序列,而终端控制序列又可用于设置颜色和终端标题。 由于bash每次显示提示时都会更新此信息,因此会相应地自动更新窗口标题。 例如,使用清单2中的以下顺序终端窗口和Xterm标题设置为user @ hostname:fullpath,并使用适当的终止符(美元或哈希)将提示设置为hostname:endpath。

清单2.设置终端标题和提示
PS1=" \[\033]0;\u@\h: \w\007\]\[\033[31m\]\h \[\033[34m\]\W \$ \[\033[00m\]"

此外,主机名在root用户时为红色,普通用户为绿色,提示的其余部分为青色。

文件和目录完成

为了帮助加快外壳程序交互的速度,bash包含了路径名补全功能-也就是说,您可以让bash填写路径名的其余部分或为您提供潜在扩展的列表。

例如,如果您查看当前目录,则存在一系列不同的子目录(请参见清单3 )。

清单3.当前目录中的子目录
$ ls -f
back/   cheffyhack/  edin/     logstomerge/  mysql-binlogs/  svn/
build/  cvs/         install/  lost+found/   mysqlsizer      vmware/
calc/   dbdumps/     logs/     my.cnf        statmon/        webs/

要进入edin目录,可以输入: $ cd edin 。 或者,在bash中使用完成功能,可以键入: $ cd e ,然后按TAB键。 默认情况下,这将尝试扩展以'e'开头的路径名; 该目录中的结果应为: $ cd edin

如果有多个匹配项,则TAB的第一次按下失败; 再次按TAB键将返回匹配路径的列表(请参见清单4 )。

清单4.返回匹配路径的列表
$ cd my
my.cnf         mysql-binlogs/ mysqlsizer

扩展将继续工作,用唯一的组件替换它所能提供的功能,直到没有进一步的扩展或只有一个扩展为止。 例如,考虑清单5中所示的以下序列。

清单5.继续扩展
$ cd my <TAB>
my.cnf         mysql-binlogs/ mysqlsizer
$ cd mys <TAB>
$ cd mysql <TAB> <TAB>
mysql-binlogs/ mysqlsizer
$ cd mysqls <TAB>
$ cd mysqlsizer

如果路径名是目录,则可以继续扩展路径名的每个部分。

别名

别名是一种简单的机制,使您能够为给定序列提供扩展。 因为别名是扩展名而不是替代名,所以它使您能够继续向别名命令添加选项和参数。

例如,通常会设置一个别名('ll'),该别名会扩展为'ls -l',以长长地列出目录或文件列表。 您可以使用以下命令行创建别名: alias ll='ls -l'

要使用,只需在提示符下键入别名: $ ll

因为别名就是真实命令的别名,所以您可以添加其他选项,例如,列出目录中的所有文件,请使用: $ ll -a ,它实际上会扩展为: $ ls -l -a

别名是快速运行命令或使用常用的命令行选项运行您喜欢的命令的有效方法。

使用目录栈

目录堆栈使您可以将一个或多个目录存储到一个临时区域中,然后再次将它们带回。 目录列表就像堆栈一样-将目录压入堆栈的顶部,然后再次从顶部弹出目录以将其取回。

要将目录推送到堆栈上,请使用pushd和要放置在堆栈上的目录-例如,您可以推送当前目录,该目录可以由单个句点标识(请参见清单6 )。

清单6.推送当前目录
$ pushd .
/export/data /export/data

Bash会以您推送的目录和当前堆栈中所有目录的列表(以空格分隔)进行响应。 通过更改目录并再次推送它,您可以更清楚地看到这一点(请参见清单7 )。

清单7.推送另一个目录
$ cd /etc
$ pushd .
/etc /etc /export/data

使用popd添加到堆栈中的最后一个目录,并更改为该目录(请参见清单8 )。

清单8.使用popd
$ cd /usr/local/bin
$ popd
/etc /export/data
$ pwd

popd命令返回目录列表,然后再切换到新目录。

当您要临时更改目录然后返回原始目录时,最常使用目录功能。 为了简化这种情况,bash通常配置有两个别名pupo ,如清单9所示。

清单9. Pu和po别名
$ alias pu='pushd .'
$ alias po='popd'

例如,假设您正在一个目录中工作,突然意识到您需要在另一个目录中创建tar归档文件(请参见清单10 )。

清单10.使用pu和po创建一个tar归档文件
$ pwd
/usr/local/bin
$ pu
/usr/local/bin /usr/local/bin
$ cd /export/data
$ tar cf webs.tar ./webs
$ po
$ pwd
/usr/local/bin

尽管目录堆栈系统支持多个目录,但是在您临时弹出其他位置时,它经常仅被使用一两个。

Bash运行时配置文件

登录时,bash除了其自己的特定.bash_profile外,还支持标准.profile文件(由Bourne shell使用)。 选择要使用的文件,如下所示:

  • 如果存在〜/ .bash_profile,请使用它,否则:
  • 如果〜/ .bash_login存在,请使用它,否则:
  • 如果〜/ .profile存在,请使用它。

对于未作为登录shell启动的bash shell(例如,当使用Xterm或其他启动子shell的应用程序时,bash查找〜/ .bashrc文件(如果存在)。

由于.bashrc和.bash_profile的内容不太可能更改,因此在清单11中找到包含以下内容的.bash_profile并不少见。

清单11. .bash_profile的内容
if [ -f ~/.bashrc ];
then
    source ~/.bashrc
fi

除了这些规则,文件的内容完全取决于您。 因为在bash环境中可以进行很多自定义,所以发现.bashrc / .bash_profile内容只是包装了许多其他〜/ .bash_ *脚本的包装器并不少见。 例如,您可以将配置拆分为:

  • 〜/ .bash_aliases-存储所有自定义别名和函数
  • 〜/ .bash_path-存储所有路径规范
  • 〜/ .bash_vars-存储所有bash变量

然后,它们在.bashrc中获得(请参见清单12 )。

清单12. .bashrc的内容
if [ -f ~/.bash_path ]; then
    source ~/.bash_path
fi

if [ -f ~/.bash_vars ]; then
    source ~/.bash_vars
fi

if [ -f ~/.bash_aliases ]; then
    source ~/.bash_aliases
fi

您应小心确保文件以正确的顺序获得。

脚本改进

bash提供了相当大的改进的最后一个方面是脚本功能。 大多数shell普遍引用的局限性之一是它们具有松散的变量类型,不支持数据数组以及没有执行基本数学或表达式的内置功能。 所有这些都在bash中得到了不同程度的解决。

bash中的变量可以在使用前声明,并且声明可以包含类型。 例如,要将变量声明为整数类型(因此始终被标识为有效数字),请使用: $ declare -i myint 。 要同时设置一个值,请使用: $ declare -i myint=235

为了执行基本的算术运算,可以将表达式嵌入$(( )) (参见清单13 )。

清单13.嵌入表达式以执行基本算术
$ echo $((4+3*12))
40

您还可以包括变量(请参见清单14 )。

清单14.包含变量
$ echo $((myint+3*12))
63

要将变量声明为数组类型,请使用$ declare -a myarray

您可以通过指定括号中的值列表来添加值: $ declare -a myarray=(tom dick harry)

要从数组中获取一个值,请指定数组引用(请参见清单15 )。

清单15.指定数组引用
$ echo ${myarray[1]} 
dick

您可以使用相同的系统来填充数组,例如,从文件列表中填充数组(请参见清单16 )。

清单16.从文件列表填充数组
$ declare -a files=`ls`
$ echo $files
back/ build/ calc/ cheffyhack/ cvs/ dbdumps/ edin/ install/ \
    logs/ logstomerge/ lost+found/ my.
cnf mysql-binlogs/ mysqlsizer statmon/ svn/ vmware/ webs/

然后,可以使用@符号作为元素规范来使用数组的全部内容(请参见清单17 )。

清单17.使用@符号作为元素规范
for file in ${files[@]}
do
    echo $file
done

这种操作和变量支持大大简化了使用Shell脚本进行编程的各个方面。

摘要

Bash与传统的Bourne,Korn和C shell相比,提供了许多重大改进。 这些扩展中的大部分可改善交互式用户的体验,即使用bash作为与系统进行交互的主要方法的用户。 有些系统已成为一种习惯,例如,路径名完成和别名,而另一些则在个别情况下至关重要。 目录堆栈功能就是一个很好的例子。 当您想要一种快速访问目录而不失思路的方法时,它变得无价。

无论在bash shell中使用什么元素,您都会发现一个丰富的环境和几乎无限的自定义数组,可用于改善交互和环境。


翻译自: https://www.ibm.com/developerworks/aix/library/au-satbash.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值