Pingfan's Blog

bash脚本debug技巧

字数统计: 687阅读时长: 3 min
2019/06/02 Share

调试

在shebang最后一行加入-x, 这样每执行一行命令都会把执行的语句打印出来。例如:

#!/usr/bin/env bash -x

backup_file() {
    if [[ -f $1 ]]  # 1. check if its a file and it does exists
    then
        # basename 将前面的路径都剔除,只保留文件名
        # $$表示pid(正在运行当前脚本的进程id)。在这里使用这个,为了防止同一天多次备份时,前面的备份被覆盖。
        local BACK="/tmp/$(basename ${1})-$(date +%F)-$$"
        echo ${BACK}
        cp $1 ${BACK}
    else
        # The file not exists
        return 1
    fi
}

backup_file /etc/hosts

if [[ $? -eq 0 ]]
then
    echo "Backup succeeded"
else
    echo "Backup failed!"
    exit 1
fi

执行结果如下:

[@bogon:bashlearn (master)]$ ./2.sh 
+ backup_file /etc/hosts
+ [[ -f /etc/hosts ]]
++ basename /etc/hosts
++ date +%F
+ local BACK=/tmp/hosts-2019-06-02-35242
+ echo /tmp/hosts-2019-06-02-35242
/tmp/hosts-2019-06-02-35242
+ cp /etc/hosts /tmp/hosts-2019-06-02-35242
+ [[ 0 -eq 0 ]]
+ echo 'Backup succeeded'
Backup succeeded


第二种写法可以使用set -x (set +x 表示停止debugging)

这样可以在脚本的任何位置控制调试的开启和关闭。

#!/usr/bin/env bash


backup_file() {
    if [[ -f $1 ]]  # 1. check if its a file and it does exists
    then
        # basename 将前面的路径都剔除,只保留文件名
        # $$表示pid(正在运行当前脚本的进程id)。在这里使用这个,为了防止同一天多次备份时,前面的备份被覆盖。
        local BACK="/tmp/$(basename ${1})-$(date +%F)-$$"
        echo ${BACK}
        cp $1 ${BACK}
    else
        # The file not exists
        return 1
    fi
}

set -x # 在此处开启调试
backup_file /etc/hosts
set +x # 在此处关闭调试,后面部分不会输出调试语句

if [[ $? -eq 0 ]]
then
    echo "Backup succeeded"
else
    echo "Backup failed!"
    exit 1
fi

PS4

在调试的时候,可以使用PS4,这条命令和-x一起使用。

上面调试时候每行都输出+,因为PS4的默认值为+

可以设置它的格式,例如:PS4='+ $BASH_SOURCE : $LINENO : '

这样之前的脚本:

#!/usr/bin/env bash

PS4='+ $BASH_SOURCE : $LINENO : '
backup_file() {
...........
........

输出结果如下:

[@bogon:bashlearn (master)]$ ./2.sh 
+ ./2.sh : 19 : backup_file /etc/hosts
+ ./2.sh : 5 : [[ -f /etc/hosts ]]
++ ./2.sh : 9 : basename /etc/hosts
++ ./2.sh : 9 : date +%F
+ ./2.sh : 9 : local BACK=/tmp/hosts-2019-06-02-35480
+ ./2.sh : 10 : echo /tmp/hosts-2019-06-02-35480
/tmp/hosts-2019-06-02-35480
+ ./2.sh : 11 : cp /etc/hosts /tmp/hosts-2019-06-02-35480
+ ./2.sh : 20 : set +x
Backup succeeded

它把行号都打印出来了,非常利于错误的定位。

-e参数

e = exit

一旦执行到错误的地方就退出。

和-x一起使用,可以精确的定位脚本哪一行出的错(因为出错就会退出)

#!/bin/bash -ex
#!/bin/bash -xe
#!/bin/bash -x -e
#!/bin/bash -e -x

例如:

#!/usr/bin/env bash -ex

FILE_NAME="/not/here"
ls ${FILE_NAME}
echo ${FILE_NAME}

由于文件不存在,执行结果如下:

[@bogon:bashlearn (master)]$ ./4.sh 
+ FILE_NAME=/not/here
+ ls /not/here
ls: /not/here: No such file or directory

CATALOG
  1. 1. 调试
  2. 2. PS4
  3. 3. -e参数