shell 编程

描述

记录shell编程出现的坑和一些常用的语法

SHELL 参数

  • ${parameter:?word}

当parameter指示的参数没有被设值的时候,将会通过标准错误的方式显示word中的语句。

shell中各种括号的使用记录

小括号(又称圆括号)

单小括号
  1. 新开一个进程来执行命令

    mage-20180425172533

    如图所示,括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。

  2. 作为$()来使用用于将()中的命令执行的结果替换回原来的位置

  3. 用于初始化数组。如:array=(a b c d)

双小括号
  1. 整数扩展。这种扩展计算是整数型的计算,不支持浮点型。((exp))结构扩展并计算一个算术表达式的值,如果表达式的结果为0,那么返回的退出状态码为1,或者 是”假”,而一个非零值的表达式所返回的退出状态码将为0,或者是”true”。若是逻辑判断,表达式exp为真则为1,假则为0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [root@zabbix-server ~]# NUM=0
    [root@zabbix-server ~]# if (($NUM));then echo true;else echo false;fi
    false
    [root@zabbix-server ~]# NUM=1
    [root@zabbix-server ~]# if (($NUM));then echo true;else echo false;fi
    true
    [root@zabbix-server ~]# if ((1>2));then echo true;else echo false;fi
    false
    [root@zabbix-server ~]# if ((1<2));then echo true;else echo false;fi
    true
    [root@zabbix-server ~]# if ((1==2));then echo true;else echo false;fi
    false
  2. 只要括号中的运算符、表达式符合C语言运算规则,都可用在\$((exp))中,甚至是三目运算符。作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制。

    1
    2
    [root@zabbix-server ~]# echo $((16#10))
    16
  3. 做数学运算

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [root@zabbix-server ~]# a=1
    [root@zabbix-server ~]# ((a++))
    [root@zabbix-server ~]# echo $a
    2
    [root@zabbix-server ~]# ((a--))
    [root@zabbix-server ~]# echo $a
    1
    [root@zabbix-server ~]# ((a=a+2))
    [root@zabbix-server ~]# echo $a
    3
    [root@zabbix-server ~]# ((a=a*2))
    [root@zabbix-server ~]# echo $a
    6
  4. 常用于算术运算比较,双括号中的变量可以不使用$符号前缀。括号内支持多个表达式用逗号分开。 只要括号中的表达式符合C语言运算规则,比如可以直接使用for((i=0;i<5;i++))

特殊公式
1
echo ${ZABBIX_SOURCE_DIR:=zabbix-3.4.8}

作用是如果ZABBIX_SOURCE_DIR不为空则输出$ZABBIX_SOURCE_DIR,否则输出zabbix-3.4.8,同时把zabbix-3.4.8赋值给ZABBIX_SOURCE_DIR。

执行命令时不走alias

关于Linux的拷贝命令我们都知道cp的参数 -f的意思是:

-f, –force if an existing destination file cannot be opened, remove it and try again

也就是说-f可以覆盖目的目录下有的文件,

但你有没有发现过这种情况,即使使用了-f也无法覆盖?

原因何在呢?

默认cp命令是有别名(alias cp=’cp -i’)的,无法强制覆盖,即使你用 -f 参数也无法强制覆盖文件。

可以使用\cp 执行cp命令时不走alias

\cp * -rf ../../test

网上还有一种解决方法:临时取消cp的alias

1
2
3
>#unalias cp
>#cp a /test/a
>

常用的判断

  • –b 当file存在并且是块文件时返回真

  • -c 当file存在并且是字符文件时返回真

  • -d 当pathname存在并且是一个目录时返回真

  • -e 当pathname指定的文件或目录存在时返回真

  • -f 当file存在并且是正规文件时返回真

  • -g 当由pathname指定的文件或目录存在并且设置了SGID位时返回为真

  • -h 当file存在并且是符号链接文件时返回真,该选项在一些老系统上无效

  • -k 当由pathname指定的文件或目录存在并且设置了“粘滞”位时返回真

  • -p 当file存在并且是命令管道时返回为真

  • -r 当由pathname指定的文件或目录存在并且可读时返回为真

  • -s 当file存在文件大小大于0时返回真

  • -u 当由pathname指定的文件或目录存在并且设置了SUID位时返回真

  • -w 当由pathname指定的文件或目录存在并且可执行时返回真。一个目录为了它的内容被访问必然是可执行的。

  • -o 当由pathname指定的文件或目录存在并且被子当前进程的有效用户ID所指定的用户拥有时返回真。


  • -eq 等于

  • -ne 不等于
  • -gt 大于
  • -lt 小于
  • -le 小于等于
  • -ge 大于等于
  • -z 空串
  • = 两个字符相等
  • != 两个字符不等
  • -n 非空串

常用的判断命令是否存在

1
2
3
$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }