系统管理员必懂的bash shell知识
2010-07-13 06:17:45 阿炯

在Linux操作系统,“/bin/bash”是默认登录shell,是在创建用户时分配的。使用chsh命令可以改变默认的shell。本文将为系统管理运维人员提供一个全局性的shell使用参考。

在shell脚本中可以定义如下两种类型的变量
系统定义变量
用户定义变量

在shell脚本中如何比较两个数字?
可以使用-gt、-lt、-ne、-eq来进行比较。

break命令一个简单的用途是退出执行中的循环,我们可以在while和until循环中使用break命令跳出循环。

continue命令不同于break命令,它只跳出当前循环的迭代,而不是整个循环。continue命令很多时候是很有用的,例如错误发生,但我们依然希望继续。

通常使用bash 命令中-x参数来调试执行脚本,如下格式:
bash -x script.sh

bash中有哪些特殊变量?
$0: 命令行中的脚本名字
$1..$9: 脚本可接受的参数个数
$#: 命令行参数的数量
$*: 所有命令参数,转换为一个字符串
$@: 所有命令参数,转换为一个字符串

bash中如何进行算术运算(expr 加法 减法 乘法 除法)?
有如下三种方法:
let i++
expr 1 + 2
$[ 2 + 3]
$(($num1 + $num2))

常用的shell的算术计算是命令是expr,但是在shell脚本中调用一次expr就fork了一个子进程,在循环中作增量操作时效率是比较低的,可以使用shell的内嵌命令:
((i=$j+$k)) 等价于 i=`expr $j + $k`
((i=$j-$k)) 等价于 i=`expr $j - $k`
((i=$j*$k)) 等价于 i=`expr $j \* $k`
((i=$j/$k)) 等价于 i=`expr $j / $k`

用shell语言实现小数的加减乘除运算

方法一
printf "%f" `echo 0.5432+2.432|bc`

方法二
echo "scale=2;0.97/0.48" | bc

如何向脚本传递一个信号?
使用trap命令来获取,如下格式:
#!/bin/bash
# auther: mage team
trap 'echo "quit";exit1' INT

当一个信号被送到脚本时,内建的trap可以用于“捕获”。任何使用TERM信号的CTRL-C,CTRL-或终止程序的操作将会首先调用cleanup。

注意
·trap的逻辑可能非常棘手(例如处理信号竞争条件)
·KILL信号不能以这种方式捕获

如何定义一个数组?
有如下方式:
declare -a NAME : 申明一个索引数组
declare -A NAME : 申明一个关联数组

如何计算一个数组的元素个数?
可以使用如下方式来引用:
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}

file_list=(`ls /www/log/access_log/`)
NUM= $[ ${#file_list[*]} - 1 ]
echo "$NUM"

如何引用一个变量?
有如下两种方式:
$VAR_NAME
${VAR_NAME}

带色彩的输出
alias ls="ls --color=auto"

简单但非常重要,使ls命令带着彩色输出。

alias ll="ls --color -al"

以彩色的列表方式列出目录里面的全部文件。

alias grep='grep --color=auto'

类似,只是在grep里输出带上颜色。

下载整个网站
wget --random-wait -r -p -e robots=off -U mozilla

显示出哪个应用程序连接到网络
lsof -P -i -n

显示出活动的端口
netstat -tulanp

除了传统的ext文件系统,Linux在抽象不同的资源的时候其实有各种不同的文件系统,都是从需求和使用出发,比如proc文件系统就是针对进程的抽象,使得修改对应进程的值就可以直接改变进程的行为。再比如,对于远程ssh登录的pts设备,Linux有对应的devpts文件系统。
file_systemdirtypeoptionsdumppass
tmpfs/dev/shmtmpfsdefaults00
devpts/dev/ptdevptsgid=5,mod=62000
sysfs/syssysfsdefaults00
proc/procprocdefaults00


好用的Linux工具

1、CPU
top 特别注意load
ps aux和ps -ef 特别注意进程状态
vmstat 1表示每秒采集一次
sar -u 1 查看所有cpu相关的运行时间

2、Memory
free
vmstat 1 注意其中的swap ram block之间的关系
sar -r 1 内存使用率
sar -W 1 查看swap,查询是否由于内存不足产生大量内存交换

3、IO
lsof -i:port 查询哪个进程占用了这个端口号
lsof -u username 用户打开的文件
lsof -p pid 进程打开的文件

流程控制语句

if/else流程控制

基本语法结构:

if condition
then
     do something
elif condition
then
    do something
elif condition
then
    do something
else
    do something
fi

另外, [ ] 两边一定要加空格, 下面这样都会报错:
if [$a=$b]
#or
if [ $a=$b]
#or
if [$a=$b ]

只有这样if [ $a=$b ]才是对的。

注意:实际上这里的[]是test命令的一种形式,[是系统的一个内置命令,存在路径是/bin/[,它是调用test命令的标识,右中括号是关闭条件判断的标识, 因此下面的两个测试语句是等效的:
if test "2>3"
then
    ...
fi



if [ "2>3" ]
then
    ...
fi

除[]之外, shell语言中还有几种其它括号, 比如: 单小括号/双小括号/双中括号/…

switch流程控制

当条件较多时, 可以选择使用switch语句, shell中的switch语句的写法和其它语言还是有些不同的, 基本结构如下:
case expression in
    pattern1)
        do something... ;;
    pattern2)
        do something... ;;
    pattern2)
        do something... ;;
    ...
esac

注意:
;;相当于其它语言中的break
每个pattern之后记得加)
最后记得加esac (即反的case)

for循环

基本结构:
for name [in list]
do
    ...
done

其中,[]括起来的 in list, 为可选部分, 如果省略in list则默认为in "$@", 即你执行此命令时传入的参数列表.

while循环

基本结构:

while condition
do
    do something...
done

until循环

基本结构:

until condition
do
    do something...
done

跳出循环

shell中也支持break跳出循环,continue跳出本次循环,用法与C、Java中相同,在上文有提及。

bash环境创建别名

在终端中运行某些命令时,该指令的执行路径没有位于该用户的PATH中,或该指令有较多的参数,而又要频繁的调用。此时为它们设置一个别名就派上用场了。在用户的主目录中存在三个配置文件中:'.bashrc','.bash_login','.profile',加入到其中一个就可以了,如果将同一别名加入到它们中,别名所对应的指令不一样的话,则那个文件最后加载的别名将成为最终别名,其它的将会被覆盖。

可以将这些别名加入到用户shell相关的个人配置文件(.bashrc)中
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

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

建议放到个人目录的'.bashrc'文件中,下列为创建一个别名到该文件中。

echo "alias np="/opt/perl/bin/perl" >~/.bashrc

更多示例

alias doc='cd ~/Documents/'
alias ps='ps aux'

alias ll='ls -l'
alias rm='rm -i'
alias cs='cd;ls'

解压 .tar.gz 文件但无法记住所需的确切参数?别名可以帮助你!只需将以下内容添加到 .bash_profile 中,然后使用 untar FileName 解压缩任何 .tar.gz 文件。
alias untar='tar -zxvf'

普通的 ping 将永远持续下去。我们不希望这样,让我们将其限制在9个 ping。
alias ping='ping -c 9'

知道你的外部公网 IP 地址。
alias ipp='curl ipinfo.io/ip'

使加入的别名立即生效:
source /home/bakhtiyor/.bashrc
or
. /home/bakhtiyor/.bashrc


bash环境的编辑器

一些在命令行下使用的指令在使用时要处于编辑状态,这时bash环境的编辑器就派上用场了,比如像crontab的默认编辑器是nano,想换为vim。可以通过定义EDITOR参数来修改crontab默认的编辑器,不过这样有些麻烦。在Debian下运行一下命令就可以查看EDITOR支持哪些编辑器:
update-alternatives --list editor

然后用
update-alternatives --config editor

来进行修改,不过这样的操作需要root权限:
$ update-alternatives --config editor
有 3 个候选项可用于替换 editor (提供 /usr/bin/editor)。
  选择       路径              优先级  状态
------------------------------------------------------------
* 0            /bin/nano            40        自动模式
  1            /bin/nano            40        手动模式
  2            /usr/bin/vim.basic   30        手动模式
  3            /usr/bin/vim.tiny    10        手动模式

要维持当前值[*]请按回车键,或者键入选择的编号:2
update-alternatives: 使用 /usr/bin/vim.basic 来提供 /usr/bin/editor (editor),于 手动模式 中。
update-alternatives: 错误: 无法创建 /etc/alternatives/editor.dpkg-tmp 为 /usr/bin/vim.basic 的符号链接:权限不够

不过还有别的办法:那就是修改select-editor的用户配置,直接修改用户配置就行了:
1、编辑.profile文件,增加  EDITOR=vi;export EDITOR

2、直接在命令行输入 EDITOR=vi;export EDITOR

update-alternatives是在系统对某个功能有多个软件时时,设置这些软件的缺省调用,例如editor。其原理是在/usr/bin中建立一个link,指向/etc/alternatives中的一个文件,而这些文件又是一个link,指向当前使用的指令。


本站内的相关参考:


Shell十三问

bash shell 内部命令

bash shell 内置参数

bash脚本编写简略教程

bash脚本编写入门教程

bash环境中快捷键介绍

Shell测试和比较函数(test)

Shell数组介绍

Shell脚本经典的用法

Shell代码编写规范

Shell正则表达式

bash中变量与运算

bash shell 环境设置参考

bash history 命令常见使用方法

Linux Shell编程中的特殊符号